update copyright dates
[deliverable/binutils-gdb.git] / bfd / i386lynx.c
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 Free Software Foundation, Inc.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
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.
11
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.
16
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. */
20
21 #define N_SHARED_LIB(x) 0
22
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
27
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"
33
34 #include "bfd.h"
35 #include "sysdep.h"
36 #include "libbfd.h"
37
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); \
45 \
46 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
47 execp->a_entry = bfd_get_start_address (abfd); \
48 \
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); \
54 \
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 */ \
60 \
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; \
66 \
67 if (! NAME(aout,write_syms) (abfd)) return FALSE; \
68 \
69 if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) \
70 != 0) \
71 return FALSE; \
72 \
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; \
78 \
79 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd))) \
80 return FALSE; \
81 } \
82 }
83 #endif
84
85 #include "libaout.h"
86 #include "aout/aout64.h"
87
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 **));
104
105 #ifdef LYNX_CORE
106
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 ();
111
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
116
117 #endif /* LYNX_CORE */
118 \f
119
120 #define KEEPIT udata.i
121
122 extern reloc_howto_type aout_32_ext_howto_table[];
123 extern reloc_howto_type aout_32_std_howto_table[];
124
125 /* Standard reloc stuff */
126 /* Output standard relocation information to a file in target byte order. */
127
128 void
129 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
130 bfd *abfd;
131 arelent *g;
132 struct reloc_std_external *natptr;
133 {
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;
142
143 PUT_WORD (abfd, g->address, natptr->r_address);
144
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;
151
152 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
153
154 /* name was clobbered by aout_write_syms to be symbol index */
155
156 /* If this relocation is relative to a symbol then set the
157 r_index to the symbols index, and the r_extern bit.
158
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
162 */
163
164
165 if (bfd_is_com_section (output_section)
166 || bfd_is_abs_section (output_section)
167 || bfd_is_und_section (output_section))
168 {
169 if (bfd_abs_section_ptr->symbol == sym)
170 {
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;
175 }
176 else
177 {
178 /* Fill in symbol */
179 r_extern = 1;
180 r_index = (*g->sym_ptr_ptr)->KEEPIT;
181 }
182 }
183 else
184 {
185 /* Just an ordinary section */
186 r_extern = 0;
187 r_index = output_section->target_index;
188 }
189
190 /* now the fun stuff */
191 if (bfd_header_big_endian (abfd))
192 {
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);
203 }
204 else
205 {
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);
216 }
217 }
218
219
220 /* Extended stuff */
221 /* Output extended relocation information to a file in target byte order. */
222
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;
228 {
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;
235
236 PUT_WORD (abfd, g->address, natptr->r_address);
237
238 r_type = (unsigned int) g->howto->type;
239
240 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
241
242
243 /* If this relocation is relative to a symbol then set the
244 r_index to the symbols index, and the r_extern bit.
245
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
249 */
250
251 if (bfd_is_com_section (output_section)
252 || bfd_is_abs_section (output_section)
253 || bfd_is_und_section (output_section))
254 {
255 if (bfd_abs_section_ptr->symbol == sym)
256 {
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;
261 }
262 else
263 {
264 r_extern = 1;
265 r_index = (*g->sym_ptr_ptr)->KEEPIT;
266 }
267 }
268 else
269 {
270 /* Just an ordinary section */
271 r_extern = 0;
272 r_index = output_section->target_index;
273 }
274
275
276 /* now the fun stuff */
277 if (bfd_header_big_endian (abfd))
278 {
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);
285 }
286 else
287 {
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);
294 }
295
296 PUT_WORD (abfd, r_addend, natptr->r_addend);
297 }
298
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.
302
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 */
306
307
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; \
338 } \
339 } \
340
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;
348 {
349 int r_index;
350 int r_extern;
351 unsigned int r_type;
352 struct aoutdata *su = &(abfd->tdata.aout_data->a);
353
354 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
355
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;
360
361 cache_ptr->howto = aout_32_ext_howto_table + r_type;
362 MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
363 }
364
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;
372 {
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);
379
380 cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
381
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;
390
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 */
393
394 MOVE_ADDRESS (0);
395 }
396
397 /* Reloc hackery */
398
399 bfd_boolean
400 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
401 bfd *abfd;
402 sec_ptr asect;
403 asymbol **symbols;
404 {
405 bfd_size_type count;
406 bfd_size_type reloc_size;
407 PTR relocs;
408 arelent *reloc_cache;
409 size_t each_size;
410
411 if (asect->relocation)
412 return TRUE;
413
414 if (asect->flags & SEC_CONSTRUCTOR)
415 return TRUE;
416
417 if (asect == obj_datasec (abfd))
418 {
419 reloc_size = exec_hdr (abfd)->a_drsize;
420 goto doit;
421 }
422
423 if (asect == obj_textsec (abfd))
424 {
425 reloc_size = exec_hdr (abfd)->a_trsize;
426 goto doit;
427 }
428
429 bfd_set_error (bfd_error_invalid_operation);
430 return FALSE;
431
432 doit:
433 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
434 return FALSE;
435 each_size = obj_reloc_entry_size (abfd);
436
437 count = reloc_size / each_size;
438
439
440 reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
441 if (!reloc_cache && count != 0)
442 return FALSE;
443
444 relocs = (PTR) bfd_alloc (abfd, reloc_size);
445 if (!relocs && reloc_size != 0)
446 {
447 free (reloc_cache);
448 return FALSE;
449 }
450
451 if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
452 {
453 bfd_release (abfd, relocs);
454 free (reloc_cache);
455 return FALSE;
456 }
457
458 if (each_size == RELOC_EXT_SIZE)
459 {
460 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
461 unsigned int counter = 0;
462 arelent *cache_ptr = reloc_cache;
463
464 for (; counter < count; counter++, rptr++, cache_ptr++)
465 {
466 NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
467 (bfd_size_type) bfd_get_symcount (abfd));
468 }
469 }
470 else
471 {
472 register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
473 unsigned int counter = 0;
474 arelent *cache_ptr = reloc_cache;
475
476 for (; counter < count; counter++, rptr++, cache_ptr++)
477 {
478 NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
479 (bfd_size_type) bfd_get_symcount (abfd));
480 }
481
482 }
483
484 bfd_release (abfd, relocs);
485 asect->relocation = reloc_cache;
486 asect->reloc_count = count;
487 return TRUE;
488 }
489
490
491
492 /* Write out a relocation section into an object file. */
493
494 bfd_boolean
495 NAME(lynx,squirt_out_relocs) (abfd, section)
496 bfd *abfd;
497 asection *section;
498 {
499 arelent **generic;
500 unsigned char *native, *natptr;
501 size_t each_size;
502
503 unsigned int count = section->reloc_count;
504 bfd_size_type natsize;
505
506 if (count == 0)
507 return TRUE;
508
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;
515
516 generic = section->orelocation;
517
518 if (each_size == RELOC_EXT_SIZE)
519 {
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);
524 }
525 else
526 {
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);
531 }
532
533 if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
534 {
535 bfd_release (abfd, native);
536 return FALSE;
537 }
538 bfd_release (abfd, native);
539
540 return TRUE;
541 }
542
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;
550 {
551 arelent *tblptr = section->relocation;
552 unsigned int count;
553
554 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
555 return -1;
556
557 if (section->flags & SEC_CONSTRUCTOR)
558 {
559 arelent_chain *chain = section->constructor_chain;
560 for (count = 0; count < section->reloc_count; count++)
561 {
562 *relptr++ = &chain->relent;
563 chain = chain->next;
564 }
565 }
566 else
567 {
568 tblptr = section->relocation;
569
570 for (count = 0; count++ < section->reloc_count;)
571 {
572 *relptr++ = tblptr++;
573 }
574 }
575 *relptr = 0;
576
577 return section->reloc_count;
578 }
579
580 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
581
582 #include "aout-target.h"
This page took 0.042415 seconds and 5 git commands to generate.