1 /* BFD back-end for i386 a.out binaries under LynxOS.
2 Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 #define BYTES_IN_WORD 4
21 #define N_SHARED_LIB(x) 0
23 #define TEXT_START_ADDR 0
24 #define TARGET_PAGE_SIZE 4096
25 #define SEGMENT_SIZE TARGET_PAGE_SIZE
26 #define DEFAULT_ARCH bfd_arch_i386
28 #define MY(OP) CAT(i386lynx_aout_,OP)
29 #define TARGETNAME "a.out-i386-lynx"
36 #define WRITE_HEADERS(abfd, execp) \
38 bfd_size_type text_size; /* dummy vars */ \
40 if (adata(abfd).magic == undecided_magic) \
41 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
43 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
44 execp->a_entry = bfd_get_start_address (abfd); \
46 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
47 obj_reloc_entry_size (abfd)); \
48 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
49 obj_reloc_entry_size (abfd)); \
50 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
52 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) return false; \
53 if (bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd) \
56 /* Now write out reloc info, followed by syms and strings */ \
58 if (bfd_get_symcount (abfd) != 0) \
60 if (bfd_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET) \
64 if (! NAME(aout,write_syms)(abfd)) return false; \
66 if (bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET) \
70 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
72 if (bfd_seek (abfd, (file_ptr)(N_DRELOFF(*execp)), SEEK_SET) \
76 if (!NAME(lynx,squirt_out_relocs)(abfd, obj_datasec (abfd))) \
83 #include "aout/aout64.h"
87 char *lynx_core_file_failing_command ();
88 int lynx_core_file_failing_signal ();
89 boolean
lynx_core_file_matches_executable_p ();
90 const bfd_target
*lynx_core_file_p ();
92 #define MY_core_file_failing_command lynx_core_file_failing_command
93 #define MY_core_file_failing_signal lynx_core_file_failing_signal
94 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
95 #define MY_core_file_p lynx_core_file_p
97 #endif /* LYNX_CORE */
100 #define KEEPIT udata.i
102 extern reloc_howto_type aout_32_ext_howto_table
[];
103 extern reloc_howto_type aout_32_std_howto_table
[];
105 /* Standard reloc stuff */
106 /* Output standard relocation information to a file in target byte order. */
109 NAME(lynx
,swap_std_reloc_out
) (abfd
, g
, natptr
)
112 struct reloc_std_external
*natptr
;
115 asymbol
*sym
= *(g
->sym_ptr_ptr
);
117 unsigned int r_length
;
119 int r_baserel
, r_jmptable
, r_relative
;
120 unsigned int r_addend
;
121 asection
*output_section
= sym
->section
->output_section
;
123 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
125 r_length
= g
->howto
->size
; /* Size as a power of two */
126 r_pcrel
= (int) g
->howto
->pc_relative
; /* Relative to PC? */
127 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
132 r_addend
= g
->addend
+ (*(g
->sym_ptr_ptr
))->section
->output_section
->vma
;
134 /* name was clobbered by aout_write_syms to be symbol index */
136 /* If this relocation is relative to a symbol then set the
137 r_index to the symbols index, and the r_extern bit.
139 Absolute symbols can come in in two ways, either as an offset
140 from the abs section, or as a symbol which has an abs value.
145 if (bfd_is_com_section (output_section
)
146 || bfd_is_abs_section (output_section
)
147 || bfd_is_und_section (output_section
))
149 if (bfd_abs_section_ptr
->symbol
== sym
)
151 /* Whoops, looked like an abs symbol, but is really an offset
152 from the abs section */
160 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
165 /* Just an ordinary section */
167 r_index
= output_section
->target_index
;
170 /* now the fun stuff */
171 if (bfd_header_big_endian (abfd
))
173 natptr
->r_index
[0] = r_index
>> 16;
174 natptr
->r_index
[1] = r_index
>> 8;
175 natptr
->r_index
[2] = r_index
;
177 (r_extern
? RELOC_STD_BITS_EXTERN_BIG
: 0)
178 | (r_pcrel
? RELOC_STD_BITS_PCREL_BIG
: 0)
179 | (r_baserel
? RELOC_STD_BITS_BASEREL_BIG
: 0)
180 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_BIG
: 0)
181 | (r_relative
? RELOC_STD_BITS_RELATIVE_BIG
: 0)
182 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_BIG
);
186 natptr
->r_index
[2] = r_index
>> 16;
187 natptr
->r_index
[1] = r_index
>> 8;
188 natptr
->r_index
[0] = r_index
;
190 (r_extern
? RELOC_STD_BITS_EXTERN_LITTLE
: 0)
191 | (r_pcrel
? RELOC_STD_BITS_PCREL_LITTLE
: 0)
192 | (r_baserel
? RELOC_STD_BITS_BASEREL_LITTLE
: 0)
193 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_LITTLE
: 0)
194 | (r_relative
? RELOC_STD_BITS_RELATIVE_LITTLE
: 0)
195 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_LITTLE
);
201 /* Output extended relocation information to a file in target byte order. */
204 NAME(lynx
,swap_ext_reloc_out
) (abfd
, g
, natptr
)
207 register struct reloc_ext_external
*natptr
;
212 unsigned int r_addend
;
213 asymbol
*sym
= *(g
->sym_ptr_ptr
);
214 asection
*output_section
= sym
->section
->output_section
;
216 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
218 r_type
= (unsigned int) g
->howto
->type
;
220 r_addend
= g
->addend
+ (*(g
->sym_ptr_ptr
))->section
->output_section
->vma
;
223 /* If this relocation is relative to a symbol then set the
224 r_index to the symbols index, and the r_extern bit.
226 Absolute symbols can come in in two ways, either as an offset
227 from the abs section, or as a symbol which has an abs value.
231 if (bfd_is_com_section (output_section
)
232 || bfd_is_abs_section (output_section
)
233 || bfd_is_und_section (output_section
))
235 if (bfd_abs_section_ptr
->symbol
== sym
)
237 /* Whoops, looked like an abs symbol, but is really an offset
238 from the abs section */
245 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
250 /* Just an ordinary section */
252 r_index
= output_section
->target_index
;
256 /* now the fun stuff */
257 if (bfd_header_big_endian (abfd
))
259 natptr
->r_index
[0] = r_index
>> 16;
260 natptr
->r_index
[1] = r_index
>> 8;
261 natptr
->r_index
[2] = r_index
;
263 (r_extern
? RELOC_EXT_BITS_EXTERN_BIG
: 0)
264 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_BIG
);
268 natptr
->r_index
[2] = r_index
>> 16;
269 natptr
->r_index
[1] = r_index
>> 8;
270 natptr
->r_index
[0] = r_index
;
272 (r_extern
? RELOC_EXT_BITS_EXTERN_LITTLE
: 0)
273 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_LITTLE
);
276 PUT_WORD (abfd
, r_addend
, natptr
->r_addend
);
279 /* BFD deals internally with all things based from the section they're
280 in. so, something in 10 bytes into a text section with a base of
281 50 would have a symbol (.text+10) and know .text vma was 50.
283 Aout keeps all it's symbols based from zero, so the symbol would
284 contain 60. This macro subs the base of each section from the value
285 to give the true offset from the section */
288 #define MOVE_ADDRESS(ad) \
290 /* undefined symbol */ \
291 cache_ptr->sym_ptr_ptr = symbols + r_index; \
292 cache_ptr->addend = ad; \
294 /* defined, section relative. replace symbol with pointer to \
295 symbol which points to section */ \
298 case N_TEXT | N_EXT: \
299 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
300 cache_ptr->addend = ad - su->textsec->vma; \
303 case N_DATA | N_EXT: \
304 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
305 cache_ptr->addend = ad - su->datasec->vma; \
308 case N_BSS | N_EXT: \
309 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
310 cache_ptr->addend = ad - su->bsssec->vma; \
314 case N_ABS | N_EXT: \
315 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
316 cache_ptr->addend = ad; \
322 NAME(lynx
,swap_ext_reloc_in
) (abfd
, bytes
, cache_ptr
, symbols
, symcount
)
324 struct reloc_ext_external
*bytes
;
327 bfd_size_type symcount
;
332 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
334 cache_ptr
->address
= (GET_SWORD (abfd
, bytes
->r_address
));
336 r_index
= bytes
->r_index
[1];
337 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_EXT_BITS_EXTERN_BIG
));
338 r_type
= (bytes
->r_index
[0] & RELOC_EXT_BITS_TYPE_BIG
)
339 >> RELOC_EXT_BITS_TYPE_SH_BIG
;
341 cache_ptr
->howto
= aout_32_ext_howto_table
+ r_type
;
342 MOVE_ADDRESS (GET_SWORD (abfd
, bytes
->r_addend
));
346 NAME(lynx
,swap_std_reloc_in
) (abfd
, bytes
, cache_ptr
, symbols
, symcount
)
348 struct reloc_std_external
*bytes
;
351 bfd_size_type symcount
;
355 unsigned int r_length
;
357 int r_baserel
, r_jmptable
, r_relative
;
358 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
360 cache_ptr
->address
= bfd_h_get_32 (abfd
, bytes
->r_address
);
362 r_index
= bytes
->r_index
[1];
363 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_EXTERN_BIG
));
364 r_pcrel
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_PCREL_BIG
));
365 r_baserel
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_BASEREL_BIG
));
366 r_jmptable
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_JMPTABLE_BIG
));
367 r_relative
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_RELATIVE_BIG
));
368 r_length
= (bytes
->r_index
[0] & RELOC_STD_BITS_LENGTH_BIG
)
369 >> RELOC_STD_BITS_LENGTH_SH_BIG
;
371 cache_ptr
->howto
= aout_32_std_howto_table
+ r_length
+ 4 * r_pcrel
;
372 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
380 NAME(lynx
,slurp_reloc_table
) (abfd
, asect
, symbols
)
386 bfd_size_type reloc_size
;
388 arelent
*reloc_cache
;
391 if (asect
->relocation
)
394 if (asect
->flags
& SEC_CONSTRUCTOR
)
397 if (asect
== obj_datasec (abfd
))
399 reloc_size
= exec_hdr (abfd
)->a_drsize
;
403 if (asect
== obj_textsec (abfd
))
405 reloc_size
= exec_hdr (abfd
)->a_trsize
;
409 bfd_set_error (bfd_error_invalid_operation
);
413 if (bfd_seek (abfd
, asect
->rel_filepos
, SEEK_SET
) != 0)
415 each_size
= obj_reloc_entry_size (abfd
);
417 count
= reloc_size
/ each_size
;
420 reloc_cache
= (arelent
*) bfd_malloc (count
* sizeof (arelent
));
421 if (!reloc_cache
&& count
!= 0)
423 memset (reloc_cache
, 0, count
* sizeof (arelent
));
425 relocs
= (PTR
) bfd_alloc (abfd
, reloc_size
);
426 if (!relocs
&& reloc_size
!= 0)
432 if (bfd_read (relocs
, 1, reloc_size
, abfd
) != reloc_size
)
434 bfd_release (abfd
, relocs
);
439 if (each_size
== RELOC_EXT_SIZE
)
441 register struct reloc_ext_external
*rptr
= (struct reloc_ext_external
*) relocs
;
442 unsigned int counter
= 0;
443 arelent
*cache_ptr
= reloc_cache
;
445 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++)
447 NAME(lynx
,swap_ext_reloc_in
) (abfd
, rptr
, cache_ptr
, symbols
,
448 bfd_get_symcount (abfd
));
453 register struct reloc_std_external
*rptr
= (struct reloc_std_external
*) relocs
;
454 unsigned int counter
= 0;
455 arelent
*cache_ptr
= reloc_cache
;
457 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++)
459 NAME(lynx
,swap_std_reloc_in
) (abfd
, rptr
, cache_ptr
, symbols
,
460 bfd_get_symcount (abfd
));
465 bfd_release (abfd
, relocs
);
466 asect
->relocation
= reloc_cache
;
467 asect
->reloc_count
= count
;
473 /* Write out a relocation section into an object file. */
476 NAME(lynx
,squirt_out_relocs
) (abfd
, section
)
481 unsigned char *native
, *natptr
;
484 unsigned int count
= section
->reloc_count
;
490 each_size
= obj_reloc_entry_size (abfd
);
491 natsize
= each_size
* count
;
492 native
= (unsigned char *) bfd_zalloc (abfd
, natsize
);
496 generic
= section
->orelocation
;
498 if (each_size
== RELOC_EXT_SIZE
)
500 for (natptr
= native
;
502 --count
, natptr
+= each_size
, ++generic
)
503 NAME(lynx
,swap_ext_reloc_out
) (abfd
, *generic
, (struct reloc_ext_external
*) natptr
);
507 for (natptr
= native
;
509 --count
, natptr
+= each_size
, ++generic
)
510 NAME(lynx
,swap_std_reloc_out
) (abfd
, *generic
, (struct reloc_std_external
*) natptr
);
513 if (bfd_write ((PTR
) native
, 1, natsize
, abfd
) != natsize
)
515 bfd_release (abfd
, native
);
518 bfd_release (abfd
, native
);
523 /* This is stupid. This function should be a boolean predicate */
525 NAME(lynx
,canonicalize_reloc
) (abfd
, section
, relptr
, symbols
)
531 arelent
*tblptr
= section
->relocation
;
534 if (!(tblptr
|| NAME(lynx
,slurp_reloc_table
) (abfd
, section
, symbols
)))
537 if (section
->flags
& SEC_CONSTRUCTOR
)
539 arelent_chain
*chain
= section
->constructor_chain
;
540 for (count
= 0; count
< section
->reloc_count
; count
++)
542 *relptr
++ = &chain
->relent
;
548 tblptr
= section
->relocation
;
550 for (count
= 0; count
++ < section
->reloc_count
;)
552 *relptr
++ = tblptr
++;
557 return section
->reloc_count
;
560 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
562 #include "aout-target.h"