1 /* BFD back-end for i386 a.out binaries under LynxOS.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996
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 #define MY(OP) CAT(i386lynx_aout_,OP)
30 #define TARGETNAME "a.out-i386-lynx"
37 #define WRITE_HEADERS(abfd, execp) \
39 bfd_size_type text_size; /* dummy vars */ \
41 if (adata(abfd).magic == undecided_magic) \
42 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
44 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
45 execp->a_entry = bfd_get_start_address (abfd); \
47 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
48 obj_reloc_entry_size (abfd)); \
49 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
50 obj_reloc_entry_size (abfd)); \
51 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
53 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) return false; \
54 if (bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd) \
57 /* Now write out reloc info, followed by syms and strings */ \
59 if (bfd_get_symcount (abfd) != 0) \
61 if (bfd_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET) \
65 if (! NAME(aout,write_syms)(abfd)) return false; \
67 if (bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET) \
71 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
73 if (bfd_seek (abfd, (file_ptr)(N_DRELOFF(*execp)), SEEK_SET) \
77 if (!NAME(lynx,squirt_out_relocs)(abfd, obj_datasec (abfd))) \
84 #include "aout/aout64.h"
88 char *lynx_core_file_failing_command ();
89 int lynx_core_file_failing_signal ();
90 boolean
lynx_core_file_matches_executable_p ();
91 const bfd_target
*lynx_core_file_p ();
93 #define MY_core_file_failing_command lynx_core_file_failing_command
94 #define MY_core_file_failing_signal lynx_core_file_failing_signal
95 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
96 #define MY_core_file_p lynx_core_file_p
98 #endif /* LYNX_CORE */
101 #define KEEPIT udata.i
103 extern reloc_howto_type aout_32_ext_howto_table
[];
104 extern reloc_howto_type aout_32_std_howto_table
[];
106 /* Standard reloc stuff */
107 /* Output standard relocation information to a file in target byte order. */
110 NAME(lynx
,swap_std_reloc_out
) (abfd
, g
, natptr
)
113 struct reloc_std_external
*natptr
;
116 asymbol
*sym
= *(g
->sym_ptr_ptr
);
118 unsigned int r_length
;
120 int r_baserel
, r_jmptable
, r_relative
;
121 unsigned int r_addend
;
122 asection
*output_section
= sym
->section
->output_section
;
124 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
126 r_length
= g
->howto
->size
; /* Size as a power of two */
127 r_pcrel
= (int) g
->howto
->pc_relative
; /* Relative to PC? */
128 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
133 r_addend
= g
->addend
+ (*(g
->sym_ptr_ptr
))->section
->output_section
->vma
;
135 /* name was clobbered by aout_write_syms to be symbol index */
137 /* If this relocation is relative to a symbol then set the
138 r_index to the symbols index, and the r_extern bit.
140 Absolute symbols can come in in two ways, either as an offset
141 from the abs section, or as a symbol which has an abs value.
146 if (bfd_is_com_section (output_section
)
147 || bfd_is_abs_section (output_section
)
148 || bfd_is_und_section (output_section
))
150 if (bfd_abs_section_ptr
->symbol
== sym
)
152 /* Whoops, looked like an abs symbol, but is really an offset
153 from the abs section */
161 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
166 /* Just an ordinary section */
168 r_index
= output_section
->target_index
;
171 /* now the fun stuff */
172 if (bfd_header_big_endian (abfd
))
174 natptr
->r_index
[0] = r_index
>> 16;
175 natptr
->r_index
[1] = r_index
>> 8;
176 natptr
->r_index
[2] = r_index
;
178 (r_extern
? RELOC_STD_BITS_EXTERN_BIG
: 0)
179 | (r_pcrel
? RELOC_STD_BITS_PCREL_BIG
: 0)
180 | (r_baserel
? RELOC_STD_BITS_BASEREL_BIG
: 0)
181 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_BIG
: 0)
182 | (r_relative
? RELOC_STD_BITS_RELATIVE_BIG
: 0)
183 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_BIG
);
187 natptr
->r_index
[2] = r_index
>> 16;
188 natptr
->r_index
[1] = r_index
>> 8;
189 natptr
->r_index
[0] = r_index
;
191 (r_extern
? RELOC_STD_BITS_EXTERN_LITTLE
: 0)
192 | (r_pcrel
? RELOC_STD_BITS_PCREL_LITTLE
: 0)
193 | (r_baserel
? RELOC_STD_BITS_BASEREL_LITTLE
: 0)
194 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_LITTLE
: 0)
195 | (r_relative
? RELOC_STD_BITS_RELATIVE_LITTLE
: 0)
196 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_LITTLE
);
202 /* Output extended relocation information to a file in target byte order. */
205 NAME(lynx
,swap_ext_reloc_out
) (abfd
, g
, natptr
)
208 register struct reloc_ext_external
*natptr
;
213 unsigned int r_addend
;
214 asymbol
*sym
= *(g
->sym_ptr_ptr
);
215 asection
*output_section
= sym
->section
->output_section
;
217 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
219 r_type
= (unsigned int) g
->howto
->type
;
221 r_addend
= g
->addend
+ (*(g
->sym_ptr_ptr
))->section
->output_section
->vma
;
224 /* If this relocation is relative to a symbol then set the
225 r_index to the symbols index, and the r_extern bit.
227 Absolute symbols can come in in two ways, either as an offset
228 from the abs section, or as a symbol which has an abs value.
232 if (bfd_is_com_section (output_section
)
233 || bfd_is_abs_section (output_section
)
234 || bfd_is_und_section (output_section
))
236 if (bfd_abs_section_ptr
->symbol
== sym
)
238 /* Whoops, looked like an abs symbol, but is really an offset
239 from the abs section */
246 r_index
= (*g
->sym_ptr_ptr
)->KEEPIT
;
251 /* Just an ordinary section */
253 r_index
= output_section
->target_index
;
257 /* now the fun stuff */
258 if (bfd_header_big_endian (abfd
))
260 natptr
->r_index
[0] = r_index
>> 16;
261 natptr
->r_index
[1] = r_index
>> 8;
262 natptr
->r_index
[2] = r_index
;
264 (r_extern
? RELOC_EXT_BITS_EXTERN_BIG
: 0)
265 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_BIG
);
269 natptr
->r_index
[2] = r_index
>> 16;
270 natptr
->r_index
[1] = r_index
>> 8;
271 natptr
->r_index
[0] = r_index
;
273 (r_extern
? RELOC_EXT_BITS_EXTERN_LITTLE
: 0)
274 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_LITTLE
);
277 PUT_WORD (abfd
, r_addend
, natptr
->r_addend
);
280 /* BFD deals internally with all things based from the section they're
281 in. so, something in 10 bytes into a text section with a base of
282 50 would have a symbol (.text+10) and know .text vma was 50.
284 Aout keeps all it's symbols based from zero, so the symbol would
285 contain 60. This macro subs the base of each section from the value
286 to give the true offset from the section */
289 #define MOVE_ADDRESS(ad) \
291 /* undefined symbol */ \
292 cache_ptr->sym_ptr_ptr = symbols + r_index; \
293 cache_ptr->addend = ad; \
295 /* defined, section relative. replace symbol with pointer to \
296 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
) (abfd
, bytes
, cache_ptr
, symbols
, symcount
)
325 struct reloc_ext_external
*bytes
;
328 bfd_size_type symcount ATTRIBUTE_UNUSED
;
333 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
335 cache_ptr
->address
= (GET_SWORD (abfd
, bytes
->r_address
));
337 r_index
= bytes
->r_index
[1];
338 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_EXT_BITS_EXTERN_BIG
));
339 r_type
= (bytes
->r_index
[0] & RELOC_EXT_BITS_TYPE_BIG
)
340 >> RELOC_EXT_BITS_TYPE_SH_BIG
;
342 cache_ptr
->howto
= aout_32_ext_howto_table
+ r_type
;
343 MOVE_ADDRESS (GET_SWORD (abfd
, bytes
->r_addend
));
347 NAME(lynx
,swap_std_reloc_in
) (abfd
, bytes
, cache_ptr
, symbols
, symcount
)
349 struct reloc_std_external
*bytes
;
352 bfd_size_type symcount ATTRIBUTE_UNUSED
;
356 unsigned int r_length
;
358 int r_baserel
, r_jmptable
, r_relative
;
359 struct aoutdata
*su
= &(abfd
->tdata
.aout_data
->a
);
361 cache_ptr
->address
= bfd_h_get_32 (abfd
, bytes
->r_address
);
363 r_index
= bytes
->r_index
[1];
364 r_extern
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_EXTERN_BIG
));
365 r_pcrel
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_PCREL_BIG
));
366 r_baserel
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_BASEREL_BIG
));
367 r_jmptable
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_JMPTABLE_BIG
));
368 r_relative
= (0 != (bytes
->r_index
[0] & RELOC_STD_BITS_RELATIVE_BIG
));
369 r_length
= (bytes
->r_index
[0] & RELOC_STD_BITS_LENGTH_BIG
)
370 >> RELOC_STD_BITS_LENGTH_SH_BIG
;
372 cache_ptr
->howto
= aout_32_std_howto_table
+ r_length
+ 4 * r_pcrel
;
373 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
381 NAME(lynx
,slurp_reloc_table
) (abfd
, asect
, symbols
)
387 bfd_size_type reloc_size
;
389 arelent
*reloc_cache
;
392 if (asect
->relocation
)
395 if (asect
->flags
& SEC_CONSTRUCTOR
)
398 if (asect
== obj_datasec (abfd
))
400 reloc_size
= exec_hdr (abfd
)->a_drsize
;
404 if (asect
== obj_textsec (abfd
))
406 reloc_size
= exec_hdr (abfd
)->a_trsize
;
410 bfd_set_error (bfd_error_invalid_operation
);
414 if (bfd_seek (abfd
, asect
->rel_filepos
, SEEK_SET
) != 0)
416 each_size
= obj_reloc_entry_size (abfd
);
418 count
= reloc_size
/ each_size
;
421 reloc_cache
= (arelent
*) bfd_malloc (count
* sizeof (arelent
));
422 if (!reloc_cache
&& count
!= 0)
424 memset (reloc_cache
, 0, count
* sizeof (arelent
));
426 relocs
= (PTR
) bfd_alloc (abfd
, reloc_size
);
427 if (!relocs
&& reloc_size
!= 0)
433 if (bfd_read (relocs
, 1, reloc_size
, abfd
) != reloc_size
)
435 bfd_release (abfd
, relocs
);
440 if (each_size
== RELOC_EXT_SIZE
)
442 register struct reloc_ext_external
*rptr
= (struct reloc_ext_external
*) relocs
;
443 unsigned int counter
= 0;
444 arelent
*cache_ptr
= reloc_cache
;
446 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++)
448 NAME(lynx
,swap_ext_reloc_in
) (abfd
, rptr
, cache_ptr
, symbols
,
449 bfd_get_symcount (abfd
));
454 register struct reloc_std_external
*rptr
= (struct reloc_std_external
*) relocs
;
455 unsigned int counter
= 0;
456 arelent
*cache_ptr
= reloc_cache
;
458 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++)
460 NAME(lynx
,swap_std_reloc_in
) (abfd
, rptr
, cache_ptr
, symbols
,
461 bfd_get_symcount (abfd
));
466 bfd_release (abfd
, relocs
);
467 asect
->relocation
= reloc_cache
;
468 asect
->reloc_count
= count
;
474 /* Write out a relocation section into an object file. */
477 NAME(lynx
,squirt_out_relocs
) (abfd
, section
)
482 unsigned char *native
, *natptr
;
485 unsigned int count
= section
->reloc_count
;
491 each_size
= obj_reloc_entry_size (abfd
);
492 natsize
= each_size
* count
;
493 native
= (unsigned char *) bfd_zalloc (abfd
, natsize
);
497 generic
= section
->orelocation
;
499 if (each_size
== RELOC_EXT_SIZE
)
501 for (natptr
= native
;
503 --count
, natptr
+= each_size
, ++generic
)
504 NAME(lynx
,swap_ext_reloc_out
) (abfd
, *generic
, (struct reloc_ext_external
*) natptr
);
508 for (natptr
= native
;
510 --count
, natptr
+= each_size
, ++generic
)
511 NAME(lynx
,swap_std_reloc_out
) (abfd
, *generic
, (struct reloc_std_external
*) natptr
);
514 if (bfd_write ((PTR
) native
, 1, natsize
, abfd
) != natsize
)
516 bfd_release (abfd
, native
);
519 bfd_release (abfd
, native
);
524 /* This is stupid. This function should be a boolean predicate */
526 NAME(lynx
,canonicalize_reloc
) (abfd
, section
, relptr
, symbols
)
532 arelent
*tblptr
= section
->relocation
;
535 if (!(tblptr
|| NAME(lynx
,slurp_reloc_table
) (abfd
, section
, symbols
)))
538 if (section
->flags
& SEC_CONSTRUCTOR
)
540 arelent_chain
*chain
= section
->constructor_chain
;
541 for (count
= 0; count
< section
->reloc_count
; count
++)
543 *relptr
++ = &chain
->relent
;
549 tblptr
= section
->relocation
;
551 for (count
= 0; count
++ < section
->reloc_count
;)
553 *relptr
++ = tblptr
++;
558 return section
->reloc_count
;
561 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
563 #include "aout-target.h"