Back to index

cell-binutils  2.17cvs20070401
i386linux.c
Go to the documentation of this file.
00001 /* BFD back-end for linux flavored i386 a.out binaries.
00002    Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2001, 2002, 2003,
00003    2004, 2006 Free Software Foundation, Inc.
00004 
00005 This file is part of BFD, the Binary File Descriptor library.
00006 
00007 This program is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 This program is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with this program; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 
00021 #define       TARGET_PAGE_SIZE     4096
00022 #define ZMAGIC_DISK_BLOCK_SIZE 1024
00023 #define       SEGMENT_SIZE TARGET_PAGE_SIZE
00024 #define TEXT_START_ADDR     0x0
00025 #define N_SHARED_LIB(x) 0
00026 
00027 #define MACHTYPE_OK(mtype) ((mtype) == M_386 || (mtype) == M_UNKNOWN)
00028 
00029 #include "bfd.h"
00030 #include "sysdep.h"
00031 #include "libbfd.h"
00032 #include "aout/aout64.h"
00033 #include "aout/stab_gnu.h"
00034 #include "aout/ar.h"
00035 #include "libaout.h"           /* BFD a.out internal data structures */
00036 
00037 #define DEFAULT_ARCH bfd_arch_i386
00038 
00039 /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
00040    remove whitespace added here, and thus will fail to concatenate
00041    the tokens.  */
00042 #define MY(OP) CONCAT2 (i386linux_,OP)
00043 #define TARGETNAME "a.out-i386-linux"
00044 
00045 extern const bfd_target MY(vec);
00046 
00047 /* We always generate QMAGIC files in preference to ZMAGIC files.  It
00048    would be possible to make this a linker option, if that ever
00049    becomes important.  */
00050 
00051 static void MY_final_link_callback
00052   PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *));
00053 static bfd_boolean i386linux_bfd_final_link
00054   PARAMS ((bfd *, struct bfd_link_info *));
00055 static bfd_boolean i386linux_write_object_contents PARAMS ((bfd *));
00056 
00057 static bfd_boolean
00058 i386linux_bfd_final_link (abfd, info)
00059      bfd *abfd;
00060      struct bfd_link_info *info;
00061 {
00062   obj_aout_subformat (abfd) = q_magic_format;
00063   return NAME(aout,final_link) (abfd, info, MY_final_link_callback);
00064 }
00065 
00066 #define MY_bfd_final_link i386linux_bfd_final_link
00067 
00068 /* Set the machine type correctly.  */
00069 
00070 static bfd_boolean
00071 i386linux_write_object_contents (abfd)
00072      bfd *abfd;
00073 {
00074   struct external_exec exec_bytes;
00075   struct internal_exec *execp = exec_hdr (abfd);
00076 
00077   N_SET_MACHTYPE (*execp, M_386);
00078 
00079   obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
00080 
00081   WRITE_HEADERS(abfd, execp);
00082 
00083   return TRUE;
00084 }
00085 
00086 #define MY_write_object_contents i386linux_write_object_contents
00087 
00088 /* Code to link against Linux a.out shared libraries.  */
00089 
00090 /* See if a symbol name is a reference to the global offset table.  */
00091 
00092 #ifndef GOT_REF_PREFIX
00093 #define       GOT_REF_PREFIX       "__GOT_"
00094 #endif
00095 
00096 #define IS_GOT_SYM(name)   (CONST_STRNEQ (name, GOT_REF_PREFIX))
00097 
00098 /* See if a symbol name is a reference to the procedure linkage table.  */
00099 
00100 #ifndef PLT_REF_PREFIX
00101 #define       PLT_REF_PREFIX       "__PLT_"
00102 #endif
00103 
00104 #define IS_PLT_SYM(name)  (CONST_STRNEQ (name, PLT_REF_PREFIX))
00105 
00106 /* This string is used to generate specialized error messages.  */
00107 
00108 #ifndef NEEDS_SHRLIB
00109 #define NEEDS_SHRLIB "__NEEDS_SHRLIB_"
00110 #endif
00111 
00112 /* This special symbol is a set vector that contains a list of
00113    pointers to fixup tables.  It will be present in any dynamically
00114    linked file.  The linker generated fixup table should also be added
00115    to the list, and it should always appear in the second slot (the
00116    first one is a dummy with a magic number that is defined in
00117    crt0.o).  */
00118 
00119 #ifndef SHARABLE_CONFLICTS
00120 #define SHARABLE_CONFLICTS "__SHARABLE_CONFLICTS__"
00121 #endif
00122 
00123 /* We keep a list of fixups.  The terminology is a bit strange, but
00124    each fixup contains two 32 bit numbers.  A regular fixup contains
00125    an address and a pointer, and at runtime we should store the
00126    address at the location pointed to by the pointer.  A builtin fixup
00127    contains two pointers, and we should read the address using one
00128    pointer and store it at the location pointed to by the other
00129    pointer.  Builtin fixups come into play when we have duplicate
00130    __GOT__ symbols for the same variable.  The builtin fixup will copy
00131    the GOT pointer from one over into the other.  */
00132 
00133 struct fixup
00134 {
00135   struct fixup *next;
00136   struct linux_link_hash_entry *h;
00137   bfd_vma value;
00138 
00139   /* Nonzero if this is a jump instruction that needs to be fixed,
00140      zero if this is just a pointer */
00141   char jump;
00142 
00143   char builtin;
00144 };
00145 
00146 /* We don't need a special hash table entry structure, but we do need
00147    to keep some information between linker passes, so we use a special
00148    hash table.  */
00149 
00150 struct linux_link_hash_entry
00151 {
00152   struct aout_link_hash_entry root;
00153 };
00154 
00155 struct linux_link_hash_table
00156 {
00157   struct aout_link_hash_table root;
00158 
00159   /* First dynamic object found in link.  */
00160   bfd *dynobj;
00161 
00162   /* Number of fixups.  */
00163   size_t fixup_count;
00164 
00165   /* Number of builtin fixups.  */
00166   size_t local_builtins;
00167 
00168   /* List of fixups.  */
00169   struct fixup *fixup_list;
00170 };
00171 
00172 static struct bfd_hash_entry *linux_link_hash_newfunc
00173   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
00174 static struct bfd_link_hash_table *linux_link_hash_table_create
00175   PARAMS ((bfd *));
00176 static struct fixup *new_fixup
00177   PARAMS ((struct bfd_link_info *, struct linux_link_hash_entry *,
00178           bfd_vma, int));
00179 static bfd_boolean linux_link_create_dynamic_sections
00180   PARAMS ((bfd *, struct bfd_link_info *));
00181 static bfd_boolean linux_add_one_symbol
00182   PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
00183           bfd_vma, const char *, bfd_boolean, bfd_boolean,
00184           struct bfd_link_hash_entry **));
00185 static bfd_boolean linux_tally_symbols
00186   PARAMS ((struct linux_link_hash_entry *, PTR));
00187 static bfd_boolean linux_finish_dynamic_link
00188   PARAMS ((bfd *, struct bfd_link_info *));
00189 
00190 /* Routine to create an entry in an Linux link hash table.  */
00191 
00192 static struct bfd_hash_entry *
00193 linux_link_hash_newfunc (entry, table, string)
00194      struct bfd_hash_entry *entry;
00195      struct bfd_hash_table *table;
00196      const char *string;
00197 {
00198   struct linux_link_hash_entry *ret = (struct linux_link_hash_entry *) entry;
00199 
00200   /* Allocate the structure if it has not already been allocated by a
00201      subclass.  */
00202   if (ret == (struct linux_link_hash_entry *) NULL)
00203     ret = ((struct linux_link_hash_entry *)
00204           bfd_hash_allocate (table, sizeof (struct linux_link_hash_entry)));
00205   if (ret == NULL)
00206     return (struct bfd_hash_entry *) ret;
00207 
00208   /* Call the allocation method of the superclass.  */
00209   ret = ((struct linux_link_hash_entry *)
00210         NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret,
00211                                    table, string));
00212   if (ret != NULL)
00213     {
00214       /* Set local fields; there aren't any.  */
00215     }
00216 
00217   return (struct bfd_hash_entry *) ret;
00218 }
00219 
00220 /* Create a Linux link hash table.  */
00221 
00222 static struct bfd_link_hash_table *
00223 linux_link_hash_table_create (abfd)
00224      bfd *abfd;
00225 {
00226   struct linux_link_hash_table *ret;
00227   bfd_size_type amt = sizeof (struct linux_link_hash_table);
00228 
00229   ret = (struct linux_link_hash_table *) bfd_alloc (abfd, amt);
00230   if (ret == (struct linux_link_hash_table *) NULL)
00231     return (struct bfd_link_hash_table *) NULL;
00232   if (!NAME(aout,link_hash_table_init) (&ret->root, abfd,
00233                                    linux_link_hash_newfunc,
00234                                    sizeof (struct linux_link_hash_entry)))
00235     {
00236       free (ret);
00237       return (struct bfd_link_hash_table *) NULL;
00238     }
00239 
00240   ret->dynobj = NULL;
00241   ret->fixup_count = 0;
00242   ret->local_builtins = 0;
00243   ret->fixup_list = NULL;
00244 
00245   return &ret->root.root;
00246 }
00247 
00248 /* Look up an entry in a Linux link hash table.  */
00249 
00250 #define linux_link_hash_lookup(table, string, create, copy, follow) \
00251   ((struct linux_link_hash_entry *) \
00252    aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\
00253                        (follow)))
00254 
00255 /* Traverse a Linux link hash table.  */
00256 
00257 #define linux_link_hash_traverse(table, func, info)                   \
00258   (aout_link_hash_traverse                                     \
00259    (&(table)->root,                                            \
00260     (bfd_boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \
00261     (info)))
00262 
00263 /* Get the Linux link hash table from the info structure.  This is
00264    just a cast.  */
00265 
00266 #define linux_hash_table(p) ((struct linux_link_hash_table *) ((p)->hash))
00267 
00268 /* Store the information for a new fixup.  */
00269 
00270 static struct fixup *
00271 new_fixup (info, h, value, builtin)
00272      struct bfd_link_info *info;
00273      struct linux_link_hash_entry *h;
00274      bfd_vma value;
00275      int builtin;
00276 {
00277   struct fixup *f;
00278 
00279   f = (struct fixup *) bfd_hash_allocate (&info->hash->table,
00280                                      sizeof (struct fixup));
00281   if (f == NULL)
00282     return f;
00283   f->next = linux_hash_table (info)->fixup_list;
00284   linux_hash_table (info)->fixup_list = f;
00285   f->h = h;
00286   f->value = value;
00287   f->builtin = builtin;
00288   f->jump = 0;
00289   ++linux_hash_table (info)->fixup_count;
00290   return f;
00291 }
00292 
00293 /* We come here once we realize that we are going to link to a shared
00294    library.  We need to create a special section that contains the
00295    fixup table, and we ultimately need to add a pointer to this into
00296    the set vector for SHARABLE_CONFLICTS.  At this point we do not
00297    know the size of the section, but that's OK - we just need to
00298    create it for now.  */
00299 
00300 static bfd_boolean
00301 linux_link_create_dynamic_sections (abfd, info)
00302      bfd *abfd;
00303      struct bfd_link_info *info ATTRIBUTE_UNUSED;
00304 {
00305   flagword flags;
00306   register asection *s;
00307 
00308   /* Note that we set the SEC_IN_MEMORY flag.  */
00309   flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
00310 
00311   /* We choose to use the name ".linux-dynamic" for the fixup table.
00312      Why not? */
00313   s = bfd_make_section_with_flags (abfd, ".linux-dynamic", flags);
00314   if (s == NULL
00315       || ! bfd_set_section_alignment (abfd, s, 2))
00316     return FALSE;
00317   s->size = 0;
00318   s->contents = 0;
00319 
00320   return TRUE;
00321 }
00322 
00323 /* Function to add a single symbol to the linker hash table.  This is
00324    a wrapper around _bfd_generic_link_add_one_symbol which handles the
00325    tweaking needed for dynamic linking support.  */
00326 
00327 static bfd_boolean
00328 linux_add_one_symbol (info, abfd, name, flags, section, value, string,
00329                     copy, collect, hashp)
00330      struct bfd_link_info *info;
00331      bfd *abfd;
00332      const char *name;
00333      flagword flags;
00334      asection *section;
00335      bfd_vma value;
00336      const char *string;
00337      bfd_boolean copy;
00338      bfd_boolean collect;
00339      struct bfd_link_hash_entry **hashp;
00340 {
00341   struct linux_link_hash_entry *h;
00342   bfd_boolean insert;
00343 
00344   /* Look up and see if we already have this symbol in the hash table.
00345      If we do, and the defining entry is from a shared library, we
00346      need to create the dynamic sections.
00347 
00348      FIXME: What if abfd->xvec != info->hash->creator?  We may want to
00349      be able to link Linux a.out and ELF objects together, but serious
00350      confusion is possible.  */
00351 
00352   insert = FALSE;
00353 
00354   if (! info->relocatable
00355       && linux_hash_table (info)->dynobj == NULL
00356       && strcmp (name, SHARABLE_CONFLICTS) == 0
00357       && (flags & BSF_CONSTRUCTOR) != 0
00358       && abfd->xvec == info->hash->creator)
00359     {
00360       if (! linux_link_create_dynamic_sections (abfd, info))
00361        return FALSE;
00362       linux_hash_table (info)->dynobj = abfd;
00363       insert = TRUE;
00364     }
00365 
00366   if (bfd_is_abs_section (section)
00367       && abfd->xvec == info->hash->creator)
00368     {
00369       h = linux_link_hash_lookup (linux_hash_table (info), name, FALSE,
00370                               FALSE, FALSE);
00371       if (h != NULL
00372          && (h->root.root.type == bfd_link_hash_defined
00373              || h->root.root.type == bfd_link_hash_defweak))
00374        {
00375          struct fixup *f;
00376 
00377          if (hashp != NULL)
00378            *hashp = (struct bfd_link_hash_entry *) h;
00379 
00380          f = new_fixup (info, h, value, ! IS_PLT_SYM (name));
00381          if (f == NULL)
00382            return FALSE;
00383          f->jump = IS_PLT_SYM (name);
00384 
00385          return TRUE;
00386        }
00387     }
00388 
00389   /* Do the usual procedure for adding a symbol.  */
00390   if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
00391                                      value, string, copy, collect,
00392                                      hashp))
00393     return FALSE;
00394 
00395   /* Insert a pointer to our table in the set vector.  The dynamic
00396      linker requires this information */
00397   if (insert)
00398     {
00399       asection *s;
00400 
00401       /* Here we do our special thing to add the pointer to the
00402         dynamic section in the SHARABLE_CONFLICTS set vector.  */
00403       s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
00404                                ".linux-dynamic");
00405       BFD_ASSERT (s != NULL);
00406 
00407       if (! (_bfd_generic_link_add_one_symbol
00408             (info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS,
00409              BSF_GLOBAL | BSF_CONSTRUCTOR, s, (bfd_vma) 0, NULL,
00410              FALSE, FALSE, NULL)))
00411        return FALSE;
00412     }
00413 
00414   return TRUE;
00415 }
00416 
00417 /* We will crawl the hash table and come here for every global symbol.
00418    We will examine each entry and see if there are indications that we
00419    need to add a fixup.  There are two possible cases - one is where
00420    you have duplicate definitions of PLT or GOT symbols - these will
00421    have already been caught and added as "builtin" fixups.  If we find
00422    that the corresponding non PLT/GOT symbol is also present, we
00423    convert it to a regular fixup instead.
00424 
00425    This function is called via linux_link_hash_traverse.  */
00426 
00427 static bfd_boolean
00428 linux_tally_symbols (h, data)
00429      struct linux_link_hash_entry *h;
00430      PTR data;
00431 {
00432   struct bfd_link_info *info = (struct bfd_link_info *) data;
00433   struct fixup *f, *f1;
00434   int is_plt;
00435   struct linux_link_hash_entry *h1, *h2;
00436   bfd_boolean exists;
00437 
00438   if (h->root.root.type == bfd_link_hash_warning)
00439     h = (struct linux_link_hash_entry *) h->root.root.u.i.link;
00440 
00441   if (h->root.root.type == bfd_link_hash_undefined
00442       && CONST_STRNEQ (h->root.root.root.string, NEEDS_SHRLIB))
00443     {
00444       const char *name;
00445       char *p;
00446       char *alloc = NULL;
00447 
00448       name = h->root.root.root.string + sizeof NEEDS_SHRLIB - 1;
00449       p = strrchr (name, '_');
00450       if (p != NULL)
00451        alloc = (char *) bfd_malloc ((bfd_size_type) strlen (name) + 1);
00452 
00453       if (p == NULL || alloc == NULL)
00454        (*_bfd_error_handler) (_("Output file requires shared library `%s'\n"),
00455                             name);
00456       else
00457        {
00458          strcpy (alloc, name);
00459          p = strrchr (alloc, '_');
00460          *p++ = '\0';
00461          (*_bfd_error_handler)
00462            (_("Output file requires shared library `%s.so.%s'\n"),
00463             alloc, p);
00464          free (alloc);
00465        }
00466 
00467       abort ();
00468     }
00469 
00470   /* If this symbol is not a PLT/GOT, we do not even need to look at it */
00471   is_plt = IS_PLT_SYM (h->root.root.root.string);
00472 
00473   if (is_plt || IS_GOT_SYM (h->root.root.root.string))
00474     {
00475       /* Look up this symbol twice.  Once just as a regular lookup,
00476         and then again following all of the indirect links until we
00477         reach a real symbol.  */
00478       h1 = linux_link_hash_lookup (linux_hash_table (info),
00479                                (h->root.root.root.string
00480                                 + sizeof PLT_REF_PREFIX - 1),
00481                                FALSE, FALSE, TRUE);
00482       /* h2 does not follow indirect symbols. */
00483       h2 = linux_link_hash_lookup (linux_hash_table (info),
00484                                (h->root.root.root.string
00485                                 + sizeof PLT_REF_PREFIX - 1),
00486                                FALSE, FALSE, FALSE);
00487 
00488       /* The real symbol must exist but if it is also an ABS symbol,
00489         there is no need to have a fixup.  This is because they both
00490         came from the same library.  If on the other hand, we had to
00491         use an indirect symbol to get to the real symbol, we add the
00492         fixup anyway, since there are cases where these symbols come
00493         from different shared libraries */
00494       if (h1 != NULL
00495          && (((h1->root.root.type == bfd_link_hash_defined
00496               || h1->root.root.type == bfd_link_hash_defweak)
00497               && ! bfd_is_abs_section (h1->root.root.u.def.section))
00498              || h2->root.root.type == bfd_link_hash_indirect))
00499        {
00500          /* See if there is a "builtin" fixup already present
00501             involving this symbol.  If so, convert it to a regular
00502             fixup.  In the end, this relaxes some of the requirements
00503             about the order of performing fixups.  */
00504          exists = FALSE;
00505          for (f1 = linux_hash_table (info)->fixup_list;
00506               f1 != NULL;
00507               f1 = f1->next)
00508            {
00509              if ((f1->h != h && f1->h != h1)
00510                 || (! f1->builtin && ! f1->jump))
00511               continue;
00512              if (f1->h == h1)
00513               exists = TRUE;
00514              if (! exists
00515                 && bfd_is_abs_section (h->root.root.u.def.section))
00516               {
00517                 f = new_fixup (info, h1, f1->h->root.root.u.def.value, 0);
00518                 f->jump = is_plt;
00519               }
00520              f1->h = h1;
00521              f1->jump = is_plt;
00522              f1->builtin = 0;
00523              exists = TRUE;
00524            }
00525          if (! exists
00526              && bfd_is_abs_section (h->root.root.u.def.section))
00527            {
00528              f = new_fixup (info, h1, h->root.root.u.def.value, 0);
00529              if (f == NULL)
00530               {
00531                 /* FIXME: No way to return error.  */
00532                 abort ();
00533               }
00534              f->jump = is_plt;
00535            }
00536        }
00537 
00538       /* Quick and dirty way of stripping these symbols from the
00539         symtab. */
00540       if (bfd_is_abs_section (h->root.root.u.def.section))
00541        h->root.written = TRUE;
00542     }
00543 
00544   return TRUE;
00545 }
00546 
00547 /* This is called to set the size of the .linux-dynamic section is.
00548    It is called by the Linux linker emulation before_allocation
00549    routine.  We have finished reading all of the input files, and now
00550    we just scan the hash tables to find out how many additional fixups
00551    are required.  */
00552 
00553 bfd_boolean
00554 bfd_i386linux_size_dynamic_sections (output_bfd, info)
00555      bfd *output_bfd;
00556      struct bfd_link_info *info;
00557 {
00558   struct fixup *f;
00559   asection *s;
00560 
00561   if (output_bfd->xvec != &MY(vec))
00562     return TRUE;
00563 
00564   /* First find the fixups... */
00565   linux_link_hash_traverse (linux_hash_table (info),
00566                          linux_tally_symbols,
00567                          (PTR) info);
00568 
00569   /* If there are builtin fixups, leave room for a marker.  This is
00570      used by the dynamic linker so that it knows that all that follow
00571      are builtin fixups instead of regular fixups.  */
00572   for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
00573     {
00574       if (f->builtin)
00575        {
00576          ++linux_hash_table (info)->fixup_count;
00577          ++linux_hash_table (info)->local_builtins;
00578          break;
00579        }
00580     }
00581 
00582   if (linux_hash_table (info)->dynobj == NULL)
00583     {
00584       if (linux_hash_table (info)->fixup_count > 0)
00585        abort ();
00586       return TRUE;
00587     }
00588 
00589   /* Allocate memory for our fixup table.  We will fill it in later.  */
00590   s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
00591                             ".linux-dynamic");
00592   if (s != NULL)
00593     {
00594       s->size = linux_hash_table (info)->fixup_count + 1;
00595       s->size *= 8;
00596       s->contents = (bfd_byte *) bfd_zalloc (output_bfd, s->size);
00597       if (s->contents == NULL)
00598        return FALSE;
00599     }
00600 
00601   return TRUE;
00602 }
00603 
00604 /* We come here once we are ready to actually write the fixup table to
00605    the output file.  Scan the fixup tables and so forth and generate
00606    the stuff we need.  */
00607 
00608 static bfd_boolean
00609 linux_finish_dynamic_link (output_bfd, info)
00610      bfd *output_bfd;
00611      struct bfd_link_info *info;
00612 {
00613   asection *s, *os, *is;
00614   bfd_byte *fixup_table;
00615   struct linux_link_hash_entry *h;
00616   struct fixup *f;
00617   unsigned int new_addr;
00618   int section_offset;
00619   unsigned int fixups_written;
00620 
00621   if (linux_hash_table (info)->dynobj == NULL)
00622     return TRUE;
00623 
00624   s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
00625                             ".linux-dynamic");
00626   BFD_ASSERT (s != NULL);
00627   os = s->output_section;
00628   fixups_written = 0;
00629 
00630 #ifdef LINUX_LINK_DEBUG
00631   printf ("Fixup table file offset: %x  VMA: %x\n",
00632          os->filepos + s->output_offset,
00633          os->vma + s->output_offset);
00634 #endif
00635 
00636   fixup_table = s->contents;
00637   bfd_put_32 (output_bfd,
00638              (bfd_vma) linux_hash_table (info)->fixup_count, fixup_table);
00639   fixup_table += 4;
00640 
00641   /* Fill in fixup table.  */
00642   for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
00643     {
00644       if (f->builtin)
00645        continue;
00646 
00647       if (f->h->root.root.type != bfd_link_hash_defined
00648          && f->h->root.root.type != bfd_link_hash_defweak)
00649        {
00650          (*_bfd_error_handler)
00651            (_("Symbol %s not defined for fixups\n"),
00652             f->h->root.root.root.string);
00653          continue;
00654        }
00655 
00656       is = f->h->root.root.u.def.section;
00657       section_offset = is->output_section->vma + is->output_offset;
00658       new_addr = f->h->root.root.u.def.value + section_offset;
00659 
00660 #ifdef LINUX_LINK_DEBUG
00661       printf ("Fixup(%d) %s: %x %x\n",f->jump, f->h->root.root.string,
00662              new_addr, f->value);
00663 #endif
00664 
00665       if (f->jump)
00666        {
00667          /* Relative address */
00668          new_addr = new_addr - (f->value + 5);
00669          bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
00670          fixup_table += 4;
00671          bfd_put_32 (output_bfd, f->value + 1, fixup_table);
00672          fixup_table += 4;
00673        }
00674       else
00675        {
00676          bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
00677          fixup_table += 4;
00678          bfd_put_32 (output_bfd, f->value, fixup_table);
00679          fixup_table += 4;
00680        }
00681       ++fixups_written;
00682     }
00683 
00684   if (linux_hash_table (info)->local_builtins != 0)
00685     {
00686       /* Special marker so we know to switch to the other type of fixup */
00687       bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
00688       fixup_table += 4;
00689       bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
00690       fixup_table += 4;
00691       ++fixups_written;
00692       for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
00693        {
00694          if (! f->builtin)
00695            continue;
00696 
00697          if (f->h->root.root.type != bfd_link_hash_defined
00698              && f->h->root.root.type != bfd_link_hash_defweak)
00699            {
00700              (*_bfd_error_handler)
00701               (_("Symbol %s not defined for fixups\n"),
00702                f->h->root.root.root.string);
00703              continue;
00704            }
00705 
00706          is = f->h->root.root.u.def.section;
00707          section_offset = is->output_section->vma + is->output_offset;
00708          new_addr = f->h->root.root.u.def.value + section_offset;
00709 
00710 #ifdef LINUX_LINK_DEBUG
00711          printf ("Fixup(B) %s: %x %x\n", f->h->root.root.string,
00712                 new_addr, f->value);
00713 #endif
00714 
00715          bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
00716          fixup_table += 4;
00717          bfd_put_32 (output_bfd, f->value, fixup_table);
00718          fixup_table += 4;
00719          ++fixups_written;
00720        }
00721   }
00722 
00723   if (linux_hash_table (info)->fixup_count != fixups_written)
00724     {
00725       (*_bfd_error_handler) (_("Warning: fixup count mismatch\n"));
00726       while (linux_hash_table (info)->fixup_count > fixups_written)
00727        {
00728          bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
00729          fixup_table += 4;
00730          bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
00731          fixup_table += 4;
00732          ++fixups_written;
00733        }
00734     }
00735 
00736   h = linux_link_hash_lookup (linux_hash_table (info),
00737                            "__BUILTIN_FIXUPS__",
00738                            FALSE, FALSE, FALSE);
00739 
00740   if (h != NULL
00741       && (h->root.root.type == bfd_link_hash_defined
00742          || h->root.root.type == bfd_link_hash_defweak))
00743     {
00744       is = h->root.root.u.def.section;
00745       section_offset = is->output_section->vma + is->output_offset;
00746       new_addr = h->root.root.u.def.value + section_offset;
00747 
00748 #ifdef LINUX_LINK_DEBUG
00749       printf ("Builtin fixup table at %x\n", new_addr);
00750 #endif
00751 
00752       bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
00753     }
00754   else
00755     bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
00756 
00757   if (bfd_seek (output_bfd, (file_ptr) (os->filepos + s->output_offset),
00758               SEEK_SET) != 0)
00759     return FALSE;
00760 
00761   if (bfd_bwrite ((PTR) s->contents, s->size, output_bfd) != s->size)
00762     return FALSE;
00763 
00764   return TRUE;
00765 }
00766 
00767 #define MY_bfd_link_hash_table_create linux_link_hash_table_create
00768 #define MY_add_one_symbol linux_add_one_symbol
00769 #define MY_finish_dynamic_link linux_finish_dynamic_link
00770 
00771 #define MY_zmagic_contiguous 1
00772 
00773 #include "aout-target.h"