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 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 2 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, MA 02110-1301, USA. */
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 /* Do not "beautify" the CONCAT* macro args. Traditional C will not
29 remove whitespace added here, and thus will fail to concatenate
31 #define MY(OP) CONCAT2 (i386lynx_aout_,OP)
32 #define TARGETNAME "a.out-i386-lynx"
39 #define WRITE_HEADERS(abfd, execp) \
41 bfd_size_type text_size; /* dummy vars */ \
43 if (adata(abfd).magic == undecided_magic) \
44 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
46 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
47 execp->a_entry = bfd_get_start_address (abfd); \
49 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
50 obj_reloc_entry_size (abfd)); \
51 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
52 obj_reloc_entry_size (abfd)); \
53 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
55 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 \
56 || bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
57 abfd) != EXEC_BYTES_SIZE) \
59 /* Now write out reloc info, followed by syms and strings */ \
61 if (bfd_get_symcount (abfd) != 0) \
63 if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) \
67 if (! NAME(aout,write_syms) (abfd)) return FALSE; \
69 if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) \
73 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
75 if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) \
79 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd))) \
86 #include "aout/aout64.h"
88 void NAME (lynx
,swap_std_reloc_out
)
89 PARAMS ((bfd
*, arelent
*, struct reloc_std_external
*));
90 void NAME (lynx
,swap_ext_reloc_out
)
91 PARAMS ((bfd
*, arelent
*, struct reloc_ext_external
*));
92 void NAME (lynx
,swap_ext_reloc_in
)
93 PARAMS ((bfd
*, struct reloc_ext_external
*, arelent
*, asymbol
**,
95 void NAME (lynx
,swap_std_reloc_in
)
96 PARAMS ((bfd
*, struct reloc_std_external
*, arelent
*, asymbol
**,
98 bfd_boolean
NAME (lynx
,slurp_reloc_table
)
99 PARAMS ((bfd
*, sec_ptr
, asymbol
**));
100 bfd_boolean
NAME (lynx
,squirt_out_relocs
)
101 PARAMS ((bfd
*, asection
*));
102 long NAME (lynx
,canonicalize_reloc
)
103 PARAMS ((bfd
*, sec_ptr
, arelent
**, asymbol
**));
107 char *lynx_core_file_failing_command ();
108 int lynx_core_file_failing_signal ();
109 bfd_boolean
lynx_core_file_matches_executable_p ();
110 const bfd_target
*lynx_core_file_p ();
112 #define MY_core_file_failing_command lynx_core_file_failing_command
113 #define MY_core_file_failing_signal lynx_core_file_failing_signal
114 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
115 #define MY_core_file_p lynx_core_file_p
117 #endif /* LYNX_CORE */
120 #define KEEPIT udata.i
122 extern reloc_howto_type aout_32_ext_howto_table
[];
123 extern reloc_howto_type aout_32_std_howto_table
[];
125 /* Standard reloc stuff */
126 /* Output standard relocation information to a file in target byte order. */
129 NAME(lynx
,swap_std_reloc_out
) (abfd
, g
, natptr
)
132 struct reloc_std_external
*natptr
;
135 asymbol
*sym
= *(g
->sym_ptr_ptr
);
137 unsigned int r_length
;
139 int r_baserel
, r_jmptable
, r_relative
;
140 unsigned int r_addend
;
141 asection
*output_section
= sym
->section
->output_section
;
143 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
145 r_length
= g
->howto
->size
; /* Size as a power of two */
146 r_pcrel
= (int) g
->howto
->pc_relative
; /* Relative to PC? */
147 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
152 r_addend
= g
->addend
+ (*(g
->sym_ptr_ptr
))->section
->output_section
->vma
;
154 /* name was clobbered by aout_write_syms to be symbol index */
156 /* If this relocation is relative to a symbol then set the
157 r_index to the symbols index, and the r_extern bit.
159 Absolute symbols can come in in two ways, either as an offset
160 from the abs section, or as a symbol which has an abs value.
165 if (bfd_is_com_section (output_section
)
166 || bfd_is_abs_section (output_section
)
167 || bfd_is_und_section (output_section
))
169 if (bfd_abs_section_ptr
->symbol
== sym
)
171 /* Whoops, looked like an abs symbol, but is really an offset
172 from the abs section */
180 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
185 /* Just an ordinary section */
187 r_index
= output_section
->target_index
;
190 /* now the fun stuff */
191 if (bfd_header_big_endian (abfd
))
193 natptr
->r_index
[0] = r_index
>> 16;
194 natptr
->r_index
[1] = r_index
>> 8;
195 natptr
->r_index
[2] = r_index
;
197 (r_extern
? RELOC_STD_BITS_EXTERN_BIG
: 0)
198 | (r_pcrel
? RELOC_STD_BITS_PCREL_BIG
: 0)
199 | (r_baserel
? RELOC_STD_BITS_BASEREL_BIG
: 0)
200 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_BIG
: 0)
201 | (r_relative
? RELOC_STD_BITS_RELATIVE_BIG
: 0)
202 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_BIG
);
206 natptr
->r_index
[2] = r_index
>> 16;
207 natptr
->r_index
[1] = r_index
>> 8;
208 natptr
->r_index
[0] = r_index
;
210 (r_extern
? RELOC_STD_BITS_EXTERN_LITTLE
: 0)
211 | (r_pcrel
? RELOC_STD_BITS_PCREL_LITTLE
: 0)
212 | (r_baserel
? RELOC_STD_BITS_BASEREL_LITTLE
: 0)
213 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_LITTLE
: 0)
214 | (r_relative
? RELOC_STD_BITS_RELATIVE_LITTLE
: 0)
215 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_LITTLE
);
221 /* Output extended relocation information to a file in target byte order. */
224 NAME(lynx
,swap_ext_reloc_out
) (abfd
, g
, natptr
)
227 register struct reloc_ext_external
*natptr
;
232 unsigned int r_addend
;
233 asymbol
*sym
= *(g
->sym_ptr_ptr
);
234 asection
*output_section
= sym
->section
->output_section
;
236 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
238 r_type
= (unsigned int) g
->howto
->type
;
240 r_addend
= g
->addend
+ (*(g
->sym_ptr_ptr
))->section
->output_section
->vma
;
243 /* If this relocation is relative to a symbol then set the
244 r_index to the symbols index, and the r_extern bit.
246 Absolute symbols can come in in two ways, either as an offset
247 from the abs section, or as a symbol which has an abs value.
251 if (bfd_is_com_section (output_section
)
252 || bfd_is_abs_section (output_section
)
253 || bfd_is_und_section (output_section
))
255 if (bfd_abs_section_ptr
->symbol
== sym
)
257 /* Whoops, looked like an abs symbol, but is really an offset
258 from the abs section */
265 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
270 /* Just an ordinary section */
272 r_index
= output_section
->target_index
;
276 /* now the fun stuff */
277 if (bfd_header_big_endian (abfd
))
279 natptr
->r_index
[0] = r_index
>> 16;
280 natptr
->r_index
[1] = r_index
>> 8;
281 natptr
->r_index
[2] = r_index
;
283 (r_extern
? RELOC_EXT_BITS_EXTERN_BIG
: 0)
284 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_BIG
);
288 natptr
->r_index
[2] = r_index
>> 16;
289 natptr
->r_index
[1] = r_index
>> 8;
290 natptr
->r_index
[0] = r_index
;
292 (r_extern
? RELOC_EXT_BITS_EXTERN_LITTLE
: 0)
293 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_LITTLE
);
296 PUT_WORD (abfd
, r_addend
, natptr
->r_addend
);
299 /* BFD deals internally with all things based from the section they're
300 in. so, something in 10 bytes into a text section with a base of
301 50 would have a symbol (.text+10) and know .text vma was 50.
303 Aout keeps all it's symbols based from zero, so the symbol would
304 contain 60. This macro subs the base of each section from the value
305 to give the true offset from the section */
308 #define MOVE_ADDRESS(ad) \
310 /* undefined symbol */ \
311 cache_ptr->sym_ptr_ptr = symbols + r_index; \
312 cache_ptr->addend = ad; \
314 /* defined, section relative. replace symbol with pointer to \
315 symbol which points to section */ \
318 case N_TEXT | N_EXT: \
319 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
320 cache_ptr->addend = ad - su->textsec->vma; \
323 case N_DATA | N_EXT: \
324 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
325 cache_ptr->addend = ad - su->datasec->vma; \
328 case N_BSS | N_EXT: \
329 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
330 cache_ptr->addend = ad - su->bsssec->vma; \
334 case N_ABS | N_EXT: \
335 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
336 cache_ptr->addend = ad; \
342 NAME(lynx
,swap_ext_reloc_in
) (abfd
, bytes
, cache_ptr
, symbols
, symcount
)
344 struct reloc_ext_external
*bytes
;
347 bfd_size_type symcount ATTRIBUTE_UNUSED
;
352 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
354 cache_ptr
->address
= (GET_SWORD (abfd
, bytes
->r_address
));
356 r_index
= bytes
->r_index
[1];
357 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_EXT_BITS_EXTERN_BIG
));
358 r_type
= (bytes
->r_index
[0] & RELOC_EXT_BITS_TYPE_BIG
)
359 >> RELOC_EXT_BITS_TYPE_SH_BIG
;
361 cache_ptr
->howto
= aout_32_ext_howto_table
+ r_type
;
362 MOVE_ADDRESS (GET_SWORD (abfd
, bytes
->r_addend
));
366 NAME(lynx
,swap_std_reloc_in
) (abfd
, bytes
, cache_ptr
, symbols
, symcount
)
368 struct reloc_std_external
*bytes
;
371 bfd_size_type symcount ATTRIBUTE_UNUSED
;
375 unsigned int r_length
;
377 int r_baserel
, r_jmptable
, r_relative
;
378 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
380 cache_ptr
->address
= H_GET_32 (abfd
, bytes
->r_address
);
382 r_index
= bytes
->r_index
[1];
383 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_EXTERN_BIG
));
384 r_pcrel
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_PCREL_BIG
));
385 r_baserel
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_BASEREL_BIG
));
386 r_jmptable
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_JMPTABLE_BIG
));
387 r_relative
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_RELATIVE_BIG
));
388 r_length
= (bytes
->r_index
[0] & RELOC_STD_BITS_LENGTH_BIG
)
389 >> RELOC_STD_BITS_LENGTH_SH_BIG
;
391 cache_ptr
->howto
= aout_32_std_howto_table
+ r_length
+ 4 * r_pcrel
;
392 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
400 NAME(lynx
,slurp_reloc_table
) (abfd
, asect
, symbols
)
406 bfd_size_type reloc_size
;
408 arelent
*reloc_cache
;
411 if (asect
->relocation
)
414 if (asect
->flags
& SEC_CONSTRUCTOR
)
417 if (asect
== obj_datasec (abfd
))
419 reloc_size
= exec_hdr (abfd
)->a_drsize
;
423 if (asect
== obj_textsec (abfd
))
425 reloc_size
= exec_hdr (abfd
)->a_trsize
;
429 bfd_set_error (bfd_error_invalid_operation
);
433 if (bfd_seek (abfd
, asect
->rel_filepos
, SEEK_SET
) != 0)
435 each_size
= obj_reloc_entry_size (abfd
);
437 count
= reloc_size
/ each_size
;
440 reloc_cache
= (arelent
*) bfd_zmalloc (count
* sizeof (arelent
));
441 if (!reloc_cache
&& count
!= 0)
444 relocs
= (PTR
) bfd_alloc (abfd
, reloc_size
);
445 if (!relocs
&& reloc_size
!= 0)
451 if (bfd_bread (relocs
, reloc_size
, abfd
) != reloc_size
)
453 bfd_release (abfd
, relocs
);
458 if (each_size
== RELOC_EXT_SIZE
)
460 register struct reloc_ext_external
*rptr
= (struct reloc_ext_external
*) relocs
;
461 unsigned int counter
= 0;
462 arelent
*cache_ptr
= reloc_cache
;
464 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++)
466 NAME(lynx
,swap_ext_reloc_in
) (abfd
, rptr
, cache_ptr
, symbols
,
467 (bfd_size_type
) bfd_get_symcount (abfd
));
472 register struct reloc_std_external
*rptr
= (struct reloc_std_external
*) relocs
;
473 unsigned int counter
= 0;
474 arelent
*cache_ptr
= reloc_cache
;
476 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++)
478 NAME(lynx
,swap_std_reloc_in
) (abfd
, rptr
, cache_ptr
, symbols
,
479 (bfd_size_type
) bfd_get_symcount (abfd
));
484 bfd_release (abfd
, relocs
);
485 asect
->relocation
= reloc_cache
;
486 asect
->reloc_count
= count
;
492 /* Write out a relocation section into an object file. */
495 NAME(lynx
,squirt_out_relocs
) (abfd
, section
)
500 unsigned char *native
, *natptr
;
503 unsigned int count
= section
->reloc_count
;
504 bfd_size_type natsize
;
509 each_size
= obj_reloc_entry_size (abfd
);
511 natsize
*= each_size
;
512 native
= (unsigned char *) bfd_zalloc (abfd
, natsize
);
516 generic
= section
->orelocation
;
518 if (each_size
== RELOC_EXT_SIZE
)
520 for (natptr
= native
;
522 --count
, natptr
+= each_size
, ++generic
)
523 NAME(lynx
,swap_ext_reloc_out
) (abfd
, *generic
, (struct reloc_ext_external
*) natptr
);
527 for (natptr
= native
;
529 --count
, natptr
+= each_size
, ++generic
)
530 NAME(lynx
,swap_std_reloc_out
) (abfd
, *generic
, (struct reloc_std_external
*) natptr
);
533 if (bfd_bwrite ((PTR
) native
, natsize
, abfd
) != natsize
)
535 bfd_release (abfd
, native
);
538 bfd_release (abfd
, native
);
543 /* This is stupid. This function should be a boolean predicate */
545 NAME(lynx
,canonicalize_reloc
) (abfd
, section
, relptr
, symbols
)
551 arelent
*tblptr
= section
->relocation
;
554 if (!(tblptr
|| NAME(lynx
,slurp_reloc_table
) (abfd
, section
, symbols
)))
557 if (section
->flags
& SEC_CONSTRUCTOR
)
559 arelent_chain
*chain
= section
->constructor_chain
;
560 for (count
= 0; count
< section
->reloc_count
; count
++)
562 *relptr
++ = &chain
->relent
;
568 tblptr
= section
->relocation
;
570 for (count
= 0; count
++ < section
->reloc_count
;)
572 *relptr
++ = tblptr
++;
577 return section
->reloc_count
;
580 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
582 #include "aout-target.h"