i386linux.c revision 33965
133965Sjdp/* BFD back-end for linux flavored i386 a.out binaries. 233965Sjdp Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. 333965Sjdp 433965SjdpThis file is part of BFD, the Binary File Descriptor library. 533965Sjdp 633965SjdpThis program is free software; you can redistribute it and/or modify 733965Sjdpit under the terms of the GNU General Public License as published by 833965Sjdpthe Free Software Foundation; either version 2 of the License, or 933965Sjdp(at your option) any later version. 1033965Sjdp 1133965SjdpThis program is distributed in the hope that it will be useful, 1233965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1333965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1433965SjdpGNU General Public License for more details. 1533965Sjdp 1633965SjdpYou should have received a copy of the GNU General Public License 1733965Sjdpalong with this program; if not, write to the Free Software 1833965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 1933965Sjdp 2033965Sjdp#define TARGET_PAGE_SIZE 4096 2133965Sjdp#define ZMAGIC_DISK_BLOCK_SIZE 1024 2233965Sjdp#define SEGMENT_SIZE TARGET_PAGE_SIZE 2333965Sjdp#define TEXT_START_ADDR 0x0 2433965Sjdp#define N_SHARED_LIB(x) 0 2533965Sjdp#define BYTES_IN_WORD 4 2633965Sjdp 2733965Sjdp#define MACHTYPE_OK(mtype) ((mtype) == M_386 || (mtype) == M_UNKNOWN) 2833965Sjdp 2933965Sjdp#include "bfd.h" 3033965Sjdp#include "sysdep.h" 3133965Sjdp#include "libbfd.h" 3233965Sjdp#include "aout/aout64.h" 3333965Sjdp#include "aout/stab_gnu.h" 3433965Sjdp#include "aout/ar.h" 3533965Sjdp#include "libaout.h" /* BFD a.out internal data structures */ 3633965Sjdp 3733965Sjdp#define DEFAULT_ARCH bfd_arch_i386 3833965Sjdp#define MY(OP) CAT(i386linux_,OP) 3933965Sjdp#define TARGETNAME "a.out-i386-linux" 4033965Sjdp 4133965Sjdpextern const bfd_target MY(vec); 4233965Sjdp 4333965Sjdp/* We always generate QMAGIC files in preference to ZMAGIC files. It 4433965Sjdp would be possible to make this a linker option, if that ever 4533965Sjdp becomes important. */ 4633965Sjdp 4733965Sjdpstatic void MY_final_link_callback 4833965Sjdp PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); 4933965Sjdpstatic boolean i386linux_bfd_final_link 5033965Sjdp PARAMS ((bfd *, struct bfd_link_info *)); 5133965Sjdpstatic boolean i386linux_write_object_contents PARAMS ((bfd *)); 5233965Sjdp 5333965Sjdpstatic boolean 5433965Sjdpi386linux_bfd_final_link (abfd, info) 5533965Sjdp bfd *abfd; 5633965Sjdp struct bfd_link_info *info; 5733965Sjdp{ 5833965Sjdp obj_aout_subformat (abfd) = q_magic_format; 5933965Sjdp return NAME(aout,final_link) (abfd, info, MY_final_link_callback); 6033965Sjdp} 6133965Sjdp 6233965Sjdp#define MY_bfd_final_link i386linux_bfd_final_link 6333965Sjdp 6433965Sjdp/* Set the machine type correctly. */ 6533965Sjdp 6633965Sjdpstatic boolean 6733965Sjdpi386linux_write_object_contents (abfd) 6833965Sjdp bfd *abfd; 6933965Sjdp{ 7033965Sjdp struct external_exec exec_bytes; 7133965Sjdp struct internal_exec *execp = exec_hdr (abfd); 7233965Sjdp 7333965Sjdp N_SET_MACHTYPE (*execp, M_386); 7433965Sjdp 7533965Sjdp obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; 7633965Sjdp 7733965Sjdp WRITE_HEADERS(abfd, execp); 7833965Sjdp 7933965Sjdp return true; 8033965Sjdp} 8133965Sjdp 8233965Sjdp#define MY_write_object_contents i386linux_write_object_contents 8333965Sjdp 8433965Sjdp/* Code to link against Linux a.out shared libraries. */ 8533965Sjdp 8633965Sjdp/* See if a symbol name is a reference to the global offset table. */ 8733965Sjdp 8833965Sjdp#ifndef GOT_REF_PREFIX 8933965Sjdp#define GOT_REF_PREFIX "__GOT_" 9033965Sjdp#endif 9133965Sjdp 9233965Sjdp#define IS_GOT_SYM(name) \ 9333965Sjdp (strncmp (name, GOT_REF_PREFIX, sizeof GOT_REF_PREFIX - 1) == 0) 9433965Sjdp 9533965Sjdp/* See if a symbol name is a reference to the procedure linkage table. */ 9633965Sjdp 9733965Sjdp#ifndef PLT_REF_PREFIX 9833965Sjdp#define PLT_REF_PREFIX "__PLT_" 9933965Sjdp#endif 10033965Sjdp 10133965Sjdp#define IS_PLT_SYM(name) \ 10233965Sjdp (strncmp (name, PLT_REF_PREFIX, sizeof PLT_REF_PREFIX - 1) == 0) 10333965Sjdp 10433965Sjdp/* This string is used to generate specialized error messages. */ 10533965Sjdp 10633965Sjdp#ifndef NEEDS_SHRLIB 10733965Sjdp#define NEEDS_SHRLIB "__NEEDS_SHRLIB_" 10833965Sjdp#endif 10933965Sjdp 11033965Sjdp/* This special symbol is a set vector that contains a list of 11133965Sjdp pointers to fixup tables. It will be present in any dynamicly 11233965Sjdp linked file. The linker generated fixup table should also be added 11333965Sjdp to the list, and it should always appear in the second slot (the 11433965Sjdp first one is a dummy with a magic number that is defined in 11533965Sjdp crt0.o). */ 11633965Sjdp 11733965Sjdp#ifndef SHARABLE_CONFLICTS 11833965Sjdp#define SHARABLE_CONFLICTS "__SHARABLE_CONFLICTS__" 11933965Sjdp#endif 12033965Sjdp 12133965Sjdp/* We keep a list of fixups. The terminology is a bit strange, but 12233965Sjdp each fixup contains two 32 bit numbers. A regular fixup contains 12333965Sjdp an address and a pointer, and at runtime we should store the 12433965Sjdp address at the location pointed to by the pointer. A builtin fixup 12533965Sjdp contains two pointers, and we should read the address using one 12633965Sjdp pointer and store it at the location pointed to by the other 12733965Sjdp pointer. Builtin fixups come into play when we have duplicate 12833965Sjdp __GOT__ symbols for the same variable. The builtin fixup will copy 12933965Sjdp the GOT pointer from one over into the other. */ 13033965Sjdp 13133965Sjdpstruct fixup 13233965Sjdp{ 13333965Sjdp struct fixup *next; 13433965Sjdp struct linux_link_hash_entry *h; 13533965Sjdp bfd_vma value; 13633965Sjdp 13733965Sjdp /* Nonzero if this is a jump instruction that needs to be fixed, 13833965Sjdp zero if this is just a pointer */ 13933965Sjdp char jump; 14033965Sjdp 14133965Sjdp char builtin; 14233965Sjdp}; 14333965Sjdp 14433965Sjdp/* We don't need a special hash table entry structure, but we do need 14533965Sjdp to keep some information between linker passes, so we use a special 14633965Sjdp hash table. */ 14733965Sjdp 14833965Sjdpstruct linux_link_hash_entry 14933965Sjdp{ 15033965Sjdp struct aout_link_hash_entry root; 15133965Sjdp}; 15233965Sjdp 15333965Sjdpstruct linux_link_hash_table 15433965Sjdp{ 15533965Sjdp struct aout_link_hash_table root; 15633965Sjdp 15733965Sjdp /* First dynamic object found in link. */ 15833965Sjdp bfd *dynobj; 15933965Sjdp 16033965Sjdp /* Number of fixups. */ 16133965Sjdp size_t fixup_count; 16233965Sjdp 16333965Sjdp /* Number of builtin fixups. */ 16433965Sjdp size_t local_builtins; 16533965Sjdp 16633965Sjdp /* List of fixups. */ 16733965Sjdp struct fixup *fixup_list; 16833965Sjdp}; 16933965Sjdp 17033965Sjdpstatic struct bfd_hash_entry *linux_link_hash_newfunc 17133965Sjdp PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); 17233965Sjdpstatic struct bfd_link_hash_table *linux_link_hash_table_create 17333965Sjdp PARAMS ((bfd *)); 17433965Sjdpstatic struct fixup *new_fixup 17533965Sjdp PARAMS ((struct bfd_link_info *, struct linux_link_hash_entry *, 17633965Sjdp bfd_vma, int)); 17733965Sjdpstatic boolean linux_link_create_dynamic_sections 17833965Sjdp PARAMS ((bfd *, struct bfd_link_info *)); 17933965Sjdpstatic boolean linux_add_one_symbol 18033965Sjdp PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *, 18133965Sjdp bfd_vma, const char *, boolean, boolean, 18233965Sjdp struct bfd_link_hash_entry **)); 18333965Sjdpstatic boolean linux_tally_symbols 18433965Sjdp PARAMS ((struct linux_link_hash_entry *, PTR)); 18533965Sjdpstatic boolean linux_finish_dynamic_link 18633965Sjdp PARAMS ((bfd *, struct bfd_link_info *)); 18733965Sjdp 18833965Sjdp/* Routine to create an entry in an Linux link hash table. */ 18933965Sjdp 19033965Sjdpstatic struct bfd_hash_entry * 19133965Sjdplinux_link_hash_newfunc (entry, table, string) 19233965Sjdp struct bfd_hash_entry *entry; 19333965Sjdp struct bfd_hash_table *table; 19433965Sjdp const char *string; 19533965Sjdp{ 19633965Sjdp struct linux_link_hash_entry *ret = (struct linux_link_hash_entry *) entry; 19733965Sjdp 19833965Sjdp /* Allocate the structure if it has not already been allocated by a 19933965Sjdp subclass. */ 20033965Sjdp if (ret == (struct linux_link_hash_entry *) NULL) 20133965Sjdp ret = ((struct linux_link_hash_entry *) 20233965Sjdp bfd_hash_allocate (table, sizeof (struct linux_link_hash_entry))); 20333965Sjdp if (ret == NULL) 20433965Sjdp return (struct bfd_hash_entry *) ret; 20533965Sjdp 20633965Sjdp /* Call the allocation method of the superclass. */ 20733965Sjdp ret = ((struct linux_link_hash_entry *) 20833965Sjdp NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret, 20933965Sjdp table, string)); 21033965Sjdp if (ret != NULL) 21133965Sjdp { 21233965Sjdp /* Set local fields; there aren't any. */ 21333965Sjdp } 21433965Sjdp 21533965Sjdp return (struct bfd_hash_entry *) ret; 21633965Sjdp} 21733965Sjdp 21833965Sjdp/* Create a Linux link hash table. */ 21933965Sjdp 22033965Sjdpstatic struct bfd_link_hash_table * 22133965Sjdplinux_link_hash_table_create (abfd) 22233965Sjdp bfd *abfd; 22333965Sjdp{ 22433965Sjdp struct linux_link_hash_table *ret; 22533965Sjdp 22633965Sjdp ret = ((struct linux_link_hash_table *) 22733965Sjdp bfd_alloc (abfd, sizeof (struct linux_link_hash_table))); 22833965Sjdp if (ret == (struct linux_link_hash_table *) NULL) 22933965Sjdp return (struct bfd_link_hash_table *) NULL; 23033965Sjdp if (! NAME(aout,link_hash_table_init) (&ret->root, abfd, 23133965Sjdp linux_link_hash_newfunc)) 23233965Sjdp { 23333965Sjdp free (ret); 23433965Sjdp return (struct bfd_link_hash_table *) NULL; 23533965Sjdp } 23633965Sjdp 23733965Sjdp ret->dynobj = NULL; 23833965Sjdp ret->fixup_count = 0; 23933965Sjdp ret->local_builtins = 0; 24033965Sjdp ret->fixup_list = NULL; 24133965Sjdp 24233965Sjdp return &ret->root.root; 24333965Sjdp} 24433965Sjdp 24533965Sjdp/* Look up an entry in a Linux link hash table. */ 24633965Sjdp 24733965Sjdp#define linux_link_hash_lookup(table, string, create, copy, follow) \ 24833965Sjdp ((struct linux_link_hash_entry *) \ 24933965Sjdp aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\ 25033965Sjdp (follow))) 25133965Sjdp 25233965Sjdp/* Traverse a Linux link hash table. */ 25333965Sjdp 25433965Sjdp#define linux_link_hash_traverse(table, func, info) \ 25533965Sjdp (aout_link_hash_traverse \ 25633965Sjdp (&(table)->root, \ 25733965Sjdp (boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \ 25833965Sjdp (info))) 25933965Sjdp 26033965Sjdp/* Get the Linux link hash table from the info structure. This is 26133965Sjdp just a cast. */ 26233965Sjdp 26333965Sjdp#define linux_hash_table(p) ((struct linux_link_hash_table *) ((p)->hash)) 26433965Sjdp 26533965Sjdp/* Store the information for a new fixup. */ 26633965Sjdp 26733965Sjdpstatic struct fixup * 26833965Sjdpnew_fixup (info, h, value, builtin) 26933965Sjdp struct bfd_link_info *info; 27033965Sjdp struct linux_link_hash_entry *h; 27133965Sjdp bfd_vma value; 27233965Sjdp int builtin; 27333965Sjdp{ 27433965Sjdp struct fixup *f; 27533965Sjdp 27633965Sjdp f = (struct fixup *) bfd_hash_allocate (&info->hash->table, 27733965Sjdp sizeof (struct fixup)); 27833965Sjdp if (f == NULL) 27933965Sjdp return f; 28033965Sjdp f->next = linux_hash_table (info)->fixup_list; 28133965Sjdp linux_hash_table (info)->fixup_list = f; 28233965Sjdp f->h = h; 28333965Sjdp f->value = value; 28433965Sjdp f->builtin = builtin; 28533965Sjdp f->jump = 0; 28633965Sjdp ++linux_hash_table (info)->fixup_count; 28733965Sjdp return f; 28833965Sjdp} 28933965Sjdp 29033965Sjdp/* We come here once we realize that we are going to link to a shared 29133965Sjdp library. We need to create a special section that contains the 29233965Sjdp fixup table, and we ultimately need to add a pointer to this into 29333965Sjdp the set vector for SHARABLE_CONFLICTS. At this point we do not 29433965Sjdp know the size of the section, but that's OK - we just need to 29533965Sjdp create it for now. */ 29633965Sjdp 29733965Sjdpstatic boolean 29833965Sjdplinux_link_create_dynamic_sections (abfd, info) 29933965Sjdp bfd *abfd; 30033965Sjdp struct bfd_link_info *info; 30133965Sjdp{ 30233965Sjdp flagword flags; 30333965Sjdp register asection *s; 30433965Sjdp 30533965Sjdp /* Note that we set the SEC_IN_MEMORY flag. */ 30633965Sjdp flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY; 30733965Sjdp 30833965Sjdp /* We choose to use the name ".linux-dynamic" for the fixup table. 30933965Sjdp Why not? */ 31033965Sjdp s = bfd_make_section (abfd, ".linux-dynamic"); 31133965Sjdp if (s == NULL 31233965Sjdp || ! bfd_set_section_flags (abfd, s, flags) 31333965Sjdp || ! bfd_set_section_alignment (abfd, s, 2)) 31433965Sjdp return false; 31533965Sjdp s->_raw_size = 0; 31633965Sjdp s->contents = 0; 31733965Sjdp 31833965Sjdp return true; 31933965Sjdp} 32033965Sjdp 32133965Sjdp/* Function to add a single symbol to the linker hash table. This is 32233965Sjdp a wrapper around _bfd_generic_link_add_one_symbol which handles the 32333965Sjdp tweaking needed for dynamic linking support. */ 32433965Sjdp 32533965Sjdpstatic boolean 32633965Sjdplinux_add_one_symbol (info, abfd, name, flags, section, value, string, 32733965Sjdp copy, collect, hashp) 32833965Sjdp struct bfd_link_info *info; 32933965Sjdp bfd *abfd; 33033965Sjdp const char *name; 33133965Sjdp flagword flags; 33233965Sjdp asection *section; 33333965Sjdp bfd_vma value; 33433965Sjdp const char *string; 33533965Sjdp boolean copy; 33633965Sjdp boolean collect; 33733965Sjdp struct bfd_link_hash_entry **hashp; 33833965Sjdp{ 33933965Sjdp struct linux_link_hash_entry *h; 34033965Sjdp boolean insert; 34133965Sjdp 34233965Sjdp /* Look up and see if we already have this symbol in the hash table. 34333965Sjdp If we do, and the defining entry is from a shared library, we 34433965Sjdp need to create the dynamic sections. 34533965Sjdp 34633965Sjdp FIXME: What if abfd->xvec != info->hash->creator? We may want to 34733965Sjdp be able to link Linux a.out and ELF objects together, but serious 34833965Sjdp confusion is possible. */ 34933965Sjdp 35033965Sjdp insert = false; 35133965Sjdp 35233965Sjdp if (! info->relocateable 35333965Sjdp && linux_hash_table (info)->dynobj == NULL 35433965Sjdp && strcmp (name, SHARABLE_CONFLICTS) == 0 35533965Sjdp && (flags & BSF_CONSTRUCTOR) != 0 35633965Sjdp && abfd->xvec == info->hash->creator) 35733965Sjdp { 35833965Sjdp if (! linux_link_create_dynamic_sections (abfd, info)) 35933965Sjdp return false; 36033965Sjdp linux_hash_table (info)->dynobj = abfd; 36133965Sjdp insert = true; 36233965Sjdp } 36333965Sjdp 36433965Sjdp if (bfd_is_abs_section (section) 36533965Sjdp && abfd->xvec == info->hash->creator) 36633965Sjdp { 36733965Sjdp h = linux_link_hash_lookup (linux_hash_table (info), name, false, 36833965Sjdp false, false); 36933965Sjdp if (h != NULL 37033965Sjdp && (h->root.root.type == bfd_link_hash_defined 37133965Sjdp || h->root.root.type == bfd_link_hash_defweak)) 37233965Sjdp { 37333965Sjdp struct fixup *f; 37433965Sjdp 37533965Sjdp if (hashp != NULL) 37633965Sjdp *hashp = (struct bfd_link_hash_entry *) h; 37733965Sjdp 37833965Sjdp f = new_fixup (info, h, value, ! IS_PLT_SYM (name)); 37933965Sjdp if (f == NULL) 38033965Sjdp return false; 38133965Sjdp f->jump = IS_PLT_SYM (name); 38233965Sjdp 38333965Sjdp return true; 38433965Sjdp } 38533965Sjdp } 38633965Sjdp 38733965Sjdp /* Do the usual procedure for adding a symbol. */ 38833965Sjdp if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, 38933965Sjdp value, string, copy, collect, 39033965Sjdp hashp)) 39133965Sjdp return false; 39233965Sjdp 39333965Sjdp /* Insert a pointer to our table in the set vector. The dynamic 39433965Sjdp linker requires this information */ 39533965Sjdp if (insert) 39633965Sjdp { 39733965Sjdp asection *s; 39833965Sjdp 39933965Sjdp /* Here we do our special thing to add the pointer to the 40033965Sjdp dynamic section in the SHARABLE_CONFLICTS set vector. */ 40133965Sjdp s = bfd_get_section_by_name (linux_hash_table (info)->dynobj, 40233965Sjdp ".linux-dynamic"); 40333965Sjdp BFD_ASSERT (s != NULL); 40433965Sjdp 40533965Sjdp if (! (_bfd_generic_link_add_one_symbol 40633965Sjdp (info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS, 40733965Sjdp BSF_GLOBAL | BSF_CONSTRUCTOR, s, 0, NULL, false, false, NULL))) 40833965Sjdp return false; 40933965Sjdp } 41033965Sjdp 41133965Sjdp return true; 41233965Sjdp} 41333965Sjdp 41433965Sjdp/* We will crawl the hash table and come here for every global symbol. 41533965Sjdp We will examine each entry and see if there are indications that we 41633965Sjdp need to add a fixup. There are two possible cases - one is where 41733965Sjdp you have duplicate definitions of PLT or GOT symbols - these will 41833965Sjdp have already been caught and added as "builtin" fixups. If we find 41933965Sjdp that the corresponding non PLT/GOT symbol is also present, we 42033965Sjdp convert it to a regular fixup instead. 42133965Sjdp 42233965Sjdp This function is called via linux_link_hash_traverse. */ 42333965Sjdp 42433965Sjdpstatic boolean 42533965Sjdplinux_tally_symbols (h, data) 42633965Sjdp struct linux_link_hash_entry *h; 42733965Sjdp PTR data; 42833965Sjdp{ 42933965Sjdp struct bfd_link_info *info = (struct bfd_link_info *) data; 43033965Sjdp struct fixup *f, *f1; 43133965Sjdp int is_plt; 43233965Sjdp struct linux_link_hash_entry *h1, *h2; 43333965Sjdp boolean exists; 43433965Sjdp 43533965Sjdp if (h->root.root.type == bfd_link_hash_undefined 43633965Sjdp && strncmp (h->root.root.root.string, NEEDS_SHRLIB, 43733965Sjdp sizeof NEEDS_SHRLIB - 1) == 0) 43833965Sjdp { 43933965Sjdp const char *name; 44033965Sjdp char *p; 44133965Sjdp char *alloc = NULL; 44233965Sjdp 44333965Sjdp name = h->root.root.root.string + sizeof NEEDS_SHRLIB - 1; 44433965Sjdp p = strrchr (name, '_'); 44533965Sjdp if (p != NULL) 44633965Sjdp alloc = (char *) bfd_malloc (strlen (name) + 1); 44733965Sjdp 44833965Sjdp if (p == NULL || alloc == NULL) 44933965Sjdp (*_bfd_error_handler) ("Output file requires shared library `%s'\n", 45033965Sjdp name); 45133965Sjdp else 45233965Sjdp { 45333965Sjdp strcpy (alloc, name); 45433965Sjdp p = strrchr (alloc, '_'); 45533965Sjdp *p++ = '\0'; 45633965Sjdp (*_bfd_error_handler) 45733965Sjdp ("Output file requires shared library `%s.so.%s'\n", 45833965Sjdp alloc, p); 45933965Sjdp free (alloc); 46033965Sjdp } 46133965Sjdp 46233965Sjdp abort (); 46333965Sjdp } 46433965Sjdp 46533965Sjdp /* If this symbol is not a PLT/GOT, we do not even need to look at it */ 46633965Sjdp is_plt = IS_PLT_SYM (h->root.root.root.string); 46733965Sjdp 46833965Sjdp if (is_plt || IS_GOT_SYM (h->root.root.root.string)) 46933965Sjdp { 47033965Sjdp /* Look up this symbol twice. Once just as a regular lookup, 47133965Sjdp and then again following all of the indirect links until we 47233965Sjdp reach a real symbol. */ 47333965Sjdp h1 = linux_link_hash_lookup (linux_hash_table (info), 47433965Sjdp (h->root.root.root.string 47533965Sjdp + sizeof PLT_REF_PREFIX - 1), 47633965Sjdp false, false, true); 47733965Sjdp /* h2 does not follow indirect symbols. */ 47833965Sjdp h2 = linux_link_hash_lookup (linux_hash_table (info), 47933965Sjdp (h->root.root.root.string 48033965Sjdp + sizeof PLT_REF_PREFIX - 1), 48133965Sjdp false, false, false); 48233965Sjdp 48333965Sjdp /* The real symbol must exist but if it is also an ABS symbol, 48433965Sjdp there is no need to have a fixup. This is because they both 48533965Sjdp came from the same library. If on the other hand, we had to 48633965Sjdp use an indirect symbol to get to the real symbol, we add the 48733965Sjdp fixup anyway, since there are cases where these symbols come 48833965Sjdp from different shared libraries */ 48933965Sjdp if (h1 != NULL 49033965Sjdp && (((h1->root.root.type == bfd_link_hash_defined 49133965Sjdp || h1->root.root.type == bfd_link_hash_defweak) 49233965Sjdp && ! bfd_is_abs_section (h1->root.root.u.def.section)) 49333965Sjdp || h2->root.root.type == bfd_link_hash_indirect)) 49433965Sjdp { 49533965Sjdp /* See if there is a "builtin" fixup already present 49633965Sjdp involving this symbol. If so, convert it to a regular 49733965Sjdp fixup. In the end, this relaxes some of the requirements 49833965Sjdp about the order of performing fixups. */ 49933965Sjdp exists = false; 50033965Sjdp for (f1 = linux_hash_table (info)->fixup_list; 50133965Sjdp f1 != NULL; 50233965Sjdp f1 = f1->next) 50333965Sjdp { 50433965Sjdp if ((f1->h != h && f1->h != h1) 50533965Sjdp || (! f1->builtin && ! f1->jump)) 50633965Sjdp continue; 50733965Sjdp if (f1->h == h1) 50833965Sjdp exists = true; 50933965Sjdp if (! exists 51033965Sjdp && bfd_is_abs_section (h->root.root.u.def.section)) 51133965Sjdp { 51233965Sjdp f = new_fixup (info, h1, f1->h->root.root.u.def.value, 0); 51333965Sjdp f->jump = is_plt; 51433965Sjdp } 51533965Sjdp f1->h = h1; 51633965Sjdp f1->jump = is_plt; 51733965Sjdp f1->builtin = 0; 51833965Sjdp exists = true; 51933965Sjdp } 52033965Sjdp if (! exists 52133965Sjdp && bfd_is_abs_section (h->root.root.u.def.section)) 52233965Sjdp { 52333965Sjdp f = new_fixup (info, h1, h->root.root.u.def.value, 0); 52433965Sjdp if (f == NULL) 52533965Sjdp { 52633965Sjdp /* FIXME: No way to return error. */ 52733965Sjdp abort (); 52833965Sjdp } 52933965Sjdp f->jump = is_plt; 53033965Sjdp } 53133965Sjdp } 53233965Sjdp 53333965Sjdp /* Quick and dirty way of stripping these symbols from the 53433965Sjdp symtab. */ 53533965Sjdp if (bfd_is_abs_section (h->root.root.u.def.section)) 53633965Sjdp h->root.written = true; 53733965Sjdp } 53833965Sjdp 53933965Sjdp return true; 54033965Sjdp} 54133965Sjdp 54233965Sjdp/* This is called to set the size of the .linux-dynamic section is. 54333965Sjdp It is called by the Linux linker emulation before_allocation 54433965Sjdp routine. We have finished reading all of the input files, and now 54533965Sjdp we just scan the hash tables to find out how many additional fixups 54633965Sjdp are required. */ 54733965Sjdp 54833965Sjdpboolean 54933965Sjdpbfd_i386linux_size_dynamic_sections (output_bfd, info) 55033965Sjdp bfd *output_bfd; 55133965Sjdp struct bfd_link_info *info; 55233965Sjdp{ 55333965Sjdp struct fixup *f; 55433965Sjdp asection *s; 55533965Sjdp 55633965Sjdp if (output_bfd->xvec != &MY(vec)) 55733965Sjdp return true; 55833965Sjdp 55933965Sjdp /* First find the fixups... */ 56033965Sjdp linux_link_hash_traverse (linux_hash_table (info), 56133965Sjdp linux_tally_symbols, 56233965Sjdp (PTR) info); 56333965Sjdp 56433965Sjdp /* If there are builtin fixups, leave room for a marker. This is 56533965Sjdp used by the dynamic linker so that it knows that all that follow 56633965Sjdp are builtin fixups instead of regular fixups. */ 56733965Sjdp for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next) 56833965Sjdp { 56933965Sjdp if (f->builtin) 57033965Sjdp { 57133965Sjdp ++linux_hash_table (info)->fixup_count; 57233965Sjdp ++linux_hash_table (info)->local_builtins; 57333965Sjdp break; 57433965Sjdp } 57533965Sjdp } 57633965Sjdp 57733965Sjdp if (linux_hash_table (info)->dynobj == NULL) 57833965Sjdp { 57933965Sjdp if (linux_hash_table (info)->fixup_count > 0) 58033965Sjdp abort (); 58133965Sjdp return true; 58233965Sjdp } 58333965Sjdp 58433965Sjdp /* Allocate memory for our fixup table. We will fill it in later. */ 58533965Sjdp s = bfd_get_section_by_name (linux_hash_table (info)->dynobj, 58633965Sjdp ".linux-dynamic"); 58733965Sjdp if (s != NULL) 58833965Sjdp { 58933965Sjdp s->_raw_size = 8 + linux_hash_table (info)->fixup_count * 8; 59033965Sjdp s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size); 59133965Sjdp if (s->contents == NULL) 59233965Sjdp return false; 59333965Sjdp memset (s->contents, 0, (size_t) s->_raw_size); 59433965Sjdp } 59533965Sjdp 59633965Sjdp return true; 59733965Sjdp} 59833965Sjdp 59933965Sjdp/* We come here once we are ready to actually write the fixup table to 60033965Sjdp the output file. Scan the fixup tables and so forth and generate 60133965Sjdp the stuff we need. */ 60233965Sjdp 60333965Sjdpstatic boolean 60433965Sjdplinux_finish_dynamic_link (output_bfd, info) 60533965Sjdp bfd *output_bfd; 60633965Sjdp struct bfd_link_info *info; 60733965Sjdp{ 60833965Sjdp asection *s, *os, *is; 60933965Sjdp bfd_byte *fixup_table; 61033965Sjdp struct linux_link_hash_entry *h; 61133965Sjdp struct fixup *f; 61233965Sjdp unsigned int new_addr; 61333965Sjdp int section_offset; 61433965Sjdp unsigned int fixups_written; 61533965Sjdp 61633965Sjdp if (linux_hash_table (info)->dynobj == NULL) 61733965Sjdp return true; 61833965Sjdp 61933965Sjdp s = bfd_get_section_by_name (linux_hash_table (info)->dynobj, 62033965Sjdp ".linux-dynamic"); 62133965Sjdp BFD_ASSERT (s != NULL); 62233965Sjdp os = s->output_section; 62333965Sjdp fixups_written = 0; 62433965Sjdp 62533965Sjdp#ifdef LINUX_LINK_DEBUG 62633965Sjdp printf ("Fixup table file offset: %x VMA: %x\n", 62733965Sjdp os->filepos + s->output_offset, 62833965Sjdp os->vma + s->output_offset); 62933965Sjdp#endif 63033965Sjdp 63133965Sjdp fixup_table = s->contents; 63233965Sjdp bfd_put_32 (output_bfd, linux_hash_table (info)->fixup_count, fixup_table); 63333965Sjdp fixup_table += 4; 63433965Sjdp 63533965Sjdp /* Fill in fixup table. */ 63633965Sjdp for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next) 63733965Sjdp { 63833965Sjdp if (f->builtin) 63933965Sjdp continue; 64033965Sjdp 64133965Sjdp if (f->h->root.root.type != bfd_link_hash_defined 64233965Sjdp && f->h->root.root.type != bfd_link_hash_defweak) 64333965Sjdp { 64433965Sjdp (*_bfd_error_handler) 64533965Sjdp ("Symbol %s not defined for fixups\n", 64633965Sjdp f->h->root.root.root.string); 64733965Sjdp continue; 64833965Sjdp } 64933965Sjdp 65033965Sjdp is = f->h->root.root.u.def.section; 65133965Sjdp section_offset = is->output_section->vma + is->output_offset; 65233965Sjdp new_addr = f->h->root.root.u.def.value + section_offset; 65333965Sjdp 65433965Sjdp#ifdef LINUX_LINK_DEBUG 65533965Sjdp printf ("Fixup(%d) %s: %x %x\n",f->jump, f->h->root.root.string, 65633965Sjdp new_addr, f->value); 65733965Sjdp#endif 65833965Sjdp 65933965Sjdp if (f->jump) 66033965Sjdp { 66133965Sjdp /* Relative address */ 66233965Sjdp new_addr = new_addr - (f->value + 5); 66333965Sjdp bfd_put_32 (output_bfd, new_addr, fixup_table); 66433965Sjdp fixup_table += 4; 66533965Sjdp bfd_put_32 (output_bfd, f->value + 1, fixup_table); 66633965Sjdp fixup_table += 4; 66733965Sjdp } 66833965Sjdp else 66933965Sjdp { 67033965Sjdp bfd_put_32 (output_bfd, new_addr, fixup_table); 67133965Sjdp fixup_table += 4; 67233965Sjdp bfd_put_32 (output_bfd, f->value, fixup_table); 67333965Sjdp fixup_table += 4; 67433965Sjdp } 67533965Sjdp ++fixups_written; 67633965Sjdp } 67733965Sjdp 67833965Sjdp if (linux_hash_table (info)->local_builtins != 0) 67933965Sjdp { 68033965Sjdp /* Special marker so we know to switch to the other type of fixup */ 68133965Sjdp bfd_put_32 (output_bfd, 0, fixup_table); 68233965Sjdp fixup_table += 4; 68333965Sjdp bfd_put_32 (output_bfd, 0, fixup_table); 68433965Sjdp fixup_table += 4; 68533965Sjdp ++fixups_written; 68633965Sjdp for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next) 68733965Sjdp { 68833965Sjdp if (! f->builtin) 68933965Sjdp continue; 69033965Sjdp 69133965Sjdp if (f->h->root.root.type != bfd_link_hash_defined 69233965Sjdp && f->h->root.root.type != bfd_link_hash_defweak) 69333965Sjdp { 69433965Sjdp (*_bfd_error_handler) 69533965Sjdp ("Symbol %s not defined for fixups\n", 69633965Sjdp f->h->root.root.root.string); 69733965Sjdp continue; 69833965Sjdp } 69933965Sjdp 70033965Sjdp is = f->h->root.root.u.def.section; 70133965Sjdp section_offset = is->output_section->vma + is->output_offset; 70233965Sjdp new_addr = f->h->root.root.u.def.value + section_offset; 70333965Sjdp 70433965Sjdp#ifdef LINUX_LINK_DEBUG 70533965Sjdp printf ("Fixup(B) %s: %x %x\n", f->h->root.root.string, 70633965Sjdp new_addr, f->value); 70733965Sjdp#endif 70833965Sjdp 70933965Sjdp bfd_put_32 (output_bfd, new_addr, fixup_table); 71033965Sjdp fixup_table += 4; 71133965Sjdp bfd_put_32 (output_bfd, f->value, fixup_table); 71233965Sjdp fixup_table += 4; 71333965Sjdp ++fixups_written; 71433965Sjdp } 71533965Sjdp } 71633965Sjdp 71733965Sjdp if (linux_hash_table (info)->fixup_count != fixups_written) 71833965Sjdp { 71933965Sjdp (*_bfd_error_handler) ("Warning: fixup count mismatch\n"); 72033965Sjdp while (linux_hash_table (info)->fixup_count > fixups_written) 72133965Sjdp { 72233965Sjdp bfd_put_32 (output_bfd, 0, fixup_table); 72333965Sjdp fixup_table += 4; 72433965Sjdp bfd_put_32 (output_bfd, 0, fixup_table); 72533965Sjdp fixup_table += 4; 72633965Sjdp ++fixups_written; 72733965Sjdp } 72833965Sjdp } 72933965Sjdp 73033965Sjdp h = linux_link_hash_lookup (linux_hash_table (info), 73133965Sjdp "__BUILTIN_FIXUPS__", 73233965Sjdp false, false, false); 73333965Sjdp 73433965Sjdp if (h != NULL 73533965Sjdp && (h->root.root.type == bfd_link_hash_defined 73633965Sjdp || h->root.root.type == bfd_link_hash_defweak)) 73733965Sjdp { 73833965Sjdp is = h->root.root.u.def.section; 73933965Sjdp section_offset = is->output_section->vma + is->output_offset; 74033965Sjdp new_addr = h->root.root.u.def.value + section_offset; 74133965Sjdp 74233965Sjdp#ifdef LINUX_LINK_DEBUG 74333965Sjdp printf ("Builtin fixup table at %x\n", new_addr); 74433965Sjdp#endif 74533965Sjdp 74633965Sjdp bfd_put_32 (output_bfd, new_addr, fixup_table); 74733965Sjdp } 74833965Sjdp else 74933965Sjdp bfd_put_32 (output_bfd, 0, fixup_table); 75033965Sjdp 75133965Sjdp if (bfd_seek (output_bfd, os->filepos + s->output_offset, SEEK_SET) != 0) 75233965Sjdp return false; 75333965Sjdp 75433965Sjdp if (bfd_write ((PTR) s->contents, 1, s->_raw_size, output_bfd) 75533965Sjdp != s->_raw_size) 75633965Sjdp return false; 75733965Sjdp 75833965Sjdp return true; 75933965Sjdp} 76033965Sjdp 76133965Sjdp#define MY_bfd_link_hash_table_create linux_link_hash_table_create 76233965Sjdp#define MY_add_one_symbol linux_add_one_symbol 76333965Sjdp#define MY_finish_dynamic_link linux_finish_dynamic_link 76433965Sjdp 76533965Sjdp#define MY_zmagic_contiguous 1 76633965Sjdp 76733965Sjdp#include "aout-target.h" 768