12159047fSniklas /* BFD back-end for linux flavored i386 a.out binaries.
2c074d1c9Sdrahn Copyright 1992, 1993, 1994, 1995, 1996, 1997, 2001, 2002, 2003
3b305b0f1Sespie Free Software Foundation, Inc.
42159047fSniklas
52159047fSniklas This file is part of BFD, the Binary File Descriptor library.
62159047fSniklas
72159047fSniklas This program is free software; you can redistribute it and/or modify
82159047fSniklas it under the terms of the GNU General Public License as published by
92159047fSniklas the Free Software Foundation; either version 2 of the License, or
102159047fSniklas (at your option) any later version.
112159047fSniklas
122159047fSniklas This program is distributed in the hope that it will be useful,
132159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
142159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
152159047fSniklas GNU General Public License for more details.
162159047fSniklas
172159047fSniklas You should have received a copy of the GNU General Public License
182159047fSniklas along with this program; if not, write to the Free Software
192159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
202159047fSniklas
212159047fSniklas #define TARGET_PAGE_SIZE 4096
222159047fSniklas #define ZMAGIC_DISK_BLOCK_SIZE 1024
23c88b1d6cSniklas #define SEGMENT_SIZE TARGET_PAGE_SIZE
242159047fSniklas #define TEXT_START_ADDR 0x0
252159047fSniklas #define N_SHARED_LIB(x) 0
262159047fSniklas
27b305b0f1Sespie #define MACHTYPE_OK(mtype) ((mtype) == M_386 || (mtype) == M_UNKNOWN)
28b305b0f1Sespie
292159047fSniklas #include "bfd.h"
302159047fSniklas #include "sysdep.h"
312159047fSniklas #include "libbfd.h"
322159047fSniklas #include "aout/aout64.h"
332159047fSniklas #include "aout/stab_gnu.h"
342159047fSniklas #include "aout/ar.h"
352159047fSniklas #include "libaout.h" /* BFD a.out internal data structures */
362159047fSniklas
372159047fSniklas #define DEFAULT_ARCH bfd_arch_i386
38c074d1c9Sdrahn
39c074d1c9Sdrahn /* Do not "beautify" the CONCAT* macro args. Traditional C will not
40c074d1c9Sdrahn remove whitespace added here, and thus will fail to concatenate
41c074d1c9Sdrahn the tokens. */
42c074d1c9Sdrahn #define MY(OP) CONCAT2 (i386linux_,OP)
432159047fSniklas #define TARGETNAME "a.out-i386-linux"
442159047fSniklas
452159047fSniklas extern const bfd_target MY(vec);
462159047fSniklas
472159047fSniklas /* We always generate QMAGIC files in preference to ZMAGIC files. It
482159047fSniklas would be possible to make this a linker option, if that ever
492159047fSniklas becomes important. */
502159047fSniklas
512159047fSniklas static void MY_final_link_callback
522159047fSniklas PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *));
53c074d1c9Sdrahn static bfd_boolean i386linux_bfd_final_link
54b305b0f1Sespie PARAMS ((bfd *, struct bfd_link_info *));
55c074d1c9Sdrahn static bfd_boolean i386linux_write_object_contents PARAMS ((bfd *));
562159047fSniklas
57c074d1c9Sdrahn static bfd_boolean
i386linux_bfd_final_link(abfd,info)582159047fSniklas i386linux_bfd_final_link (abfd, info)
592159047fSniklas bfd *abfd;
602159047fSniklas struct bfd_link_info *info;
612159047fSniklas {
622159047fSniklas obj_aout_subformat (abfd) = q_magic_format;
632159047fSniklas return NAME(aout,final_link) (abfd, info, MY_final_link_callback);
642159047fSniklas }
652159047fSniklas
662159047fSniklas #define MY_bfd_final_link i386linux_bfd_final_link
672159047fSniklas
682159047fSniklas /* Set the machine type correctly. */
692159047fSniklas
70c074d1c9Sdrahn static bfd_boolean
i386linux_write_object_contents(abfd)712159047fSniklas i386linux_write_object_contents (abfd)
722159047fSniklas bfd *abfd;
732159047fSniklas {
742159047fSniklas struct external_exec exec_bytes;
752159047fSniklas struct internal_exec *execp = exec_hdr (abfd);
762159047fSniklas
772159047fSniklas N_SET_MACHTYPE (*execp, M_386);
782159047fSniklas
792159047fSniklas obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
802159047fSniklas
812159047fSniklas WRITE_HEADERS(abfd, execp);
822159047fSniklas
83c074d1c9Sdrahn return TRUE;
842159047fSniklas }
852159047fSniklas
862159047fSniklas #define MY_write_object_contents i386linux_write_object_contents
872159047fSniklas
882159047fSniklas /* Code to link against Linux a.out shared libraries. */
892159047fSniklas
902159047fSniklas /* See if a symbol name is a reference to the global offset table. */
912159047fSniklas
922159047fSniklas #ifndef GOT_REF_PREFIX
932159047fSniklas #define GOT_REF_PREFIX "__GOT_"
942159047fSniklas #endif
952159047fSniklas
962159047fSniklas #define IS_GOT_SYM(name) \
972159047fSniklas (strncmp (name, GOT_REF_PREFIX, sizeof GOT_REF_PREFIX - 1) == 0)
982159047fSniklas
992159047fSniklas /* See if a symbol name is a reference to the procedure linkage table. */
1002159047fSniklas
1012159047fSniklas #ifndef PLT_REF_PREFIX
1022159047fSniklas #define PLT_REF_PREFIX "__PLT_"
1032159047fSniklas #endif
1042159047fSniklas
1052159047fSniklas #define IS_PLT_SYM(name) \
1062159047fSniklas (strncmp (name, PLT_REF_PREFIX, sizeof PLT_REF_PREFIX - 1) == 0)
1072159047fSniklas
1082159047fSniklas /* This string is used to generate specialized error messages. */
1092159047fSniklas
1102159047fSniklas #ifndef NEEDS_SHRLIB
1112159047fSniklas #define NEEDS_SHRLIB "__NEEDS_SHRLIB_"
1122159047fSniklas #endif
1132159047fSniklas
1142159047fSniklas /* This special symbol is a set vector that contains a list of
115*007c2a45Smiod pointers to fixup tables. It will be present in any dynamically
1162159047fSniklas linked file. The linker generated fixup table should also be added
1172159047fSniklas to the list, and it should always appear in the second slot (the
1182159047fSniklas first one is a dummy with a magic number that is defined in
1192159047fSniklas crt0.o). */
1202159047fSniklas
1212159047fSniklas #ifndef SHARABLE_CONFLICTS
1222159047fSniklas #define SHARABLE_CONFLICTS "__SHARABLE_CONFLICTS__"
1232159047fSniklas #endif
1242159047fSniklas
1252159047fSniklas /* We keep a list of fixups. The terminology is a bit strange, but
1262159047fSniklas each fixup contains two 32 bit numbers. A regular fixup contains
1272159047fSniklas an address and a pointer, and at runtime we should store the
1282159047fSniklas address at the location pointed to by the pointer. A builtin fixup
1292159047fSniklas contains two pointers, and we should read the address using one
1302159047fSniklas pointer and store it at the location pointed to by the other
1312159047fSniklas pointer. Builtin fixups come into play when we have duplicate
1322159047fSniklas __GOT__ symbols for the same variable. The builtin fixup will copy
1332159047fSniklas the GOT pointer from one over into the other. */
1342159047fSniklas
1352159047fSniklas struct fixup
1362159047fSniklas {
1372159047fSniklas struct fixup *next;
1382159047fSniklas struct linux_link_hash_entry *h;
1392159047fSniklas bfd_vma value;
1402159047fSniklas
1412159047fSniklas /* Nonzero if this is a jump instruction that needs to be fixed,
1422159047fSniklas zero if this is just a pointer */
1432159047fSniklas char jump;
1442159047fSniklas
1452159047fSniklas char builtin;
1462159047fSniklas };
1472159047fSniklas
1482159047fSniklas /* We don't need a special hash table entry structure, but we do need
1492159047fSniklas to keep some information between linker passes, so we use a special
1502159047fSniklas hash table. */
1512159047fSniklas
1522159047fSniklas struct linux_link_hash_entry
1532159047fSniklas {
1542159047fSniklas struct aout_link_hash_entry root;
1552159047fSniklas };
1562159047fSniklas
1572159047fSniklas struct linux_link_hash_table
1582159047fSniklas {
1592159047fSniklas struct aout_link_hash_table root;
1602159047fSniklas
1612159047fSniklas /* First dynamic object found in link. */
1622159047fSniklas bfd *dynobj;
1632159047fSniklas
1642159047fSniklas /* Number of fixups. */
1652159047fSniklas size_t fixup_count;
1662159047fSniklas
1672159047fSniklas /* Number of builtin fixups. */
1682159047fSniklas size_t local_builtins;
1692159047fSniklas
1702159047fSniklas /* List of fixups. */
1712159047fSniklas struct fixup *fixup_list;
1722159047fSniklas };
1732159047fSniklas
1742159047fSniklas static struct bfd_hash_entry *linux_link_hash_newfunc
1752159047fSniklas PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
1762159047fSniklas static struct bfd_link_hash_table *linux_link_hash_table_create
1772159047fSniklas PARAMS ((bfd *));
1782159047fSniklas static struct fixup *new_fixup
1792159047fSniklas PARAMS ((struct bfd_link_info *, struct linux_link_hash_entry *,
1802159047fSniklas bfd_vma, int));
181c074d1c9Sdrahn static bfd_boolean linux_link_create_dynamic_sections
1822159047fSniklas PARAMS ((bfd *, struct bfd_link_info *));
183c074d1c9Sdrahn static bfd_boolean linux_add_one_symbol
1842159047fSniklas PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
185c074d1c9Sdrahn bfd_vma, const char *, bfd_boolean, bfd_boolean,
1862159047fSniklas struct bfd_link_hash_entry **));
187c074d1c9Sdrahn static bfd_boolean linux_tally_symbols
1882159047fSniklas PARAMS ((struct linux_link_hash_entry *, PTR));
189c074d1c9Sdrahn static bfd_boolean linux_finish_dynamic_link
1902159047fSniklas PARAMS ((bfd *, struct bfd_link_info *));
1912159047fSniklas
1922159047fSniklas /* Routine to create an entry in an Linux link hash table. */
1932159047fSniklas
1942159047fSniklas static struct bfd_hash_entry *
linux_link_hash_newfunc(entry,table,string)1952159047fSniklas linux_link_hash_newfunc (entry, table, string)
1962159047fSniklas struct bfd_hash_entry *entry;
1972159047fSniklas struct bfd_hash_table *table;
1982159047fSniklas const char *string;
1992159047fSniklas {
2002159047fSniklas struct linux_link_hash_entry *ret = (struct linux_link_hash_entry *) entry;
2012159047fSniklas
2022159047fSniklas /* Allocate the structure if it has not already been allocated by a
2032159047fSniklas subclass. */
2042159047fSniklas if (ret == (struct linux_link_hash_entry *) NULL)
2052159047fSniklas ret = ((struct linux_link_hash_entry *)
2062159047fSniklas bfd_hash_allocate (table, sizeof (struct linux_link_hash_entry)));
2072159047fSniklas if (ret == NULL)
2082159047fSniklas return (struct bfd_hash_entry *) ret;
2092159047fSniklas
2102159047fSniklas /* Call the allocation method of the superclass. */
2112159047fSniklas ret = ((struct linux_link_hash_entry *)
2122159047fSniklas NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret,
2132159047fSniklas table, string));
2142159047fSniklas if (ret != NULL)
2152159047fSniklas {
2162159047fSniklas /* Set local fields; there aren't any. */
2172159047fSniklas }
2182159047fSniklas
2192159047fSniklas return (struct bfd_hash_entry *) ret;
2202159047fSniklas }
2212159047fSniklas
2222159047fSniklas /* Create a Linux link hash table. */
2232159047fSniklas
2242159047fSniklas static struct bfd_link_hash_table *
linux_link_hash_table_create(abfd)2252159047fSniklas linux_link_hash_table_create (abfd)
2262159047fSniklas bfd *abfd;
2272159047fSniklas {
2282159047fSniklas struct linux_link_hash_table *ret;
229c074d1c9Sdrahn bfd_size_type amt = sizeof (struct linux_link_hash_table);
2302159047fSniklas
231c074d1c9Sdrahn ret = (struct linux_link_hash_table *) bfd_alloc (abfd, amt);
2322159047fSniklas if (ret == (struct linux_link_hash_table *) NULL)
2332159047fSniklas return (struct bfd_link_hash_table *) NULL;
2342159047fSniklas if (! NAME(aout,link_hash_table_init) (&ret->root, abfd,
2352159047fSniklas linux_link_hash_newfunc))
2362159047fSniklas {
2372159047fSniklas free (ret);
2382159047fSniklas return (struct bfd_link_hash_table *) NULL;
2392159047fSniklas }
2402159047fSniklas
2412159047fSniklas ret->dynobj = NULL;
2422159047fSniklas ret->fixup_count = 0;
2432159047fSniklas ret->local_builtins = 0;
2442159047fSniklas ret->fixup_list = NULL;
2452159047fSniklas
2462159047fSniklas return &ret->root.root;
2472159047fSniklas }
2482159047fSniklas
2492159047fSniklas /* Look up an entry in a Linux link hash table. */
2502159047fSniklas
2512159047fSniklas #define linux_link_hash_lookup(table, string, create, copy, follow) \
2522159047fSniklas ((struct linux_link_hash_entry *) \
2532159047fSniklas aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\
2542159047fSniklas (follow)))
2552159047fSniklas
2562159047fSniklas /* Traverse a Linux link hash table. */
2572159047fSniklas
2582159047fSniklas #define linux_link_hash_traverse(table, func, info) \
2592159047fSniklas (aout_link_hash_traverse \
2602159047fSniklas (&(table)->root, \
261c074d1c9Sdrahn (bfd_boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \
2622159047fSniklas (info)))
2632159047fSniklas
2642159047fSniklas /* Get the Linux link hash table from the info structure. This is
2652159047fSniklas just a cast. */
2662159047fSniklas
2672159047fSniklas #define linux_hash_table(p) ((struct linux_link_hash_table *) ((p)->hash))
2682159047fSniklas
2692159047fSniklas /* Store the information for a new fixup. */
2702159047fSniklas
2712159047fSniklas static struct fixup *
new_fixup(info,h,value,builtin)2722159047fSniklas new_fixup (info, h, value, builtin)
2732159047fSniklas struct bfd_link_info *info;
2742159047fSniklas struct linux_link_hash_entry *h;
2752159047fSniklas bfd_vma value;
2762159047fSniklas int builtin;
2772159047fSniklas {
2782159047fSniklas struct fixup *f;
2792159047fSniklas
2802159047fSniklas f = (struct fixup *) bfd_hash_allocate (&info->hash->table,
2812159047fSniklas sizeof (struct fixup));
2822159047fSniklas if (f == NULL)
2832159047fSniklas return f;
2842159047fSniklas f->next = linux_hash_table (info)->fixup_list;
2852159047fSniklas linux_hash_table (info)->fixup_list = f;
2862159047fSniklas f->h = h;
2872159047fSniklas f->value = value;
2882159047fSniklas f->builtin = builtin;
2892159047fSniklas f->jump = 0;
2902159047fSniklas ++linux_hash_table (info)->fixup_count;
2912159047fSniklas return f;
2922159047fSniklas }
2932159047fSniklas
2942159047fSniklas /* We come here once we realize that we are going to link to a shared
2952159047fSniklas library. We need to create a special section that contains the
2962159047fSniklas fixup table, and we ultimately need to add a pointer to this into
2972159047fSniklas the set vector for SHARABLE_CONFLICTS. At this point we do not
2982159047fSniklas know the size of the section, but that's OK - we just need to
2992159047fSniklas create it for now. */
3002159047fSniklas
301c074d1c9Sdrahn static bfd_boolean
linux_link_create_dynamic_sections(abfd,info)3022159047fSniklas linux_link_create_dynamic_sections (abfd, info)
3032159047fSniklas bfd *abfd;
304b305b0f1Sespie struct bfd_link_info *info ATTRIBUTE_UNUSED;
3052159047fSniklas {
3062159047fSniklas flagword flags;
3072159047fSniklas register asection *s;
3082159047fSniklas
3092159047fSniklas /* Note that we set the SEC_IN_MEMORY flag. */
3102159047fSniklas flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
3112159047fSniklas
3122159047fSniklas /* We choose to use the name ".linux-dynamic" for the fixup table.
3132159047fSniklas Why not? */
3142159047fSniklas s = bfd_make_section (abfd, ".linux-dynamic");
3152159047fSniklas if (s == NULL
3162159047fSniklas || ! bfd_set_section_flags (abfd, s, flags)
3172159047fSniklas || ! bfd_set_section_alignment (abfd, s, 2))
318c074d1c9Sdrahn return FALSE;
3192159047fSniklas s->_raw_size = 0;
3202159047fSniklas s->contents = 0;
3212159047fSniklas
322c074d1c9Sdrahn return TRUE;
3232159047fSniklas }
3242159047fSniklas
3252159047fSniklas /* Function to add a single symbol to the linker hash table. This is
3262159047fSniklas a wrapper around _bfd_generic_link_add_one_symbol which handles the
3272159047fSniklas tweaking needed for dynamic linking support. */
3282159047fSniklas
329c074d1c9Sdrahn static bfd_boolean
linux_add_one_symbol(info,abfd,name,flags,section,value,string,copy,collect,hashp)3302159047fSniklas linux_add_one_symbol (info, abfd, name, flags, section, value, string,
3312159047fSniklas copy, collect, hashp)
3322159047fSniklas struct bfd_link_info *info;
3332159047fSniklas bfd *abfd;
3342159047fSniklas const char *name;
3352159047fSniklas flagword flags;
3362159047fSniklas asection *section;
3372159047fSniklas bfd_vma value;
3382159047fSniklas const char *string;
339c074d1c9Sdrahn bfd_boolean copy;
340c074d1c9Sdrahn bfd_boolean collect;
3412159047fSniklas struct bfd_link_hash_entry **hashp;
3422159047fSniklas {
3432159047fSniklas struct linux_link_hash_entry *h;
344c074d1c9Sdrahn bfd_boolean insert;
3452159047fSniklas
3462159047fSniklas /* Look up and see if we already have this symbol in the hash table.
3472159047fSniklas If we do, and the defining entry is from a shared library, we
3482159047fSniklas need to create the dynamic sections.
3492159047fSniklas
3502159047fSniklas FIXME: What if abfd->xvec != info->hash->creator? We may want to
3512159047fSniklas be able to link Linux a.out and ELF objects together, but serious
3522159047fSniklas confusion is possible. */
3532159047fSniklas
354c074d1c9Sdrahn insert = FALSE;
3552159047fSniklas
356*007c2a45Smiod if (! info->relocatable
3572159047fSniklas && linux_hash_table (info)->dynobj == NULL
3582159047fSniklas && strcmp (name, SHARABLE_CONFLICTS) == 0
3592159047fSniklas && (flags & BSF_CONSTRUCTOR) != 0
3602159047fSniklas && abfd->xvec == info->hash->creator)
3612159047fSniklas {
3622159047fSniklas if (! linux_link_create_dynamic_sections (abfd, info))
363c074d1c9Sdrahn return FALSE;
3642159047fSniklas linux_hash_table (info)->dynobj = abfd;
365c074d1c9Sdrahn insert = TRUE;
3662159047fSniklas }
3672159047fSniklas
3682159047fSniklas if (bfd_is_abs_section (section)
3692159047fSniklas && abfd->xvec == info->hash->creator)
3702159047fSniklas {
371c074d1c9Sdrahn h = linux_link_hash_lookup (linux_hash_table (info), name, FALSE,
372c074d1c9Sdrahn FALSE, FALSE);
3732159047fSniklas if (h != NULL
3742159047fSniklas && (h->root.root.type == bfd_link_hash_defined
3752159047fSniklas || h->root.root.type == bfd_link_hash_defweak))
3762159047fSniklas {
3772159047fSniklas struct fixup *f;
3782159047fSniklas
3792159047fSniklas if (hashp != NULL)
3802159047fSniklas *hashp = (struct bfd_link_hash_entry *) h;
3812159047fSniklas
3822159047fSniklas f = new_fixup (info, h, value, ! IS_PLT_SYM (name));
3832159047fSniklas if (f == NULL)
384c074d1c9Sdrahn return FALSE;
3852159047fSniklas f->jump = IS_PLT_SYM (name);
3862159047fSniklas
387c074d1c9Sdrahn return TRUE;
3882159047fSniklas }
3892159047fSniklas }
3902159047fSniklas
3912159047fSniklas /* Do the usual procedure for adding a symbol. */
3922159047fSniklas if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
3932159047fSniklas value, string, copy, collect,
3942159047fSniklas hashp))
395c074d1c9Sdrahn return FALSE;
3962159047fSniklas
3972159047fSniklas /* Insert a pointer to our table in the set vector. The dynamic
3982159047fSniklas linker requires this information */
3992159047fSniklas if (insert)
4002159047fSniklas {
4012159047fSniklas asection *s;
4022159047fSniklas
4032159047fSniklas /* Here we do our special thing to add the pointer to the
4042159047fSniklas dynamic section in the SHARABLE_CONFLICTS set vector. */
4052159047fSniklas s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
4062159047fSniklas ".linux-dynamic");
4072159047fSniklas BFD_ASSERT (s != NULL);
4082159047fSniklas
4092159047fSniklas if (! (_bfd_generic_link_add_one_symbol
4102159047fSniklas (info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS,
411c074d1c9Sdrahn BSF_GLOBAL | BSF_CONSTRUCTOR, s, (bfd_vma) 0, NULL,
412c074d1c9Sdrahn FALSE, FALSE, NULL)))
413c074d1c9Sdrahn return FALSE;
4142159047fSniklas }
4152159047fSniklas
416c074d1c9Sdrahn return TRUE;
4172159047fSniklas }
4182159047fSniklas
4192159047fSniklas /* We will crawl the hash table and come here for every global symbol.
4202159047fSniklas We will examine each entry and see if there are indications that we
4212159047fSniklas need to add a fixup. There are two possible cases - one is where
4222159047fSniklas you have duplicate definitions of PLT or GOT symbols - these will
4232159047fSniklas have already been caught and added as "builtin" fixups. If we find
4242159047fSniklas that the corresponding non PLT/GOT symbol is also present, we
4252159047fSniklas convert it to a regular fixup instead.
4262159047fSniklas
4272159047fSniklas This function is called via linux_link_hash_traverse. */
4282159047fSniklas
429c074d1c9Sdrahn static bfd_boolean
linux_tally_symbols(h,data)4302159047fSniklas linux_tally_symbols (h, data)
4312159047fSniklas struct linux_link_hash_entry *h;
4322159047fSniklas PTR data;
4332159047fSniklas {
4342159047fSniklas struct bfd_link_info *info = (struct bfd_link_info *) data;
4352159047fSniklas struct fixup *f, *f1;
4362159047fSniklas int is_plt;
4372159047fSniklas struct linux_link_hash_entry *h1, *h2;
438c074d1c9Sdrahn bfd_boolean exists;
439c074d1c9Sdrahn
440c074d1c9Sdrahn if (h->root.root.type == bfd_link_hash_warning)
441c074d1c9Sdrahn h = (struct linux_link_hash_entry *) h->root.root.u.i.link;
4422159047fSniklas
4432159047fSniklas if (h->root.root.type == bfd_link_hash_undefined
4442159047fSniklas && strncmp (h->root.root.root.string, NEEDS_SHRLIB,
4452159047fSniklas sizeof NEEDS_SHRLIB - 1) == 0)
4462159047fSniklas {
4472159047fSniklas const char *name;
4482159047fSniklas char *p;
4492159047fSniklas char *alloc = NULL;
4502159047fSniklas
4512159047fSniklas name = h->root.root.root.string + sizeof NEEDS_SHRLIB - 1;
4522159047fSniklas p = strrchr (name, '_');
4532159047fSniklas if (p != NULL)
454c074d1c9Sdrahn alloc = (char *) bfd_malloc ((bfd_size_type) strlen (name) + 1);
4552159047fSniklas
4562159047fSniklas if (p == NULL || alloc == NULL)
457b305b0f1Sespie (*_bfd_error_handler) (_("Output file requires shared library `%s'\n"),
4582159047fSniklas name);
4592159047fSniklas else
4602159047fSniklas {
4612159047fSniklas strcpy (alloc, name);
4622159047fSniklas p = strrchr (alloc, '_');
4632159047fSniklas *p++ = '\0';
4642159047fSniklas (*_bfd_error_handler)
465b305b0f1Sespie (_("Output file requires shared library `%s.so.%s'\n"),
4662159047fSniklas alloc, p);
4672159047fSniklas free (alloc);
4682159047fSniklas }
4692159047fSniklas
4702159047fSniklas abort ();
4712159047fSniklas }
4722159047fSniklas
4732159047fSniklas /* If this symbol is not a PLT/GOT, we do not even need to look at it */
4742159047fSniklas is_plt = IS_PLT_SYM (h->root.root.root.string);
4752159047fSniklas
4762159047fSniklas if (is_plt || IS_GOT_SYM (h->root.root.root.string))
4772159047fSniklas {
4782159047fSniklas /* Look up this symbol twice. Once just as a regular lookup,
4792159047fSniklas and then again following all of the indirect links until we
4802159047fSniklas reach a real symbol. */
4812159047fSniklas h1 = linux_link_hash_lookup (linux_hash_table (info),
4822159047fSniklas (h->root.root.root.string
4832159047fSniklas + sizeof PLT_REF_PREFIX - 1),
484c074d1c9Sdrahn FALSE, FALSE, TRUE);
4852159047fSniklas /* h2 does not follow indirect symbols. */
4862159047fSniklas h2 = linux_link_hash_lookup (linux_hash_table (info),
4872159047fSniklas (h->root.root.root.string
4882159047fSniklas + sizeof PLT_REF_PREFIX - 1),
489c074d1c9Sdrahn FALSE, FALSE, FALSE);
4902159047fSniklas
4912159047fSniklas /* The real symbol must exist but if it is also an ABS symbol,
4922159047fSniklas there is no need to have a fixup. This is because they both
4932159047fSniklas came from the same library. If on the other hand, we had to
4942159047fSniklas use an indirect symbol to get to the real symbol, we add the
4952159047fSniklas fixup anyway, since there are cases where these symbols come
4962159047fSniklas from different shared libraries */
4972159047fSniklas if (h1 != NULL
4982159047fSniklas && (((h1->root.root.type == bfd_link_hash_defined
4992159047fSniklas || h1->root.root.type == bfd_link_hash_defweak)
5002159047fSniklas && ! bfd_is_abs_section (h1->root.root.u.def.section))
5012159047fSniklas || h2->root.root.type == bfd_link_hash_indirect))
5022159047fSniklas {
5032159047fSniklas /* See if there is a "builtin" fixup already present
5042159047fSniklas involving this symbol. If so, convert it to a regular
5052159047fSniklas fixup. In the end, this relaxes some of the requirements
5062159047fSniklas about the order of performing fixups. */
507c074d1c9Sdrahn exists = FALSE;
5082159047fSniklas for (f1 = linux_hash_table (info)->fixup_list;
5092159047fSniklas f1 != NULL;
5102159047fSniklas f1 = f1->next)
5112159047fSniklas {
5122159047fSniklas if ((f1->h != h && f1->h != h1)
5132159047fSniklas || (! f1->builtin && ! f1->jump))
5142159047fSniklas continue;
5152159047fSniklas if (f1->h == h1)
516c074d1c9Sdrahn exists = TRUE;
5172159047fSniklas if (! exists
5182159047fSniklas && bfd_is_abs_section (h->root.root.u.def.section))
5192159047fSniklas {
5202159047fSniklas f = new_fixup (info, h1, f1->h->root.root.u.def.value, 0);
5212159047fSniklas f->jump = is_plt;
5222159047fSniklas }
5232159047fSniklas f1->h = h1;
5242159047fSniklas f1->jump = is_plt;
5252159047fSniklas f1->builtin = 0;
526c074d1c9Sdrahn exists = TRUE;
5272159047fSniklas }
5282159047fSniklas if (! exists
5292159047fSniklas && bfd_is_abs_section (h->root.root.u.def.section))
5302159047fSniklas {
5312159047fSniklas f = new_fixup (info, h1, h->root.root.u.def.value, 0);
5322159047fSniklas if (f == NULL)
5332159047fSniklas {
5342159047fSniklas /* FIXME: No way to return error. */
5352159047fSniklas abort ();
5362159047fSniklas }
5372159047fSniklas f->jump = is_plt;
5382159047fSniklas }
5392159047fSniklas }
5402159047fSniklas
5412159047fSniklas /* Quick and dirty way of stripping these symbols from the
5422159047fSniklas symtab. */
5432159047fSniklas if (bfd_is_abs_section (h->root.root.u.def.section))
544c074d1c9Sdrahn h->root.written = TRUE;
5452159047fSniklas }
5462159047fSniklas
547c074d1c9Sdrahn return TRUE;
5482159047fSniklas }
5492159047fSniklas
5502159047fSniklas /* This is called to set the size of the .linux-dynamic section is.
5512159047fSniklas It is called by the Linux linker emulation before_allocation
5522159047fSniklas routine. We have finished reading all of the input files, and now
5532159047fSniklas we just scan the hash tables to find out how many additional fixups
5542159047fSniklas are required. */
5552159047fSniklas
556c074d1c9Sdrahn bfd_boolean
bfd_i386linux_size_dynamic_sections(output_bfd,info)557c88b1d6cSniklas bfd_i386linux_size_dynamic_sections (output_bfd, info)
5582159047fSniklas bfd *output_bfd;
5592159047fSniklas struct bfd_link_info *info;
5602159047fSniklas {
5612159047fSniklas struct fixup *f;
5622159047fSniklas asection *s;
5632159047fSniklas
5642159047fSniklas if (output_bfd->xvec != &MY(vec))
565c074d1c9Sdrahn return TRUE;
5662159047fSniklas
5672159047fSniklas /* First find the fixups... */
5682159047fSniklas linux_link_hash_traverse (linux_hash_table (info),
5692159047fSniklas linux_tally_symbols,
5702159047fSniklas (PTR) info);
5712159047fSniklas
5722159047fSniklas /* If there are builtin fixups, leave room for a marker. This is
5732159047fSniklas used by the dynamic linker so that it knows that all that follow
5742159047fSniklas are builtin fixups instead of regular fixups. */
5752159047fSniklas for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
5762159047fSniklas {
5772159047fSniklas if (f->builtin)
5782159047fSniklas {
5792159047fSniklas ++linux_hash_table (info)->fixup_count;
5802159047fSniklas ++linux_hash_table (info)->local_builtins;
5812159047fSniklas break;
5822159047fSniklas }
5832159047fSniklas }
5842159047fSniklas
5852159047fSniklas if (linux_hash_table (info)->dynobj == NULL)
5862159047fSniklas {
5872159047fSniklas if (linux_hash_table (info)->fixup_count > 0)
5882159047fSniklas abort ();
589c074d1c9Sdrahn return TRUE;
5902159047fSniklas }
5912159047fSniklas
5922159047fSniklas /* Allocate memory for our fixup table. We will fill it in later. */
5932159047fSniklas s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
5942159047fSniklas ".linux-dynamic");
5952159047fSniklas if (s != NULL)
5962159047fSniklas {
597c074d1c9Sdrahn s->_raw_size = linux_hash_table (info)->fixup_count + 1;
598c074d1c9Sdrahn s->_raw_size *= 8;
599c074d1c9Sdrahn s->contents = (bfd_byte *) bfd_zalloc (output_bfd, s->_raw_size);
6002159047fSniklas if (s->contents == NULL)
601c074d1c9Sdrahn return FALSE;
6022159047fSniklas }
6032159047fSniklas
604c074d1c9Sdrahn return TRUE;
6052159047fSniklas }
6062159047fSniklas
6072159047fSniklas /* We come here once we are ready to actually write the fixup table to
6082159047fSniklas the output file. Scan the fixup tables and so forth and generate
6092159047fSniklas the stuff we need. */
6102159047fSniklas
611c074d1c9Sdrahn static bfd_boolean
linux_finish_dynamic_link(output_bfd,info)6122159047fSniklas linux_finish_dynamic_link (output_bfd, info)
6132159047fSniklas bfd *output_bfd;
6142159047fSniklas struct bfd_link_info *info;
6152159047fSniklas {
6162159047fSniklas asection *s, *os, *is;
6172159047fSniklas bfd_byte *fixup_table;
6182159047fSniklas struct linux_link_hash_entry *h;
6192159047fSniklas struct fixup *f;
6202159047fSniklas unsigned int new_addr;
6212159047fSniklas int section_offset;
6222159047fSniklas unsigned int fixups_written;
6232159047fSniklas
6242159047fSniklas if (linux_hash_table (info)->dynobj == NULL)
625c074d1c9Sdrahn return TRUE;
6262159047fSniklas
6272159047fSniklas s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
6282159047fSniklas ".linux-dynamic");
6292159047fSniklas BFD_ASSERT (s != NULL);
6302159047fSniklas os = s->output_section;
6312159047fSniklas fixups_written = 0;
6322159047fSniklas
6332159047fSniklas #ifdef LINUX_LINK_DEBUG
6342159047fSniklas printf ("Fixup table file offset: %x VMA: %x\n",
6352159047fSniklas os->filepos + s->output_offset,
6362159047fSniklas os->vma + s->output_offset);
6372159047fSniklas #endif
6382159047fSniklas
6392159047fSniklas fixup_table = s->contents;
640c074d1c9Sdrahn bfd_put_32 (output_bfd,
641c074d1c9Sdrahn (bfd_vma) linux_hash_table (info)->fixup_count, fixup_table);
6422159047fSniklas fixup_table += 4;
6432159047fSniklas
6442159047fSniklas /* Fill in fixup table. */
6452159047fSniklas for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
6462159047fSniklas {
6472159047fSniklas if (f->builtin)
6482159047fSniklas continue;
6492159047fSniklas
6502159047fSniklas if (f->h->root.root.type != bfd_link_hash_defined
6512159047fSniklas && f->h->root.root.type != bfd_link_hash_defweak)
6522159047fSniklas {
6532159047fSniklas (*_bfd_error_handler)
654b305b0f1Sespie (_("Symbol %s not defined for fixups\n"),
6552159047fSniklas f->h->root.root.root.string);
6562159047fSniklas continue;
6572159047fSniklas }
6582159047fSniklas
6592159047fSniklas is = f->h->root.root.u.def.section;
6602159047fSniklas section_offset = is->output_section->vma + is->output_offset;
6612159047fSniklas new_addr = f->h->root.root.u.def.value + section_offset;
6622159047fSniklas
6632159047fSniklas #ifdef LINUX_LINK_DEBUG
6642159047fSniklas printf ("Fixup(%d) %s: %x %x\n",f->jump, f->h->root.root.string,
6652159047fSniklas new_addr, f->value);
6662159047fSniklas #endif
6672159047fSniklas
6682159047fSniklas if (f->jump)
6692159047fSniklas {
6702159047fSniklas /* Relative address */
6712159047fSniklas new_addr = new_addr - (f->value + 5);
672c074d1c9Sdrahn bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
6732159047fSniklas fixup_table += 4;
6742159047fSniklas bfd_put_32 (output_bfd, f->value + 1, fixup_table);
6752159047fSniklas fixup_table += 4;
6762159047fSniklas }
6772159047fSniklas else
6782159047fSniklas {
679c074d1c9Sdrahn bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
6802159047fSniklas fixup_table += 4;
6812159047fSniklas bfd_put_32 (output_bfd, f->value, fixup_table);
6822159047fSniklas fixup_table += 4;
6832159047fSniklas }
6842159047fSniklas ++fixups_written;
6852159047fSniklas }
6862159047fSniklas
6872159047fSniklas if (linux_hash_table (info)->local_builtins != 0)
6882159047fSniklas {
6892159047fSniklas /* Special marker so we know to switch to the other type of fixup */
690c074d1c9Sdrahn bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
6912159047fSniklas fixup_table += 4;
692c074d1c9Sdrahn bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
6932159047fSniklas fixup_table += 4;
6942159047fSniklas ++fixups_written;
6952159047fSniklas for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
6962159047fSniklas {
6972159047fSniklas if (! f->builtin)
6982159047fSniklas continue;
6992159047fSniklas
7002159047fSniklas if (f->h->root.root.type != bfd_link_hash_defined
7012159047fSniklas && f->h->root.root.type != bfd_link_hash_defweak)
7022159047fSniklas {
7032159047fSniklas (*_bfd_error_handler)
704b305b0f1Sespie (_("Symbol %s not defined for fixups\n"),
7052159047fSniklas f->h->root.root.root.string);
7062159047fSniklas continue;
7072159047fSniklas }
7082159047fSniklas
7092159047fSniklas is = f->h->root.root.u.def.section;
7102159047fSniklas section_offset = is->output_section->vma + is->output_offset;
7112159047fSniklas new_addr = f->h->root.root.u.def.value + section_offset;
7122159047fSniklas
7132159047fSniklas #ifdef LINUX_LINK_DEBUG
7142159047fSniklas printf ("Fixup(B) %s: %x %x\n", f->h->root.root.string,
7152159047fSniklas new_addr, f->value);
7162159047fSniklas #endif
7172159047fSniklas
718c074d1c9Sdrahn bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
7192159047fSniklas fixup_table += 4;
7202159047fSniklas bfd_put_32 (output_bfd, f->value, fixup_table);
7212159047fSniklas fixup_table += 4;
7222159047fSniklas ++fixups_written;
7232159047fSniklas }
7242159047fSniklas }
7252159047fSniklas
7262159047fSniklas if (linux_hash_table (info)->fixup_count != fixups_written)
7272159047fSniklas {
728b305b0f1Sespie (*_bfd_error_handler) (_("Warning: fixup count mismatch\n"));
7292159047fSniklas while (linux_hash_table (info)->fixup_count > fixups_written)
7302159047fSniklas {
731c074d1c9Sdrahn bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
7322159047fSniklas fixup_table += 4;
733c074d1c9Sdrahn bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
7342159047fSniklas fixup_table += 4;
7352159047fSniklas ++fixups_written;
7362159047fSniklas }
7372159047fSniklas }
7382159047fSniklas
7392159047fSniklas h = linux_link_hash_lookup (linux_hash_table (info),
7402159047fSniklas "__BUILTIN_FIXUPS__",
741c074d1c9Sdrahn FALSE, FALSE, FALSE);
7422159047fSniklas
7432159047fSniklas if (h != NULL
7442159047fSniklas && (h->root.root.type == bfd_link_hash_defined
7452159047fSniklas || h->root.root.type == bfd_link_hash_defweak))
7462159047fSniklas {
7472159047fSniklas is = h->root.root.u.def.section;
7482159047fSniklas section_offset = is->output_section->vma + is->output_offset;
7492159047fSniklas new_addr = h->root.root.u.def.value + section_offset;
7502159047fSniklas
7512159047fSniklas #ifdef LINUX_LINK_DEBUG
7522159047fSniklas printf ("Builtin fixup table at %x\n", new_addr);
7532159047fSniklas #endif
7542159047fSniklas
755c074d1c9Sdrahn bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
7562159047fSniklas }
7572159047fSniklas else
758c074d1c9Sdrahn bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
7592159047fSniklas
760c074d1c9Sdrahn if (bfd_seek (output_bfd, (file_ptr) (os->filepos + s->output_offset),
761c074d1c9Sdrahn SEEK_SET) != 0)
762c074d1c9Sdrahn return FALSE;
7632159047fSniklas
764c074d1c9Sdrahn if (bfd_bwrite ((PTR) s->contents, s->_raw_size, output_bfd) != s->_raw_size)
765c074d1c9Sdrahn return FALSE;
7662159047fSniklas
767c074d1c9Sdrahn return TRUE;
7682159047fSniklas }
7692159047fSniklas
7702159047fSniklas #define MY_bfd_link_hash_table_create linux_link_hash_table_create
7712159047fSniklas #define MY_add_one_symbol linux_add_one_symbol
7722159047fSniklas #define MY_finish_dynamic_link linux_finish_dynamic_link
7732159047fSniklas
7742159047fSniklas #define MY_zmagic_contiguous 1
7752159047fSniklas
7762159047fSniklas #include "aout-target.h"
777