1 /* BFD back-end for i386 a.out binaries under LynxOS.
2 Copyright (C) 1990-2023 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
21 #define TEXT_START_ADDR 0
22 #define TARGET_PAGE_SIZE 4096
23 #define SEGMENT_SIZE TARGET_PAGE_SIZE
24 #define DEFAULT_ARCH bfd_arch_i386
26 /* Do not "beautify" the CONCAT* macro args. Traditional C will not
27 remove whitespace added here, and thus will fail to concatenate
29 #define MY(OP) CONCAT2 (i386_aout_lynx_,OP)
30 #define TARGETNAME "a.out-i386-lynx"
37 #define WRITE_HEADERS(abfd, execp) \
39 if (adata(abfd).magic == undecided_magic) \
40 NAME(aout,adjust_sizes_and_vmas) (abfd); \
42 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
43 execp->a_entry = bfd_get_start_address (abfd); \
45 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
46 obj_reloc_entry_size (abfd)); \
47 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
48 obj_reloc_entry_size (abfd)); \
49 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
51 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 \
52 || bfd_bwrite (&exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
53 abfd) != EXEC_BYTES_SIZE) \
55 /* Now write out reloc info, followed by syms and strings */ \
57 if (bfd_get_symcount (abfd) != 0) \
59 if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (execp)), SEEK_SET) \
63 if (! NAME(aout,write_syms) (abfd)) return false; \
65 if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (execp)), SEEK_SET) \
69 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
71 if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (execp)), SEEK_SET) \
75 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd))) \
82 #include "aout/aout64.h"
87 char *lynx_core_file_failing_command ();
88 int lynx_core_file_failing_signal ();
89 bool lynx_core_file_matches_executable_p ();
90 bfd_cleanup
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
) (bfd
*abfd
,
111 struct reloc_std_external
*natptr
)
114 asymbol
*sym
= *(g
->sym_ptr_ptr
);
116 unsigned int r_length
;
118 int r_baserel
, r_jmptable
, r_relative
;
119 asection
*output_section
= sym
->section
->output_section
;
121 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
123 r_length
= bfd_log2 (bfd_get_reloc_size (g
->howto
));
124 r_pcrel
= (int) g
->howto
->pc_relative
; /* Relative to PC? */
125 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
130 /* name was clobbered by aout_write_syms to be symbol index */
132 /* If this relocation is relative to a symbol then set the
133 r_index to the symbols index, and the r_extern bit.
135 Absolute symbols can come in in two ways, either as an offset
136 from the abs section, or as a symbol which has an abs value.
140 if (bfd_is_com_section (output_section
)
141 || bfd_is_abs_section (output_section
)
142 || bfd_is_und_section (output_section
))
144 if (bfd_abs_section_ptr
->symbol
== sym
)
146 /* Whoops, looked like an abs symbol, but is really an offset
147 from the abs section */
155 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
160 /* Just an ordinary section */
162 r_index
= output_section
->target_index
;
165 /* now the fun stuff */
166 if (bfd_header_big_endian (abfd
))
168 natptr
->r_index
[0] = r_index
>> 16;
169 natptr
->r_index
[1] = r_index
>> 8;
170 natptr
->r_index
[2] = r_index
;
172 (r_extern
? RELOC_STD_BITS_EXTERN_BIG
: 0)
173 | (r_pcrel
? RELOC_STD_BITS_PCREL_BIG
: 0)
174 | (r_baserel
? RELOC_STD_BITS_BASEREL_BIG
: 0)
175 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_BIG
: 0)
176 | (r_relative
? RELOC_STD_BITS_RELATIVE_BIG
: 0)
177 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_BIG
);
181 natptr
->r_index
[2] = r_index
>> 16;
182 natptr
->r_index
[1] = r_index
>> 8;
183 natptr
->r_index
[0] = r_index
;
185 (r_extern
? RELOC_STD_BITS_EXTERN_LITTLE
: 0)
186 | (r_pcrel
? RELOC_STD_BITS_PCREL_LITTLE
: 0)
187 | (r_baserel
? RELOC_STD_BITS_BASEREL_LITTLE
: 0)
188 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_LITTLE
: 0)
189 | (r_relative
? RELOC_STD_BITS_RELATIVE_LITTLE
: 0)
190 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_LITTLE
);
196 /* Output extended relocation information to a file in target byte order. */
199 NAME(lynx
,swap_ext_reloc_out
) (bfd
*abfd
,
201 struct reloc_ext_external
*natptr
)
206 unsigned int r_addend
;
207 asymbol
*sym
= *(g
->sym_ptr_ptr
);
208 asection
*output_section
= sym
->section
->output_section
;
210 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
212 r_type
= (unsigned int) g
->howto
->type
;
214 r_addend
= g
->addend
+ (*(g
->sym_ptr_ptr
))->section
->output_section
->vma
;
217 /* If this relocation is relative to a symbol then set the
218 r_index to the symbols index, and the r_extern bit.
220 Absolute symbols can come in in two ways, either as an offset
221 from the abs section, or as a symbol which has an abs value.
225 if (bfd_is_com_section (output_section
)
226 || bfd_is_abs_section (output_section
)
227 || bfd_is_und_section (output_section
))
229 if (bfd_abs_section_ptr
->symbol
== sym
)
231 /* Whoops, looked like an abs symbol, but is really an offset
232 from the abs section */
239 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
244 /* Just an ordinary section */
246 r_index
= output_section
->target_index
;
250 /* now the fun stuff */
251 if (bfd_header_big_endian (abfd
))
253 natptr
->r_index
[0] = r_index
>> 16;
254 natptr
->r_index
[1] = r_index
>> 8;
255 natptr
->r_index
[2] = r_index
;
257 (r_extern
? RELOC_EXT_BITS_EXTERN_BIG
: 0)
258 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_BIG
);
262 natptr
->r_index
[2] = r_index
>> 16;
263 natptr
->r_index
[1] = r_index
>> 8;
264 natptr
->r_index
[0] = r_index
;
266 (r_extern
? RELOC_EXT_BITS_EXTERN_LITTLE
: 0)
267 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_LITTLE
);
270 PUT_WORD (abfd
, r_addend
, natptr
->r_addend
);
273 /* BFD deals internally with all things based from the section they're
274 in. so, something in 10 bytes into a text section with a base of
275 50 would have a symbol (.text+10) and know .text vma was 50.
277 Aout keeps all it's symbols based from zero, so the symbol would
278 contain 60. This macro subs the base of each section from the value
279 to give the true offset from the section */
282 #define MOVE_ADDRESS(ad) \
285 /* undefined symbol */ \
286 if (symbols != NULL && r_index < bfd_get_symcount (abfd)) \
287 cache_ptr->sym_ptr_ptr = symbols + r_index; \
289 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
290 cache_ptr->addend = ad; \
294 /* defined, section relative. replace symbol with pointer to \
295 symbol which points to section */ \
299 case N_TEXT | N_EXT: \
300 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
301 cache_ptr->addend = ad - su->textsec->vma; \
304 case N_DATA | N_EXT: \
305 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
306 cache_ptr->addend = ad - su->datasec->vma; \
309 case N_BSS | N_EXT: \
310 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
311 cache_ptr->addend = ad - su->bsssec->vma; \
315 case N_ABS | N_EXT: \
316 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
317 cache_ptr->addend = ad; \
323 NAME(lynx
,swap_ext_reloc_in
) (bfd
*abfd
,
324 struct reloc_ext_external
*bytes
,
327 bfd_size_type symcount ATTRIBUTE_UNUSED
)
329 unsigned int r_index
;
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
) (bfd
*abfd
,
347 struct reloc_std_external
*bytes
,
350 bfd_size_type symcount ATTRIBUTE_UNUSED
)
352 unsigned int r_index
;
354 unsigned int r_length
;
356 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
358 cache_ptr
->address
= H_GET_32 (abfd
, bytes
->r_address
);
360 r_index
= bytes
->r_index
[1];
361 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_EXTERN_BIG
));
362 r_pcrel
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_PCREL_BIG
));
363 r_length
= (bytes
->r_index
[0] & RELOC_STD_BITS_LENGTH_BIG
)
364 >> RELOC_STD_BITS_LENGTH_SH_BIG
;
366 cache_ptr
->howto
= aout_32_std_howto_table
+ r_length
+ 4 * r_pcrel
;
367 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
375 NAME(lynx
,slurp_reloc_table
) (bfd
*abfd
,
380 bfd_size_type reloc_size
;
382 arelent
*reloc_cache
;
385 if (asect
->relocation
)
388 if (asect
->flags
& SEC_CONSTRUCTOR
)
391 if (asect
== obj_datasec (abfd
))
393 reloc_size
= exec_hdr (abfd
)->a_drsize
;
397 if (asect
== obj_textsec (abfd
))
399 reloc_size
= exec_hdr (abfd
)->a_trsize
;
403 bfd_set_error (bfd_error_invalid_operation
);
407 if (bfd_seek (abfd
, asect
->rel_filepos
, SEEK_SET
) != 0)
409 each_size
= obj_reloc_entry_size (abfd
);
411 count
= reloc_size
/ each_size
;
414 reloc_cache
= (arelent
*) bfd_zmalloc (count
* sizeof (arelent
));
415 if (!reloc_cache
&& count
!= 0)
418 relocs
= _bfd_alloc_and_read (abfd
, reloc_size
, reloc_size
);
419 if (!relocs
&& reloc_size
!= 0)
425 if (each_size
== RELOC_EXT_SIZE
)
427 struct reloc_ext_external
*rptr
= (struct reloc_ext_external
*) relocs
;
428 unsigned int counter
= 0;
429 arelent
*cache_ptr
= reloc_cache
;
431 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++)
433 NAME(lynx
,swap_ext_reloc_in
) (abfd
, rptr
, cache_ptr
, symbols
,
434 (bfd_size_type
) bfd_get_symcount (abfd
));
439 struct reloc_std_external
*rptr
= (struct reloc_std_external
*) relocs
;
440 unsigned int counter
= 0;
441 arelent
*cache_ptr
= reloc_cache
;
443 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++)
445 NAME(lynx
,swap_std_reloc_in
) (abfd
, rptr
, cache_ptr
, symbols
,
446 (bfd_size_type
) bfd_get_symcount (abfd
));
451 bfd_release (abfd
, relocs
);
452 asect
->relocation
= reloc_cache
;
453 asect
->reloc_count
= count
;
459 /* Write out a relocation section into an object file. */
462 NAME(lynx
,squirt_out_relocs
) (bfd
*abfd
, asection
*section
)
465 unsigned char *native
, *natptr
;
467 unsigned int count
= section
->reloc_count
;
468 bfd_size_type natsize
;
473 each_size
= obj_reloc_entry_size (abfd
);
475 natsize
*= each_size
;
476 native
= (unsigned char *) bfd_zalloc (abfd
, natsize
);
480 generic
= section
->orelocation
;
482 if (each_size
== RELOC_EXT_SIZE
)
484 for (natptr
= native
;
486 --count
, natptr
+= each_size
, ++generic
)
487 NAME(lynx
,swap_ext_reloc_out
) (abfd
, *generic
, (struct reloc_ext_external
*) natptr
);
491 for (natptr
= native
;
493 --count
, natptr
+= each_size
, ++generic
)
494 NAME(lynx
,swap_std_reloc_out
) (abfd
, *generic
, (struct reloc_std_external
*) natptr
);
497 if (bfd_bwrite (native
, natsize
, abfd
) != natsize
)
499 bfd_release (abfd
, native
);
502 bfd_release (abfd
, native
);
507 /* This is stupid. This function should be a boolean predicate */
509 NAME(lynx
,canonicalize_reloc
) (bfd
*abfd
,
514 arelent
*tblptr
= section
->relocation
;
517 if (!(tblptr
|| NAME(lynx
,slurp_reloc_table
) (abfd
, section
, symbols
)))
520 if (section
->flags
& SEC_CONSTRUCTOR
)
522 arelent_chain
*chain
= section
->constructor_chain
;
523 for (count
= 0; count
< section
->reloc_count
; count
++)
525 *relptr
++ = &chain
->relent
;
531 tblptr
= section
->relocation
;
533 for (count
= 0; count
++ < section
->reloc_count
;)
535 *relptr
++ = tblptr
++;
540 return section
->reloc_count
;
543 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
545 #include "aout-target.h"