1 |
/* BFD back-end for linux flavored i386 a.out binaries. |
/* BFD back-end for linux flavored i386 a.out binaries. |
2 |
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 2001, 2002 |
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2001, 2002, 2003, |
3 |
Free Software Foundation, Inc. |
2004 Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
6 |
|
|
23 |
#define SEGMENT_SIZE TARGET_PAGE_SIZE |
#define SEGMENT_SIZE TARGET_PAGE_SIZE |
24 |
#define TEXT_START_ADDR 0x0 |
#define TEXT_START_ADDR 0x0 |
25 |
#define N_SHARED_LIB(x) 0 |
#define N_SHARED_LIB(x) 0 |
|
#define BYTES_IN_WORD 4 |
|
26 |
|
|
27 |
#define MACHTYPE_OK(mtype) ((mtype) == M_386 || (mtype) == M_UNKNOWN) |
#define MACHTYPE_OK(mtype) ((mtype) == M_386 || (mtype) == M_UNKNOWN) |
28 |
|
|
50 |
|
|
51 |
static void MY_final_link_callback |
static void MY_final_link_callback |
52 |
PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); |
PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); |
53 |
static boolean i386linux_bfd_final_link |
static bfd_boolean i386linux_bfd_final_link |
54 |
PARAMS ((bfd *, struct bfd_link_info *)); |
PARAMS ((bfd *, struct bfd_link_info *)); |
55 |
static boolean i386linux_write_object_contents PARAMS ((bfd *)); |
static bfd_boolean i386linux_write_object_contents PARAMS ((bfd *)); |
56 |
|
|
57 |
static boolean |
static bfd_boolean |
58 |
i386linux_bfd_final_link (abfd, info) |
i386linux_bfd_final_link (abfd, info) |
59 |
bfd *abfd; |
bfd *abfd; |
60 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
67 |
|
|
68 |
/* Set the machine type correctly. */ |
/* Set the machine type correctly. */ |
69 |
|
|
70 |
static boolean |
static bfd_boolean |
71 |
i386linux_write_object_contents (abfd) |
i386linux_write_object_contents (abfd) |
72 |
bfd *abfd; |
bfd *abfd; |
73 |
{ |
{ |
80 |
|
|
81 |
WRITE_HEADERS(abfd, execp); |
WRITE_HEADERS(abfd, execp); |
82 |
|
|
83 |
return true; |
return TRUE; |
84 |
} |
} |
85 |
|
|
86 |
#define MY_write_object_contents i386linux_write_object_contents |
#define MY_write_object_contents i386linux_write_object_contents |
112 |
#endif |
#endif |
113 |
|
|
114 |
/* This special symbol is a set vector that contains a list of |
/* This special symbol is a set vector that contains a list of |
115 |
pointers to fixup tables. It will be present in any dynamicly |
pointers to fixup tables. It will be present in any dynamically |
116 |
linked file. The linker generated fixup table should also be added |
linked file. The linker generated fixup table should also be added |
117 |
to the list, and it should always appear in the second slot (the |
to the list, and it should always appear in the second slot (the |
118 |
first one is a dummy with a magic number that is defined in |
first one is a dummy with a magic number that is defined in |
178 |
static struct fixup *new_fixup |
static struct fixup *new_fixup |
179 |
PARAMS ((struct bfd_link_info *, struct linux_link_hash_entry *, |
PARAMS ((struct bfd_link_info *, struct linux_link_hash_entry *, |
180 |
bfd_vma, int)); |
bfd_vma, int)); |
181 |
static boolean linux_link_create_dynamic_sections |
static bfd_boolean linux_link_create_dynamic_sections |
182 |
PARAMS ((bfd *, struct bfd_link_info *)); |
PARAMS ((bfd *, struct bfd_link_info *)); |
183 |
static boolean linux_add_one_symbol |
static bfd_boolean linux_add_one_symbol |
184 |
PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *, |
PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *, |
185 |
bfd_vma, const char *, boolean, boolean, |
bfd_vma, const char *, bfd_boolean, bfd_boolean, |
186 |
struct bfd_link_hash_entry **)); |
struct bfd_link_hash_entry **)); |
187 |
static boolean linux_tally_symbols |
static bfd_boolean linux_tally_symbols |
188 |
PARAMS ((struct linux_link_hash_entry *, PTR)); |
PARAMS ((struct linux_link_hash_entry *, PTR)); |
189 |
static boolean linux_finish_dynamic_link |
static bfd_boolean linux_finish_dynamic_link |
190 |
PARAMS ((bfd *, struct bfd_link_info *)); |
PARAMS ((bfd *, struct bfd_link_info *)); |
191 |
|
|
192 |
/* Routine to create an entry in an Linux link hash table. */ |
/* Routine to create an entry in an Linux link hash table. */ |
258 |
#define linux_link_hash_traverse(table, func, info) \ |
#define linux_link_hash_traverse(table, func, info) \ |
259 |
(aout_link_hash_traverse \ |
(aout_link_hash_traverse \ |
260 |
(&(table)->root, \ |
(&(table)->root, \ |
261 |
(boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \ |
(bfd_boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \ |
262 |
(info))) |
(info))) |
263 |
|
|
264 |
/* Get the Linux link hash table from the info structure. This is |
/* Get the Linux link hash table from the info structure. This is |
298 |
know the size of the section, but that's OK - we just need to |
know the size of the section, but that's OK - we just need to |
299 |
create it for now. */ |
create it for now. */ |
300 |
|
|
301 |
static boolean |
static bfd_boolean |
302 |
linux_link_create_dynamic_sections (abfd, info) |
linux_link_create_dynamic_sections (abfd, info) |
303 |
bfd *abfd; |
bfd *abfd; |
304 |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
315 |
if (s == NULL |
if (s == NULL |
316 |
|| ! bfd_set_section_flags (abfd, s, flags) |
|| ! bfd_set_section_flags (abfd, s, flags) |
317 |
|| ! bfd_set_section_alignment (abfd, s, 2)) |
|| ! bfd_set_section_alignment (abfd, s, 2)) |
318 |
return false; |
return FALSE; |
319 |
s->_raw_size = 0; |
s->size = 0; |
320 |
s->contents = 0; |
s->contents = 0; |
321 |
|
|
322 |
return true; |
return TRUE; |
323 |
} |
} |
324 |
|
|
325 |
/* Function to add a single symbol to the linker hash table. This is |
/* Function to add a single symbol to the linker hash table. This is |
326 |
a wrapper around _bfd_generic_link_add_one_symbol which handles the |
a wrapper around _bfd_generic_link_add_one_symbol which handles the |
327 |
tweaking needed for dynamic linking support. */ |
tweaking needed for dynamic linking support. */ |
328 |
|
|
329 |
static boolean |
static bfd_boolean |
330 |
linux_add_one_symbol (info, abfd, name, flags, section, value, string, |
linux_add_one_symbol (info, abfd, name, flags, section, value, string, |
331 |
copy, collect, hashp) |
copy, collect, hashp) |
332 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
336 |
asection *section; |
asection *section; |
337 |
bfd_vma value; |
bfd_vma value; |
338 |
const char *string; |
const char *string; |
339 |
boolean copy; |
bfd_boolean copy; |
340 |
boolean collect; |
bfd_boolean collect; |
341 |
struct bfd_link_hash_entry **hashp; |
struct bfd_link_hash_entry **hashp; |
342 |
{ |
{ |
343 |
struct linux_link_hash_entry *h; |
struct linux_link_hash_entry *h; |
344 |
boolean insert; |
bfd_boolean insert; |
345 |
|
|
346 |
/* Look up and see if we already have this symbol in the hash table. |
/* Look up and see if we already have this symbol in the hash table. |
347 |
If we do, and the defining entry is from a shared library, we |
If we do, and the defining entry is from a shared library, we |
351 |
be able to link Linux a.out and ELF objects together, but serious |
be able to link Linux a.out and ELF objects together, but serious |
352 |
confusion is possible. */ |
confusion is possible. */ |
353 |
|
|
354 |
insert = false; |
insert = FALSE; |
355 |
|
|
356 |
if (! info->relocateable |
if (! info->relocatable |
357 |
&& linux_hash_table (info)->dynobj == NULL |
&& linux_hash_table (info)->dynobj == NULL |
358 |
&& strcmp (name, SHARABLE_CONFLICTS) == 0 |
&& strcmp (name, SHARABLE_CONFLICTS) == 0 |
359 |
&& (flags & BSF_CONSTRUCTOR) != 0 |
&& (flags & BSF_CONSTRUCTOR) != 0 |
360 |
&& abfd->xvec == info->hash->creator) |
&& abfd->xvec == info->hash->creator) |
361 |
{ |
{ |
362 |
if (! linux_link_create_dynamic_sections (abfd, info)) |
if (! linux_link_create_dynamic_sections (abfd, info)) |
363 |
return false; |
return FALSE; |
364 |
linux_hash_table (info)->dynobj = abfd; |
linux_hash_table (info)->dynobj = abfd; |
365 |
insert = true; |
insert = TRUE; |
366 |
} |
} |
367 |
|
|
368 |
if (bfd_is_abs_section (section) |
if (bfd_is_abs_section (section) |
369 |
&& abfd->xvec == info->hash->creator) |
&& abfd->xvec == info->hash->creator) |
370 |
{ |
{ |
371 |
h = linux_link_hash_lookup (linux_hash_table (info), name, false, |
h = linux_link_hash_lookup (linux_hash_table (info), name, FALSE, |
372 |
false, false); |
FALSE, FALSE); |
373 |
if (h != NULL |
if (h != NULL |
374 |
&& (h->root.root.type == bfd_link_hash_defined |
&& (h->root.root.type == bfd_link_hash_defined |
375 |
|| h->root.root.type == bfd_link_hash_defweak)) |
|| h->root.root.type == bfd_link_hash_defweak)) |
381 |
|
|
382 |
f = new_fixup (info, h, value, ! IS_PLT_SYM (name)); |
f = new_fixup (info, h, value, ! IS_PLT_SYM (name)); |
383 |
if (f == NULL) |
if (f == NULL) |
384 |
return false; |
return FALSE; |
385 |
f->jump = IS_PLT_SYM (name); |
f->jump = IS_PLT_SYM (name); |
386 |
|
|
387 |
return true; |
return TRUE; |
388 |
} |
} |
389 |
} |
} |
390 |
|
|
392 |
if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, |
if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, |
393 |
value, string, copy, collect, |
value, string, copy, collect, |
394 |
hashp)) |
hashp)) |
395 |
return false; |
return FALSE; |
396 |
|
|
397 |
/* Insert a pointer to our table in the set vector. The dynamic |
/* Insert a pointer to our table in the set vector. The dynamic |
398 |
linker requires this information */ |
linker requires this information */ |
409 |
if (! (_bfd_generic_link_add_one_symbol |
if (! (_bfd_generic_link_add_one_symbol |
410 |
(info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS, |
(info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS, |
411 |
BSF_GLOBAL | BSF_CONSTRUCTOR, s, (bfd_vma) 0, NULL, |
BSF_GLOBAL | BSF_CONSTRUCTOR, s, (bfd_vma) 0, NULL, |
412 |
false, false, NULL))) |
FALSE, FALSE, NULL))) |
413 |
return false; |
return FALSE; |
414 |
} |
} |
415 |
|
|
416 |
return true; |
return TRUE; |
417 |
} |
} |
418 |
|
|
419 |
/* We will crawl the hash table and come here for every global symbol. |
/* We will crawl the hash table and come here for every global symbol. |
426 |
|
|
427 |
This function is called via linux_link_hash_traverse. */ |
This function is called via linux_link_hash_traverse. */ |
428 |
|
|
429 |
static boolean |
static bfd_boolean |
430 |
linux_tally_symbols (h, data) |
linux_tally_symbols (h, data) |
431 |
struct linux_link_hash_entry *h; |
struct linux_link_hash_entry *h; |
432 |
PTR data; |
PTR data; |
435 |
struct fixup *f, *f1; |
struct fixup *f, *f1; |
436 |
int is_plt; |
int is_plt; |
437 |
struct linux_link_hash_entry *h1, *h2; |
struct linux_link_hash_entry *h1, *h2; |
438 |
boolean exists; |
bfd_boolean exists; |
439 |
|
|
440 |
if (h->root.root.type == bfd_link_hash_warning) |
if (h->root.root.type == bfd_link_hash_warning) |
441 |
h = (struct linux_link_hash_entry *) h->root.root.u.i.link; |
h = (struct linux_link_hash_entry *) h->root.root.u.i.link; |
481 |
h1 = linux_link_hash_lookup (linux_hash_table (info), |
h1 = linux_link_hash_lookup (linux_hash_table (info), |
482 |
(h->root.root.root.string |
(h->root.root.root.string |
483 |
+ sizeof PLT_REF_PREFIX - 1), |
+ sizeof PLT_REF_PREFIX - 1), |
484 |
false, false, true); |
FALSE, FALSE, TRUE); |
485 |
/* h2 does not follow indirect symbols. */ |
/* h2 does not follow indirect symbols. */ |
486 |
h2 = linux_link_hash_lookup (linux_hash_table (info), |
h2 = linux_link_hash_lookup (linux_hash_table (info), |
487 |
(h->root.root.root.string |
(h->root.root.root.string |
488 |
+ sizeof PLT_REF_PREFIX - 1), |
+ sizeof PLT_REF_PREFIX - 1), |
489 |
false, false, false); |
FALSE, FALSE, FALSE); |
490 |
|
|
491 |
/* The real symbol must exist but if it is also an ABS symbol, |
/* The real symbol must exist but if it is also an ABS symbol, |
492 |
there is no need to have a fixup. This is because they both |
there is no need to have a fixup. This is because they both |
504 |
involving this symbol. If so, convert it to a regular |
involving this symbol. If so, convert it to a regular |
505 |
fixup. In the end, this relaxes some of the requirements |
fixup. In the end, this relaxes some of the requirements |
506 |
about the order of performing fixups. */ |
about the order of performing fixups. */ |
507 |
exists = false; |
exists = FALSE; |
508 |
for (f1 = linux_hash_table (info)->fixup_list; |
for (f1 = linux_hash_table (info)->fixup_list; |
509 |
f1 != NULL; |
f1 != NULL; |
510 |
f1 = f1->next) |
f1 = f1->next) |
513 |
|| (! f1->builtin && ! f1->jump)) |
|| (! f1->builtin && ! f1->jump)) |
514 |
continue; |
continue; |
515 |
if (f1->h == h1) |
if (f1->h == h1) |
516 |
exists = true; |
exists = TRUE; |
517 |
if (! exists |
if (! exists |
518 |
&& bfd_is_abs_section (h->root.root.u.def.section)) |
&& bfd_is_abs_section (h->root.root.u.def.section)) |
519 |
{ |
{ |
523 |
f1->h = h1; |
f1->h = h1; |
524 |
f1->jump = is_plt; |
f1->jump = is_plt; |
525 |
f1->builtin = 0; |
f1->builtin = 0; |
526 |
exists = true; |
exists = TRUE; |
527 |
} |
} |
528 |
if (! exists |
if (! exists |
529 |
&& bfd_is_abs_section (h->root.root.u.def.section)) |
&& bfd_is_abs_section (h->root.root.u.def.section)) |
541 |
/* Quick and dirty way of stripping these symbols from the |
/* Quick and dirty way of stripping these symbols from the |
542 |
symtab. */ |
symtab. */ |
543 |
if (bfd_is_abs_section (h->root.root.u.def.section)) |
if (bfd_is_abs_section (h->root.root.u.def.section)) |
544 |
h->root.written = true; |
h->root.written = TRUE; |
545 |
} |
} |
546 |
|
|
547 |
return true; |
return TRUE; |
548 |
} |
} |
549 |
|
|
550 |
/* This is called to set the size of the .linux-dynamic section is. |
/* This is called to set the size of the .linux-dynamic section is. |
553 |
we just scan the hash tables to find out how many additional fixups |
we just scan the hash tables to find out how many additional fixups |
554 |
are required. */ |
are required. */ |
555 |
|
|
556 |
boolean |
bfd_boolean |
557 |
bfd_i386linux_size_dynamic_sections (output_bfd, info) |
bfd_i386linux_size_dynamic_sections (output_bfd, info) |
558 |
bfd *output_bfd; |
bfd *output_bfd; |
559 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
562 |
asection *s; |
asection *s; |
563 |
|
|
564 |
if (output_bfd->xvec != &MY(vec)) |
if (output_bfd->xvec != &MY(vec)) |
565 |
return true; |
return TRUE; |
566 |
|
|
567 |
/* First find the fixups... */ |
/* First find the fixups... */ |
568 |
linux_link_hash_traverse (linux_hash_table (info), |
linux_link_hash_traverse (linux_hash_table (info), |
586 |
{ |
{ |
587 |
if (linux_hash_table (info)->fixup_count > 0) |
if (linux_hash_table (info)->fixup_count > 0) |
588 |
abort (); |
abort (); |
589 |
return true; |
return TRUE; |
590 |
} |
} |
591 |
|
|
592 |
/* Allocate memory for our fixup table. We will fill it in later. */ |
/* Allocate memory for our fixup table. We will fill it in later. */ |
594 |
".linux-dynamic"); |
".linux-dynamic"); |
595 |
if (s != NULL) |
if (s != NULL) |
596 |
{ |
{ |
597 |
s->_raw_size = linux_hash_table (info)->fixup_count + 1; |
s->size = linux_hash_table (info)->fixup_count + 1; |
598 |
s->_raw_size *= 8; |
s->size *= 8; |
599 |
s->contents = (bfd_byte *) bfd_zalloc (output_bfd, s->_raw_size); |
s->contents = (bfd_byte *) bfd_zalloc (output_bfd, s->size); |
600 |
if (s->contents == NULL) |
if (s->contents == NULL) |
601 |
return false; |
return FALSE; |
602 |
} |
} |
603 |
|
|
604 |
return true; |
return TRUE; |
605 |
} |
} |
606 |
|
|
607 |
/* We come here once we are ready to actually write the fixup table to |
/* We come here once we are ready to actually write the fixup table to |
608 |
the output file. Scan the fixup tables and so forth and generate |
the output file. Scan the fixup tables and so forth and generate |
609 |
the stuff we need. */ |
the stuff we need. */ |
610 |
|
|
611 |
static boolean |
static bfd_boolean |
612 |
linux_finish_dynamic_link (output_bfd, info) |
linux_finish_dynamic_link (output_bfd, info) |
613 |
bfd *output_bfd; |
bfd *output_bfd; |
614 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
622 |
unsigned int fixups_written; |
unsigned int fixups_written; |
623 |
|
|
624 |
if (linux_hash_table (info)->dynobj == NULL) |
if (linux_hash_table (info)->dynobj == NULL) |
625 |
return true; |
return TRUE; |
626 |
|
|
627 |
s = bfd_get_section_by_name (linux_hash_table (info)->dynobj, |
s = bfd_get_section_by_name (linux_hash_table (info)->dynobj, |
628 |
".linux-dynamic"); |
".linux-dynamic"); |
738 |
|
|
739 |
h = linux_link_hash_lookup (linux_hash_table (info), |
h = linux_link_hash_lookup (linux_hash_table (info), |
740 |
"__BUILTIN_FIXUPS__", |
"__BUILTIN_FIXUPS__", |
741 |
false, false, false); |
FALSE, FALSE, FALSE); |
742 |
|
|
743 |
if (h != NULL |
if (h != NULL |
744 |
&& (h->root.root.type == bfd_link_hash_defined |
&& (h->root.root.type == bfd_link_hash_defined |
759 |
|
|
760 |
if (bfd_seek (output_bfd, (file_ptr) (os->filepos + s->output_offset), |
if (bfd_seek (output_bfd, (file_ptr) (os->filepos + s->output_offset), |
761 |
SEEK_SET) != 0) |
SEEK_SET) != 0) |
762 |
return false; |
return FALSE; |
763 |
|
|
764 |
if (bfd_bwrite ((PTR) s->contents, s->_raw_size, output_bfd) != s->_raw_size) |
if (bfd_bwrite ((PTR) s->contents, s->size, output_bfd) != s->size) |
765 |
return false; |
return FALSE; |
766 |
|
|
767 |
return true; |
return TRUE; |
768 |
} |
} |
769 |
|
|
770 |
#define MY_bfd_link_hash_table_create linux_link_hash_table_create |
#define MY_bfd_link_hash_table_create linux_link_hash_table_create |