1 /* BFD back-end for i386 a.out binaries under LynxOS.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2001, 2002,
3 2003, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
22 #define TEXT_START_ADDR 0
23 #define TARGET_PAGE_SIZE 4096
24 #define SEGMENT_SIZE TARGET_PAGE_SIZE
25 #define DEFAULT_ARCH bfd_arch_i386
27 /* Do not "beautify" the CONCAT* macro args. Traditional C will not
28 remove whitespace added here, and thus will fail to concatenate
30 #define MY(OP) CONCAT2 (i386lynx_aout_,OP)
31 #define TARGETNAME "a.out-i386-lynx"
38 #define WRITE_HEADERS(abfd, execp) \
40 bfd_size_type text_size; /* dummy vars */ \
42 if (adata(abfd).magic == undecided_magic) \
43 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
45 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
46 execp->a_entry = bfd_get_start_address (abfd); \
48 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
49 obj_reloc_entry_size (abfd)); \
50 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
51 obj_reloc_entry_size (abfd)); \
52 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
54 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 \
55 || bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
56 abfd) != EXEC_BYTES_SIZE) \
58 /* Now write out reloc info, followed by syms and strings */ \
60 if (bfd_get_symcount (abfd) != 0) \
62 if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) \
66 if (! NAME(aout,write_syms) (abfd)) return FALSE; \
68 if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) \
72 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
74 if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) \
78 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd))) \
85 #include "aout/aout64.h"
87 void NAME (lynx
,swap_std_reloc_out
)
88 PARAMS ((bfd
*, arelent
*, struct reloc_std_external
*));
89 void NAME (lynx
,swap_ext_reloc_out
)
90 PARAMS ((bfd
*, arelent
*, struct reloc_ext_external
*));
91 void NAME (lynx
,swap_ext_reloc_in
)
92 PARAMS ((bfd
*, struct reloc_ext_external
*, arelent
*, asymbol
**,
94 void NAME (lynx
,swap_std_reloc_in
)
95 PARAMS ((bfd
*, struct reloc_std_external
*, arelent
*, asymbol
**,
97 bfd_boolean
NAME (lynx
,slurp_reloc_table
)
98 PARAMS ((bfd
*, sec_ptr
, asymbol
**));
99 bfd_boolean
NAME (lynx
,squirt_out_relocs
)
100 PARAMS ((bfd
*, asection
*));
101 long NAME (lynx
,canonicalize_reloc
)
102 PARAMS ((bfd
*, sec_ptr
, arelent
**, asymbol
**));
106 char *lynx_core_file_failing_command ();
107 int lynx_core_file_failing_signal ();
108 bfd_boolean
lynx_core_file_matches_executable_p ();
109 const bfd_target
*lynx_core_file_p ();
111 #define MY_core_file_failing_command lynx_core_file_failing_command
112 #define MY_core_file_failing_signal lynx_core_file_failing_signal
113 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
114 #define MY_core_file_p lynx_core_file_p
116 #endif /* LYNX_CORE */
119 #define KEEPIT udata.i
121 extern reloc_howto_type aout_32_ext_howto_table
[];
122 extern reloc_howto_type aout_32_std_howto_table
[];
124 /* Standard reloc stuff */
125 /* Output standard relocation information to a file in target byte order. */
128 NAME(lynx
,swap_std_reloc_out
) (abfd
, g
, natptr
)
131 struct reloc_std_external
*natptr
;
134 asymbol
*sym
= *(g
->sym_ptr_ptr
);
136 unsigned int r_length
;
138 int r_baserel
, r_jmptable
, r_relative
;
139 asection
*output_section
= sym
->section
->output_section
;
141 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
143 r_length
= g
->howto
->size
; /* Size as a power of two */
144 r_pcrel
= (int) g
->howto
->pc_relative
; /* Relative to PC? */
145 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
150 /* name was clobbered by aout_write_syms to be symbol index */
152 /* If this relocation is relative to a symbol then set the
153 r_index to the symbols index, and the r_extern bit.
155 Absolute symbols can come in in two ways, either as an offset
156 from the abs section, or as a symbol which has an abs value.
161 if (bfd_is_com_section (output_section
)
162 || bfd_is_abs_section (output_section
)
163 || bfd_is_und_section (output_section
))
165 if (bfd_abs_section_ptr
->symbol
== sym
)
167 /* Whoops, looked like an abs symbol, but is really an offset
168 from the abs section */
176 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
181 /* Just an ordinary section */
183 r_index
= output_section
->target_index
;
186 /* now the fun stuff */
187 if (bfd_header_big_endian (abfd
))
189 natptr
->r_index
[0] = r_index
>> 16;
190 natptr
->r_index
[1] = r_index
>> 8;
191 natptr
->r_index
[2] = r_index
;
193 (r_extern
? RELOC_STD_BITS_EXTERN_BIG
: 0)
194 | (r_pcrel
? RELOC_STD_BITS_PCREL_BIG
: 0)
195 | (r_baserel
? RELOC_STD_BITS_BASEREL_BIG
: 0)
196 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_BIG
: 0)
197 | (r_relative
? RELOC_STD_BITS_RELATIVE_BIG
: 0)
198 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_BIG
);
202 natptr
->r_index
[2] = r_index
>> 16;
203 natptr
->r_index
[1] = r_index
>> 8;
204 natptr
->r_index
[0] = r_index
;
206 (r_extern
? RELOC_STD_BITS_EXTERN_LITTLE
: 0)
207 | (r_pcrel
? RELOC_STD_BITS_PCREL_LITTLE
: 0)
208 | (r_baserel
? RELOC_STD_BITS_BASEREL_LITTLE
: 0)
209 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_LITTLE
: 0)
210 | (r_relative
? RELOC_STD_BITS_RELATIVE_LITTLE
: 0)
211 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_LITTLE
);
217 /* Output extended relocation information to a file in target byte order. */
220 NAME(lynx
,swap_ext_reloc_out
) (abfd
, g
, natptr
)
223 register struct reloc_ext_external
*natptr
;
228 unsigned int r_addend
;
229 asymbol
*sym
= *(g
->sym_ptr_ptr
);
230 asection
*output_section
= sym
->section
->output_section
;
232 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
234 r_type
= (unsigned int) g
->howto
->type
;
236 r_addend
= g
->addend
+ (*(g
->sym_ptr_ptr
))->section
->output_section
->vma
;
239 /* If this relocation is relative to a symbol then set the
240 r_index to the symbols index, and the r_extern bit.
242 Absolute symbols can come in in two ways, either as an offset
243 from the abs section, or as a symbol which has an abs value.
247 if (bfd_is_com_section (output_section
)
248 || bfd_is_abs_section (output_section
)
249 || bfd_is_und_section (output_section
))
251 if (bfd_abs_section_ptr
->symbol
== sym
)
253 /* Whoops, looked like an abs symbol, but is really an offset
254 from the abs section */
261 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
266 /* Just an ordinary section */
268 r_index
= output_section
->target_index
;
272 /* now the fun stuff */
273 if (bfd_header_big_endian (abfd
))
275 natptr
->r_index
[0] = r_index
>> 16;
276 natptr
->r_index
[1] = r_index
>> 8;
277 natptr
->r_index
[2] = r_index
;
279 (r_extern
? RELOC_EXT_BITS_EXTERN_BIG
: 0)
280 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_BIG
);
284 natptr
->r_index
[2] = r_index
>> 16;
285 natptr
->r_index
[1] = r_index
>> 8;
286 natptr
->r_index
[0] = r_index
;
288 (r_extern
? RELOC_EXT_BITS_EXTERN_LITTLE
: 0)
289 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_LITTLE
);
292 PUT_WORD (abfd
, r_addend
, natptr
->r_addend
);
295 /* BFD deals internally with all things based from the section they're
296 in. so, something in 10 bytes into a text section with a base of
297 50 would have a symbol (.text+10) and know .text vma was 50.
299 Aout keeps all it's symbols based from zero, so the symbol would
300 contain 60. This macro subs the base of each section from the value
301 to give the true offset from the section */
304 #define MOVE_ADDRESS(ad) \
306 /* undefined symbol */ \
307 cache_ptr->sym_ptr_ptr = symbols + r_index; \
308 cache_ptr->addend = ad; \
310 /* defined, section relative. replace symbol with pointer to \
311 symbol which points to section */ \
314 case N_TEXT | N_EXT: \
315 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
316 cache_ptr->addend = ad - su->textsec->vma; \
319 case N_DATA | N_EXT: \
320 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
321 cache_ptr->addend = ad - su->datasec->vma; \
324 case N_BSS | N_EXT: \
325 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
326 cache_ptr->addend = ad - su->bsssec->vma; \
330 case N_ABS | N_EXT: \
331 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
332 cache_ptr->addend = ad; \
338 NAME(lynx
,swap_ext_reloc_in
) (abfd
, bytes
, cache_ptr
, symbols
, symcount
)
340 struct reloc_ext_external
*bytes
;
343 bfd_size_type symcount ATTRIBUTE_UNUSED
;
348 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
350 cache_ptr
->address
= (GET_SWORD (abfd
, bytes
->r_address
));
352 r_index
= bytes
->r_index
[1];
353 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_EXT_BITS_EXTERN_BIG
));
354 r_type
= (bytes
->r_index
[0] & RELOC_EXT_BITS_TYPE_BIG
)
355 >> RELOC_EXT_BITS_TYPE_SH_BIG
;
357 cache_ptr
->howto
= aout_32_ext_howto_table
+ r_type
;
358 MOVE_ADDRESS (GET_SWORD (abfd
, bytes
->r_addend
));
362 NAME(lynx
,swap_std_reloc_in
) (abfd
, bytes
, cache_ptr
, symbols
, symcount
)
364 struct reloc_std_external
*bytes
;
367 bfd_size_type symcount ATTRIBUTE_UNUSED
;
371 unsigned int r_length
;
373 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
375 cache_ptr
->address
= H_GET_32 (abfd
, bytes
->r_address
);
377 r_index
= bytes
->r_index
[1];
378 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_EXTERN_BIG
));
379 r_pcrel
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_PCREL_BIG
));
380 r_length
= (bytes
->r_index
[0] & RELOC_STD_BITS_LENGTH_BIG
)
381 >> RELOC_STD_BITS_LENGTH_SH_BIG
;
383 cache_ptr
->howto
= aout_32_std_howto_table
+ r_length
+ 4 * r_pcrel
;
384 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
392 NAME(lynx
,slurp_reloc_table
) (abfd
, asect
, symbols
)
398 bfd_size_type reloc_size
;
400 arelent
*reloc_cache
;
403 if (asect
->relocation
)
406 if (asect
->flags
& SEC_CONSTRUCTOR
)
409 if (asect
== obj_datasec (abfd
))
411 reloc_size
= exec_hdr (abfd
)->a_drsize
;
415 if (asect
== obj_textsec (abfd
))
417 reloc_size
= exec_hdr (abfd
)->a_trsize
;
421 bfd_set_error (bfd_error_invalid_operation
);
425 if (bfd_seek (abfd
, asect
->rel_filepos
, SEEK_SET
) != 0)
427 each_size
= obj_reloc_entry_size (abfd
);
429 count
= reloc_size
/ each_size
;
432 reloc_cache
= (arelent
*) bfd_zmalloc (count
* sizeof (arelent
));
433 if (!reloc_cache
&& count
!= 0)
436 relocs
= (PTR
) bfd_alloc (abfd
, reloc_size
);
437 if (!relocs
&& reloc_size
!= 0)
443 if (bfd_bread (relocs
, reloc_size
, abfd
) != reloc_size
)
445 bfd_release (abfd
, relocs
);
450 if (each_size
== RELOC_EXT_SIZE
)
452 register struct reloc_ext_external
*rptr
= (struct reloc_ext_external
*) relocs
;
453 unsigned int counter
= 0;
454 arelent
*cache_ptr
= reloc_cache
;
456 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++)
458 NAME(lynx
,swap_ext_reloc_in
) (abfd
, rptr
, cache_ptr
, symbols
,
459 (bfd_size_type
) bfd_get_symcount (abfd
));
464 register struct reloc_std_external
*rptr
= (struct reloc_std_external
*) relocs
;
465 unsigned int counter
= 0;
466 arelent
*cache_ptr
= reloc_cache
;
468 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++)
470 NAME(lynx
,swap_std_reloc_in
) (abfd
, rptr
, cache_ptr
, symbols
,
471 (bfd_size_type
) bfd_get_symcount (abfd
));
476 bfd_release (abfd
, relocs
);
477 asect
->relocation
= reloc_cache
;
478 asect
->reloc_count
= count
;
484 /* Write out a relocation section into an object file. */
487 NAME(lynx
,squirt_out_relocs
) (abfd
, section
)
492 unsigned char *native
, *natptr
;
495 unsigned int count
= section
->reloc_count
;
496 bfd_size_type natsize
;
501 each_size
= obj_reloc_entry_size (abfd
);
503 natsize
*= each_size
;
504 native
= (unsigned char *) bfd_zalloc (abfd
, natsize
);
508 generic
= section
->orelocation
;
510 if (each_size
== RELOC_EXT_SIZE
)
512 for (natptr
= native
;
514 --count
, natptr
+= each_size
, ++generic
)
515 NAME(lynx
,swap_ext_reloc_out
) (abfd
, *generic
, (struct reloc_ext_external
*) natptr
);
519 for (natptr
= native
;
521 --count
, natptr
+= each_size
, ++generic
)
522 NAME(lynx
,swap_std_reloc_out
) (abfd
, *generic
, (struct reloc_std_external
*) natptr
);
525 if (bfd_bwrite ((PTR
) native
, natsize
, abfd
) != natsize
)
527 bfd_release (abfd
, native
);
530 bfd_release (abfd
, native
);
535 /* This is stupid. This function should be a boolean predicate */
537 NAME(lynx
,canonicalize_reloc
) (abfd
, section
, relptr
, symbols
)
543 arelent
*tblptr
= section
->relocation
;
546 if (!(tblptr
|| NAME(lynx
,slurp_reloc_table
) (abfd
, section
, symbols
)))
549 if (section
->flags
& SEC_CONSTRUCTOR
)
551 arelent_chain
*chain
= section
->constructor_chain
;
552 for (count
= 0; count
< section
->reloc_count
; count
++)
554 *relptr
++ = &chain
->relent
;
560 tblptr
= section
->relocation
;
562 for (count
= 0; count
++ < section
->reloc_count
;)
564 *relptr
++ = tblptr
++;
569 return section
->reloc_count
;
572 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
574 #include "aout-target.h"