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, 2010, 2012 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 (&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"
90 char *lynx_core_file_failing_command ();
91 int lynx_core_file_failing_signal ();
92 bfd_boolean lynx_core_file_matches_executable_p ();
93 const bfd_target *lynx_core_file_p ();
95 #define MY_core_file_failing_command lynx_core_file_failing_command
96 #define MY_core_file_failing_signal lynx_core_file_failing_signal
97 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
98 #define MY_core_file_p lynx_core_file_p
100 #endif /* LYNX_CORE */
103 #define KEEPIT udata.i
105 extern reloc_howto_type aout_32_ext_howto_table[];
106 extern reloc_howto_type aout_32_std_howto_table[];
108 /* Standard reloc stuff */
109 /* Output standard relocation information to a file in target byte order. */
112 NAME(lynx,swap_std_reloc_out) (bfd *abfd,
114 struct reloc_std_external *natptr)
117 asymbol *sym = *(g->sym_ptr_ptr);
119 unsigned int r_length;
121 int r_baserel, r_jmptable, r_relative;
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 /* name was clobbered by aout_write_syms to be symbol index */
135 /* If this relocation is relative to a symbol then set the
136 r_index to the symbols index, and the r_extern bit.
138 Absolute symbols can come in in two ways, either as an offset
139 from the abs section, or as a symbol which has an abs value.
143 if (bfd_is_com_section (output_section)
144 || bfd_is_abs_section (output_section)
145 || bfd_is_und_section (output_section))
147 if (bfd_abs_section_ptr->symbol == sym)
149 /* Whoops, looked like an abs symbol, but is really an offset
150 from the abs section */
158 r_index = (*g->sym_ptr_ptr)->KEEPIT;
163 /* Just an ordinary section */
165 r_index = output_section->target_index;
168 /* now the fun stuff */
169 if (bfd_header_big_endian (abfd))
171 natptr->r_index[0] = r_index >> 16;
172 natptr->r_index[1] = r_index >> 8;
173 natptr->r_index[2] = r_index;
175 (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
176 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
177 | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
178 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
179 | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
180 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
184 natptr->r_index[2] = r_index >> 16;
185 natptr->r_index[1] = r_index >> 8;
186 natptr->r_index[0] = r_index;
188 (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
189 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
190 | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
191 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
192 | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
193 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
199 /* Output extended relocation information to a file in target byte order. */
202 NAME(lynx,swap_ext_reloc_out) (bfd *abfd,
204 struct reloc_ext_external *natptr)
209 unsigned int r_addend;
210 asymbol *sym = *(g->sym_ptr_ptr);
211 asection *output_section = sym->section->output_section;
213 PUT_WORD (abfd, g->address, natptr->r_address);
215 r_type = (unsigned int) g->howto->type;
217 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
220 /* If this relocation is relative to a symbol then set the
221 r_index to the symbols index, and the r_extern bit.
223 Absolute symbols can come in in two ways, either as an offset
224 from the abs section, or as a symbol which has an abs value.
228 if (bfd_is_com_section (output_section)
229 || bfd_is_abs_section (output_section)
230 || bfd_is_und_section (output_section))
232 if (bfd_abs_section_ptr->symbol == sym)
234 /* Whoops, looked like an abs symbol, but is really an offset
235 from the abs section */
242 r_index = (*g->sym_ptr_ptr)->KEEPIT;
247 /* Just an ordinary section */
249 r_index = output_section->target_index;
253 /* now the fun stuff */
254 if (bfd_header_big_endian (abfd))
256 natptr->r_index[0] = r_index >> 16;
257 natptr->r_index[1] = r_index >> 8;
258 natptr->r_index[2] = r_index;
260 (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
261 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
265 natptr->r_index[2] = r_index >> 16;
266 natptr->r_index[1] = r_index >> 8;
267 natptr->r_index[0] = r_index;
269 (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
270 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
273 PUT_WORD (abfd, r_addend, natptr->r_addend);
276 /* BFD deals internally with all things based from the section they're
277 in. so, something in 10 bytes into a text section with a base of
278 50 would have a symbol (.text+10) and know .text vma was 50.
280 Aout keeps all it's symbols based from zero, so the symbol would
281 contain 60. This macro subs the base of each section from the value
282 to give the true offset from the section */
285 #define MOVE_ADDRESS(ad) \
288 /* undefined symbol */ \
289 cache_ptr->sym_ptr_ptr = symbols + r_index; \
290 cache_ptr->addend = ad; \
294 /* defined, section relative. replace symbol with pointer to \
295 symbol which points to section */ \
298 case N_TEXT | N_EXT: \
299 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
300 cache_ptr->addend = ad - su->textsec->vma; \
303 case N_DATA | N_EXT: \
304 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
305 cache_ptr->addend = ad - su->datasec->vma; \
308 case N_BSS | N_EXT: \
309 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
310 cache_ptr->addend = ad - su->bsssec->vma; \
314 case N_ABS | N_EXT: \
315 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
316 cache_ptr->addend = ad; \
322 NAME(lynx,swap_ext_reloc_in) (bfd *abfd,
323 struct reloc_ext_external *bytes,
326 bfd_size_type symcount ATTRIBUTE_UNUSED)
331 struct aoutdata *su = &(abfd->tdata.aout_data->a);
333 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
335 r_index = bytes->r_index[1];
336 r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
337 r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
338 >> RELOC_EXT_BITS_TYPE_SH_BIG;
340 cache_ptr->howto = aout_32_ext_howto_table + r_type;
341 MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
345 NAME(lynx,swap_std_reloc_in) (bfd *abfd,
346 struct reloc_std_external *bytes,
349 bfd_size_type symcount ATTRIBUTE_UNUSED)
353 unsigned int r_length;
355 struct aoutdata *su = &(abfd->tdata.aout_data->a);
357 cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
359 r_index = bytes->r_index[1];
360 r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
361 r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
362 r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
363 >> RELOC_STD_BITS_LENGTH_SH_BIG;
365 cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
366 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
374 NAME(lynx,slurp_reloc_table) (bfd *abfd,
379 bfd_size_type reloc_size;
381 arelent *reloc_cache;
384 if (asect->relocation)
387 if (asect->flags & SEC_CONSTRUCTOR)
390 if (asect == obj_datasec (abfd))
392 reloc_size = exec_hdr (abfd)->a_drsize;
396 if (asect == obj_textsec (abfd))
398 reloc_size = exec_hdr (abfd)->a_trsize;
402 bfd_set_error (bfd_error_invalid_operation);
406 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
408 each_size = obj_reloc_entry_size (abfd);
410 count = reloc_size / each_size;
413 reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
414 if (!reloc_cache && count != 0)
417 relocs = bfd_alloc (abfd, reloc_size);
418 if (!relocs && reloc_size != 0)
424 if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
426 bfd_release (abfd, relocs);
431 if (each_size == RELOC_EXT_SIZE)
433 struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
434 unsigned int counter = 0;
435 arelent *cache_ptr = reloc_cache;
437 for (; counter < count; counter++, rptr++, cache_ptr++)
439 NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
440 (bfd_size_type) bfd_get_symcount (abfd));
445 struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
446 unsigned int counter = 0;
447 arelent *cache_ptr = reloc_cache;
449 for (; counter < count; counter++, rptr++, cache_ptr++)
451 NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
452 (bfd_size_type) bfd_get_symcount (abfd));
457 bfd_release (abfd, relocs);
458 asect->relocation = reloc_cache;
459 asect->reloc_count = count;
465 /* Write out a relocation section into an object file. */
468 NAME(lynx,squirt_out_relocs) (bfd *abfd, asection *section)
471 unsigned char *native, *natptr;
473 unsigned int count = section->reloc_count;
474 bfd_size_type natsize;
479 each_size = obj_reloc_entry_size (abfd);
481 natsize *= each_size;
482 native = (unsigned char *) bfd_zalloc (abfd, natsize);
486 generic = section->orelocation;
488 if (each_size == RELOC_EXT_SIZE)
490 for (natptr = native;
492 --count, natptr += each_size, ++generic)
493 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
497 for (natptr = native;
499 --count, natptr += each_size, ++generic)
500 NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
503 if (bfd_bwrite (native, natsize, abfd) != natsize)
505 bfd_release (abfd, native);
508 bfd_release (abfd, native);
513 /* This is stupid. This function should be a boolean predicate */
515 NAME(lynx,canonicalize_reloc) (bfd *abfd,
520 arelent *tblptr = section->relocation;
523 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
526 if (section->flags & SEC_CONSTRUCTOR)
528 arelent_chain *chain = section->constructor_chain;
529 for (count = 0; count < section->reloc_count; count++)
531 *relptr++ = &chain->relent;
537 tblptr = section->relocation;
539 for (count = 0; count++ < section->reloc_count;)
541 *relptr++ = tblptr++;
546 return section->reloc_count;
549 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
551 #include "aout-target.h"