]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - ld/ldwrite.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / ld / ldwrite.c
index e4bec32cac8b6e1433895a3513691f12643570d0..2db0b63b79224d4205e52f25be934a6ae30fe2e6 100644 (file)
@@ -1,28 +1,29 @@
 /* ldwrite.c -- write out the linked file
-   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2003
-   Free Software Foundation, Inc.
+   Copyright (C) 1991-2021 Free Software Foundation, Inc.
    Written by Steve Chamberlain sac@cygnus.com
 
-This file is part of GLD, the Gnu Linker.
+   This file is part of the GNU Binutils.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "bfdlink.h"
 #include "libiberty.h"
+#include "ctf-api.h"
 #include "safe-ctype.h"
 
 #include "ld.h"
@@ -45,99 +46,68 @@ build_link_order (lang_statement_union_type *statement)
        asection *output_section;
        struct bfd_link_order *link_order;
        bfd_vma value;
-       bfd_boolean big_endian = FALSE;
 
        output_section = statement->data_statement.output_section;
-       ASSERT (output_section->owner == output_bfd);
+       ASSERT (output_section->owner == link_info.output_bfd);
+
+       if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
+             || ((output_section->flags & SEC_LOAD) != 0
+                 && (output_section->flags & SEC_THREAD_LOCAL))))
+         break;
 
-       link_order = bfd_new_link_order (output_bfd, output_section);
+       link_order = bfd_new_link_order (link_info.output_bfd, output_section);
        if (link_order == NULL)
-         einfo (_("%P%F: bfd_new_link_order failed\n"));
+         einfo (_("%F%P: bfd_new_link_order failed\n"));
 
        link_order->type = bfd_data_link_order;
-       link_order->offset = statement->data_statement.output_vma;
-       link_order->u.data.contents = xmalloc (QUAD_SIZE);
+       link_order->offset = statement->data_statement.output_offset;
+       link_order->u.data.contents = (bfd_byte *) xmalloc (QUAD_SIZE);
 
        value = statement->data_statement.value;
 
-       /* If the endianness of the output BFD is not known, then we
-          base the endianness of the data on the first input file.
-          By convention, the bfd_put routines for an unknown
+       /* By convention, the bfd_put routines for an unknown
           endianness are big endian, so we must swap here if the
-          input file is little endian.  */
-       if (bfd_big_endian (output_bfd))
-         big_endian = TRUE;
-       else if (bfd_little_endian (output_bfd))
-         big_endian = FALSE;
-       else
+          input is little endian.  */
+       if (!bfd_big_endian (link_info.output_bfd)
+           && !bfd_little_endian (link_info.output_bfd)
+           && !link_info.big_endian)
          {
-           bfd_boolean swap;
-
-           swap = FALSE;
-           if (command_line.endian == ENDIAN_BIG)
-             big_endian = TRUE;
-           else if (command_line.endian == ENDIAN_LITTLE)
-             {
-               big_endian = FALSE;
-               swap = TRUE;
-             }
-           else if (command_line.endian == ENDIAN_UNSET)
-             {
-               big_endian = TRUE;
-               {
-                 LANG_FOR_EACH_INPUT_STATEMENT (s)
-                   {
-                     if (s->the_bfd != NULL)
-                       {
-                         if (bfd_little_endian (s->the_bfd))
-                           {
-                             big_endian = FALSE;
-                             swap = TRUE;
-                           }
-                         break;
-                       }
-                   }
-               }
-             }
+           bfd_byte buffer[8];
 
-           if (swap)
+           switch (statement->data_statement.type)
              {
-               bfd_byte buffer[8];
-
-               switch (statement->data_statement.type)
+             case QUAD:
+             case SQUAD:
+               if (sizeof (bfd_vma) >= QUAD_SIZE)
                  {
-                 case QUAD:
-                 case SQUAD:
-                   if (sizeof (bfd_vma) >= QUAD_SIZE)
-                     {
-                       bfd_putl64 (value, buffer);
-                       value = bfd_getb64 (buffer);
-                       break;
-                     }
-                   /* Fall through.  */
-                 case LONG:
-                   bfd_putl32 (value, buffer);
-                   value = bfd_getb32 (buffer);
-                   break;
-                 case SHORT:
-                   bfd_putl16 (value, buffer);
-                   value = bfd_getb16 (buffer);
+                   bfd_putl64 (value, buffer);
+                   value = bfd_getb64 (buffer);
                    break;
-                 case BYTE:
-                   break;
-                 default:
-                   abort ();
                  }
+               /* Fall through.  */
+             case LONG:
+               bfd_putl32 (value, buffer);
+               value = bfd_getb32 (buffer);
+               break;
+             case SHORT:
+               bfd_putl16 (value, buffer);
+               value = bfd_getb16 (buffer);
+               break;
+             case BYTE:
+               break;
+             default:
+               abort ();
              }
          }
 
-       ASSERT (output_section->owner == output_bfd);
+       ASSERT (output_section->owner == link_info.output_bfd);
        switch (statement->data_statement.type)
          {
          case QUAD:
          case SQUAD:
            if (sizeof (bfd_vma) >= QUAD_SIZE)
-             bfd_put_64 (output_bfd, value, link_order->u.data.contents);
+             bfd_put_64 (link_info.output_bfd, value,
+                         link_order->u.data.contents);
            else
              {
                bfd_vma high;
@@ -148,30 +118,34 @@ build_link_order (lang_statement_union_type *statement)
                  high = 0;
                else
                  high = (bfd_vma) -1;
-               bfd_put_32 (output_bfd, high,
+               bfd_put_32 (link_info.output_bfd, high,
                            (link_order->u.data.contents
-                            + (big_endian ? 0 : 4)));
-               bfd_put_32 (output_bfd, value,
+                            + (link_info.big_endian ? 0 : 4)));
+               bfd_put_32 (link_info.output_bfd, value,
                            (link_order->u.data.contents
-                            + (big_endian ? 4 : 0)));
+                            + (link_info.big_endian ? 4 : 0)));
              }
            link_order->size = QUAD_SIZE;
            break;
          case LONG:
-           bfd_put_32 (output_bfd, value, link_order->u.data.contents);
+           bfd_put_32 (link_info.output_bfd, value,
+                       link_order->u.data.contents);
            link_order->size = LONG_SIZE;
            break;
          case SHORT:
-           bfd_put_16 (output_bfd, value, link_order->u.data.contents);
+           bfd_put_16 (link_info.output_bfd, value,
+                       link_order->u.data.contents);
            link_order->size = SHORT_SIZE;
            break;
          case BYTE:
-           bfd_put_8 (output_bfd, value, link_order->u.data.contents);
+           bfd_put_8 (link_info.output_bfd, value,
+                      link_order->u.data.contents);
            link_order->size = BYTE_SIZE;
            break;
          default:
            abort ();
          }
+       link_order->u.data.size = link_order->size;
       }
       break;
 
@@ -184,16 +158,22 @@ build_link_order (lang_statement_union_type *statement)
        rs = &statement->reloc_statement;
 
        output_section = rs->output_section;
-       ASSERT (output_section->owner == output_bfd);
+       ASSERT (output_section->owner == link_info.output_bfd);
 
-       link_order = bfd_new_link_order (output_bfd, output_section);
+       if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
+             || ((output_section->flags & SEC_LOAD) != 0
+                 && (output_section->flags & SEC_THREAD_LOCAL))))
+         break;
+
+       link_order = bfd_new_link_order (link_info.output_bfd, output_section);
        if (link_order == NULL)
-         einfo (_("%P%F: bfd_new_link_order failed\n"));
+         einfo (_("%F%P: bfd_new_link_order failed\n"));
 
-       link_order->offset = rs->output_vma;
+       link_order->offset = rs->output_offset;
        link_order->size = bfd_get_reloc_size (rs->howto);
 
-       link_order->u.reloc.p = xmalloc (sizeof (struct bfd_link_order_reloc));
+       link_order->u.reloc.p = (struct bfd_link_order_reloc *)
+         xmalloc (sizeof (struct bfd_link_order_reloc));
 
        link_order->u.reloc.p->reloc = rs->reloc;
        link_order->u.reloc.p->addend = rs->addend_value;
@@ -201,7 +181,7 @@ build_link_order (lang_statement_union_type *statement)
        if (rs->name == NULL)
          {
            link_order->type = bfd_section_reloc_link_order;
-           if (rs->section->owner == output_bfd)
+           if (rs->section->owner == link_info.output_bfd)
              link_order->u.reloc.p->u.section = rs->section;
            else
              {
@@ -218,45 +198,48 @@ build_link_order (lang_statement_union_type *statement)
       break;
 
     case lang_input_section_enum:
-      /* Create a new link_order in the output section with this
-        attached */
-      if (!statement->input_section.ifile->just_syms_flag)
-       {
-         asection *i = statement->input_section.section;
-         asection *output_section = i->output_section;
+      {
+       /* Create a new link_order in the output section with this
+          attached */
+       asection *i = statement->input_section.section;
 
-         ASSERT (output_section->owner == output_bfd);
+       if (i->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
+           && (i->flags & SEC_EXCLUDE) == 0)
+         {
+           asection *output_section = i->output_section;
+           struct bfd_link_order *link_order;
 
-         if ((output_section->flags & SEC_HAS_CONTENTS) != 0
-             || ((output_section->flags & SEC_LOAD) != 0
-                 && (output_section->flags & SEC_THREAD_LOCAL)))
-           {
-             struct bfd_link_order *link_order;
+           ASSERT (output_section->owner == link_info.output_bfd);
 
-             link_order = bfd_new_link_order (output_bfd, output_section);
+           if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
+                 || ((output_section->flags & SEC_LOAD) != 0
+                     && (output_section->flags & SEC_THREAD_LOCAL))))
+             break;
 
-             if (i->flags & SEC_NEVER_LOAD)
-               {
-                 /* We've got a never load section inside one which
-                    is going to be output, we'll change it into a
-                    fill.  */
-                 link_order->type = bfd_data_link_order;
-                 link_order->u.data.contents = "";
-                 link_order->u.data.size = 1;
-               }
-             else
-               {
-                 link_order->type = bfd_indirect_link_order;
-                 link_order->u.indirect.section = i;
-                 ASSERT (i->output_section == output_section);
-               }
-             if (i->_cooked_size)
-               link_order->size = i->_cooked_size;
-             else
-               link_order->size = bfd_get_section_size_before_reloc (i);
-             link_order->offset = i->output_offset;
-           }
-       }
+           link_order = bfd_new_link_order (link_info.output_bfd,
+                                            output_section);
+           if (link_order == NULL)
+             einfo (_("%F%P: bfd_new_link_order failed\n"));
+
+           if ((i->flags & SEC_NEVER_LOAD) != 0
+               && (i->flags & SEC_DEBUGGING) == 0)
+             {
+               /* We've got a never load section inside one which is
+                  going to be output, we'll change it into a fill.  */
+               link_order->type = bfd_data_link_order;
+               link_order->u.data.contents = (unsigned char *) "";
+               link_order->u.data.size = 1;
+             }
+           else
+             {
+               link_order->type = bfd_indirect_link_order;
+               link_order->u.indirect.section = i;
+               ASSERT (i->output_section == output_section);
+             }
+           link_order->size = i->size;
+           link_order->offset = i->output_offset;
+         }
+      }
       break;
 
     case lang_padding_statement_enum:
@@ -267,16 +250,22 @@ build_link_order (lang_statement_union_type *statement)
 
        output_section = statement->padding_statement.output_section;
        ASSERT (statement->padding_statement.output_section->owner
-               == output_bfd);
-       if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
-         {
-           link_order = bfd_new_link_order (output_bfd, output_section);
-           link_order->type = bfd_data_link_order;
-           link_order->size = statement->padding_statement.size;
-           link_order->offset = statement->padding_statement.output_offset;
-           link_order->u.data.contents = statement->padding_statement.fill->data;
-           link_order->u.data.size = statement->padding_statement.fill->size;
-         }
+               == link_info.output_bfd);
+
+       if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
+             || ((output_section->flags & SEC_LOAD) != 0
+                 && (output_section->flags & SEC_THREAD_LOCAL))))
+         break;
+
+       link_order = bfd_new_link_order (link_info.output_bfd,
+                                        output_section);
+       if (link_order == NULL)
+         einfo (_("%F%P: bfd_new_link_order failed\n"));
+       link_order->type = bfd_data_link_order;
+       link_order->size = statement->padding_statement.size;
+       link_order->offset = statement->padding_statement.output_offset;
+       link_order->u.data.contents = statement->padding_statement.fill->data;
+       link_order->u.data.size = statement->padding_statement.fill->size;
       }
       break;
 
@@ -292,7 +281,7 @@ build_link_order (lang_statement_union_type *statement)
 static bfd_boolean
 unsplittable_name (const char *name)
 {
-  if (strncmp (name, ".stab", 5) == 0)
+  if (CONST_STRNEQ (name, ".stab"))
     {
       /* There are several stab like string sections. We pattern match on
         ".stab...str"  */
@@ -315,14 +304,14 @@ clone_section (bfd *abfd, asection *s, const char *name, int *count)
 {
   char *tname;
   char *sname;
-  unsigned int len;    
+  unsigned int len;
   asection *n;
   struct bfd_link_hash_entry *h;
 
   /* Invent a section name from the section name and a dotted numeric
      suffix.   */
   len = strlen (name);
-  tname = xmalloc (len + 1);
+  tname = (char *) xmalloc (len + 1);
   memcpy (tname, name, len + 1);
   /* Remove a dotted number suffix, from a previous split link. */
   while (len && ISDIGIT (tname[len-1]))
@@ -337,7 +326,7 @@ clone_section (bfd *abfd, asection *s, const char *name, int *count)
     {
       /* Some section names cannot be truncated, as the name is
         used to locate some other section.  */
-      if (strncmp (name, ".stab", 5) == 0
+      if (CONST_STRNEQ (name, ".stab")
          || strcmp (name, "$GDB_SYMBOLS$") == 0)
        {
          einfo (_ ("%F%P: cannot create split section name for %s\n"), name);
@@ -346,7 +335,7 @@ clone_section (bfd *abfd, asection *s, const char *name, int *count)
        }
       tname[5] = 0;
     }
-  
+
   if ((sname = bfd_get_unique_section_name (abfd, tname, count)) == NULL
       || (n = bfd_make_section_anyway (abfd, sname)) == NULL
       || (h = bfd_link_hash_lookup (link_info.hash,
@@ -357,7 +346,7 @@ clone_section (bfd *abfd, asection *s, const char *name, int *count)
       return NULL;
     }
   free (tname);
-  
+
   /* Set up section symbol.  */
   h->type = bfd_link_hash_defined;
   h->u.def.value = 0;
@@ -367,13 +356,15 @@ clone_section (bfd *abfd, asection *s, const char *name, int *count)
   n->vma = s->vma;
   n->user_set_vma = s->user_set_vma;
   n->lma = s->lma;
-  n->_cooked_size = 0;
-  n->_raw_size = 0;
+  n->size = 0;
   n->output_offset = s->output_offset;
   n->output_section = n;
   n->orelocation = 0;
   n->reloc_count = 0;
   n->alignment_power = s->alignment_power;
+
+  bfd_copy_private_section_data (abfd, s, abfd, n);
+
   return n;
 }
 
@@ -381,18 +372,14 @@ clone_section (bfd *abfd, asection *s, const char *name, int *count)
 static void
 ds (asection *s)
 {
-  struct bfd_link_order *l = s->link_order_head;
-  printf ("vma %x size %x\n", s->vma, s->_raw_size);
+  struct bfd_link_order *l = s->map_head.link_order;
+  printf ("vma %x size %x\n", s->vma, s->size);
   while (l)
     {
       if (l->type == bfd_indirect_link_order)
-       {
-         printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
-       }
+       printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
       else
-       {
-         printf (_("%8x something else\n"), l->offset);
-       }
+       printf (_("%8x something else\n"), l->offset);
       l = l->next;
     }
   printf ("\n");
@@ -413,7 +400,7 @@ sanity_check (bfd *abfd)
     {
       struct bfd_link_order *p;
       bfd_vma prev = 0;
-      for (p = s->link_order_head; p; p = p->next)
+      for (p = s->map_head.link_order; p; p = p->next)
        {
          if (p->offset > 100000)
            abort ();
@@ -450,7 +437,7 @@ split_sections (bfd *abfd, struct bfd_link_info *info)
 
       /* Count up the relocations and line entries to see if anything
         would be too big to fit.  Accumulate section size too.  */
-      for (l = NULL, p = cursor->link_order_head; p != NULL; p = l->next)
+      for (l = NULL, p = cursor->map_head.link_order; p != NULL; p = l->next)
        {
          unsigned int thislines = 0;
          unsigned int thisrelocs = 0;
@@ -465,16 +452,13 @@ split_sections (bfd *abfd, struct bfd_link_info *info)
                  || info->strip == strip_some)
                thislines = sec->lineno_count;
 
-             if (info->relocatable)
+             if (bfd_link_relocatable (info))
                thisrelocs = sec->reloc_count;
 
-             if (sec->_cooked_size != 0)
-               thissize = sec->_cooked_size;
-             else
-               thissize = sec->_raw_size;
+             thissize = sec->size;
 
            }
-         else if (info->relocatable
+         else if (bfd_link_relocatable (info)
                   && (p->type == bfd_section_reloc_link_order
                       || p->type == bfd_symbol_reloc_link_order))
            thisrelocs++;
@@ -494,9 +478,9 @@ split_sections (bfd *abfd, struct bfd_link_info *info)
 
              /* Attach the link orders to the new section and snip
                 them off from the old section.  */
-             n->link_order_head = p;
-             n->link_order_tail = cursor->link_order_tail;
-             cursor->link_order_tail = l;
+             n->map_head.link_order = p;
+             n->map_tail.link_order = cursor->map_tail.link_order;
+             cursor->map_tail.link_order = l;
              l->next = NULL;
              l = p;
 
@@ -506,13 +490,8 @@ split_sections (bfd *abfd, struct bfd_link_info *info)
              dump ("before snip", cursor, n);
 
              shift_offset = p->offset;
-             if (cursor->_cooked_size != 0)
-               {
-                 n->_cooked_size = cursor->_cooked_size - shift_offset;
-                 cursor->_cooked_size = shift_offset;
-               }
-             n->_raw_size = cursor->_raw_size - shift_offset;
-             cursor->_raw_size = shift_offset;
+             n->size = cursor->size - shift_offset;
+             cursor->size = shift_offset;
 
              vma += shift_offset;
              n->lma = n->vma = vma;
@@ -557,12 +536,13 @@ ldwrite (void)
   /* Reset error indicator, which can typically something like invalid
      format from opening up the .o files.  */
   bfd_set_error (bfd_error_no_error);
+  lang_clear_os_map ();
   lang_for_each_statement (build_link_order);
 
   if (config.split_by_reloc != (unsigned) -1
       || config.split_by_file != (bfd_size_type) -1)
-    split_sections (output_bfd, &link_info);
-  if (!bfd_final_link (output_bfd, &link_info))
+    split_sections (link_info.output_bfd, &link_info);
+  if (!bfd_final_link (link_info.output_bfd, &link_info))
     {
       /* If there was an error recorded, print it out.  Otherwise assume
         an appropriate error message like unknown symbol was printed