Back to index

cell-binutils  2.17cvs20070401
m68klinux.c
Go to the documentation of this file.
00001 /* BFD back-end for linux flavored m68k 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, 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_68020 || (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 TARGET_IS_BIG_ENDIAN_P
00038 #define DEFAULT_ARCH bfd_arch_m68k
00039 
00040 /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
00041    remove whitespace added here, and thus will fail to concatenate
00042    the tokens.  */
00043 #define MY(OP) CONCAT2 (m68klinux_,OP)
00044 #define TARGETNAME "a.out-m68k-linux"
00045 
00046 extern const bfd_target MY(vec);
00047 
00048 /* We always generate QMAGIC files in preference to ZMAGIC files.  It
00049    would be possible to make this a linker option, if that ever
00050    becomes important.  */
00051 
00052 static void MY_final_link_callback
00053   PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *));
00054 static bfd_boolean m68klinux_bfd_final_link
00055   PARAMS ((bfd *, struct bfd_link_info *));
00056 static bfd_boolean m68klinux_write_object_contents PARAMS ((bfd *));
00057 
00058 static bfd_boolean
00059 m68klinux_bfd_final_link (abfd, info)
00060      bfd *abfd;
00061      struct bfd_link_info *info;
00062 {
00063   obj_aout_subformat (abfd) = q_magic_format;
00064   return NAME(aout,final_link) (abfd, info, MY_final_link_callback);
00065 }
00066 
00067 #define MY_bfd_final_link m68klinux_bfd_final_link
00068 
00069 /* Set the machine type correctly.  */
00070 
00071 static bfd_boolean
00072 m68klinux_write_object_contents (abfd)
00073      bfd *abfd;
00074 {
00075   struct external_exec exec_bytes;
00076   struct internal_exec *execp = exec_hdr (abfd);
00077 
00078   N_SET_MACHTYPE (*execp, M_68020);
00079 
00080   obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
00081 
00082   WRITE_HEADERS(abfd, execp);
00083 
00084   return TRUE;
00085 }
00086 
00087 #define MY_write_object_contents m68klinux_write_object_contents
00088 
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     {
00233       bfd_set_error (bfd_error_no_memory);
00234       return (struct bfd_link_hash_table *) NULL;
00235     }
00236   if (!NAME(aout,link_hash_table_init) (&ret->root, abfd,
00237                                    linux_link_hash_newfunc,
00238                                    sizeof (struct linux_link_hash_entry)))
00239     {
00240       free (ret);
00241       return (struct bfd_link_hash_table *) NULL;
00242     }
00243 
00244   ret->dynobj = NULL;
00245   ret->fixup_count = 0;
00246   ret->local_builtins = 0;
00247   ret->fixup_list = NULL;
00248 
00249   return &ret->root.root;
00250 }
00251 
00252 /* Look up an entry in a Linux link hash table.  */
00253 
00254 #define linux_link_hash_lookup(table, string, create, copy, follow) \
00255   ((struct linux_link_hash_entry *) \
00256    aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\
00257                        (follow)))
00258 
00259 /* Traverse a Linux link hash table.  */
00260 
00261 #define linux_link_hash_traverse(table, func, info)                   \
00262   (aout_link_hash_traverse                                     \
00263    (&(table)->root,                                            \
00264     (bfd_boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func),  \
00265     (info)))
00266 
00267 /* Get the Linux link hash table from the info structure.  This is
00268    just a cast.  */
00269 
00270 #define linux_hash_table(p) ((struct linux_link_hash_table *) ((p)->hash))
00271 
00272 /* Store the information for a new fixup.  */
00273 
00274 static struct fixup *
00275 new_fixup (info, h, value, builtin)
00276      struct bfd_link_info *info;
00277      struct linux_link_hash_entry *h;
00278      bfd_vma value;
00279      int builtin;
00280 {
00281   struct fixup *f;
00282 
00283   f = (struct fixup *) bfd_hash_allocate (&info->hash->table,
00284                                      sizeof (struct fixup));
00285   if (f == NULL)
00286     return f;
00287   f->next = linux_hash_table (info)->fixup_list;
00288   linux_hash_table (info)->fixup_list = f;
00289   f->h = h;
00290   f->value = value;
00291   f->builtin = builtin;
00292   f->jump = 0;
00293   ++linux_hash_table (info)->fixup_count;
00294   return f;
00295 }
00296 
00297 /* We come here once we realize that we are going to link to a shared
00298    library.  We need to create a special section that contains the
00299    fixup table, and we ultimately need to add a pointer to this into
00300    the set vector for SHARABLE_CONFLICTS.  At this point we do not
00301    know the size of the section, but that's OK - we just need to
00302    create it for now.  */
00303 
00304 static bfd_boolean
00305 linux_link_create_dynamic_sections (abfd, info)
00306      bfd *abfd;
00307      struct bfd_link_info *info ATTRIBUTE_UNUSED;
00308 {
00309   flagword flags;
00310   register asection *s;
00311 
00312   /* Note that we set the SEC_IN_MEMORY flag.  */
00313   flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
00314 
00315   /* We choose to use the name ".linux-dynamic" for the fixup table.
00316      Why not? */
00317   s = bfd_make_section_with_flags (abfd, ".linux-dynamic", flags);
00318   if (s == NULL
00319       || ! bfd_set_section_alignment (abfd, s, 2))
00320     return FALSE;
00321   s->size = 0;
00322   s->contents = 0;
00323 
00324   return TRUE;
00325 }
00326 
00327 /* Function to add a single symbol to the linker hash table.  This is
00328    a wrapper around _bfd_generic_link_add_one_symbol which handles the
00329    tweaking needed for dynamic linking support.  */
00330 
00331 static bfd_boolean
00332 linux_add_one_symbol (info, abfd, name, flags, section, value, string,
00333                     copy, collect, hashp)
00334      struct bfd_link_info *info;
00335      bfd *abfd;
00336      const char *name;
00337      flagword flags;
00338      asection *section;
00339      bfd_vma value;
00340      const char *string;
00341      bfd_boolean copy;
00342      bfd_boolean collect;
00343      struct bfd_link_hash_entry **hashp;
00344 {
00345   struct linux_link_hash_entry *h;
00346   bfd_boolean insert;
00347 
00348   /* Look up and see if we already have this symbol in the hash table.
00349      If we do, and the defining entry is from a shared library, we
00350      need to create the dynamic sections.
00351 
00352      FIXME: What if abfd->xvec != info->hash->creator?  We may want to
00353      be able to link Linux a.out and ELF objects together, but serious
00354      confusion is possible.  */
00355 
00356   insert = FALSE;
00357 
00358   if (! info->relocatable
00359       && linux_hash_table (info)->dynobj == NULL
00360       && strcmp (name, SHARABLE_CONFLICTS) == 0
00361       && (flags & BSF_CONSTRUCTOR) != 0
00362       && abfd->xvec == info->hash->creator)
00363     {
00364       if (! linux_link_create_dynamic_sections (abfd, info))
00365        return FALSE;
00366       linux_hash_table (info)->dynobj = abfd;
00367       insert = TRUE;
00368     }
00369 
00370   if (bfd_is_abs_section (section)
00371       && abfd->xvec == info->hash->creator)
00372     {
00373       h = linux_link_hash_lookup (linux_hash_table (info), name, FALSE,
00374                               FALSE, FALSE);
00375       if (h != NULL
00376          && (h->root.root.type == bfd_link_hash_defined
00377              || h->root.root.type == bfd_link_hash_defweak))
00378        {
00379          struct fixup *f;
00380 
00381          if (hashp != NULL)
00382            *hashp = (struct bfd_link_hash_entry *) h;
00383 
00384          f = new_fixup (info, h, value, ! IS_PLT_SYM (name));
00385          if (f == NULL)
00386            return FALSE;
00387          f->jump = IS_PLT_SYM (name);
00388 
00389          return TRUE;
00390        }
00391     }
00392 
00393   /* Do the usual procedure for adding a symbol.  */
00394   if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
00395                                      value, string, copy, collect,
00396                                      hashp))
00397     return FALSE;
00398 
00399   /* Insert a pointer to our table in the set vector.  The dynamic
00400      linker requires this information */
00401   if (insert)
00402     {
00403       asection *s;
00404 
00405       /* Here we do our special thing to add the pointer to the
00406         dynamic section in the SHARABLE_CONFLICTS set vector.  */
00407       s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
00408                                ".linux-dynamic");
00409       BFD_ASSERT (s != NULL);
00410 
00411       if (! (_bfd_generic_link_add_one_symbol
00412             (info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS,
00413              BSF_GLOBAL | BSF_CONSTRUCTOR, s, (bfd_vma) 0, NULL,
00414              FALSE, FALSE, NULL)))
00415        return FALSE;
00416     }
00417 
00418   return TRUE;
00419 }
00420 
00421 /* We will crawl the hash table and come here for every global symbol.
00422    We will examine each entry and see if there are indications that we
00423    need to add a fixup.  There are two possible cases - one is where
00424    you have duplicate definitions of PLT or GOT symbols - these will
00425    have already been caught and added as "builtin" fixups.  If we find
00426    that the corresponding non PLT/GOT symbol is also present, we
00427    convert it to a regular fixup instead.
00428 
00429    This function is called via linux_link_hash_traverse.  */
00430 
00431 static bfd_boolean
00432 linux_tally_symbols (h, data)
00433      struct linux_link_hash_entry *h;
00434      PTR data;
00435 {
00436   struct bfd_link_info *info = (struct bfd_link_info *) data;
00437   struct fixup *f, *f1;
00438   int is_plt;
00439   struct linux_link_hash_entry *h1, *h2;
00440   bfd_boolean exists;
00441 
00442   if (h->root.root.type == bfd_link_hash_warning)
00443     h = (struct linux_link_hash_entry *) h->root.root.u.i.link;
00444 
00445   if (h->root.root.type == bfd_link_hash_undefined
00446       && CONST_STRNEQ (h->root.root.root.string, NEEDS_SHRLIB))
00447     {
00448       const char *name;
00449       char *p;
00450       char *alloc = NULL;
00451 
00452       name = h->root.root.root.string + sizeof NEEDS_SHRLIB - 1;
00453       p = strrchr (name, '_');
00454       if (p != NULL)
00455        alloc = (char *) bfd_malloc ((bfd_size_type) strlen (name) + 1);
00456 
00457       if (p == NULL || alloc == NULL)
00458        (*_bfd_error_handler) (_("Output file requires shared library `%s'\n"),
00459                             name);
00460       else
00461        {
00462          strcpy (alloc, name);
00463          p = strrchr (alloc, '_');
00464          *p++ = '\0';
00465          (*_bfd_error_handler)
00466            (_("Output file requires shared library `%s.so.%s'\n"),
00467             alloc, p);
00468          free (alloc);
00469        }
00470 
00471       abort ();
00472     }
00473 
00474   /* If this symbol is not a PLT/GOT, we do not even need to look at it */
00475   is_plt = IS_PLT_SYM (h->root.root.root.string);
00476 
00477   if (is_plt || IS_GOT_SYM (h->root.root.root.string))
00478     {
00479       /* Look up this symbol twice.  Once just as a regular lookup,
00480         and then again following all of the indirect links until we
00481         reach a real symbol.  */
00482       h1 = linux_link_hash_lookup (linux_hash_table (info),
00483                                (h->root.root.root.string
00484                                 + sizeof PLT_REF_PREFIX - 1),
00485                                FALSE, FALSE, TRUE);
00486       /* h2 does not follow indirect symbols.  */
00487       h2 = linux_link_hash_lookup (linux_hash_table (info),
00488                                (h->root.root.root.string
00489                                 + sizeof PLT_REF_PREFIX - 1),
00490                                FALSE, FALSE, FALSE);
00491 
00492       /* The real symbol must exist but if it is also an ABS symbol,
00493         there is no need to have a fixup.  This is because they both
00494         came from the same library.  If on the other hand, we had to
00495         use an indirect symbol to get to the real symbol, we add the
00496         fixup anyway, since there are cases where these symbols come
00497         from different shared libraries */
00498       if (h1 != NULL
00499          && (((h1->root.root.type == bfd_link_hash_defined
00500               || h1->root.root.type == bfd_link_hash_defweak)
00501               && ! bfd_is_abs_section (h1->root.root.u.def.section))
00502              || h2->root.root.type == bfd_link_hash_indirect))
00503        {
00504          /* See if there is a "builtin" fixup already present
00505             involving this symbol.  If so, convert it to a regular
00506             fixup.  In the end, this relaxes some of the requirements
00507             about the order of performing fixups.  */
00508          exists = FALSE;
00509          for (f1 = linux_hash_table (info)->fixup_list;
00510               f1 != NULL;
00511               f1 = f1->next)
00512            {
00513              if ((f1->h != h && f1->h != h1)
00514                 || (! f1->builtin && ! f1->jump))
00515               continue;
00516              if (f1->h == h1)
00517               exists = TRUE;
00518              if (! exists
00519                 && bfd_is_abs_section (h->root.root.u.def.section))
00520               {
00521                 f = new_fixup (info, h1, f1->h->root.root.u.def.value, 0);
00522                 f->jump = is_plt;
00523               }
00524              f1->h = h1;
00525              f1->jump = is_plt;
00526              f1->builtin = 0;
00527              exists = TRUE;
00528            }
00529          if (! exists
00530              && bfd_is_abs_section (h->root.root.u.def.section))
00531            {
00532              f = new_fixup (info, h1, h->root.root.u.def.value, 0);
00533              if (f == NULL)
00534               {
00535                 /* FIXME: No way to return error.  */
00536                 abort ();
00537               }
00538              f->jump = is_plt;
00539            }
00540        }
00541 
00542       /* Quick and dirty way of stripping these symbols from the
00543         symtab.  */
00544       if (bfd_is_abs_section (h->root.root.u.def.section))
00545        h->root.written = TRUE;
00546     }
00547 
00548   return TRUE;
00549 }
00550 
00551 /* This is called to set the size of the .linux-dynamic section is.
00552    It is called by the Linux linker emulation before_allocation
00553    routine.  We have finished reading all of the input files, and now
00554    we just scan the hash tables to find out how many additional fixups
00555    are required.  */
00556 
00557 bfd_boolean
00558 bfd_m68klinux_size_dynamic_sections (output_bfd, info)
00559      bfd *output_bfd;
00560      struct bfd_link_info *info;
00561 {
00562   struct fixup *f;
00563   asection *s;
00564 
00565   if (output_bfd->xvec != &MY(vec))
00566     return TRUE;
00567 
00568   /* First find the fixups...  */
00569   linux_link_hash_traverse (linux_hash_table (info),
00570                          linux_tally_symbols,
00571                          (PTR) info);
00572 
00573   /* If there are builtin fixups, leave room for a marker.  This is
00574      used by the dynamic linker so that it knows that all that follow
00575      are builtin fixups instead of regular fixups.  */
00576   for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
00577     {
00578       if (f->builtin)
00579        {
00580          ++linux_hash_table (info)->fixup_count;
00581          ++linux_hash_table (info)->local_builtins;
00582          break;
00583        }
00584     }
00585 
00586   if (linux_hash_table (info)->dynobj == NULL)
00587     {
00588       if (linux_hash_table (info)->fixup_count > 0)
00589        abort ();
00590       return TRUE;
00591     }
00592 
00593   /* Allocate memory for our fixup table.  We will fill it in later.  */
00594   s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
00595                             ".linux-dynamic");
00596   if (s != NULL)
00597     {
00598       s->size = linux_hash_table (info)->fixup_count + 1;
00599       s->size *= 8;
00600       s->contents = (bfd_byte *) bfd_zalloc (output_bfd, s->size);
00601       if (s->contents == NULL)
00602        {
00603          bfd_set_error (bfd_error_no_memory);
00604          return FALSE;
00605        }
00606     }
00607 
00608   return TRUE;
00609 }
00610 
00611 /* We come here once we are ready to actually write the fixup table to
00612    the output file.  Scan the fixup tables and so forth and generate
00613    the stuff we need.  */
00614 
00615 static bfd_boolean
00616 linux_finish_dynamic_link (output_bfd, info)
00617      bfd *output_bfd;
00618      struct bfd_link_info *info;
00619 {
00620   asection *s, *os, *is;
00621   bfd_byte *fixup_table;
00622   struct linux_link_hash_entry *h;
00623   struct fixup *f;
00624   unsigned int new_addr;
00625   int section_offset;
00626   unsigned int fixups_written;
00627 
00628   if (linux_hash_table (info)->dynobj == NULL)
00629     return TRUE;
00630 
00631   s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
00632                             ".linux-dynamic");
00633   BFD_ASSERT (s != NULL);
00634   os = s->output_section;
00635   fixups_written = 0;
00636 
00637 #ifdef LINUX_LINK_DEBUG
00638   printf ("Fixup table file offset: %x  VMA: %x\n",
00639          os->filepos + s->output_offset,
00640          os->vma + s->output_offset);
00641 #endif
00642 
00643   fixup_table = s->contents;
00644   bfd_put_32 (output_bfd, (bfd_vma) linux_hash_table (info)->fixup_count,
00645              fixup_table);
00646   fixup_table += 4;
00647 
00648   /* Fill in fixup table.  */
00649   for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
00650     {
00651       if (f->builtin)
00652        continue;
00653 
00654       if (f->h->root.root.type != bfd_link_hash_defined
00655          && f->h->root.root.type != bfd_link_hash_defweak)
00656        {
00657          (*_bfd_error_handler)
00658            (_("Symbol %s not defined for fixups\n"),
00659             f->h->root.root.root.string);
00660          continue;
00661        }
00662 
00663       is = f->h->root.root.u.def.section;
00664       section_offset = is->output_section->vma + is->output_offset;
00665       new_addr = f->h->root.root.u.def.value + section_offset;
00666 
00667 #ifdef LINUX_LINK_DEBUG
00668       printf ("Fixup(%d) %s: %x %x\n",f->jump, f->h->root.root.string,
00669              new_addr, f->value);
00670 #endif
00671 
00672       if (f->jump)
00673        {
00674          bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
00675          fixup_table += 4;
00676          bfd_put_32 (output_bfd, f->value + 2, fixup_table);
00677          fixup_table += 4;
00678        }
00679       else
00680        {
00681          bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
00682          fixup_table += 4;
00683          bfd_put_32 (output_bfd, f->value, fixup_table);
00684          fixup_table += 4;
00685        }
00686       ++fixups_written;
00687     }
00688 
00689   if (linux_hash_table (info)->local_builtins != 0)
00690     {
00691       /* Special marker so we know to switch to the other type of fixup */
00692       bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
00693       fixup_table += 4;
00694       bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
00695       fixup_table += 4;
00696       ++fixups_written;
00697       for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
00698        {
00699          if (! f->builtin)
00700            continue;
00701 
00702          if (f->h->root.root.type != bfd_link_hash_defined
00703              && f->h->root.root.type != bfd_link_hash_defweak)
00704            {
00705              (*_bfd_error_handler)
00706               (_("Symbol %s not defined for fixups\n"),
00707                f->h->root.root.root.string);
00708              continue;
00709            }
00710 
00711          is = f->h->root.root.u.def.section;
00712          section_offset = is->output_section->vma + is->output_offset;
00713          new_addr = f->h->root.root.u.def.value + section_offset;
00714 
00715 #ifdef LINUX_LINK_DEBUG
00716          printf ("Fixup(B) %s: %x %x\n", f->h->root.root.string,
00717                 new_addr, f->value);
00718 #endif
00719 
00720          bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
00721          fixup_table += 4;
00722          bfd_put_32 (output_bfd, f->value, fixup_table);
00723          fixup_table += 4;
00724          ++fixups_written;
00725        }
00726   }
00727 
00728   if (linux_hash_table (info)->fixup_count != fixups_written)
00729     {
00730       (*_bfd_error_handler) (_("Warning: fixup count mismatch\n"));
00731       while (linux_hash_table (info)->fixup_count > fixups_written)
00732        {
00733          bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
00734          fixup_table += 4;
00735          bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
00736          fixup_table += 4;
00737          ++fixups_written;
00738        }
00739     }
00740 
00741   h = linux_link_hash_lookup (linux_hash_table (info),
00742                            "__BUILTIN_FIXUPS__",
00743                            FALSE, FALSE, FALSE);
00744 
00745   if (h != NULL
00746       && (h->root.root.type == bfd_link_hash_defined
00747          || h->root.root.type == bfd_link_hash_defweak))
00748     {
00749       is = h->root.root.u.def.section;
00750       section_offset = is->output_section->vma + is->output_offset;
00751       new_addr = h->root.root.u.def.value + section_offset;
00752 
00753 #ifdef LINUX_LINK_DEBUG
00754       printf ("Builtin fixup table at %x\n", new_addr);
00755 #endif
00756 
00757       bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
00758     }
00759   else
00760     bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
00761 
00762   if (bfd_seek (output_bfd, (file_ptr) (os->filepos + s->output_offset),
00763               SEEK_SET) != 0)
00764     return FALSE;
00765 
00766   if (bfd_bwrite ((PTR) s->contents, s->size, output_bfd) != s->size)
00767     return FALSE;
00768 
00769   return TRUE;
00770 }
00771 
00772 #define MY_bfd_link_hash_table_create linux_link_hash_table_create
00773 #define MY_add_one_symbol linux_add_one_symbol
00774 #define MY_finish_dynamic_link linux_finish_dynamic_link
00775 
00776 #define MY_zmagic_contiguous 1
00777 
00778 #include "aout-target.h"