* lib/ld-lib.exp (default_ld_simple_link): Permit the linker to
[deliverable/binutils-gdb.git] / ld / ldwrite.c
index c9caf83572eb786ca1d42d768e95dc2084d8d1e5..4160ae2508b3a06974d9efe827059ae98b74fb4a 100644 (file)
@@ -16,7 +16,7 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -35,6 +35,8 @@ static void print_symbol_table PARAMS ((void));
 static void print_file_stuff PARAMS ((lang_input_statement_type *));
 static boolean print_symbol PARAMS ((struct bfd_link_hash_entry *, PTR));
 
+extern char *strdup();
+
 /* Build link_order structures for the BFD linker.  */
 
 static void
@@ -54,7 +56,7 @@ build_link_order (statement)
 
        link_order = bfd_new_link_order (output_bfd, output_section);
        if (link_order == NULL)
-         einfo ("%P%F: bfd_new_link_order failed");
+         einfo ("%P%F: bfd_new_link_order failed\n");
 
        link_order->type = bfd_data_link_order;
        link_order->offset = statement->data_statement.output_vma;
@@ -62,6 +64,58 @@ build_link_order (statement)
 
        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
+          endianness are big endian, so we must swap here if the
+          input file is little endian.  */
+       if (! bfd_big_endian (output_bfd)
+           && ! bfd_little_endian (output_bfd))
+         {
+           boolean swap;
+
+           swap = false;
+           if (command_line.endian == ENDIAN_LITTLE)
+             swap = true;
+           else if (command_line.endian == ENDIAN_UNSET)
+             {
+               LANG_FOR_EACH_INPUT_STATEMENT (s)
+                 {
+                   if (s->the_bfd != NULL)
+                     {
+                       if (bfd_little_endian (s->the_bfd))
+                         swap = true;
+                       break;
+                     }
+                 }
+             }
+
+           if (swap)
+             {
+               bfd_byte buffer[8];
+
+               switch (statement->data_statement.type)
+                 {
+                 case QUAD:
+                   bfd_putl64 (value, buffer);
+                   value = bfd_getb64 (buffer);
+                   break;
+                 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);
        switch (statement->data_statement.type)
          {
@@ -100,7 +154,7 @@ build_link_order (statement)
 
        link_order = bfd_new_link_order (output_bfd, output_section);
        if (link_order == NULL)
-         einfo ("%P%F: bfd_new_link_order failed");
+         einfo ("%P%F: bfd_new_link_order failed\n");
 
        link_order->offset = rs->output_vma;
        link_order->size = bfd_get_reloc_size (rs->howto);
@@ -112,9 +166,8 @@ build_link_order (statement)
        link_order->u.reloc.p->reloc = rs->reloc;
        link_order->u.reloc.p->addend = rs->addend_value;
 
-       if (rs->section != (asection *) NULL)
+       if (rs->name == NULL)
          {
-           ASSERT (rs->name == (const char *) NULL);
            link_order->type = bfd_section_reloc_link_order;
            if (rs->section->owner == output_bfd)
              link_order->u.reloc.p->u.section = rs->section;
@@ -126,7 +179,6 @@ build_link_order (statement)
          }
        else
          {
-           ASSERT (rs->name != (const char *) NULL);
            link_order->type = bfd_symbol_reloc_link_order;
            link_order->u.reloc.p->u.name = rs->name;
          }
@@ -218,12 +270,12 @@ clone_section (abfd, s, count)
 #define SSIZE 8
   char sname[SSIZE];           /* ??  find the name for this size */
   asection *n;
-
+  struct bfd_link_hash_entry *h;
   /* Invent a section name - use first five
      chars of base section name and a digit suffix */
   do
     {
-      int i;
+      unsigned int i;
       char b[6];
       for (i = 0; i < sizeof (b) - 1 && s->name[i]; i++)
        b[i] = s->name[i];
@@ -234,6 +286,15 @@ clone_section (abfd, s, count)
 
   n = bfd_make_section_anyway (abfd, strdup (sname));
 
+  /* Create a symbol of the same name */
+
+  h = bfd_link_hash_lookup (link_info.hash,
+                           sname, true, true, false);
+  h->type = bfd_link_hash_defined;
+  h->u.def.value = 0;
+  h->u.def.section = n   ;
+
+
   n->flags = s->flags;
   n->vma = s->vma;
   n->user_set_vma = s->user_set_vma;
@@ -244,7 +305,7 @@ clone_section (abfd, s, count)
   n->output_section = n;
   n->orelocation = 0;
   n->reloc_count = 0;
-
+  n->alignment_power = s->alignment_power;
   return n;
 }
 
@@ -317,6 +378,7 @@ split_sections (abfd, info)
        original_sec && nsecs;
        original_sec = original_sec->next, nsecs--)
     {
+      boolean first = true;
       int count = 0;
       int lines = 0;
       int relocs = 0;
@@ -324,6 +386,7 @@ split_sections (abfd, info)
       bfd_vma vma = original_sec->vma;
       bfd_vma shift_offset = 0;
       asection *cursor = original_sec;
+
       /* count up the relocations and line entries to see if
         anything would be too big to fit */
       for (pp = &(cursor->link_order_head); *pp; pp = &((*pp)->next))
@@ -350,9 +413,10 @@ split_sections (abfd, info)
                       || p->type == bfd_symbol_reloc_link_order))
            thisrelocs++;
 
-         if (thisrelocs + relocs > config.split_by_reloc
-             || thislines + lines > config.split_by_reloc
-             || config.split_by_file)
+         if (! first
+             && (thisrelocs + relocs > config.split_by_reloc
+                 || thislines + lines > config.split_by_reloc
+                 || config.split_by_file))
            {
              /* create a new section and put this link order and the
                 following link orders into it */
@@ -398,6 +462,8 @@ split_sections (abfd, info)
              relocs += thisrelocs;
              lines += thislines;
            }
+
+         first = false;
        }
     }
   sanity_check (abfd);
@@ -406,12 +472,24 @@ split_sections (abfd, info)
 void
 ldwrite ()
 {
+  /* Reset error indicator, which can typically something like invalid
+     format from openning up the .o files */
+  bfd_set_error (bfd_error_no_error);
   lang_for_each_statement (build_link_order);
 
   if (config.split_by_reloc || config.split_by_file)
     split_sections (output_bfd, &link_info);
   if (!bfd_final_link (output_bfd, &link_info))
-    einfo ("%F%P: final link failed: %E\n", output_bfd);
+    {
+      /* If there was an error recorded, print it out.  Otherwise assume
+        an appropriate error message like unknown symbol was printed
+        out.  */
+
+      if (bfd_get_error () != bfd_error_no_error)
+       einfo ("%F%P: final link failed: %E\n", output_bfd);
+      else
+       xexit(1);
+    }
 
   if (config.map_file)
     {
@@ -425,7 +503,7 @@ ldwrite ()
 static void
 print_symbol_table ()
 {
-  fprintf (config.map_file, "**FILES**\n\n");
+  fprintf (config.map_file, "\n**FILES**\n\n");
   lang_for_each_file (print_file_stuff);
 
   fprintf (config.map_file, "**GLOBAL SYMBOLS**\n\n");
@@ -453,6 +531,14 @@ print_file_stuff (f)
               s != (asection *) NULL;
               s = s->next)
            {
+#ifdef WINDOWS_NT
+              /* Don't include any information that goes into the '.junk'
+                 section.  This includes the code view .debug$ data and
+                 stuff from .drectve sections */
+              if (strcmp (s->name, ".drectve") == 0 ||
+                  strncmp (s->name, ".debug$", 7) == 0)
+                continue;
+#endif
              print_address (s->output_offset);
              if (s->reloc_done)
                {
@@ -509,13 +595,14 @@ print_symbol (p, ignore)
       print_nl ();
       break;
 
-    case bfd_link_hash_weak:
+    case bfd_link_hash_undefweak:
       fprintf (config.map_file, "weak                          ");
       fprintf (config.map_file, "%s ", p->root.string);
       print_nl ();
       break;
 
     case bfd_link_hash_defined:
+    case bfd_link_hash_defweak:
       {
        asection *defsec = p->u.def.section;
 
@@ -531,7 +618,9 @@ print_symbol (p, ignore)
          {
            fprintf (config.map_file, "         .......");
          }
-       fprintf (config.map_file, " %s ", p->root.string);
+       fprintf (config.map_file, " %s", p->root.string);
+       if (p->type == bfd_link_hash_defweak)
+         fprintf (config.map_file, " [weak]");
       }
       print_nl ();
       break;
This page took 0.027478 seconds and 4 git commands to generate.