* binemul.h (do_ar_emul_append): Declare.
[binutils.git] / bfd / i386lynx.c
blob0a1b854849d4c00305c1d8b80f1056d021645824
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 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
29 the tokens. */
30 #define MY(OP) CONCAT2 (i386lynx_aout_,OP)
31 #define TARGETNAME "a.out-i386-lynx"
33 #include "sysdep.h"
34 #include "bfd.h"
35 #include "libbfd.h"
37 #ifndef WRITE_HEADERS
38 #define WRITE_HEADERS(abfd, execp) \
39 { \
40 bfd_size_type text_size; /* dummy vars */ \
41 file_ptr text_end; \
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 ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
56 abfd) != EXEC_BYTES_SIZE) \
57 return FALSE; \
58 /* Now write out reloc info, followed by syms and strings */ \
60 if (bfd_get_symcount (abfd) != 0) \
61 { \
62 if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) \
63 != 0) \
64 return FALSE; \
66 if (! NAME(aout,write_syms) (abfd)) return FALSE; \
68 if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) \
69 != 0) \
70 return FALSE; \
72 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
73 return FALSE; \
74 if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) \
75 != 0) \
76 return 0; \
78 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd))) \
79 return FALSE; \
80 } \
82 #endif
84 #include "libaout.h"
85 #include "aout/aout64.h"
87 void NAME (lynx,swap_std_reloc_out)
88 PARAMS ((bfd *, arelent *, struct reloc_std_external *));
89 void NAME (lynx,swap_ext_reloc_out)
90 PARAMS ((bfd *, arelent *, struct reloc_ext_external *));
91 void NAME (lynx,swap_ext_reloc_in)
92 PARAMS ((bfd *, struct reloc_ext_external *, arelent *, asymbol **,
93 bfd_size_type));
94 void NAME (lynx,swap_std_reloc_in)
95 PARAMS ((bfd *, struct reloc_std_external *, arelent *, asymbol **,
96 bfd_size_type));
97 bfd_boolean NAME (lynx,slurp_reloc_table)
98 PARAMS ((bfd *, sec_ptr, asymbol **));
99 bfd_boolean NAME (lynx,squirt_out_relocs)
100 PARAMS ((bfd *, asection *));
101 long NAME (lynx,canonicalize_reloc)
102 PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
104 #ifdef LYNX_CORE
106 char *lynx_core_file_failing_command ();
107 int lynx_core_file_failing_signal ();
108 bfd_boolean lynx_core_file_matches_executable_p ();
109 const bfd_target *lynx_core_file_p ();
111 #define MY_core_file_failing_command lynx_core_file_failing_command
112 #define MY_core_file_failing_signal lynx_core_file_failing_signal
113 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
114 #define MY_core_file_p lynx_core_file_p
116 #endif /* LYNX_CORE */
119 #define KEEPIT udata.i
121 extern reloc_howto_type aout_32_ext_howto_table[];
122 extern reloc_howto_type aout_32_std_howto_table[];
124 /* Standard reloc stuff */
125 /* Output standard relocation information to a file in target byte order. */
127 void
128 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
129 bfd *abfd;
130 arelent *g;
131 struct reloc_std_external *natptr;
133 int r_index;
134 asymbol *sym = *(g->sym_ptr_ptr);
135 int r_extern;
136 unsigned int r_length;
137 int r_pcrel;
138 int r_baserel, r_jmptable, r_relative;
139 asection *output_section = sym->section->output_section;
141 PUT_WORD (abfd, g->address, natptr->r_address);
143 r_length = g->howto->size; /* Size as a power of two */
144 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
145 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
146 r_baserel = 0;
147 r_jmptable = 0;
148 r_relative = 0;
150 /* name was clobbered by aout_write_syms to be symbol index */
152 /* If this relocation is relative to a symbol then set the
153 r_index to the symbols index, and the r_extern bit.
155 Absolute symbols can come in in two ways, either as an offset
156 from the abs section, or as a symbol which has an abs value.
157 check for that here
161 if (bfd_is_com_section (output_section)
162 || bfd_is_abs_section (output_section)
163 || bfd_is_und_section (output_section))
165 if (bfd_abs_section_ptr->symbol == sym)
167 /* Whoops, looked like an abs symbol, but is really an offset
168 from the abs section */
169 r_index = 0;
170 r_extern = 0;
172 else
174 /* Fill in symbol */
175 r_extern = 1;
176 r_index = (*g->sym_ptr_ptr)->KEEPIT;
179 else
181 /* Just an ordinary section */
182 r_extern = 0;
183 r_index = output_section->target_index;
186 /* now the fun stuff */
187 if (bfd_header_big_endian (abfd))
189 natptr->r_index[0] = r_index >> 16;
190 natptr->r_index[1] = r_index >> 8;
191 natptr->r_index[2] = r_index;
192 natptr->r_type[0] =
193 (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
194 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
195 | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
196 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
197 | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
198 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
200 else
202 natptr->r_index[2] = r_index >> 16;
203 natptr->r_index[1] = r_index >> 8;
204 natptr->r_index[0] = r_index;
205 natptr->r_type[0] =
206 (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
207 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
208 | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
209 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
210 | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
211 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
216 /* Extended stuff */
217 /* Output extended relocation information to a file in target byte order. */
219 void
220 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
221 bfd *abfd;
222 arelent *g;
223 register struct reloc_ext_external *natptr;
225 int r_index;
226 int r_extern;
227 unsigned int r_type;
228 unsigned int r_addend;
229 asymbol *sym = *(g->sym_ptr_ptr);
230 asection *output_section = sym->section->output_section;
232 PUT_WORD (abfd, g->address, natptr->r_address);
234 r_type = (unsigned int) g->howto->type;
236 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
239 /* If this relocation is relative to a symbol then set the
240 r_index to the symbols index, and the r_extern bit.
242 Absolute symbols can come in in two ways, either as an offset
243 from the abs section, or as a symbol which has an abs value.
244 check for that here
247 if (bfd_is_com_section (output_section)
248 || bfd_is_abs_section (output_section)
249 || bfd_is_und_section (output_section))
251 if (bfd_abs_section_ptr->symbol == sym)
253 /* Whoops, looked like an abs symbol, but is really an offset
254 from the abs section */
255 r_index = 0;
256 r_extern = 0;
258 else
260 r_extern = 1;
261 r_index = (*g->sym_ptr_ptr)->KEEPIT;
264 else
266 /* Just an ordinary section */
267 r_extern = 0;
268 r_index = output_section->target_index;
272 /* now the fun stuff */
273 if (bfd_header_big_endian (abfd))
275 natptr->r_index[0] = r_index >> 16;
276 natptr->r_index[1] = r_index >> 8;
277 natptr->r_index[2] = r_index;
278 natptr->r_type[0] =
279 (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
280 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
282 else
284 natptr->r_index[2] = r_index >> 16;
285 natptr->r_index[1] = r_index >> 8;
286 natptr->r_index[0] = r_index;
287 natptr->r_type[0] =
288 (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
289 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
292 PUT_WORD (abfd, r_addend, natptr->r_addend);
295 /* BFD deals internally with all things based from the section they're
296 in. so, something in 10 bytes into a text section with a base of
297 50 would have a symbol (.text+10) and know .text vma was 50.
299 Aout keeps all it's symbols based from zero, so the symbol would
300 contain 60. This macro subs the base of each section from the value
301 to give the true offset from the section */
304 #define MOVE_ADDRESS(ad) \
305 if (r_extern) { \
306 /* undefined symbol */ \
307 cache_ptr->sym_ptr_ptr = symbols + r_index; \
308 cache_ptr->addend = ad; \
309 } else { \
310 /* defined, section relative. replace symbol with pointer to \
311 symbol which points to section */ \
312 switch (r_index) { \
313 case N_TEXT: \
314 case N_TEXT | N_EXT: \
315 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
316 cache_ptr->addend = ad - su->textsec->vma; \
317 break; \
318 case N_DATA: \
319 case N_DATA | N_EXT: \
320 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
321 cache_ptr->addend = ad - su->datasec->vma; \
322 break; \
323 case N_BSS: \
324 case N_BSS | N_EXT: \
325 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
326 cache_ptr->addend = ad - su->bsssec->vma; \
327 break; \
328 default: \
329 case N_ABS: \
330 case N_ABS | N_EXT: \
331 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
332 cache_ptr->addend = ad; \
333 break; \
337 void
338 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
339 bfd *abfd;
340 struct reloc_ext_external *bytes;
341 arelent *cache_ptr;
342 asymbol **symbols;
343 bfd_size_type symcount ATTRIBUTE_UNUSED;
345 int r_index;
346 int r_extern;
347 unsigned int r_type;
348 struct aoutdata *su = &(abfd->tdata.aout_data->a);
350 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
352 r_index = bytes->r_index[1];
353 r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
354 r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
355 >> RELOC_EXT_BITS_TYPE_SH_BIG;
357 cache_ptr->howto = aout_32_ext_howto_table + r_type;
358 MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
361 void
362 NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
363 bfd *abfd;
364 struct reloc_std_external *bytes;
365 arelent *cache_ptr;
366 asymbol **symbols;
367 bfd_size_type symcount ATTRIBUTE_UNUSED;
369 int r_index;
370 int r_extern;
371 unsigned int r_length;
372 int r_pcrel;
373 struct aoutdata *su = &(abfd->tdata.aout_data->a);
375 cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
377 r_index = bytes->r_index[1];
378 r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
379 r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
380 r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
381 >> RELOC_STD_BITS_LENGTH_SH_BIG;
383 cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
384 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
386 MOVE_ADDRESS (0);
389 /* Reloc hackery */
391 bfd_boolean
392 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
393 bfd *abfd;
394 sec_ptr asect;
395 asymbol **symbols;
397 bfd_size_type count;
398 bfd_size_type reloc_size;
399 PTR relocs;
400 arelent *reloc_cache;
401 size_t each_size;
403 if (asect->relocation)
404 return TRUE;
406 if (asect->flags & SEC_CONSTRUCTOR)
407 return TRUE;
409 if (asect == obj_datasec (abfd))
411 reloc_size = exec_hdr (abfd)->a_drsize;
412 goto doit;
415 if (asect == obj_textsec (abfd))
417 reloc_size = exec_hdr (abfd)->a_trsize;
418 goto doit;
421 bfd_set_error (bfd_error_invalid_operation);
422 return FALSE;
424 doit:
425 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
426 return FALSE;
427 each_size = obj_reloc_entry_size (abfd);
429 count = reloc_size / each_size;
432 reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
433 if (!reloc_cache && count != 0)
434 return FALSE;
436 relocs = (PTR) bfd_alloc (abfd, reloc_size);
437 if (!relocs && reloc_size != 0)
439 free (reloc_cache);
440 return FALSE;
443 if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
445 bfd_release (abfd, relocs);
446 free (reloc_cache);
447 return FALSE;
450 if (each_size == RELOC_EXT_SIZE)
452 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
453 unsigned int counter = 0;
454 arelent *cache_ptr = reloc_cache;
456 for (; counter < count; counter++, rptr++, cache_ptr++)
458 NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
459 (bfd_size_type) bfd_get_symcount (abfd));
462 else
464 register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
465 unsigned int counter = 0;
466 arelent *cache_ptr = reloc_cache;
468 for (; counter < count; counter++, rptr++, cache_ptr++)
470 NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
471 (bfd_size_type) bfd_get_symcount (abfd));
476 bfd_release (abfd, relocs);
477 asect->relocation = reloc_cache;
478 asect->reloc_count = count;
479 return TRUE;
484 /* Write out a relocation section into an object file. */
486 bfd_boolean
487 NAME(lynx,squirt_out_relocs) (abfd, section)
488 bfd *abfd;
489 asection *section;
491 arelent **generic;
492 unsigned char *native, *natptr;
493 size_t each_size;
495 unsigned int count = section->reloc_count;
496 bfd_size_type natsize;
498 if (count == 0)
499 return TRUE;
501 each_size = obj_reloc_entry_size (abfd);
502 natsize = count;
503 natsize *= each_size;
504 native = (unsigned char *) bfd_zalloc (abfd, natsize);
505 if (!native)
506 return FALSE;
508 generic = section->orelocation;
510 if (each_size == RELOC_EXT_SIZE)
512 for (natptr = native;
513 count != 0;
514 --count, natptr += each_size, ++generic)
515 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
517 else
519 for (natptr = native;
520 count != 0;
521 --count, natptr += each_size, ++generic)
522 NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
525 if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
527 bfd_release (abfd, native);
528 return FALSE;
530 bfd_release (abfd, native);
532 return TRUE;
535 /* This is stupid. This function should be a boolean predicate */
536 long
537 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
538 bfd *abfd;
539 sec_ptr section;
540 arelent **relptr;
541 asymbol **symbols;
543 arelent *tblptr = section->relocation;
544 unsigned int count;
546 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
547 return -1;
549 if (section->flags & SEC_CONSTRUCTOR)
551 arelent_chain *chain = section->constructor_chain;
552 for (count = 0; count < section->reloc_count; count++)
554 *relptr++ = &chain->relent;
555 chain = chain->next;
558 else
560 tblptr = section->relocation;
562 for (count = 0; count++ < section->reloc_count;)
564 *relptr++ = tblptr++;
567 *relptr = 0;
569 return section->reloc_count;
572 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
574 #include "aout-target.h"