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 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 unsigned int r_addend
;
140 asection
*output_section
= sym
->section
->output_section
;
142 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
144 r_length
= g
->howto
->size
; /* Size as a power of two */
145 r_pcrel
= (int) g
->howto
->pc_relative
; /* Relative to PC? */
146 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
151 r_addend
= g
->addend
+ (*(g
->sym_ptr_ptr
))->section
->output_section
->vma
;
153 /* name was clobbered by aout_write_syms to be symbol index */
155 /* If this relocation is relative to a symbol then set the
156 r_index to the symbols index, and the r_extern bit.
158 Absolute symbols can come in in two ways, either as an offset
159 from the abs section, or as a symbol which has an abs value.
164 if (bfd_is_com_section (output_section
)
165 || bfd_is_abs_section (output_section
)
166 || bfd_is_und_section (output_section
))
168 if (bfd_abs_section_ptr
->symbol
== sym
)
170 /* Whoops, looked like an abs symbol, but is really an offset
171 from the abs section */
179 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
184 /* Just an ordinary section */
186 r_index
= output_section
->target_index
;
189 /* now the fun stuff */
190 if (bfd_header_big_endian (abfd
))
192 natptr
->r_index
[0] = r_index
>> 16;
193 natptr
->r_index
[1] = r_index
>> 8;
194 natptr
->r_index
[2] = r_index
;
196 (r_extern
? RELOC_STD_BITS_EXTERN_BIG
: 0)
197 | (r_pcrel
? RELOC_STD_BITS_PCREL_BIG
: 0)
198 | (r_baserel
? RELOC_STD_BITS_BASEREL_BIG
: 0)
199 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_BIG
: 0)
200 | (r_relative
? RELOC_STD_BITS_RELATIVE_BIG
: 0)
201 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_BIG
);
205 natptr
->r_index
[2] = r_index
>> 16;
206 natptr
->r_index
[1] = r_index
>> 8;
207 natptr
->r_index
[0] = r_index
;
209 (r_extern
? RELOC_STD_BITS_EXTERN_LITTLE
: 0)
210 | (r_pcrel
? RELOC_STD_BITS_PCREL_LITTLE
: 0)
211 | (r_baserel
? RELOC_STD_BITS_BASEREL_LITTLE
: 0)
212 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_LITTLE
: 0)
213 | (r_relative
? RELOC_STD_BITS_RELATIVE_LITTLE
: 0)
214 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_LITTLE
);
220 /* Output extended relocation information to a file in target byte order. */
223 NAME(lynx
,swap_ext_reloc_out
) (abfd
, g
, natptr
)
226 register struct reloc_ext_external
*natptr
;
231 unsigned int r_addend
;
232 asymbol
*sym
= *(g
->sym_ptr_ptr
);
233 asection
*output_section
= sym
->section
->output_section
;
235 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
237 r_type
= (unsigned int) g
->howto
->type
;
239 r_addend
= g
->addend
+ (*(g
->sym_ptr_ptr
))->section
->output_section
->vma
;
242 /* If this relocation is relative to a symbol then set the
243 r_index to the symbols index, and the r_extern bit.
245 Absolute symbols can come in in two ways, either as an offset
246 from the abs section, or as a symbol which has an abs value.
250 if (bfd_is_com_section (output_section
)
251 || bfd_is_abs_section (output_section
)
252 || bfd_is_und_section (output_section
))
254 if (bfd_abs_section_ptr
->symbol
== sym
)
256 /* Whoops, looked like an abs symbol, but is really an offset
257 from the abs section */
264 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
269 /* Just an ordinary section */
271 r_index
= output_section
->target_index
;
275 /* now the fun stuff */
276 if (bfd_header_big_endian (abfd
))
278 natptr
->r_index
[0] = r_index
>> 16;
279 natptr
->r_index
[1] = r_index
>> 8;
280 natptr
->r_index
[2] = r_index
;
282 (r_extern
? RELOC_EXT_BITS_EXTERN_BIG
: 0)
283 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_BIG
);
287 natptr
->r_index
[2] = r_index
>> 16;
288 natptr
->r_index
[1] = r_index
>> 8;
289 natptr
->r_index
[0] = r_index
;
291 (r_extern
? RELOC_EXT_BITS_EXTERN_LITTLE
: 0)
292 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_LITTLE
);
295 PUT_WORD (abfd
, r_addend
, natptr
->r_addend
);
298 /* BFD deals internally with all things based from the section they're
299 in. so, something in 10 bytes into a text section with a base of
300 50 would have a symbol (.text+10) and know .text vma was 50.
302 Aout keeps all it's symbols based from zero, so the symbol would
303 contain 60. This macro subs the base of each section from the value
304 to give the true offset from the section */
307 #define MOVE_ADDRESS(ad) \
309 /* undefined symbol */ \
310 cache_ptr->sym_ptr_ptr = symbols + r_index; \
311 cache_ptr->addend = ad; \
313 /* defined, section relative. replace symbol with pointer to \
314 symbol which points to section */ \
317 case N_TEXT | N_EXT: \
318 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
319 cache_ptr->addend = ad - su->textsec->vma; \
322 case N_DATA | N_EXT: \
323 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
324 cache_ptr->addend = ad - su->datasec->vma; \
327 case N_BSS | N_EXT: \
328 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
329 cache_ptr->addend = ad - su->bsssec->vma; \
333 case N_ABS | N_EXT: \
334 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
335 cache_ptr->addend = ad; \
341 NAME(lynx
,swap_ext_reloc_in
) (abfd
, bytes
, cache_ptr
, symbols
, symcount
)
343 struct reloc_ext_external
*bytes
;
346 bfd_size_type symcount ATTRIBUTE_UNUSED
;
351 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
353 cache_ptr
->address
= (GET_SWORD (abfd
, bytes
->r_address
));
355 r_index
= bytes
->r_index
[1];
356 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_EXT_BITS_EXTERN_BIG
));
357 r_type
= (bytes
->r_index
[0] & RELOC_EXT_BITS_TYPE_BIG
)
358 >> RELOC_EXT_BITS_TYPE_SH_BIG
;
360 cache_ptr
->howto
= aout_32_ext_howto_table
+ r_type
;
361 MOVE_ADDRESS (GET_SWORD (abfd
, bytes
->r_addend
));
365 NAME(lynx
,swap_std_reloc_in
) (abfd
, bytes
, cache_ptr
, symbols
, symcount
)
367 struct reloc_std_external
*bytes
;
370 bfd_size_type symcount ATTRIBUTE_UNUSED
;
374 unsigned int r_length
;
376 int r_baserel
, r_jmptable
, r_relative
;
377 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
379 cache_ptr
->address
= H_GET_32 (abfd
, bytes
->r_address
);
381 r_index
= bytes
->r_index
[1];
382 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_EXTERN_BIG
));
383 r_pcrel
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_PCREL_BIG
));
384 r_baserel
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_BASEREL_BIG
));
385 r_jmptable
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_JMPTABLE_BIG
));
386 r_relative
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_RELATIVE_BIG
));
387 r_length
= (bytes
->r_index
[0] & RELOC_STD_BITS_LENGTH_BIG
)
388 >> RELOC_STD_BITS_LENGTH_SH_BIG
;
390 cache_ptr
->howto
= aout_32_std_howto_table
+ r_length
+ 4 * r_pcrel
;
391 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
399 NAME(lynx
,slurp_reloc_table
) (abfd
, asect
, symbols
)
405 bfd_size_type reloc_size
;
407 arelent
*reloc_cache
;
410 if (asect
->relocation
)
413 if (asect
->flags
& SEC_CONSTRUCTOR
)
416 if (asect
== obj_datasec (abfd
))
418 reloc_size
= exec_hdr (abfd
)->a_drsize
;
422 if (asect
== obj_textsec (abfd
))
424 reloc_size
= exec_hdr (abfd
)->a_trsize
;
428 bfd_set_error (bfd_error_invalid_operation
);
432 if (bfd_seek (abfd
, asect
->rel_filepos
, SEEK_SET
) != 0)
434 each_size
= obj_reloc_entry_size (abfd
);
436 count
= reloc_size
/ each_size
;
439 reloc_cache
= (arelent
*) bfd_zmalloc (count
* sizeof (arelent
));
440 if (!reloc_cache
&& count
!= 0)
443 relocs
= (PTR
) bfd_alloc (abfd
, reloc_size
);
444 if (!relocs
&& reloc_size
!= 0)
450 if (bfd_bread (relocs
, reloc_size
, abfd
) != reloc_size
)
452 bfd_release (abfd
, relocs
);
457 if (each_size
== RELOC_EXT_SIZE
)
459 register struct reloc_ext_external
*rptr
= (struct reloc_ext_external
*) relocs
;
460 unsigned int counter
= 0;
461 arelent
*cache_ptr
= reloc_cache
;
463 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++)
465 NAME(lynx
,swap_ext_reloc_in
) (abfd
, rptr
, cache_ptr
, symbols
,
466 (bfd_size_type
) bfd_get_symcount (abfd
));
471 register struct reloc_std_external
*rptr
= (struct reloc_std_external
*) relocs
;
472 unsigned int counter
= 0;
473 arelent
*cache_ptr
= reloc_cache
;
475 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++)
477 NAME(lynx
,swap_std_reloc_in
) (abfd
, rptr
, cache_ptr
, symbols
,
478 (bfd_size_type
) bfd_get_symcount (abfd
));
483 bfd_release (abfd
, relocs
);
484 asect
->relocation
= reloc_cache
;
485 asect
->reloc_count
= count
;
491 /* Write out a relocation section into an object file. */
494 NAME(lynx
,squirt_out_relocs
) (abfd
, section
)
499 unsigned char *native
, *natptr
;
502 unsigned int count
= section
->reloc_count
;
503 bfd_size_type natsize
;
508 each_size
= obj_reloc_entry_size (abfd
);
510 natsize
*= each_size
;
511 native
= (unsigned char *) bfd_zalloc (abfd
, natsize
);
515 generic
= section
->orelocation
;
517 if (each_size
== RELOC_EXT_SIZE
)
519 for (natptr
= native
;
521 --count
, natptr
+= each_size
, ++generic
)
522 NAME(lynx
,swap_ext_reloc_out
) (abfd
, *generic
, (struct reloc_ext_external
*) natptr
);
526 for (natptr
= native
;
528 --count
, natptr
+= each_size
, ++generic
)
529 NAME(lynx
,swap_std_reloc_out
) (abfd
, *generic
, (struct reloc_std_external
*) natptr
);
532 if (bfd_bwrite ((PTR
) native
, natsize
, abfd
) != natsize
)
534 bfd_release (abfd
, native
);
537 bfd_release (abfd
, native
);
542 /* This is stupid. This function should be a boolean predicate */
544 NAME(lynx
,canonicalize_reloc
) (abfd
, section
, relptr
, symbols
)
550 arelent
*tblptr
= section
->relocation
;
553 if (!(tblptr
|| NAME(lynx
,slurp_reloc_table
) (abfd
, section
, symbols
)))
556 if (section
->flags
& SEC_CONSTRUCTOR
)
558 arelent_chain
*chain
= section
->constructor_chain
;
559 for (count
= 0; count
< section
->reloc_count
; count
++)
561 *relptr
++ = &chain
->relent
;
567 tblptr
= section
->relocation
;
569 for (count
= 0; count
++ < section
->reloc_count
;)
571 *relptr
++ = tblptr
++;
576 return section
->reloc_count
;
579 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
581 #include "aout-target.h"