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