2004-08-26 Paolo Bonzini <bonzini@gnu.org>
[binutils.git] / bfd / i386lynx.c
blob32274ea6c7f7831332f4e17bd95fd9b20e11a42a
1 /* BFD back-end for i386 a.out binaries under LynxOS.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 2001, 2002, 2003
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 N_SHARED_LIB(x) 0
23 #define TEXT_START_ADDR 0
24 #define TARGET_PAGE_SIZE 4096
25 #define SEGMENT_SIZE TARGET_PAGE_SIZE
26 #define DEFAULT_ARCH bfd_arch_i386
28 /* Do not "beautify" the CONCAT* macro args. Traditional C will not
29 remove whitespace added here, and thus will fail to concatenate
30 the tokens. */
31 #define MY(OP) CONCAT2 (i386lynx_aout_,OP)
32 #define TARGETNAME "a.out-i386-lynx"
34 #include "bfd.h"
35 #include "sysdep.h"
36 #include "libbfd.h"
38 #ifndef WRITE_HEADERS
39 #define WRITE_HEADERS(abfd, execp) \
40 { \
41 bfd_size_type text_size; /* dummy vars */ \
42 file_ptr text_end; \
43 if (adata(abfd).magic == undecided_magic) \
44 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
46 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
47 execp->a_entry = bfd_get_start_address (abfd); \
49 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
50 obj_reloc_entry_size (abfd)); \
51 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
52 obj_reloc_entry_size (abfd)); \
53 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
55 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 \
56 || bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
57 abfd) != EXEC_BYTES_SIZE) \
58 return FALSE; \
59 /* Now write out reloc info, followed by syms and strings */ \
61 if (bfd_get_symcount (abfd) != 0) \
62 { \
63 if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) \
64 != 0) \
65 return FALSE; \
67 if (! NAME(aout,write_syms) (abfd)) return FALSE; \
69 if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) \
70 != 0) \
71 return FALSE; \
73 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
74 return FALSE; \
75 if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) \
76 != 0) \
77 return 0; \
79 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd))) \
80 return FALSE; \
81 } \
83 #endif
85 #include "libaout.h"
86 #include "aout/aout64.h"
88 void NAME (lynx,swap_std_reloc_out)
89 PARAMS ((bfd *, arelent *, struct reloc_std_external *));
90 void NAME (lynx,swap_ext_reloc_out)
91 PARAMS ((bfd *, arelent *, struct reloc_ext_external *));
92 void NAME (lynx,swap_ext_reloc_in)
93 PARAMS ((bfd *, struct reloc_ext_external *, arelent *, asymbol **,
94 bfd_size_type));
95 void NAME (lynx,swap_std_reloc_in)
96 PARAMS ((bfd *, struct reloc_std_external *, arelent *, asymbol **,
97 bfd_size_type));
98 bfd_boolean NAME (lynx,slurp_reloc_table)
99 PARAMS ((bfd *, sec_ptr, asymbol **));
100 bfd_boolean NAME (lynx,squirt_out_relocs)
101 PARAMS ((bfd *, asection *));
102 long NAME (lynx,canonicalize_reloc)
103 PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
105 #ifdef LYNX_CORE
107 char *lynx_core_file_failing_command ();
108 int lynx_core_file_failing_signal ();
109 bfd_boolean lynx_core_file_matches_executable_p ();
110 const bfd_target *lynx_core_file_p ();
112 #define MY_core_file_failing_command lynx_core_file_failing_command
113 #define MY_core_file_failing_signal lynx_core_file_failing_signal
114 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
115 #define MY_core_file_p lynx_core_file_p
117 #endif /* LYNX_CORE */
120 #define KEEPIT udata.i
122 extern reloc_howto_type aout_32_ext_howto_table[];
123 extern reloc_howto_type aout_32_std_howto_table[];
125 /* Standard reloc stuff */
126 /* Output standard relocation information to a file in target byte order. */
128 void
129 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
130 bfd *abfd;
131 arelent *g;
132 struct reloc_std_external *natptr;
134 int r_index;
135 asymbol *sym = *(g->sym_ptr_ptr);
136 int r_extern;
137 unsigned int r_length;
138 int r_pcrel;
139 int r_baserel, r_jmptable, r_relative;
140 unsigned int r_addend;
141 asection *output_section = sym->section->output_section;
143 PUT_WORD (abfd, g->address, natptr->r_address);
145 r_length = g->howto->size; /* Size as a power of two */
146 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
147 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
148 r_baserel = 0;
149 r_jmptable = 0;
150 r_relative = 0;
152 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
154 /* name was clobbered by aout_write_syms to be symbol index */
156 /* If this relocation is relative to a symbol then set the
157 r_index to the symbols index, and the r_extern bit.
159 Absolute symbols can come in in two ways, either as an offset
160 from the abs section, or as a symbol which has an abs value.
161 check for that here
165 if (bfd_is_com_section (output_section)
166 || bfd_is_abs_section (output_section)
167 || bfd_is_und_section (output_section))
169 if (bfd_abs_section_ptr->symbol == sym)
171 /* Whoops, looked like an abs symbol, but is really an offset
172 from the abs section */
173 r_index = 0;
174 r_extern = 0;
176 else
178 /* Fill in symbol */
179 r_extern = 1;
180 r_index = (*g->sym_ptr_ptr)->KEEPIT;
183 else
185 /* Just an ordinary section */
186 r_extern = 0;
187 r_index = output_section->target_index;
190 /* now the fun stuff */
191 if (bfd_header_big_endian (abfd))
193 natptr->r_index[0] = r_index >> 16;
194 natptr->r_index[1] = r_index >> 8;
195 natptr->r_index[2] = r_index;
196 natptr->r_type[0] =
197 (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
198 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
199 | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
200 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
201 | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
202 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
204 else
206 natptr->r_index[2] = r_index >> 16;
207 natptr->r_index[1] = r_index >> 8;
208 natptr->r_index[0] = r_index;
209 natptr->r_type[0] =
210 (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
211 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
212 | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
213 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
214 | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
215 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
220 /* Extended stuff */
221 /* Output extended relocation information to a file in target byte order. */
223 void
224 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
225 bfd *abfd;
226 arelent *g;
227 register struct reloc_ext_external *natptr;
229 int r_index;
230 int r_extern;
231 unsigned int r_type;
232 unsigned int r_addend;
233 asymbol *sym = *(g->sym_ptr_ptr);
234 asection *output_section = sym->section->output_section;
236 PUT_WORD (abfd, g->address, natptr->r_address);
238 r_type = (unsigned int) g->howto->type;
240 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
243 /* If this relocation is relative to a symbol then set the
244 r_index to the symbols index, and the r_extern bit.
246 Absolute symbols can come in in two ways, either as an offset
247 from the abs section, or as a symbol which has an abs value.
248 check for that here
251 if (bfd_is_com_section (output_section)
252 || bfd_is_abs_section (output_section)
253 || bfd_is_und_section (output_section))
255 if (bfd_abs_section_ptr->symbol == sym)
257 /* Whoops, looked like an abs symbol, but is really an offset
258 from the abs section */
259 r_index = 0;
260 r_extern = 0;
262 else
264 r_extern = 1;
265 r_index = (*g->sym_ptr_ptr)->KEEPIT;
268 else
270 /* Just an ordinary section */
271 r_extern = 0;
272 r_index = output_section->target_index;
276 /* now the fun stuff */
277 if (bfd_header_big_endian (abfd))
279 natptr->r_index[0] = r_index >> 16;
280 natptr->r_index[1] = r_index >> 8;
281 natptr->r_index[2] = r_index;
282 natptr->r_type[0] =
283 (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
284 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
286 else
288 natptr->r_index[2] = r_index >> 16;
289 natptr->r_index[1] = r_index >> 8;
290 natptr->r_index[0] = r_index;
291 natptr->r_type[0] =
292 (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
293 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
296 PUT_WORD (abfd, r_addend, natptr->r_addend);
299 /* BFD deals internally with all things based from the section they're
300 in. so, something in 10 bytes into a text section with a base of
301 50 would have a symbol (.text+10) and know .text vma was 50.
303 Aout keeps all it's symbols based from zero, so the symbol would
304 contain 60. This macro subs the base of each section from the value
305 to give the true offset from the section */
308 #define MOVE_ADDRESS(ad) \
309 if (r_extern) { \
310 /* undefined symbol */ \
311 cache_ptr->sym_ptr_ptr = symbols + r_index; \
312 cache_ptr->addend = ad; \
313 } else { \
314 /* defined, section relative. replace symbol with pointer to \
315 symbol which points to section */ \
316 switch (r_index) { \
317 case N_TEXT: \
318 case N_TEXT | N_EXT: \
319 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
320 cache_ptr->addend = ad - su->textsec->vma; \
321 break; \
322 case N_DATA: \
323 case N_DATA | N_EXT: \
324 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
325 cache_ptr->addend = ad - su->datasec->vma; \
326 break; \
327 case N_BSS: \
328 case N_BSS | N_EXT: \
329 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
330 cache_ptr->addend = ad - su->bsssec->vma; \
331 break; \
332 default: \
333 case N_ABS: \
334 case N_ABS | N_EXT: \
335 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
336 cache_ptr->addend = ad; \
337 break; \
341 void
342 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
343 bfd *abfd;
344 struct reloc_ext_external *bytes;
345 arelent *cache_ptr;
346 asymbol **symbols;
347 bfd_size_type symcount ATTRIBUTE_UNUSED;
349 int r_index;
350 int r_extern;
351 unsigned int r_type;
352 struct aoutdata *su = &(abfd->tdata.aout_data->a);
354 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
356 r_index = bytes->r_index[1];
357 r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
358 r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
359 >> RELOC_EXT_BITS_TYPE_SH_BIG;
361 cache_ptr->howto = aout_32_ext_howto_table + r_type;
362 MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
365 void
366 NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
367 bfd *abfd;
368 struct reloc_std_external *bytes;
369 arelent *cache_ptr;
370 asymbol **symbols;
371 bfd_size_type symcount ATTRIBUTE_UNUSED;
373 int r_index;
374 int r_extern;
375 unsigned int r_length;
376 int r_pcrel;
377 int r_baserel, r_jmptable, r_relative;
378 struct aoutdata *su = &(abfd->tdata.aout_data->a);
380 cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
382 r_index = bytes->r_index[1];
383 r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
384 r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
385 r_baserel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_BASEREL_BIG));
386 r_jmptable = (0 != (bytes->r_index[0] & RELOC_STD_BITS_JMPTABLE_BIG));
387 r_relative = (0 != (bytes->r_index[0] & RELOC_STD_BITS_RELATIVE_BIG));
388 r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
389 >> RELOC_STD_BITS_LENGTH_SH_BIG;
391 cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
392 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
394 MOVE_ADDRESS (0);
397 /* Reloc hackery */
399 bfd_boolean
400 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
401 bfd *abfd;
402 sec_ptr asect;
403 asymbol **symbols;
405 bfd_size_type count;
406 bfd_size_type reloc_size;
407 PTR relocs;
408 arelent *reloc_cache;
409 size_t each_size;
411 if (asect->relocation)
412 return TRUE;
414 if (asect->flags & SEC_CONSTRUCTOR)
415 return TRUE;
417 if (asect == obj_datasec (abfd))
419 reloc_size = exec_hdr (abfd)->a_drsize;
420 goto doit;
423 if (asect == obj_textsec (abfd))
425 reloc_size = exec_hdr (abfd)->a_trsize;
426 goto doit;
429 bfd_set_error (bfd_error_invalid_operation);
430 return FALSE;
432 doit:
433 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
434 return FALSE;
435 each_size = obj_reloc_entry_size (abfd);
437 count = reloc_size / each_size;
440 reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
441 if (!reloc_cache && count != 0)
442 return FALSE;
444 relocs = (PTR) bfd_alloc (abfd, reloc_size);
445 if (!relocs && reloc_size != 0)
447 free (reloc_cache);
448 return FALSE;
451 if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
453 bfd_release (abfd, relocs);
454 free (reloc_cache);
455 return FALSE;
458 if (each_size == RELOC_EXT_SIZE)
460 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
461 unsigned int counter = 0;
462 arelent *cache_ptr = reloc_cache;
464 for (; counter < count; counter++, rptr++, cache_ptr++)
466 NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
467 (bfd_size_type) bfd_get_symcount (abfd));
470 else
472 register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
473 unsigned int counter = 0;
474 arelent *cache_ptr = reloc_cache;
476 for (; counter < count; counter++, rptr++, cache_ptr++)
478 NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
479 (bfd_size_type) bfd_get_symcount (abfd));
484 bfd_release (abfd, relocs);
485 asect->relocation = reloc_cache;
486 asect->reloc_count = count;
487 return TRUE;
492 /* Write out a relocation section into an object file. */
494 bfd_boolean
495 NAME(lynx,squirt_out_relocs) (abfd, section)
496 bfd *abfd;
497 asection *section;
499 arelent **generic;
500 unsigned char *native, *natptr;
501 size_t each_size;
503 unsigned int count = section->reloc_count;
504 bfd_size_type natsize;
506 if (count == 0)
507 return TRUE;
509 each_size = obj_reloc_entry_size (abfd);
510 natsize = count;
511 natsize *= each_size;
512 native = (unsigned char *) bfd_zalloc (abfd, natsize);
513 if (!native)
514 return FALSE;
516 generic = section->orelocation;
518 if (each_size == RELOC_EXT_SIZE)
520 for (natptr = native;
521 count != 0;
522 --count, natptr += each_size, ++generic)
523 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
525 else
527 for (natptr = native;
528 count != 0;
529 --count, natptr += each_size, ++generic)
530 NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
533 if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
535 bfd_release (abfd, native);
536 return FALSE;
538 bfd_release (abfd, native);
540 return TRUE;
543 /* This is stupid. This function should be a boolean predicate */
544 long
545 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
546 bfd *abfd;
547 sec_ptr section;
548 arelent **relptr;
549 asymbol **symbols;
551 arelent *tblptr = section->relocation;
552 unsigned int count;
554 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
555 return -1;
557 if (section->flags & SEC_CONSTRUCTOR)
559 arelent_chain *chain = section->constructor_chain;
560 for (count = 0; count < section->reloc_count; count++)
562 *relptr++ = &chain->relent;
563 chain = chain->next;
566 else
568 tblptr = section->relocation;
570 for (count = 0; count++ < section->reloc_count;)
572 *relptr++ = tblptr++;
575 *relptr = 0;
577 return section->reloc_count;
580 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
582 #include "aout-target.h"