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