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