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, 2007 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 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)
90 PARAMS ((bfd *, arelent *, struct reloc_std_external *));
91 void NAME (lynx,swap_ext_reloc_out)
92 PARAMS ((bfd *, arelent *, struct reloc_ext_external *));
93 void NAME (lynx,swap_ext_reloc_in)
94 PARAMS ((bfd *, struct reloc_ext_external *, arelent *, asymbol **,
96 void NAME (lynx,swap_std_reloc_in)
97 PARAMS ((bfd *, struct reloc_std_external *, arelent *, asymbol **,
99 bfd_boolean NAME (lynx,slurp_reloc_table)
100 PARAMS ((bfd *, sec_ptr, asymbol **));
101 bfd_boolean NAME (lynx,squirt_out_relocs)
102 PARAMS ((bfd *, asection *));
103 long NAME (lynx,canonicalize_reloc)
104 PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
108 char *lynx_core_file_failing_command ();
109 int lynx_core_file_failing_signal ();
110 bfd_boolean lynx_core_file_matches_executable_p ();
111 const bfd_target *lynx_core_file_p ();
113 #define MY_core_file_failing_command lynx_core_file_failing_command
114 #define MY_core_file_failing_signal lynx_core_file_failing_signal
115 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
116 #define MY_core_file_p lynx_core_file_p
118 #endif /* LYNX_CORE */
121 #define KEEPIT udata.i
123 extern reloc_howto_type aout_32_ext_howto_table[];
124 extern reloc_howto_type aout_32_std_howto_table[];
126 /* Standard reloc stuff */
127 /* Output standard relocation information to a file in target byte order. */
130 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
133 struct reloc_std_external *natptr;
136 asymbol *sym = *(g->sym_ptr_ptr);
138 unsigned int r_length;
140 int r_baserel, r_jmptable, r_relative;
141 unsigned int r_addend;
142 asection *output_section = sym->section->output_section;
144 PUT_WORD (abfd, g->address, natptr->r_address);
146 r_length = g->howto->size; /* Size as a power of two */
147 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
148 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
153 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
155 /* name was clobbered by aout_write_syms to be symbol index */
157 /* If this relocation is relative to a symbol then set the
158 r_index to the symbols index, and the r_extern bit.
160 Absolute symbols can come in in two ways, either as an offset
161 from the abs section, or as a symbol which has an abs value.
166 if (bfd_is_com_section (output_section)
167 || bfd_is_abs_section (output_section)
168 || bfd_is_und_section (output_section))
170 if (bfd_abs_section_ptr->symbol == sym)
172 /* Whoops, looked like an abs symbol, but is really an offset
173 from the abs section */
181 r_index = (*g->sym_ptr_ptr)->KEEPIT;
186 /* Just an ordinary section */
188 r_index = output_section->target_index;
191 /* now the fun stuff */
192 if (bfd_header_big_endian (abfd))
194 natptr->r_index[0] = r_index >> 16;
195 natptr->r_index[1] = r_index >> 8;
196 natptr->r_index[2] = r_index;
198 (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
199 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
200 | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
201 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
202 | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
203 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
207 natptr->r_index[2] = r_index >> 16;
208 natptr->r_index[1] = r_index >> 8;
209 natptr->r_index[0] = r_index;
211 (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
212 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
213 | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
214 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
215 | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
216 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
222 /* Output extended relocation information to a file in target byte order. */
225 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
228 register struct reloc_ext_external *natptr;
233 unsigned int r_addend;
234 asymbol *sym = *(g->sym_ptr_ptr);
235 asection *output_section = sym->section->output_section;
237 PUT_WORD (abfd, g->address, natptr->r_address);
239 r_type = (unsigned int) g->howto->type;
241 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
244 /* If this relocation is relative to a symbol then set the
245 r_index to the symbols index, and the r_extern bit.
247 Absolute symbols can come in in two ways, either as an offset
248 from the abs section, or as a symbol which has an abs value.
252 if (bfd_is_com_section (output_section)
253 || bfd_is_abs_section (output_section)
254 || bfd_is_und_section (output_section))
256 if (bfd_abs_section_ptr->symbol == sym)
258 /* Whoops, looked like an abs symbol, but is really an offset
259 from the abs section */
266 r_index = (*g->sym_ptr_ptr)->KEEPIT;
271 /* Just an ordinary section */
273 r_index = output_section->target_index;
277 /* now the fun stuff */
278 if (bfd_header_big_endian (abfd))
280 natptr->r_index[0] = r_index >> 16;
281 natptr->r_index[1] = r_index >> 8;
282 natptr->r_index[2] = r_index;
284 (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
285 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
289 natptr->r_index[2] = r_index >> 16;
290 natptr->r_index[1] = r_index >> 8;
291 natptr->r_index[0] = r_index;
293 (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
294 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
297 PUT_WORD (abfd, r_addend, natptr->r_addend);
300 /* BFD deals internally with all things based from the section they're
301 in. so, something in 10 bytes into a text section with a base of
302 50 would have a symbol (.text+10) and know .text vma was 50.
304 Aout keeps all it's symbols based from zero, so the symbol would
305 contain 60. This macro subs the base of each section from the value
306 to give the true offset from the section */
309 #define MOVE_ADDRESS(ad) \
311 /* undefined symbol */ \
312 cache_ptr->sym_ptr_ptr = symbols + r_index; \
313 cache_ptr->addend = ad; \
315 /* defined, section relative. replace symbol with pointer to \
316 symbol which points to section */ \
319 case N_TEXT | N_EXT: \
320 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
321 cache_ptr->addend = ad - su->textsec->vma; \
324 case N_DATA | N_EXT: \
325 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
326 cache_ptr->addend = ad - su->datasec->vma; \
329 case N_BSS | N_EXT: \
330 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
331 cache_ptr->addend = ad - su->bsssec->vma; \
335 case N_ABS | N_EXT: \
336 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
337 cache_ptr->addend = ad; \
343 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
345 struct reloc_ext_external *bytes;
348 bfd_size_type symcount ATTRIBUTE_UNUSED;
353 struct aoutdata *su = &(abfd->tdata.aout_data->a);
355 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
357 r_index = bytes->r_index[1];
358 r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
359 r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
360 >> RELOC_EXT_BITS_TYPE_SH_BIG;
362 cache_ptr->howto = aout_32_ext_howto_table + r_type;
363 MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
367 NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
369 struct reloc_std_external *bytes;
372 bfd_size_type symcount ATTRIBUTE_UNUSED;
376 unsigned int r_length;
378 int r_baserel, r_jmptable, r_relative;
379 struct aoutdata *su = &(abfd->tdata.aout_data->a);
381 cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
383 r_index = bytes->r_index[1];
384 r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
385 r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
386 r_baserel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_BASEREL_BIG));
387 r_jmptable = (0 != (bytes->r_index[0] & RELOC_STD_BITS_JMPTABLE_BIG));
388 r_relative = (0 != (bytes->r_index[0] & RELOC_STD_BITS_RELATIVE_BIG));
389 r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
390 >> RELOC_STD_BITS_LENGTH_SH_BIG;
392 cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
393 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
401 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
407 bfd_size_type reloc_size;
409 arelent *reloc_cache;
412 if (asect->relocation)
415 if (asect->flags & SEC_CONSTRUCTOR)
418 if (asect == obj_datasec (abfd))
420 reloc_size = exec_hdr (abfd)->a_drsize;
424 if (asect == obj_textsec (abfd))
426 reloc_size = exec_hdr (abfd)->a_trsize;
430 bfd_set_error (bfd_error_invalid_operation);
434 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
436 each_size = obj_reloc_entry_size (abfd);
438 count = reloc_size / each_size;
441 reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
442 if (!reloc_cache && count != 0)
445 relocs = (PTR) bfd_alloc (abfd, reloc_size);
446 if (!relocs && reloc_size != 0)
452 if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
454 bfd_release (abfd, relocs);
459 if (each_size == RELOC_EXT_SIZE)
461 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
462 unsigned int counter = 0;
463 arelent *cache_ptr = reloc_cache;
465 for (; counter < count; counter++, rptr++, cache_ptr++)
467 NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
468 (bfd_size_type) bfd_get_symcount (abfd));
473 register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
474 unsigned int counter = 0;
475 arelent *cache_ptr = reloc_cache;
477 for (; counter < count; counter++, rptr++, cache_ptr++)
479 NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
480 (bfd_size_type) bfd_get_symcount (abfd));
485 bfd_release (abfd, relocs);
486 asect->relocation = reloc_cache;
487 asect->reloc_count = count;
493 /* Write out a relocation section into an object file. */
496 NAME(lynx,squirt_out_relocs) (abfd, section)
501 unsigned char *native, *natptr;
504 unsigned int count = section->reloc_count;
505 bfd_size_type natsize;
510 each_size = obj_reloc_entry_size (abfd);
512 natsize *= each_size;
513 native = (unsigned char *) bfd_zalloc (abfd, natsize);
517 generic = section->orelocation;
519 if (each_size == RELOC_EXT_SIZE)
521 for (natptr = native;
523 --count, natptr += each_size, ++generic)
524 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
528 for (natptr = native;
530 --count, natptr += each_size, ++generic)
531 NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
534 if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
536 bfd_release (abfd, native);
539 bfd_release (abfd, native);
544 /* This is stupid. This function should be a boolean predicate */
546 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
552 arelent *tblptr = section->relocation;
555 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
558 if (section->flags & SEC_CONSTRUCTOR)
560 arelent_chain *chain = section->constructor_chain;
561 for (count = 0; count < section->reloc_count; count++)
563 *relptr++ = &chain->relent;
569 tblptr = section->relocation;
571 for (count = 0; count++ < section->reloc_count;)
573 *relptr++ = tblptr++;
578 return section->reloc_count;
581 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
583 #include "aout-target.h"