Back to index

cell-binutils  2.17cvs20070401
ldwrite.c
Go to the documentation of this file.
00001 /* ldwrite.c -- write out the linked file
00002    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002,
00003    2003, 2004, 2005, 2006 Free Software Foundation, Inc.
00004    Written by Steve Chamberlain sac@cygnus.com
00005 
00006 This file is part of GLD, the Gnu Linker.
00007 
00008 This program is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2 of the License, or
00011 (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with this program; if not, write to the Free Software
00020 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 #include "bfd.h"
00023 #include "sysdep.h"
00024 #include "bfdlink.h"
00025 #include "libiberty.h"
00026 #include "safe-ctype.h"
00027 
00028 #include "ld.h"
00029 #include "ldexp.h"
00030 #include "ldlang.h"
00031 #include "ldwrite.h"
00032 #include "ldmisc.h"
00033 #include <ldgram.h>
00034 #include "ldmain.h"
00035 
00036 /* Build link_order structures for the BFD linker.  */
00037 
00038 static void
00039 build_link_order (lang_statement_union_type *statement)
00040 {
00041   switch (statement->header.type)
00042     {
00043     case lang_data_statement_enum:
00044       {
00045        asection *output_section;
00046        struct bfd_link_order *link_order;
00047        bfd_vma value;
00048        bfd_boolean big_endian = FALSE;
00049 
00050        output_section = statement->data_statement.output_section;
00051        ASSERT (output_section->owner == output_bfd);
00052 
00053        link_order = bfd_new_link_order (output_bfd, output_section);
00054        if (link_order == NULL)
00055          einfo (_("%P%F: bfd_new_link_order failed\n"));
00056 
00057        link_order->type = bfd_data_link_order;
00058        link_order->offset = statement->data_statement.output_offset;
00059        link_order->u.data.contents = xmalloc (QUAD_SIZE);
00060 
00061        value = statement->data_statement.value;
00062 
00063        /* If the endianness of the output BFD is not known, then we
00064           base the endianness of the data on the first input file.
00065           By convention, the bfd_put routines for an unknown
00066           endianness are big endian, so we must swap here if the
00067           input file is little endian.  */
00068        if (bfd_big_endian (output_bfd))
00069          big_endian = TRUE;
00070        else if (bfd_little_endian (output_bfd))
00071          big_endian = FALSE;
00072        else
00073          {
00074            bfd_boolean swap;
00075 
00076            swap = FALSE;
00077            if (command_line.endian == ENDIAN_BIG)
00078              big_endian = TRUE;
00079            else if (command_line.endian == ENDIAN_LITTLE)
00080              {
00081               big_endian = FALSE;
00082               swap = TRUE;
00083              }
00084            else if (command_line.endian == ENDIAN_UNSET)
00085              {
00086               big_endian = TRUE;
00087               {
00088                 LANG_FOR_EACH_INPUT_STATEMENT (s)
00089                   {
00090                     if (s->the_bfd != NULL)
00091                      {
00092                        if (bfd_little_endian (s->the_bfd))
00093                          {
00094                            big_endian = FALSE;
00095                            swap = TRUE;
00096                          }
00097                        break;
00098                      }
00099                   }
00100               }
00101              }
00102 
00103            if (swap)
00104              {
00105               bfd_byte buffer[8];
00106 
00107               switch (statement->data_statement.type)
00108                 {
00109                 case QUAD:
00110                 case SQUAD:
00111                   if (sizeof (bfd_vma) >= QUAD_SIZE)
00112                     {
00113                      bfd_putl64 (value, buffer);
00114                      value = bfd_getb64 (buffer);
00115                      break;
00116                     }
00117                   /* Fall through.  */
00118                 case LONG:
00119                   bfd_putl32 (value, buffer);
00120                   value = bfd_getb32 (buffer);
00121                   break;
00122                 case SHORT:
00123                   bfd_putl16 (value, buffer);
00124                   value = bfd_getb16 (buffer);
00125                   break;
00126                 case BYTE:
00127                   break;
00128                 default:
00129                   abort ();
00130                 }
00131              }
00132          }
00133 
00134        ASSERT (output_section->owner == output_bfd);
00135        switch (statement->data_statement.type)
00136          {
00137          case QUAD:
00138          case SQUAD:
00139            if (sizeof (bfd_vma) >= QUAD_SIZE)
00140              bfd_put_64 (output_bfd, value, link_order->u.data.contents);
00141            else
00142              {
00143               bfd_vma high;
00144 
00145               if (statement->data_statement.type == QUAD)
00146                 high = 0;
00147               else if ((value & 0x80000000) == 0)
00148                 high = 0;
00149               else
00150                 high = (bfd_vma) -1;
00151               bfd_put_32 (output_bfd, high,
00152                          (link_order->u.data.contents
00153                           + (big_endian ? 0 : 4)));
00154               bfd_put_32 (output_bfd, value,
00155                          (link_order->u.data.contents
00156                           + (big_endian ? 4 : 0)));
00157              }
00158            link_order->size = QUAD_SIZE;
00159            break;
00160          case LONG:
00161            bfd_put_32 (output_bfd, value, link_order->u.data.contents);
00162            link_order->size = LONG_SIZE;
00163            break;
00164          case SHORT:
00165            bfd_put_16 (output_bfd, value, link_order->u.data.contents);
00166            link_order->size = SHORT_SIZE;
00167            break;
00168          case BYTE:
00169            bfd_put_8 (output_bfd, value, link_order->u.data.contents);
00170            link_order->size = BYTE_SIZE;
00171            break;
00172          default:
00173            abort ();
00174          }
00175       }
00176       break;
00177 
00178     case lang_reloc_statement_enum:
00179       {
00180        lang_reloc_statement_type *rs;
00181        asection *output_section;
00182        struct bfd_link_order *link_order;
00183 
00184        rs = &statement->reloc_statement;
00185 
00186        output_section = rs->output_section;
00187        ASSERT (output_section->owner == output_bfd);
00188 
00189        link_order = bfd_new_link_order (output_bfd, output_section);
00190        if (link_order == NULL)
00191          einfo (_("%P%F: bfd_new_link_order failed\n"));
00192 
00193        link_order->offset = rs->output_offset;
00194        link_order->size = bfd_get_reloc_size (rs->howto);
00195 
00196        link_order->u.reloc.p = xmalloc (sizeof (struct bfd_link_order_reloc));
00197 
00198        link_order->u.reloc.p->reloc = rs->reloc;
00199        link_order->u.reloc.p->addend = rs->addend_value;
00200 
00201        if (rs->name == NULL)
00202          {
00203            link_order->type = bfd_section_reloc_link_order;
00204            if (rs->section->owner == output_bfd)
00205              link_order->u.reloc.p->u.section = rs->section;
00206            else
00207              {
00208               link_order->u.reloc.p->u.section = rs->section->output_section;
00209               link_order->u.reloc.p->addend += rs->section->output_offset;
00210              }
00211          }
00212        else
00213          {
00214            link_order->type = bfd_symbol_reloc_link_order;
00215            link_order->u.reloc.p->u.name = rs->name;
00216          }
00217       }
00218       break;
00219 
00220     case lang_input_section_enum:
00221       {
00222        /* Create a new link_order in the output section with this
00223           attached */
00224        asection *i = statement->input_section.section;
00225 
00226        if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
00227            && (i->flags & SEC_EXCLUDE) == 0)
00228          {
00229            asection *output_section = i->output_section;
00230 
00231            ASSERT (output_section->owner == output_bfd);
00232 
00233            if ((output_section->flags & SEC_HAS_CONTENTS) != 0
00234               || ((output_section->flags & SEC_LOAD) != 0
00235                   && (output_section->flags & SEC_THREAD_LOCAL)))
00236              {
00237               struct bfd_link_order *link_order;
00238 
00239               link_order = bfd_new_link_order (output_bfd, output_section);
00240 
00241               if (i->flags & SEC_NEVER_LOAD)
00242                 {
00243                   /* We've got a never load section inside one which
00244                      is going to be output, we'll change it into a
00245                      fill.  */
00246                   link_order->type = bfd_data_link_order;
00247                   link_order->u.data.contents = (unsigned char *) "";
00248                   link_order->u.data.size = 1;
00249                 }
00250               else
00251                 {
00252                   link_order->type = bfd_indirect_link_order;
00253                   link_order->u.indirect.section = i;
00254                   ASSERT (i->output_section == output_section);
00255                 }
00256               link_order->size = i->size;
00257               link_order->offset = i->output_offset;
00258              }
00259          }
00260       }
00261       break;
00262 
00263     case lang_padding_statement_enum:
00264       /* Make a new link_order with the right filler */
00265       {
00266        asection *output_section;
00267        struct bfd_link_order *link_order;
00268 
00269        output_section = statement->padding_statement.output_section;
00270        ASSERT (statement->padding_statement.output_section->owner
00271               == output_bfd);
00272        if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
00273          {
00274            link_order = bfd_new_link_order (output_bfd, output_section);
00275            link_order->type = bfd_data_link_order;
00276            link_order->size = statement->padding_statement.size;
00277            link_order->offset = statement->padding_statement.output_offset;
00278            link_order->u.data.contents = statement->padding_statement.fill->data;
00279            link_order->u.data.size = statement->padding_statement.fill->size;
00280          }
00281       }
00282       break;
00283 
00284     default:
00285       /* All the other ones fall through */
00286       break;
00287     }
00288 }
00289 
00290 /* Return true if NAME is the name of an unsplittable section. These
00291    are the stabs strings, dwarf strings.  */
00292 
00293 static bfd_boolean
00294 unsplittable_name (const char *name)
00295 {
00296   if (CONST_STRNEQ (name, ".stab"))
00297     {
00298       /* There are several stab like string sections. We pattern match on
00299         ".stab...str"  */
00300       unsigned len = strlen (name);
00301       if (strcmp (&name[len-3], "str") == 0)
00302        return TRUE;
00303     }
00304   else if (strcmp (name, "$GDB_STRINGS$") == 0)
00305     return TRUE;
00306   return FALSE;
00307 }
00308 
00309 /* Wander around the input sections, make sure that
00310    we'll never try and create an output section with more relocs
00311    than will fit.. Do this by always assuming the worst case, and
00312    creating new output sections with all the right bits.  */
00313 #define TESTIT 1
00314 static asection *
00315 clone_section (bfd *abfd, asection *s, const char *name, int *count)
00316 {
00317   char *tname;
00318   char *sname;
00319   unsigned int len;  
00320   asection *n;
00321   struct bfd_link_hash_entry *h;
00322 
00323   /* Invent a section name from the section name and a dotted numeric
00324      suffix.   */
00325   len = strlen (name);
00326   tname = xmalloc (len + 1);
00327   memcpy (tname, name, len + 1);
00328   /* Remove a dotted number suffix, from a previous split link. */
00329   while (len && ISDIGIT (tname[len-1]))
00330     len--;
00331   if (len > 1 && tname[len-1] == '.')
00332     /* It was a dotted number. */
00333     tname[len-1] = 0;
00334 
00335   /* We want to use the whole of the original section name for the
00336      split name, but coff can be restricted to 8 character names.  */
00337   if (bfd_family_coff (abfd) && strlen (tname) > 5)
00338     {
00339       /* Some section names cannot be truncated, as the name is
00340         used to locate some other section.  */
00341       if (CONST_STRNEQ (name, ".stab")
00342          || strcmp (name, "$GDB_SYMBOLS$") == 0)
00343        {
00344          einfo (_ ("%F%P: cannot create split section name for %s\n"), name);
00345          /* Silence gcc warnings.  einfo exits, so we never reach here.  */
00346          return NULL;
00347        }
00348       tname[5] = 0;
00349     }
00350   
00351   if ((sname = bfd_get_unique_section_name (abfd, tname, count)) == NULL
00352       || (n = bfd_make_section_anyway (abfd, sname)) == NULL
00353       || (h = bfd_link_hash_lookup (link_info.hash,
00354                                 sname, TRUE, TRUE, FALSE)) == NULL)
00355     {
00356       einfo (_("%F%P: clone section failed: %E\n"));
00357       /* Silence gcc warnings.  einfo exits, so we never reach here.  */
00358       return NULL;
00359     }
00360   free (tname);
00361   
00362   /* Set up section symbol.  */
00363   h->type = bfd_link_hash_defined;
00364   h->u.def.value = 0;
00365   h->u.def.section = n;
00366 
00367   n->flags = s->flags;
00368   n->vma = s->vma;
00369   n->user_set_vma = s->user_set_vma;
00370   n->lma = s->lma;
00371   n->size = 0;
00372   n->output_offset = s->output_offset;
00373   n->output_section = n;
00374   n->orelocation = 0;
00375   n->reloc_count = 0;
00376   n->alignment_power = s->alignment_power;
00377   return n;
00378 }
00379 
00380 #if TESTING
00381 static void
00382 ds (asection *s)
00383 {
00384   struct bfd_link_order *l = s->map_head.link_order;
00385   printf ("vma %x size %x\n", s->vma, s->size);
00386   while (l)
00387     {
00388       if (l->type == bfd_indirect_link_order)
00389        {
00390          printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
00391        }
00392       else
00393        {
00394          printf (_("%8x something else\n"), l->offset);
00395        }
00396       l = l->next;
00397     }
00398   printf ("\n");
00399 }
00400 
00401 dump (char *s, asection *a1, asection *a2)
00402 {
00403   printf ("%s\n", s);
00404   ds (a1);
00405   ds (a2);
00406 }
00407 
00408 static void
00409 sanity_check (bfd *abfd)
00410 {
00411   asection *s;
00412   for (s = abfd->sections; s; s = s->next)
00413     {
00414       struct bfd_link_order *p;
00415       bfd_vma prev = 0;
00416       for (p = s->map_head.link_order; p; p = p->next)
00417        {
00418          if (p->offset > 100000)
00419            abort ();
00420          if (p->offset < prev)
00421            abort ();
00422          prev = p->offset;
00423        }
00424     }
00425 }
00426 #else
00427 #define sanity_check(a)
00428 #define dump(a, b, c)
00429 #endif
00430 
00431 static void
00432 split_sections (bfd *abfd, struct bfd_link_info *info)
00433 {
00434   asection *original_sec;
00435   int nsecs = abfd->section_count;
00436   sanity_check (abfd);
00437   /* Look through all the original sections.  */
00438   for (original_sec = abfd->sections;
00439        original_sec && nsecs;
00440        original_sec = original_sec->next, nsecs--)
00441     {
00442       int count = 0;
00443       unsigned int lines = 0;
00444       unsigned int relocs = 0;
00445       bfd_size_type sec_size = 0;
00446       struct bfd_link_order *l;
00447       struct bfd_link_order *p;
00448       bfd_vma vma = original_sec->vma;
00449       asection *cursor = original_sec;
00450 
00451       /* Count up the relocations and line entries to see if anything
00452         would be too big to fit.  Accumulate section size too.  */
00453       for (l = NULL, p = cursor->map_head.link_order; p != NULL; p = l->next)
00454        {
00455          unsigned int thislines = 0;
00456          unsigned int thisrelocs = 0;
00457          bfd_size_type thissize = 0;
00458          if (p->type == bfd_indirect_link_order)
00459            {
00460              asection *sec;
00461 
00462              sec = p->u.indirect.section;
00463 
00464              if (info->strip == strip_none
00465                 || info->strip == strip_some)
00466               thislines = sec->lineno_count;
00467 
00468              if (info->relocatable)
00469               thisrelocs = sec->reloc_count;
00470 
00471              thissize = sec->size;
00472 
00473            }
00474          else if (info->relocatable
00475                  && (p->type == bfd_section_reloc_link_order
00476                      || p->type == bfd_symbol_reloc_link_order))
00477            thisrelocs++;
00478 
00479          if (l != NULL
00480              && (thisrelocs + relocs >= config.split_by_reloc
00481                 || thislines + lines >= config.split_by_reloc
00482                 || (thissize + sec_size >= config.split_by_file))
00483              && !unsplittable_name (cursor->name))
00484            {
00485              /* Create a new section and put this link order and the
00486                following link orders into it.  */
00487              bfd_vma shift_offset;
00488              asection *n;
00489 
00490              n = clone_section (abfd, cursor, original_sec->name, &count);
00491 
00492              /* Attach the link orders to the new section and snip
00493                them off from the old section.  */
00494              n->map_head.link_order = p;
00495              n->map_tail.link_order = cursor->map_tail.link_order;
00496              cursor->map_tail.link_order = l;
00497              l->next = NULL;
00498              l = p;
00499 
00500              /* Change the size of the original section and
00501                update the vma of the new one.  */
00502 
00503              dump ("before snip", cursor, n);
00504 
00505              shift_offset = p->offset;
00506              n->size = cursor->size - shift_offset;
00507              cursor->size = shift_offset;
00508 
00509              vma += shift_offset;
00510              n->lma = n->vma = vma;
00511 
00512              /* Run down the chain and change the output section to
00513                the right one, update the offsets too.  */
00514              do
00515               {
00516                 p->offset -= shift_offset;
00517                 if (p->type == bfd_indirect_link_order)
00518                   {
00519                     p->u.indirect.section->output_section = n;
00520                     p->u.indirect.section->output_offset = p->offset;
00521                   }
00522                 p = p->next;
00523               }
00524              while (p);
00525 
00526              dump ("after snip", cursor, n);
00527              cursor = n;
00528              relocs = thisrelocs;
00529              lines = thislines;
00530              sec_size = thissize;
00531            }
00532          else
00533            {
00534              l = p;
00535              relocs += thisrelocs;
00536              lines += thislines;
00537              sec_size += thissize;
00538            }
00539        }
00540     }
00541   sanity_check (abfd);
00542 }
00543 
00544 /* Call BFD to write out the linked file.  */
00545 
00546 void
00547 ldwrite (void)
00548 {
00549   /* Reset error indicator, which can typically something like invalid
00550      format from opening up the .o files.  */
00551   bfd_set_error (bfd_error_no_error);
00552   lang_for_each_statement (build_link_order);
00553 
00554   if (config.split_by_reloc != (unsigned) -1
00555       || config.split_by_file != (bfd_size_type) -1)
00556     split_sections (output_bfd, &link_info);
00557   if (!bfd_final_link (output_bfd, &link_info))
00558     {
00559       /* If there was an error recorded, print it out.  Otherwise assume
00560         an appropriate error message like unknown symbol was printed
00561         out.  */
00562 
00563       if (bfd_get_error () != bfd_error_no_error)
00564        einfo (_("%F%P: final link failed: %E\n"));
00565       else
00566        xexit (1);
00567     }
00568 }