]> Git Repo - binutils.git/blobdiff - ld/ldwrite.c
* mdebugread.c (parse_symbol): Don't call ecoff_swap_tir_in or
[binutils.git] / ld / ldwrite.c
index 0f545d09d1995255508fb22bf1715c53b15809b0..1dacb3de2a7a30c8abf5888739e002bce90c4a59 100644 (file)
@@ -1,5 +1,7 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
-   
+/* ldwrite.c -- write out the linked file
+   Copyright (C) 1993 Free Software Foundation, Inc.
+   Written by Steve Chamberlain [email protected]
+
 This file is part of GLD, the Gnu Linker.
 
 This program is free software; you can redistribute it and/or modify
@@ -16,400 +18,325 @@ 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.  */
 
-/*
- * $Id$ 
-*/
-
-/* 
-   This module writes out the final image by reading sections from the
-   input files, relocating them and writing them out
-
-   There are two main paths through this module, one for normal
-   operation and one for partial linking. 
-
-   During  normal operation, raw section data is read along with the
-   associated relocation information, the relocation info applied and
-   the section data written out on a section by section basis.
-
-   When partially linking, all the relocation records are read to work
-   out how big the output relocation vector will be. Then raw data is
-   read, relocated and written section by section.
-
-   Written by Steve Chamberlain [email protected]
-
-*/
-
-
 #include "bfd.h"
 #include "sysdep.h"
+#include "bfdlink.h"
 
-#include "ldlang.h"
 #include "ld.h"
+#include "ldexp.h"
+#include "ldlang.h"
 #include "ldwrite.h"
 #include "ldmisc.h"
-#include "ldsym.h"
 #include "ldgram.h"
+#include "ldmain.h"
 
+static void build_link_order PARAMS ((lang_statement_union_type *));
+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));
 
+/* Build link_order structures for the BFD linker.  */
 
+static void
+build_link_order (statement)
+     lang_statement_union_type *statement;
+{
+  switch (statement->header.type)
+    {
+    case lang_data_statement_enum:
+      /* FIXME: This should probably build a link_order, but instead
+        it just does the output directly.  */
+      {
+       bfd_vma value = statement->data_statement.value;
+       bfd_byte play_area[QUAD_SIZE];
+       unsigned int size = 0;
+       asection *output_section = statement->data_statement.output_section;
+
+       ASSERT (output_section->owner == output_bfd);
+       switch (statement->data_statement.type)
+         {
+         case QUAD:
+           bfd_put_64 (output_bfd, value, play_area);
+           size = QUAD_SIZE;
+           break;
+         case LONG:
+           bfd_put_32 (output_bfd, value, play_area);
+           size = LONG_SIZE;
+           break;
+         case SHORT:
+           bfd_put_16 (output_bfd, value, play_area);
+           size = SHORT_SIZE;
+           break;
+         case BYTE:
+           bfd_put_8 (output_bfd, value, play_area);
+           size = BYTE_SIZE;
+           break;
+         default:
+           abort ();
+         }
 
-/* Static vars for do_warnings and subroutines of it */
-int list_unresolved_refs;      /* List unresolved refs */
-int list_warning_symbols;      /* List warning syms */
-int list_multiple_defs;                /* List multiple definitions */
-extern int errno;
-extern char *sys_errlist[];
+       if (! bfd_set_section_contents (output_bfd, output_section,
+                                       play_area,
+                                       statement->data_statement.output_vma,
+                                       size))
+         einfo ("%P%X: writing data failed: %E\n");
+      }
+      break;
 
-extern unsigned int undefined_global_sym_count;
+    case lang_reloc_statement_enum:
+      {
+       lang_reloc_statement_type *rs;
+       asection *output_section;
+       struct bfd_link_order *link_order;
 
-extern bfd *output_bfd;
+       rs = &statement->reloc_statement;
 
-extern struct lang_output_section_statement_struct * create_object_symbols;
+       output_section = rs->output_section;
+       ASSERT (output_section->owner == output_bfd);
 
-extern char lprefix;
+       link_order = bfd_new_link_order (output_bfd, output_section);
+       if (link_order == NULL)
+         einfo ("%P%F: bfd_new_link_order failed");
 
-#ifdef __STDC__
-void lang_for_each_statement(void (*func)());
-#else /* __STDC__ */
-void lang_for_each_statement();
-#endif /* __STDC__ */
+       link_order->offset = rs->output_vma;
+       link_order->size = bfd_get_reloc_size (rs->howto);
 
-extern bfd_size_type largest_section;
-ld_config_type config;
+       link_order->u.reloc.p =
+         ((struct bfd_link_order_reloc *)
+          xmalloc (sizeof (struct bfd_link_order_reloc)));
 
-extern unsigned int global_symbol_count;
+       link_order->u.reloc.p->reloc = rs->reloc;
+       link_order->u.reloc.p->addend = rs->addend_value;
 
-boolean trace_files;
+       if (rs->section != (asection *) 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;
+           else
+             {
+               link_order->u.reloc.p->u.section = rs->section->output_section;
+               link_order->u.reloc.p->addend += rs->section->output_offset;
+             }
+         }
+       else
+         {
+           ASSERT (rs->name != (const char *) NULL);
+           link_order->type = bfd_symbol_reloc_link_order;
+           link_order->u.reloc.p->u.name = rs->name;
+         }
+      }
+      break;
 
-static void 
-DEFUN(perform_relocation,(input_bfd,
-                         input_section,
-                         data,
-                         symbols),
-      bfd *input_bfd AND
-      asection *input_section AND
-      PTR data AND
-      asymbol **symbols)
-{
-  static asymbol *error_symbol = (asymbol *)NULL;
-  static unsigned int error_count = 0;
-#define MAX_ERRORS_IN_A_ROW 5
-  bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd, input_section);
-
-  arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
-  arelent **parent;
-  bfd *ob = output_bfd;
-  asection *os = input_section->output_section;
-  if (config.relocateable_output == false) ob = (bfd *)NULL;
-
-  input_section->_cooked_size = input_section->_raw_size;
-  input_section->reloc_done = 1;
-  
-  if (bfd_canonicalize_reloc(input_bfd, 
-                            input_section,
-                            reloc_vector,
-                            symbols) )
-    {
-      for (parent = reloc_vector; *parent; parent++) 
+    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 == false)
        {
+         asection *i = statement->input_section.section;
+         asection *output_section = i->output_section;
 
-         bfd_reloc_status_type r=
-           bfd_perform_relocation(input_bfd,
-                                  *parent,
-                                  data,
-                                  input_section, 
-                                  ob);
+         ASSERT (output_section->owner == output_bfd);
 
-         if (r == bfd_reloc_ok) {
-           if (ob != (bfd *)NULL) {
-             /* A parital link, so keep the relocs */
-
-             /* Add to each relocation the offset of where it lives
-                in the output section */
-/*           (*parent)->address += input_section->output_offset;*/
-
-             os->orelocation[os->reloc_count] = *parent;
-             os->reloc_count++;
-           }
-         }
-         else
+         if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
            {
-             asymbol *s;
-             arelent *p = *parent;
+             struct bfd_link_order *link_order;
 
-             if (ob != (bfd *)NULL) {
-               /* A parital link, so keep the relocs */
-               os->orelocation[os->reloc_count] = *parent;
-               os->reloc_count++;
-             }
+             link_order = bfd_new_link_order (output_bfd, output_section);
 
-             if (p->sym_ptr_ptr != (asymbol **)NULL) {
-               s = *(p->sym_ptr_ptr);
-             }
-             else {
-               s = (asymbol *)NULL;
-             }
-             switch (r)
+             if (i->flags & SEC_NEVER_LOAD)
                {
-               case bfd_reloc_undefined:
-                 /* We remember the symbol, and never print more than
-                    a reasonable number of them in a row */
-                 if (s == error_symbol) {
-                   error_count++;
-                 }
-                 else {
-                   error_count = 0;
-                   error_symbol = s;
-                 }
-                 if (error_count < MAX_ERRORS_IN_A_ROW) {
-                   einfo("%C: undefined reference to `%T'\n",
-                         input_bfd, input_section, symbols,
-                         (*parent)->address, s);
-                   config.make_executable = false;
-                 }
-                 else if (error_count == MAX_ERRORS_IN_A_ROW) {
-                   einfo("%C: more undefined references to `%T' follow\n",
-                         input_bfd, input_section,
-                         symbols, (*parent)->address, s);
-                 }                 
-                 else {
-                   /* Don't print any more */
-                 }
-                 break;
-               case bfd_reloc_dangerous: 
-                 einfo("%B: relocation may be wrong `%T'\n",
-                       input_bfd, s);
-                 break;
-               case bfd_reloc_outofrange:
-                 einfo("%B:%s relocation address out of range %T (%V)\n",
-                       input_bfd, input_section->name, s, p->address); 
-                 break;
-               case bfd_reloc_overflow:
-                 einfo("%B:%s relocation overflow in %T reloc type %d\n",
-                       input_bfd, input_section->name, s, p->howto->type);
-                 break;
-               default:
-                 einfo("%F%B: relocation error, symbol `%T'\n",
-                       input_bfd, s);
-                 break;
+                 /* We've got a never load section inside one which
+                    is going to be output, we'll change it into a
+                    fill link_order */
+                 link_order->type = bfd_fill_link_order;
+                 link_order->u.fill.value = 0;
                }
+             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;
            }
        }
+      break;
+
+    case lang_padding_statement_enum:
+      /* Make a new link_order with the right filler */
+      {
+       asection *output_section;
+       struct bfd_link_order *link_order;
+
+       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_fill_link_order;
+           link_order->size = statement->padding_statement.size;
+           link_order->offset = statement->padding_statement.output_offset;
+           link_order->u.fill.value = statement->padding_statement.fill;
+         }
+      }
+      break;
+
+    default:
+      /* All the other ones fall through */
+      break;
     }
-  free((char *)reloc_vector);
 }
 
+/* Call BFD to write out the linked file.  */
 
+void
+ldwrite ()
+{
+  lang_for_each_statement (build_link_order);
 
+  if (! bfd_final_link (output_bfd, &link_info))
+    einfo ("%F%P: final link failed: %E\n", output_bfd);
 
+  if (config.map_file)
+    {
+      print_symbol_table ();
+      lang_map ();
+    }
+}
 
-
-PTR data_area;
+/* Print the symbol table.  */
 
 static void
-DEFUN(copy_and_relocate,(statement),
-      lang_statement_union_type *statement)
+print_symbol_table ()
 {
-  switch (statement->header.type) {
-  case lang_fill_statement_enum: 
-      {
-#if 0
-      bfd_byte play_area[SHORT_SIZE];
-      unsigned int i;
-      bfd_putshort(output_bfd, statement->fill_statement.fill, play_area);
-      /* Write out all entire shorts */
-      for (i = 0;
-          i < statement->fill_statement.size - SHORT_SIZE + 1;
-          i+= SHORT_SIZE)
-       {
-         bfd_set_section_contents(output_bfd,
-                                  statement->fill_statement.output_section,
-                                  play_area,
-                                  statement->data_statement.output_offset +i,
-                                  SHORT_SIZE);
+  fprintf (config.map_file, "**FILES**\n\n");
+  lang_for_each_file (print_file_stuff);
 
-       }
+  fprintf (config.map_file, "**GLOBAL SYMBOLS**\n\n");
+  fprintf (config.map_file, "offset    section    offset   symbol\n");
+  bfd_link_hash_traverse (link_info.hash, print_symbol, (PTR) NULL);
+}
 
-      /* Now write any remaining byte */
-      if (i < statement->fill_statement.size) 
-       {
-         bfd_set_section_contents(output_bfd,
-                                  statement->fill_statement.output_section,
-                                  play_area,
-                                  statement->data_statement.output_offset +i,
-                                  1);
+/* Print information about a file.  */
 
-       }
-#endif
-    }
-    break;
-  case lang_data_statement_enum:
+static void
+print_file_stuff (f)
+     lang_input_statement_type * f;
+{
+  fprintf (config.map_file, "  %s\n", f->filename);
+  if (f->just_syms_flag)
     {
-      bfd_vma value = statement->data_statement.value;
-      bfd_byte play_area[LONG_SIZE];
-      unsigned int size = 0;
-      switch (statement->data_statement.type) {
-      case LONG:
-       bfd_put_32(output_bfd, value,  play_area);
-       size = LONG_SIZE;
-       break;
-      case SHORT:
-       bfd_put_16(output_bfd, value,  play_area);
-       size = SHORT_SIZE;
-       break;
-      case BYTE:
-       bfd_put_8(output_bfd, value,  play_area);
-       size = BYTE_SIZE;
-       break;
-      }
-      
-      bfd_set_section_contents(output_bfd,
-                              statement->data_statement.output_section,
-                              play_area,
-                              statement->data_statement.output_vma,
-                              size);
-                              
-                              
-
-
+      fprintf (config.map_file, " symbols only\n");
     }
-    break;
-  case lang_input_section_enum:
-      {
-
-       asection *i  = statement->input_section.section;
-       asection *output_section = i->output_section;
-       lang_input_statement_type *ifile =
-         statement->input_section.ifile;
-       if (ifile->just_syms_flag == false) {
-         bfd *inbfd = ifile->the_bfd;
-
-         if (output_section->flags & SEC_LOAD &&
-             output_section->flags & SEC_ALLOC
-             && bfd_get_section_size_before_reloc(i) != 0) 
-             {
-               if(bfd_get_section_contents(inbfd,
-                                           i,
-                                           data_area,
-                                           (file_ptr)0,
-                                           bfd_get_section_size_before_reloc(i)) == false) 
-                   {
-                     einfo("%F%B error reading section contents %E\n", inbfd);
-                   }
-               /* Set the reloc bit */
-               perform_relocation (inbfd,  i,  data_area, ifile->asymbols);
-
-
-               if(bfd_set_section_contents(output_bfd,
-                                           output_section,
-                                           data_area,
-                                           (file_ptr)i->output_offset,
-                                           bfd_get_section_size_after_reloc(i)) == false) 
-                   {
-                     einfo("%F%B error writing section contents of %E\n",
-                           output_bfd);
-                   }
+  else
+    {
+      asection *s;
+      if (true)
+       {
+         for (s = f->the_bfd->sections;
+              s != (asection *) NULL;
+              s = s->next)
+           {
+             print_address (s->output_offset);
+             if (s->reloc_done)
+               {
+                 fprintf (config.map_file, " %08x 2**%2ud %s\n",
+                          (unsigned) bfd_get_section_size_after_reloc (s),
+                          s->alignment_power, s->name);
+               }
 
-             }
+             else
+               {
+                 fprintf (config.map_file, " %08x 2**%2ud %s\n",
+                          (unsigned) bfd_get_section_size_before_reloc (s),
+                          s->alignment_power, s->name);
+               }
+           }
        }
-
-      }
-    break;
-
-  default:
-    /* All the other ones fall through */
-    ;
-
-  }
-}
-
-void
-DEFUN_VOID(write_norel)
-{
-  /* Output the text and data segments, relocating as we go.  */
-  lang_for_each_statement(copy_and_relocate);
-}
-
-
-static void 
-DEFUN(read_relocs,(abfd, section, symbols),
-      bfd *abfd AND
-      asection *section AND
-      asymbol **symbols)
-{
-  /* Work out the output section ascociated with this input section */
-  asection *output_section = section->output_section;
-
-  bfd_size_type reloc_size = bfd_get_reloc_upper_bound(abfd, section);
-  arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
-
-  if (bfd_canonicalize_reloc(abfd, 
-                            section,
-                            reloc_vector,
-                            symbols)) {
-    output_section->reloc_count   += section->reloc_count;
-  }
+      else
+       {
+         for (s = f->the_bfd->sections;
+              s != (asection *) NULL;
+              s = s->next)
+           {
+             fprintf (config.map_file, "%s ", s->name);
+             print_address (s->output_offset);
+             fprintf (config.map_file, "(%x)",
+                      (unsigned) bfd_get_section_size_after_reloc (s));
+           }
+         fprintf (config.map_file, "hex \n");
+       }
+    }
+  print_nl ();
 }
 
+/* Print a symbol.  */
 
-static  void
-DEFUN_VOID(write_rel)
+/*ARGSUSED*/
+static boolean
+print_symbol (p, ignore)
+     struct bfd_link_hash_entry *p;
+     PTR ignore;
 {
-  /*
-     Run through each section of each file and work work out the total
-     number of relocation records which will finally be in each output
-     section 
-     */
-
-  LANG_FOR_EACH_INPUT_SECTION
-    (statement, abfd, section,
-     (read_relocs(abfd, section, statement->asymbols)));
-
-
-
-  /*
-     Now run though all the output sections and allocate the space for
-     all the relocations
-     */
-  LANG_FOR_EACH_OUTPUT_SECTION
-    (section, 
-     (section->orelocation =
-      (arelent **)ldmalloc((bfd_size_type)(sizeof(arelent **)*
-                                   section->reloc_count)),
-      section->reloc_count = 0,
-     section->flags |= SEC_HAS_CONTENTS));
-
-
-  /*
-     Copy the data, relocating as we go
-     */
-  lang_for_each_statement(copy_and_relocate);
-}
+  while (p->type == bfd_link_hash_indirect
+        || p->type == bfd_link_hash_warning)
+    p = p->u.i.link;
 
-void
-DEFUN(ldwrite, (write_map),
-      boolean write_map)
-{
-  data_area = (PTR) ldmalloc(largest_section);
-  if (config.relocateable_output == true)
-      {
-       write_rel();
-      }
-  else 
+  switch (p->type) 
+    {
+    case bfd_link_hash_new:
+      abort ();
+
+    case bfd_link_hash_undefined:
+      fprintf (config.map_file, "undefined                     ");
+      fprintf (config.map_file, "%s ", p->root.string);
+      print_nl ();    
+      break;
+
+    case bfd_link_hash_weak:
+      fprintf (config.map_file, "weak                          ");
+      fprintf (config.map_file, "%s ", p->root.string);
+      print_nl ();    
+      break;
+
+    case bfd_link_hash_defined:            
       {
-       write_relaxnorel(output_bfd);
+       asection *defsec = p->u.def.section;
+
+       print_address (p->u.def.value);
+       if (defsec)
+         {
+           fprintf (config.map_file, "  %-10s",
+                    bfd_section_name (output_bfd, defsec));
+           print_space ();
+           print_address (p->u.def.value + defsec->vma);
+         }
+       else
+         {
+           fprintf (config.map_file, "         .......");
+         }
+       fprintf (config.map_file, " %s ", p->root.string);
       }
-  free(data_area);
-  /* Output the symbol table (both globals and locals).  */
-
-  /* Print a map, if requested.  */
-
-  if (write_map) {
-    ldsym_print_symbol_table ();
-    lang_map(stdout);
-  }
-
-  ldsym_write ();
+      print_nl ();    
+      break;
+
+    case bfd_link_hash_common:
+      fprintf (config.map_file, "common               ");
+      print_address (p->u.c.size);
+      fprintf (config.map_file, " %s ", p->root.string);
+      print_nl ();
+      break;
+
+    default:
+      abort ();
+    }
 
+  return true;
 }
-    
This page took 0.039674 seconds and 4 git commands to generate.