1 /* BFD back-end for i386 a.out binaries under LynxOS.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 2001, 2002
3 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #define BYTES_IN_WORD 4
22 #define N_SHARED_LIB(x) 0
24 #define TEXT_START_ADDR 0
25 #define TARGET_PAGE_SIZE 4096
26 #define SEGMENT_SIZE TARGET_PAGE_SIZE
27 #define DEFAULT_ARCH bfd_arch_i386
29 /* Do not "beautify" the CONCAT* macro args. Traditional C will not
30 remove whitespace added here, and thus will fail to concatenate
32 #define MY(OP) CONCAT2 (i386lynx_aout_,OP)
33 #define TARGETNAME "a.out-i386-lynx"
40 #define WRITE_HEADERS(abfd, execp) \
42 bfd_size_type text_size; /* dummy vars */ \
44 if (adata(abfd).magic == undecided_magic) \
45 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
47 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
48 execp->a_entry = bfd_get_start_address (abfd); \
50 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
51 obj_reloc_entry_size (abfd)); \
52 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
53 obj_reloc_entry_size (abfd)); \
54 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
56 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 \
57 || bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
58 abfd) != EXEC_BYTES_SIZE) \
60 /* Now write out reloc info, followed by syms and strings */ \
62 if (bfd_get_symcount (abfd) != 0) \
64 if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) \
68 if (! NAME(aout,write_syms) (abfd)) return false; \
70 if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) \
74 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
76 if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) \
80 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd))) \
87 #include "aout/aout64.h"
89 void NAME (lynx
,swap_std_reloc_out
) PARAMS ((bfd
*, arelent
*, struct reloc_std_external
*));
90 void NAME (lynx
,swap_ext_reloc_out
) PARAMS ((bfd
*, arelent
*, struct reloc_ext_external
*));
91 void NAME (lynx
,swap_ext_reloc_in
) PARAMS ((bfd
*, struct reloc_ext_external
*, arelent
*, asymbol
**, bfd_size_type
));
92 void NAME (lynx
,swap_std_reloc_in
) PARAMS ((bfd
*, struct reloc_std_external
*, arelent
*, asymbol
**, bfd_size_type
));
93 boolean
NAME (lynx
,slurp_reloc_table
) PARAMS ((bfd
*, sec_ptr
, asymbol
**));
94 boolean
NAME (lynx
,squirt_out_relocs
) PARAMS ((bfd
*, asection
*));
95 long NAME (lynx
,canonicalize_reloc
) PARAMS ((bfd
*, sec_ptr
, arelent
**, asymbol
**));
99 char *lynx_core_file_failing_command ();
100 int lynx_core_file_failing_signal ();
101 boolean
lynx_core_file_matches_executable_p ();
102 const bfd_target
*lynx_core_file_p ();
104 #define MY_core_file_failing_command lynx_core_file_failing_command
105 #define MY_core_file_failing_signal lynx_core_file_failing_signal
106 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
107 #define MY_core_file_p lynx_core_file_p
109 #endif /* LYNX_CORE */
112 #define KEEPIT udata.i
114 extern reloc_howto_type aout_32_ext_howto_table
[];
115 extern reloc_howto_type aout_32_std_howto_table
[];
117 /* Standard reloc stuff */
118 /* Output standard relocation information to a file in target byte order. */
121 NAME(lynx
,swap_std_reloc_out
) (abfd
, g
, natptr
)
124 struct reloc_std_external
*natptr
;
127 asymbol
*sym
= *(g
->sym_ptr_ptr
);
129 unsigned int r_length
;
131 int r_baserel
, r_jmptable
, r_relative
;
132 unsigned int r_addend
;
133 asection
*output_section
= sym
->section
->output_section
;
135 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
137 r_length
= g
->howto
->size
; /* Size as a power of two */
138 r_pcrel
= (int) g
->howto
->pc_relative
; /* Relative to PC? */
139 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
144 r_addend
= g
->addend
+ (*(g
->sym_ptr_ptr
))->section
->output_section
->vma
;
146 /* name was clobbered by aout_write_syms to be symbol index */
148 /* If this relocation is relative to a symbol then set the
149 r_index to the symbols index, and the r_extern bit.
151 Absolute symbols can come in in two ways, either as an offset
152 from the abs section, or as a symbol which has an abs value.
157 if (bfd_is_com_section (output_section
)
158 || bfd_is_abs_section (output_section
)
159 || bfd_is_und_section (output_section
))
161 if (bfd_abs_section_ptr
->symbol
== sym
)
163 /* Whoops, looked like an abs symbol, but is really an offset
164 from the abs section */
172 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
177 /* Just an ordinary section */
179 r_index
= output_section
->target_index
;
182 /* now the fun stuff */
183 if (bfd_header_big_endian (abfd
))
185 natptr
->r_index
[0] = r_index
>> 16;
186 natptr
->r_index
[1] = r_index
>> 8;
187 natptr
->r_index
[2] = r_index
;
189 (r_extern
? RELOC_STD_BITS_EXTERN_BIG
: 0)
190 | (r_pcrel
? RELOC_STD_BITS_PCREL_BIG
: 0)
191 | (r_baserel
? RELOC_STD_BITS_BASEREL_BIG
: 0)
192 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_BIG
: 0)
193 | (r_relative
? RELOC_STD_BITS_RELATIVE_BIG
: 0)
194 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_BIG
);
198 natptr
->r_index
[2] = r_index
>> 16;
199 natptr
->r_index
[1] = r_index
>> 8;
200 natptr
->r_index
[0] = r_index
;
202 (r_extern
? RELOC_STD_BITS_EXTERN_LITTLE
: 0)
203 | (r_pcrel
? RELOC_STD_BITS_PCREL_LITTLE
: 0)
204 | (r_baserel
? RELOC_STD_BITS_BASEREL_LITTLE
: 0)
205 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_LITTLE
: 0)
206 | (r_relative
? RELOC_STD_BITS_RELATIVE_LITTLE
: 0)
207 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_LITTLE
);
213 /* Output extended relocation information to a file in target byte order. */
216 NAME(lynx
,swap_ext_reloc_out
) (abfd
, g
, natptr
)
219 register struct reloc_ext_external
*natptr
;
224 unsigned int r_addend
;
225 asymbol
*sym
= *(g
->sym_ptr_ptr
);
226 asection
*output_section
= sym
->section
->output_section
;
228 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
230 r_type
= (unsigned int) g
->howto
->type
;
232 r_addend
= g
->addend
+ (*(g
->sym_ptr_ptr
))->section
->output_section
->vma
;
235 /* If this relocation is relative to a symbol then set the
236 r_index to the symbols index, and the r_extern bit.
238 Absolute symbols can come in in two ways, either as an offset
239 from the abs section, or as a symbol which has an abs value.
243 if (bfd_is_com_section (output_section
)
244 || bfd_is_abs_section (output_section
)
245 || bfd_is_und_section (output_section
))
247 if (bfd_abs_section_ptr
->symbol
== sym
)
249 /* Whoops, looked like an abs symbol, but is really an offset
250 from the abs section */
257 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
262 /* Just an ordinary section */
264 r_index
= output_section
->target_index
;
268 /* now the fun stuff */
269 if (bfd_header_big_endian (abfd
))
271 natptr
->r_index
[0] = r_index
>> 16;
272 natptr
->r_index
[1] = r_index
>> 8;
273 natptr
->r_index
[2] = r_index
;
275 (r_extern
? RELOC_EXT_BITS_EXTERN_BIG
: 0)
276 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_BIG
);
280 natptr
->r_index
[2] = r_index
>> 16;
281 natptr
->r_index
[1] = r_index
>> 8;
282 natptr
->r_index
[0] = r_index
;
284 (r_extern
? RELOC_EXT_BITS_EXTERN_LITTLE
: 0)
285 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_LITTLE
);
288 PUT_WORD (abfd
, r_addend
, natptr
->r_addend
);
291 /* BFD deals internally with all things based from the section they're
292 in. so, something in 10 bytes into a text section with a base of
293 50 would have a symbol (.text+10) and know .text vma was 50.
295 Aout keeps all it's symbols based from zero, so the symbol would
296 contain 60. This macro subs the base of each section from the value
297 to give the true offset from the section */
300 #define MOVE_ADDRESS(ad) \
302 /* undefined symbol */ \
303 cache_ptr->sym_ptr_ptr = symbols + r_index; \
304 cache_ptr->addend = ad; \
306 /* defined, section relative. replace symbol with pointer to \
307 symbol which points to section */ \
310 case N_TEXT | N_EXT: \
311 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
312 cache_ptr->addend = ad - su->textsec->vma; \
315 case N_DATA | N_EXT: \
316 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
317 cache_ptr->addend = ad - su->datasec->vma; \
320 case N_BSS | N_EXT: \
321 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
322 cache_ptr->addend = ad - su->bsssec->vma; \
326 case N_ABS | N_EXT: \
327 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
328 cache_ptr->addend = ad; \
334 NAME(lynx
,swap_ext_reloc_in
) (abfd
, bytes
, cache_ptr
, symbols
, symcount
)
336 struct reloc_ext_external
*bytes
;
339 bfd_size_type symcount ATTRIBUTE_UNUSED
;
344 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
346 cache_ptr
->address
= (GET_SWORD (abfd
, bytes
->r_address
));
348 r_index
= bytes
->r_index
[1];
349 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_EXT_BITS_EXTERN_BIG
));
350 r_type
= (bytes
->r_index
[0] & RELOC_EXT_BITS_TYPE_BIG
)
351 >> RELOC_EXT_BITS_TYPE_SH_BIG
;
353 cache_ptr
->howto
= aout_32_ext_howto_table
+ r_type
;
354 MOVE_ADDRESS (GET_SWORD (abfd
, bytes
->r_addend
));
358 NAME(lynx
,swap_std_reloc_in
) (abfd
, bytes
, cache_ptr
, symbols
, symcount
)
360 struct reloc_std_external
*bytes
;
363 bfd_size_type symcount ATTRIBUTE_UNUSED
;
367 unsigned int r_length
;
369 int r_baserel
, r_jmptable
, r_relative
;
370 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
372 cache_ptr
->address
= H_GET_32 (abfd
, bytes
->r_address
);
374 r_index
= bytes
->r_index
[1];
375 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_EXTERN_BIG
));
376 r_pcrel
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_PCREL_BIG
));
377 r_baserel
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_BASEREL_BIG
));
378 r_jmptable
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_JMPTABLE_BIG
));
379 r_relative
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_RELATIVE_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"