2009-07-02 Tristan Gingold <gingold@adacore.com>
[binutils.git] / bfd / i386lynx.c
blobf8b8e02610ad6414d284594afb91389b50b7b477
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
31 the tokens. */
32 #define MY(OP) CONCAT2 (i386lynx_aout_,OP)
33 #define TARGETNAME "a.out-i386-lynx"
35 #include "sysdep.h"
36 #include "bfd.h"
37 #include "libbfd.h"
39 #ifndef WRITE_HEADERS
40 #define WRITE_HEADERS(abfd, execp) \
41 { \
42 bfd_size_type text_size; /* dummy vars */ \
43 file_ptr text_end; \
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) \
59 return FALSE; \
60 /* Now write out reloc info, followed by syms and strings */ \
62 if (bfd_get_symcount (abfd) != 0) \
63 { \
64 if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) \
65 != 0) \
66 return FALSE; \
68 if (! NAME(aout,write_syms) (abfd)) return FALSE; \
70 if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) \
71 != 0) \
72 return FALSE; \
74 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
75 return FALSE; \
76 if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) \
77 != 0) \
78 return 0; \
80 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd))) \
81 return FALSE; \
82 } \
84 #endif
86 #include "libaout.h"
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 **,
95 bfd_size_type));
96 void NAME (lynx,swap_std_reloc_in)
97 PARAMS ((bfd *, struct reloc_std_external *, arelent *, asymbol **,
98 bfd_size_type));
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 **));
106 #ifdef LYNX_CORE
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. */
129 void
130 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
131 bfd *abfd;
132 arelent *g;
133 struct reloc_std_external *natptr;
135 int r_index;
136 asymbol *sym = *(g->sym_ptr_ptr);
137 int r_extern;
138 unsigned int r_length;
139 int r_pcrel;
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 */
149 r_baserel = 0;
150 r_jmptable = 0;
151 r_relative = 0;
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.
162 check for that here
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 */
174 r_index = 0;
175 r_extern = 0;
177 else
179 /* Fill in symbol */
180 r_extern = 1;
181 r_index = (*g->sym_ptr_ptr)->KEEPIT;
184 else
186 /* Just an ordinary section */
187 r_extern = 0;
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;
197 natptr->r_type[0] =
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);
205 else
207 natptr->r_index[2] = r_index >> 16;
208 natptr->r_index[1] = r_index >> 8;
209 natptr->r_index[0] = r_index;
210 natptr->r_type[0] =
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);
221 /* Extended stuff */
222 /* Output extended relocation information to a file in target byte order. */
224 void
225 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
226 bfd *abfd;
227 arelent *g;
228 register struct reloc_ext_external *natptr;
230 int r_index;
231 int r_extern;
232 unsigned int r_type;
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.
249 check for that here
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 */
260 r_index = 0;
261 r_extern = 0;
263 else
265 r_extern = 1;
266 r_index = (*g->sym_ptr_ptr)->KEEPIT;
269 else
271 /* Just an ordinary section */
272 r_extern = 0;
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;
283 natptr->r_type[0] =
284 (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
285 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
287 else
289 natptr->r_index[2] = r_index >> 16;
290 natptr->r_index[1] = r_index >> 8;
291 natptr->r_index[0] = r_index;
292 natptr->r_type[0] =
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) \
310 if (r_extern) { \
311 /* undefined symbol */ \
312 cache_ptr->sym_ptr_ptr = symbols + r_index; \
313 cache_ptr->addend = ad; \
314 } else { \
315 /* defined, section relative. replace symbol with pointer to \
316 symbol which points to section */ \
317 switch (r_index) { \
318 case N_TEXT: \
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; \
322 break; \
323 case N_DATA: \
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; \
327 break; \
328 case N_BSS: \
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; \
332 break; \
333 default: \
334 case N_ABS: \
335 case N_ABS | N_EXT: \
336 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
337 cache_ptr->addend = ad; \
338 break; \
342 void
343 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
344 bfd *abfd;
345 struct reloc_ext_external *bytes;
346 arelent *cache_ptr;
347 asymbol **symbols;
348 bfd_size_type symcount ATTRIBUTE_UNUSED;
350 int r_index;
351 int r_extern;
352 unsigned int r_type;
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));
366 void
367 NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
368 bfd *abfd;
369 struct reloc_std_external *bytes;
370 arelent *cache_ptr;
371 asymbol **symbols;
372 bfd_size_type symcount ATTRIBUTE_UNUSED;
374 int r_index;
375 int r_extern;
376 unsigned int r_length;
377 int r_pcrel;
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 */
395 MOVE_ADDRESS (0);
398 /* Reloc hackery */
400 bfd_boolean
401 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
402 bfd *abfd;
403 sec_ptr asect;
404 asymbol **symbols;
406 bfd_size_type count;
407 bfd_size_type reloc_size;
408 PTR relocs;
409 arelent *reloc_cache;
410 size_t each_size;
412 if (asect->relocation)
413 return TRUE;
415 if (asect->flags & SEC_CONSTRUCTOR)
416 return TRUE;
418 if (asect == obj_datasec (abfd))
420 reloc_size = exec_hdr (abfd)->a_drsize;
421 goto doit;
424 if (asect == obj_textsec (abfd))
426 reloc_size = exec_hdr (abfd)->a_trsize;
427 goto doit;
430 bfd_set_error (bfd_error_invalid_operation);
431 return FALSE;
433 doit:
434 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
435 return FALSE;
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)
443 return FALSE;
445 relocs = (PTR) bfd_alloc (abfd, reloc_size);
446 if (!relocs && reloc_size != 0)
448 free (reloc_cache);
449 return FALSE;
452 if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
454 bfd_release (abfd, relocs);
455 free (reloc_cache);
456 return FALSE;
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));
471 else
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;
488 return TRUE;
493 /* Write out a relocation section into an object file. */
495 bfd_boolean
496 NAME(lynx,squirt_out_relocs) (abfd, section)
497 bfd *abfd;
498 asection *section;
500 arelent **generic;
501 unsigned char *native, *natptr;
502 size_t each_size;
504 unsigned int count = section->reloc_count;
505 bfd_size_type natsize;
507 if (count == 0)
508 return TRUE;
510 each_size = obj_reloc_entry_size (abfd);
511 natsize = count;
512 natsize *= each_size;
513 native = (unsigned char *) bfd_zalloc (abfd, natsize);
514 if (!native)
515 return FALSE;
517 generic = section->orelocation;
519 if (each_size == RELOC_EXT_SIZE)
521 for (natptr = native;
522 count != 0;
523 --count, natptr += each_size, ++generic)
524 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
526 else
528 for (natptr = native;
529 count != 0;
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);
537 return FALSE;
539 bfd_release (abfd, native);
541 return TRUE;
544 /* This is stupid. This function should be a boolean predicate */
545 long
546 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
547 bfd *abfd;
548 sec_ptr section;
549 arelent **relptr;
550 asymbol **symbols;
552 arelent *tblptr = section->relocation;
553 unsigned int count;
555 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
556 return -1;
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;
564 chain = chain->next;
567 else
569 tblptr = section->relocation;
571 for (count = 0; count++ < section->reloc_count;)
573 *relptr++ = tblptr++;
576 *relptr = 0;
578 return section->reloc_count;
581 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
583 #include "aout-target.h"