1 /* BFD back-end for i386 a.out binaries under LynxOS.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 2001
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 \
54 || bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
55 abfd) != EXEC_BYTES_SIZE) \
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"
86 void NAME (lynx,swap_std_reloc_out) PARAMS ((bfd *, arelent *, struct reloc_std_external *));
87 void NAME (lynx,swap_ext_reloc_out) PARAMS ((bfd *, arelent *, struct reloc_ext_external *));
88 void NAME (lynx,swap_ext_reloc_in) PARAMS ((bfd *, struct reloc_ext_external *, arelent *, asymbol **, bfd_size_type));
89 void NAME (lynx,swap_std_reloc_in) PARAMS ((bfd *, struct reloc_std_external *, arelent *, asymbol **, bfd_size_type));
90 boolean NAME (lynx,slurp_reloc_table) PARAMS ((bfd *, sec_ptr, asymbol **));
91 boolean NAME (lynx,squirt_out_relocs) PARAMS ((bfd *, asection *));
92 long NAME (lynx,canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
96 char *lynx_core_file_failing_command ();
97 int lynx_core_file_failing_signal ();
98 boolean lynx_core_file_matches_executable_p ();
99 const bfd_target *lynx_core_file_p ();
101 #define MY_core_file_failing_command lynx_core_file_failing_command
102 #define MY_core_file_failing_signal lynx_core_file_failing_signal
103 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
104 #define MY_core_file_p lynx_core_file_p
106 #endif /* LYNX_CORE */
109 #define KEEPIT udata.i
111 extern reloc_howto_type aout_32_ext_howto_table[];
112 extern reloc_howto_type aout_32_std_howto_table[];
114 /* Standard reloc stuff */
115 /* Output standard relocation information to a file in target byte order. */
118 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
121 struct reloc_std_external *natptr;
124 asymbol *sym = *(g->sym_ptr_ptr);
126 unsigned int r_length;
128 int r_baserel, r_jmptable, r_relative;
129 unsigned int r_addend;
130 asection *output_section = sym->section->output_section;
132 PUT_WORD (abfd, g->address, natptr->r_address);
134 r_length = g->howto->size; /* Size as a power of two */
135 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
136 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
141 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
143 /* name was clobbered by aout_write_syms to be symbol index */
145 /* If this relocation is relative to a symbol then set the
146 r_index to the symbols index, and the r_extern bit.
148 Absolute symbols can come in in two ways, either as an offset
149 from the abs section, or as a symbol which has an abs value.
154 if (bfd_is_com_section (output_section)
155 || bfd_is_abs_section (output_section)
156 || bfd_is_und_section (output_section))
158 if (bfd_abs_section_ptr->symbol == sym)
160 /* Whoops, looked like an abs symbol, but is really an offset
161 from the abs section */
169 r_index = (*g->sym_ptr_ptr)->KEEPIT;
174 /* Just an ordinary section */
176 r_index = output_section->target_index;
179 /* now the fun stuff */
180 if (bfd_header_big_endian (abfd))
182 natptr->r_index[0] = r_index >> 16;
183 natptr->r_index[1] = r_index >> 8;
184 natptr->r_index[2] = r_index;
186 (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
187 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
188 | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
189 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
190 | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
191 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
195 natptr->r_index[2] = r_index >> 16;
196 natptr->r_index[1] = r_index >> 8;
197 natptr->r_index[0] = r_index;
199 (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
200 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
201 | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
202 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
203 | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
204 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
210 /* Output extended relocation information to a file in target byte order. */
213 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
216 register struct reloc_ext_external *natptr;
221 unsigned int r_addend;
222 asymbol *sym = *(g->sym_ptr_ptr);
223 asection *output_section = sym->section->output_section;
225 PUT_WORD (abfd, g->address, natptr->r_address);
227 r_type = (unsigned int) g->howto->type;
229 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
232 /* If this relocation is relative to a symbol then set the
233 r_index to the symbols index, and the r_extern bit.
235 Absolute symbols can come in in two ways, either as an offset
236 from the abs section, or as a symbol which has an abs value.
240 if (bfd_is_com_section (output_section)
241 || bfd_is_abs_section (output_section)
242 || bfd_is_und_section (output_section))
244 if (bfd_abs_section_ptr->symbol == sym)
246 /* Whoops, looked like an abs symbol, but is really an offset
247 from the abs section */
254 r_index = (*g->sym_ptr_ptr)->KEEPIT;
259 /* Just an ordinary section */
261 r_index = output_section->target_index;
265 /* now the fun stuff */
266 if (bfd_header_big_endian (abfd))
268 natptr->r_index[0] = r_index >> 16;
269 natptr->r_index[1] = r_index >> 8;
270 natptr->r_index[2] = r_index;
272 (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
273 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
277 natptr->r_index[2] = r_index >> 16;
278 natptr->r_index[1] = r_index >> 8;
279 natptr->r_index[0] = r_index;
281 (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
282 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
285 PUT_WORD (abfd, r_addend, natptr->r_addend);
288 /* BFD deals internally with all things based from the section they're
289 in. so, something in 10 bytes into a text section with a base of
290 50 would have a symbol (.text+10) and know .text vma was 50.
292 Aout keeps all it's symbols based from zero, so the symbol would
293 contain 60. This macro subs the base of each section from the value
294 to give the true offset from the section */
297 #define MOVE_ADDRESS(ad) \
299 /* undefined symbol */ \
300 cache_ptr->sym_ptr_ptr = symbols + r_index; \
301 cache_ptr->addend = ad; \
303 /* defined, section relative. replace symbol with pointer to \
304 symbol which points to section */ \
307 case N_TEXT | N_EXT: \
308 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
309 cache_ptr->addend = ad - su->textsec->vma; \
312 case N_DATA | N_EXT: \
313 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
314 cache_ptr->addend = ad - su->datasec->vma; \
317 case N_BSS | N_EXT: \
318 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
319 cache_ptr->addend = ad - su->bsssec->vma; \
323 case N_ABS | N_EXT: \
324 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
325 cache_ptr->addend = ad; \
331 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
333 struct reloc_ext_external *bytes;
336 bfd_size_type symcount ATTRIBUTE_UNUSED;
341 struct aoutdata *su = &(abfd->tdata.aout_data->a);
343 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
345 r_index = bytes->r_index[1];
346 r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
347 r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
348 >> RELOC_EXT_BITS_TYPE_SH_BIG;
350 cache_ptr->howto = aout_32_ext_howto_table + r_type;
351 MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
355 NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
357 struct reloc_std_external *bytes;
360 bfd_size_type symcount ATTRIBUTE_UNUSED;
364 unsigned int r_length;
366 int r_baserel, r_jmptable, r_relative;
367 struct aoutdata *su = &(abfd->tdata.aout_data->a);
369 cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
371 r_index = bytes->r_index[1];
372 r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
373 r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
374 r_baserel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_BASEREL_BIG));
375 r_jmptable = (0 != (bytes->r_index[0] & RELOC_STD_BITS_JMPTABLE_BIG));
376 r_relative = (0 != (bytes->r_index[0] & RELOC_STD_BITS_RELATIVE_BIG));
377 r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
378 >> RELOC_STD_BITS_LENGTH_SH_BIG;
380 cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
381 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
389 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
395 bfd_size_type reloc_size;
397 arelent *reloc_cache;
400 if (asect->relocation)
403 if (asect->flags & SEC_CONSTRUCTOR)
406 if (asect == obj_datasec (abfd))
408 reloc_size = exec_hdr (abfd)->a_drsize;
412 if (asect == obj_textsec (abfd))
414 reloc_size = exec_hdr (abfd)->a_trsize;
418 bfd_set_error (bfd_error_invalid_operation);
422 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
424 each_size = obj_reloc_entry_size (abfd);
426 count = reloc_size / each_size;
429 reloc_cache = (arelent *) bfd_malloc (count * sizeof (arelent));
430 if (!reloc_cache && count != 0)
432 memset (reloc_cache, 0, (size_t) count * sizeof (arelent));
434 relocs = (PTR) bfd_alloc (abfd, reloc_size);
435 if (!relocs && reloc_size != 0)
441 if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
443 bfd_release (abfd, relocs);
448 if (each_size == RELOC_EXT_SIZE)
450 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
451 unsigned int counter = 0;
452 arelent *cache_ptr = reloc_cache;
454 for (; counter < count; counter++, rptr++, cache_ptr++)
456 NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
457 (bfd_size_type) bfd_get_symcount (abfd));
462 register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
463 unsigned int counter = 0;
464 arelent *cache_ptr = reloc_cache;
466 for (; counter < count; counter++, rptr++, cache_ptr++)
468 NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
469 (bfd_size_type) bfd_get_symcount (abfd));
474 bfd_release (abfd, relocs);
475 asect->relocation = reloc_cache;
476 asect->reloc_count = count;
482 /* Write out a relocation section into an object file. */
485 NAME(lynx,squirt_out_relocs) (abfd, section)
490 unsigned char *native, *natptr;
493 unsigned int count = section->reloc_count;
494 bfd_size_type natsize;
499 each_size = obj_reloc_entry_size (abfd);
501 natsize *= each_size;
502 native = (unsigned char *) bfd_zalloc (abfd, natsize);
506 generic = section->orelocation;
508 if (each_size == RELOC_EXT_SIZE)
510 for (natptr = native;
512 --count, natptr += each_size, ++generic)
513 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
517 for (natptr = native;
519 --count, natptr += each_size, ++generic)
520 NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
523 if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
525 bfd_release (abfd, native);
528 bfd_release (abfd, native);
533 /* This is stupid. This function should be a boolean predicate */
535 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
541 arelent *tblptr = section->relocation;
544 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
547 if (section->flags & SEC_CONSTRUCTOR)
549 arelent_chain *chain = section->constructor_chain;
550 for (count = 0; count < section->reloc_count; count++)
552 *relptr++ = &chain->relent;
558 tblptr = section->relocation;
560 for (count = 0; count++ < section->reloc_count;)
562 *relptr++ = tblptr++;
567 return section->reloc_count;
570 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
572 #include "aout-target.h"