Back to index

cell-binutils  2.17cvs20070401
sparclinux.c
Go to the documentation of this file.
00001 /* BFD back-end for linux flavored sparc a.out binaries.
00002    Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
00003    2003, 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,
00020    USA.  */
00021 
00022 #define TARGET_PAGE_SIZE    4096
00023 #define ZMAGIC_DISK_BLOCK_SIZE     1024
00024 #define SEGMENT_SIZE        TARGET_PAGE_SIZE
00025 #define TEXT_START_ADDR            0x0
00026 #define N_SHARED_LIB(x)            0
00027 
00028 #define MACHTYPE_OK(mtype) ((mtype) == M_SPARC || (mtype) == M_UNKNOWN)
00029 
00030 #include "bfd.h"
00031 #include "sysdep.h"
00032 #include "libbfd.h"
00033 #include "aout/aout64.h"
00034 #include "aout/stab_gnu.h"
00035 #include "aout/ar.h"
00036 #include "libaout.h"           /* BFD a.out internal data structures */
00037 
00038 #define DEFAULT_ARCH bfd_arch_sparc
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 (sparclinux_,OP)
00043 #define TARGETNAME "a.out-sparc-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 
00054 static bfd_boolean sparclinux_bfd_final_link
00055   PARAMS ((bfd *abfd, struct bfd_link_info *info));
00056 
00057 static bfd_boolean
00058 sparclinux_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 sparclinux_bfd_final_link
00067 
00068 /* Set the machine type correctly.  */
00069 
00070 static bfd_boolean sparclinux_write_object_contents PARAMS ((bfd *abfd));
00071 
00072 static bfd_boolean
00073 sparclinux_write_object_contents (abfd)
00074      bfd *abfd;
00075 {
00076   struct external_exec exec_bytes;
00077   struct internal_exec *execp = exec_hdr (abfd);
00078 
00079   N_SET_MACHTYPE (*execp, M_SPARC);
00080 
00081   obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
00082 
00083   WRITE_HEADERS(abfd, execp);
00084 
00085   return TRUE;
00086 }
00087 
00088 #define MY_write_object_contents sparclinux_write_object_contents
00089 /* Code to link against Linux a.out shared libraries.  */
00090 
00091 /* See if a symbol name is a reference to the global offset table.  */
00092 
00093 #ifndef GOT_REF_PREFIX
00094 #define GOT_REF_PREFIX  "__GOT_"
00095 #endif
00096 
00097 #define IS_GOT_SYM(name)  (CONST_STRNEQ (name, GOT_REF_PREFIX))
00098 
00099 /* See if a symbol name is a reference to the procedure linkage table.  */
00100 
00101 #ifndef PLT_REF_PREFIX
00102 #define PLT_REF_PREFIX  "__PLT_"
00103 #endif
00104 
00105 #define IS_PLT_SYM(name)  (CONST_STRNEQ (name, PLT_REF_PREFIX))
00106 
00107 /* This string is used to generate specialized error messages.  */
00108 
00109 #ifndef NEEDS_SHRLIB
00110 #define NEEDS_SHRLIB "__NEEDS_SHRLIB_"
00111 #endif
00112 
00113 /* This special symbol is a set vector that contains a list of
00114    pointers to fixup tables.  It will be present in any dynamically
00115    linked file.  The linker generated fixup table should also be added
00116    to the list, and it should always appear in the second slot (the
00117    first one is a dummy with a magic number that is defined in
00118    crt0.o).  */
00119 
00120 #ifndef SHARABLE_CONFLICTS
00121 #define SHARABLE_CONFLICTS "__SHARABLE_CONFLICTS__"
00122 #endif
00123 
00124 /* We keep a list of fixups.  The terminology is a bit strange, but
00125    each fixup contains two 32 bit numbers.  A regular fixup contains
00126    an address and a pointer, and at runtime we should store the
00127    address at the location pointed to by the pointer.  A builtin fixup
00128    contains two pointers, and we should read the address using one
00129    pointer and store it at the location pointed to by the other
00130    pointer.  Builtin fixups come into play when we have duplicate
00131    __GOT__ symbols for the same variable.  The builtin fixup will copy
00132    the GOT pointer from one over into the other.  */
00133 
00134 struct fixup
00135 {
00136   struct fixup *next;
00137   struct linux_link_hash_entry *h;
00138   bfd_vma value;
00139 
00140   /* Nonzero if this is a jump instruction that needs to be fixed,
00141      zero if this is just a pointer */
00142   char jump;
00143 
00144   char builtin;
00145 };
00146 
00147 /* We don't need a special hash table entry structure, but we do need
00148    to keep some information between linker passes, so we use a special
00149    hash table.  */
00150 
00151 struct linux_link_hash_entry
00152 {
00153   struct aout_link_hash_entry root;
00154 };
00155 
00156 struct linux_link_hash_table
00157 {
00158   struct aout_link_hash_table root;
00159 
00160   /* First dynamic object found in link.  */
00161   bfd *dynobj;
00162 
00163   /* Number of fixups.  */
00164   size_t fixup_count;
00165 
00166   /* Number of builtin fixups.  */
00167   size_t local_builtins;
00168 
00169   /* List of fixups.  */
00170   struct fixup *fixup_list;
00171 };
00172 
00173 static struct bfd_hash_entry *linux_link_hash_newfunc
00174   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
00175 static struct bfd_link_hash_table *linux_link_hash_table_create
00176   PARAMS ((bfd *));
00177 static struct fixup *new_fixup
00178   PARAMS ((struct bfd_link_info *, struct linux_link_hash_entry *,
00179          bfd_vma, int));
00180 static bfd_boolean linux_link_create_dynamic_sections
00181   PARAMS ((bfd *, struct bfd_link_info *));
00182 static bfd_boolean linux_add_one_symbol
00183   PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
00184          bfd_vma, const char *, bfd_boolean, bfd_boolean,
00185          struct bfd_link_hash_entry **));
00186 static bfd_boolean linux_tally_symbols
00187   PARAMS ((struct linux_link_hash_entry *, PTR));
00188 static bfd_boolean linux_finish_dynamic_link
00189   PARAMS ((bfd *, struct bfd_link_info *));
00190 
00191 /* Routine to create an entry in an Linux link hash table.  */
00192 
00193 static struct bfd_hash_entry *
00194 linux_link_hash_newfunc (entry, table, string)
00195      struct bfd_hash_entry *entry;
00196      struct bfd_hash_table *table;
00197      const char *string;
00198 {
00199   struct linux_link_hash_entry *ret = (struct linux_link_hash_entry *) entry;
00200 
00201   /* Allocate the structure if it has not already been allocated by a
00202      subclass.  */
00203   if (ret == (struct linux_link_hash_entry *) NULL)
00204     ret = ((struct linux_link_hash_entry *)
00205           bfd_hash_allocate (table, sizeof (struct linux_link_hash_entry)));
00206   if (ret == NULL)
00207     return (struct bfd_hash_entry *) ret;
00208 
00209   /* Call the allocation method of the superclass.  */
00210   ret = ((struct linux_link_hash_entry *)
00211         NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret,
00212                                    table, string));
00213   if (ret != NULL)
00214     {
00215       /* Set local fields; there aren't any.  */
00216     }
00217 
00218   return (struct bfd_hash_entry *) ret;
00219 }
00220 
00221 /* Create a Linux link hash table.  */
00222 
00223 static struct bfd_link_hash_table *
00224 linux_link_hash_table_create (abfd)
00225      bfd *abfd;
00226 {
00227   struct linux_link_hash_table *ret;
00228   bfd_size_type amt = sizeof (struct linux_link_hash_table);
00229 
00230   ret = (struct linux_link_hash_table *) bfd_malloc (amt);
00231   if (ret == (struct linux_link_hash_table *) NULL)
00232     return (struct bfd_link_hash_table *) NULL;
00233   if (!NAME(aout,link_hash_table_init) (&ret->root, abfd,
00234                                    linux_link_hash_newfunc,
00235                                    sizeof (struct linux_link_hash_entry)))
00236     {
00237       free (ret);
00238       return (struct bfd_link_hash_table *) NULL;
00239     }
00240 
00241   ret->dynobj = NULL;
00242   ret->fixup_count = 0;
00243   ret->local_builtins = 0;
00244   ret->fixup_list = NULL;
00245 
00246   return &ret->root.root;
00247 }
00248 
00249 /* Look up an entry in a Linux link hash table.  */
00250 
00251 #define linux_link_hash_lookup(table, string, create, copy, follow) \
00252   ((struct linux_link_hash_entry *) \
00253    aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\
00254                        (follow)))
00255 
00256 /* Traverse a Linux link hash table.  */
00257 
00258 #define linux_link_hash_traverse(table, func, info)                   \
00259   (aout_link_hash_traverse                                     \
00260    (&(table)->root,                                            \
00261     (bfd_boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \
00262     (info)))
00263 
00264 /* Get the Linux link hash table from the info structure.  This is
00265    just a cast.  */
00266 
00267 #define linux_hash_table(p) ((struct linux_link_hash_table *) ((p)->hash))
00268 
00269 /* Store the information for a new fixup.  */
00270 
00271 static struct fixup *
00272 new_fixup (info, h, value, builtin)
00273      struct bfd_link_info *info;
00274      struct linux_link_hash_entry *h;
00275      bfd_vma value;
00276      int builtin;
00277 {
00278   struct fixup *f;
00279 
00280   f = (struct fixup *) bfd_hash_allocate (&info->hash->table,
00281                                      sizeof (struct fixup));
00282   if (f == NULL)
00283     return f;
00284   f->next = linux_hash_table (info)->fixup_list;
00285   linux_hash_table (info)->fixup_list = f;
00286   f->h = h;
00287   f->value = value;
00288   f->builtin = builtin;
00289   f->jump = 0;
00290   ++linux_hash_table (info)->fixup_count;
00291   return f;
00292 }
00293 
00294 /* We come here once we realize that we are going to link to a shared
00295    library.  We need to create a special section that contains the
00296    fixup table, and we ultimately need to add a pointer to this into
00297    the set vector for SHARABLE_CONFLICTS.  At this point we do not
00298    know the size of the section, but that's OK - we just need to
00299    create it for now.  */
00300 
00301 static bfd_boolean
00302 linux_link_create_dynamic_sections (abfd, info)
00303      bfd *abfd;
00304      struct bfd_link_info *info ATTRIBUTE_UNUSED;
00305 {
00306   flagword flags;
00307   register asection *s;
00308 
00309   /* Note that we set the SEC_IN_MEMORY flag.  */
00310   flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
00311 
00312   /* We choose to use the name ".linux-dynamic" for the fixup table.
00313      Why not?  */
00314   s = bfd_make_section_with_flags (abfd, ".linux-dynamic", flags);
00315   if (s == NULL
00316       || ! bfd_set_section_alignment (abfd, s, 2))
00317     return FALSE;
00318   s->size = 0;
00319   s->contents = 0;
00320 
00321   return TRUE;
00322 }
00323 
00324 /* Function to add a single symbol to the linker hash table.  This is
00325    a wrapper around _bfd_generic_link_add_one_symbol which handles the
00326    tweaking needed for dynamic linking support.  */
00327 
00328 static bfd_boolean
00329 linux_add_one_symbol (info, abfd, name, flags, section, value, string,
00330                     copy, collect, hashp)
00331      struct bfd_link_info *info;
00332      bfd *abfd;
00333      const char *name;
00334      flagword flags;
00335      asection *section;
00336      bfd_vma value;
00337      const char *string;
00338      bfd_boolean copy;
00339      bfd_boolean collect;
00340      struct bfd_link_hash_entry **hashp;
00341 {
00342   struct linux_link_hash_entry *h;
00343   bfd_boolean insert;
00344 
00345   /* Look up and see if we already have this symbol in the hash table.
00346      If we do, and the defining entry is from a shared library, we
00347      need to create the dynamic sections.
00348 
00349      FIXME: What if abfd->xvec != info->hash->creator?  We may want to
00350      be able to link Linux a.out and ELF objects together, but serious
00351      confusion is possible.  */
00352 
00353   insert = FALSE;
00354 
00355   if (! info->relocatable
00356       && linux_hash_table (info)->dynobj == NULL
00357       && strcmp (name, SHARABLE_CONFLICTS) == 0
00358       && (flags & BSF_CONSTRUCTOR) != 0
00359       && abfd->xvec == info->hash->creator)
00360     {
00361       if (! linux_link_create_dynamic_sections (abfd, info))
00362        return FALSE;
00363       linux_hash_table (info)->dynobj = abfd;
00364       insert = TRUE;
00365     }
00366 
00367   if (bfd_is_abs_section (section)
00368       && abfd->xvec == info->hash->creator)
00369     {
00370       h = linux_link_hash_lookup (linux_hash_table (info), name, FALSE,
00371                               FALSE, FALSE);
00372       if (h != NULL
00373          && (h->root.root.type == bfd_link_hash_defined
00374              || h->root.root.type == bfd_link_hash_defweak))
00375        {
00376          struct fixup *f;
00377 
00378          if (hashp != NULL)
00379            *hashp = (struct bfd_link_hash_entry *) h;
00380 
00381          f = new_fixup (info, h, value, ! IS_PLT_SYM (name));
00382          if (f == NULL)
00383            return FALSE;
00384          f->jump = IS_PLT_SYM (name);
00385 
00386          return TRUE;
00387        }
00388     }
00389 
00390   /* Do the usual procedure for adding a symbol.  */
00391   if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
00392                                      value, string, copy, collect,
00393                                      hashp))
00394     return FALSE;
00395 
00396   /* Insert a pointer to our table in the set vector.  The dynamic
00397      linker requires this information.  */
00398   if (insert)
00399     {
00400       asection *s;
00401 
00402       /* Here we do our special thing to add the pointer to the
00403         dynamic section in the SHARABLE_CONFLICTS set vector.  */
00404       s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
00405                                ".linux-dynamic");
00406       BFD_ASSERT (s != NULL);
00407 
00408       if (! (_bfd_generic_link_add_one_symbol
00409             (info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS,
00410              BSF_GLOBAL | BSF_CONSTRUCTOR, s, (bfd_vma) 0, NULL,
00411              FALSE, FALSE, NULL)))
00412        return FALSE;
00413     }
00414 
00415   return TRUE;
00416 }
00417 
00418 /* We will crawl the hash table and come here for every global symbol.
00419    We will examine each entry and see if there are indications that we
00420    need to add a fixup.  There are two possible cases - one is where
00421    you have duplicate definitions of PLT or GOT symbols - these will
00422    have already been caught and added as "builtin" fixups.  If we find
00423    that the corresponding non PLT/GOT symbol is also present, we
00424    convert it to a regular fixup instead.
00425 
00426    This function is called via linux_link_hash_traverse.  */
00427 
00428 static bfd_boolean
00429 linux_tally_symbols (struct linux_link_hash_entry *h, void * data)
00430 {
00431   struct bfd_link_info *info = (struct bfd_link_info *) data;
00432   struct fixup *f, *f1;
00433   int is_plt;
00434   struct linux_link_hash_entry *h1, *h2;
00435   bfd_boolean exists;
00436 
00437   if (h->root.root.type == bfd_link_hash_warning)
00438     h = (struct linux_link_hash_entry *) h->root.root.u.i.link;
00439 
00440   if (h->root.root.type == bfd_link_hash_undefined
00441       && CONST_STRNEQ (h->root.root.root.string, NEEDS_SHRLIB))
00442     {
00443       const char *name;
00444       char *p;
00445       char *alloc = NULL;
00446 
00447       name = h->root.root.root.string + sizeof NEEDS_SHRLIB - 1;
00448       p = strrchr (name, '_');
00449       if (p != NULL)
00450        alloc = (char *) bfd_malloc ((bfd_size_type) strlen (name) + 1);
00451 
00452       if (p == NULL || alloc == NULL)
00453        (*_bfd_error_handler) (_("Output file requires shared library `%s'\n"),
00454                             name);
00455       else
00456        {
00457          strcpy (alloc, name);
00458          p = strrchr (alloc, '_');
00459          *p++ = '\0';
00460          (*_bfd_error_handler)
00461            (_("Output file requires shared library `%s.so.%s'\n"),
00462             alloc, p);
00463          free (alloc);
00464        }
00465 
00466       abort ();
00467     }
00468 
00469   /* If this symbol is not a PLT/GOT, we do not even need to look at
00470      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_sparclinux_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"