* aclocal.m4: Rebuild with new libtool.
[deliverable/binutils-gdb.git] / ld / ldwrite.c
index 93af48c26b678ac0b125e24e448a87eb7b3b1a2f..4160ae2508b3a06974d9efe827059ae98b74fb4a 100644 (file)
-/* 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 sac@cygnus.com
+
 This file is part of GLD, the Gnu Linker.
 
-GLD is free software; you can redistribute it and/or modify
+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 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
-GLD is distributed in the hope that it will be useful,
+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 GLD; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-/*
- * $Id$ 
- *
- *  $Log$
- *  Revision 1.3  1991/03/22 22:32:22  steve
- *  *** empty log message ***
- *
- * Revision 1.2  1991/03/22  22:31:37  steve
- * *** empty log message ***
- *
- * Revision 1.1.1.1  1991/03/21  21:29:05  gumby
- * Back from Intel with Steve
- *
- * Revision 1.1  1991/03/21  21:29:04  gumby
- * Initial revision
- *
- * Revision 1.2  1991/03/15  18:45:55  rich
- * foo
- *
- * Revision 1.1  1991/03/13  00:48:37  chrisb
- * Initial revision
- *
- * Revision 1.7  1991/03/10  19:15:03  sac
- * Took out the abort() which had been put in the wrong place
- * Updated the version #.
- *
- * Revision 1.6  1991/03/10  09:31:41  rich
- *  Modified Files:
- *     Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
- *     ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
- *     ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
- *     ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
- *     ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
- *
- * As of this round of changes, ld now builds on all hosts of (Intel960)
- * interest and copy passes my copy test on big endian hosts again.
- *
- * Revision 1.5  1991/03/09  03:25:08  sac
- * Added support for LONG, SHORT and BYTE keywords in scripts
- *
- * Revision 1.4  1991/03/06  21:59:34  sac
- * Completed G++ support
- *
- * Revision 1.3  1991/03/06  02:29:52  sac
- * Added support for partial linking.
- *
- * Revision 1.2  1991/02/22  17:15:11  sac
- * Added RCS keywords and copyrights
- *
-*/
-
-/* 
-   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 steve@cygnus.com
-
-*/
-
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-#include "sysdep.h"
 #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.tab.h"
-
-
+#include "ldgram.h"
+#include "ldmain.h"
 
-char *ldmalloc();
-/* 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[];
+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));
 
-extern unsigned int undefined_global_sym_count;
+extern char *strdup();
 
-extern bfd *output_bfd;
+/* Build link_order structures for the BFD linker.  */
 
-extern struct lang_output_section_statement_struct * create_object_symbols;
-
-extern char lprefix;
-
-#ifdef __STDC__
-void lang_for_each_statement(void (*func)());
-#else /* __STDC__ */
-void lang_for_each_statement();
-#endif /* __STDC__ */
-
-extern size_t largest_section;
-ld_config_type config;
+static void
+build_link_order (statement)
+     lang_statement_union_type *statement;
+{
+  switch (statement->header.type)
+    {
+    case lang_data_statement_enum:
+      {
+       asection *output_section;
+       struct bfd_link_order *link_order;
+       bfd_vma value;
+
+       output_section = statement->data_statement.output_section;
+       ASSERT (output_section->owner == output_bfd);
+
+       link_order = bfd_new_link_order (output_bfd, output_section);
+       if (link_order == NULL)
+         einfo ("%P%F: 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 = (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
+          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;
+                     }
+                 }
+             }
 
-extern unsigned int global_symbol_count;
+           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 ();
+                 }
+             }
+         }
 
-boolean trace_files;
+       ASSERT (output_section->owner == output_bfd);
+       switch (statement->data_statement.type)
+         {
+         case QUAD:
+           bfd_put_64 (output_bfd, value, link_order->u.data.contents);
+           link_order->size = QUAD_SIZE;
+           break;
+         case LONG:
+           bfd_put_32 (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);
+           link_order->size = SHORT_SIZE;
+           break;
+         case BYTE:
+           bfd_put_8 (output_bfd, value, link_order->u.data.contents);
+           link_order->size = BYTE_SIZE;
+           break;
+         default:
+           abort ();
+         }
+      }
+      break;
+
+    case lang_reloc_statement_enum:
+      {
+       lang_reloc_statement_type *rs;
+       asection *output_section;
+       struct bfd_link_order *link_order;
+
+       rs = &statement->reloc_statement;
+
+       output_section = rs->output_section;
+       ASSERT (output_section->owner == output_bfd);
+
+       link_order = bfd_new_link_order (output_bfd, output_section);
+       if (link_order == NULL)
+         einfo ("%P%F: bfd_new_link_order failed\n");
+
+       link_order->offset = rs->output_vma;
+       link_order->size = bfd_get_reloc_size (rs->howto);
+
+       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;
+
+       if (rs->name == 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
+         {
+           link_order->type = bfd_symbol_reloc_link_order;
+           link_order->u.reloc.p->u.name = rs->name;
+         }
+      }
+      break;
 
-static void perform_relocation(input_bfd,
-                              input_section,
-                              data,
-                              symbols)
-bfd *input_bfd;
-asection *input_section;
-void *data;
-asymbol **symbols;
-{
-  static asymbol *error_symbol = (asymbol *)NULL;
-  static unsigned int error_count = 0;
-#define MAX_ERRORS_IN_A_ROW 5
-  size_t reloc_size = 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;
-
-  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_enum_type r=
-           bfd_perform_relocation(input_bfd,
-                                  *parent,
-                                  data,
-                                  input_section, 
-                                  ob);
-
-         if (r == bfd_reloc_ok) {
-           if (ob != (bfd *)NULL) {
-             /* A parital link, so keep the relocs */
-             os->orelocation[os->reloc_count] = *parent;
-             os->reloc_count++;
-           }
-         }
-         else
+         ASSERT (output_section->owner == output_bfd);
+
+         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) {
-                   info("%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) {
-                   info("%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: 
-                 info("%B: relocation may be wrong `%T'\n",
-                      input_bfd,
-                      s);
-                 break;
-               case bfd_reloc_outofrange:
-                 info("%B:%s relocation address out of range %T (%x)\n",
-                      input_bfd,
-                      input_section->name,
-                      s,
-                      p->address); 
-                 break;
-               case bfd_reloc_overflow:
-                 info("%B:%s relocation overflow in %T reloc type %d\n",
-                      input_bfd,
-                      input_section->name,
-                      s,
-                      p->howto->type);
-                 break;
-               default:
-                 info("%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  *data_area;
-
-static void
-copy_and_relocate(statement)
-lang_statement_union_type *statement;
+/* Wander around the input sections, make sure that
+   we'll never try and create an output section with more relocs
+   than will fit.. Do this by always assuming the worst case, and
+   creating new output sections with all the right bits */
+#define TESTIT 1
+static asection *
+clone_section (abfd, s, count)
+     bfd *abfd;
+     asection *s;
+     int *count;
 {
-  switch (statement->header.type) {
-  case lang_fill_statement_enum: 
+#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
     {
-#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);
+      char b[6];
+      for (i = 0; i < sizeof (b) - 1 && s->name[i]; i++)
+       b[i] = s->name[i];
+      b[i] = 0;
+      sprintf (sname, "%s%d", b, (*count)++);
+    }
+  while (bfd_get_section_by_name (abfd, sname));
+
+  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;
+  n->lma = s->lma;
+  n->_cooked_size = 0;
+  n->_raw_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;
+  return n;
+}
 
+#if TESTING
+static void 
+ds (s)
+     asection *s;
+{
+  struct bfd_link_order *l = s->link_order_head;
+  printf ("vma %x size %x\n", s->vma, s->_raw_size);
+  while (l)
+    {
+      if (l->type == bfd_indirect_link_order)
+       {
+         printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
        }
-
-      /* Now write any remaining byte */
-      if (i < statement->fill_statement.size) 
+      else
        {
-         bfd_set_section_contents(output_bfd,
-                                  statement->fill_statement.output_section,
-                                  play_area,
-                                  statement->data_statement.output_offset +i,
-                                  1);
-
+         printf ("%8x something else\n", l->offset);
        }
-#endif
+      l = l->next;
     }
-    break;
-  case lang_data_statement_enum:
+  printf ("\n");
+}
+dump (s, a1, a2)
+     char *s;
+     asection *a1;
+     asection *a2;
+{
+  printf ("%s\n", s);
+  ds (a1);
+  ds (a2);
+}
+
+static void 
+sanity_check (abfd)
+     bfd *abfd;
+{
+  asection *s;
+  for (s = abfd->sections; s; s = s->next)
     {
-      bfd_vma value = statement->data_statement.value;
-      bfd_byte play_area[LONG_SIZE];
-      unsigned int size;
-      switch (statement->data_statement.type) {
-      case LONG:
-       bfd_putlong(output_bfd, value,  play_area);
-       size = LONG_SIZE;
-       break;
-      case SHORT:
-       bfd_putshort(output_bfd, value,  play_area);
-       size = SHORT_SIZE;
-       break;
-      case BYTE:
-       bfd_putchar(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);
-                              
-                              
+      struct bfd_link_order *p;
+      bfd_vma prev = 0;
+      for (p = s->link_order_head; p; p = p->next)
+       {
+         if (p->offset > 100000)
+           abort ();
+         if (p->offset < prev)
+           abort ();
+         prev = p->offset;
+       }
+    }
+}
+#else
+#define sanity_check(a)
+#define dump(a, b, c)
+#endif
 
 
-    }
-    break;
-  case lang_input_section_enum:
+void 
+split_sections (abfd, info)
+     bfd *abfd;
+     struct bfd_link_info *info;
+{
+  asection *original_sec;
+  int nsecs = abfd->section_count;
+  sanity_check (abfd);
+  /* look through all the original sections */
+  for (original_sec = abfd->sections;
+       original_sec && nsecs;
+       original_sec = original_sec->next, nsecs--)
     {
-    
-      asection *i  = statement->input_section.section;
-      asection *output_section = i->output_section;
-      lang_input_statement_type *ifile = statement->input_section.ifile;
-      bfd *inbfd = ifile->the_bfd;
-      if (output_section->flags & SEC_LOAD && i->size != 0) 
+      boolean first = true;
+      int count = 0;
+      int lines = 0;
+      int relocs = 0;
+      struct bfd_link_order **pp;
+      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))
        {
-         if(bfd_get_section_contents(inbfd,
-                                     i,
-                                     data_area,
-                                     0L,
-                                     i->size) == false) 
+         struct bfd_link_order *p = *pp;
+         int thislines = 0;
+         int thisrelocs = 0;
+         if (p->type == bfd_indirect_link_order)
            {
-             info("%F%B error reading section contents %E\n",
-                  inbfd);
+             asection *sec;
+
+             sec = p->u.indirect.section;
+
+             if (info->strip == strip_none
+                 || info->strip == strip_some)
+               thislines = sec->lineno_count;
+
+             if (info->relocateable)
+               thisrelocs = sec->reloc_count;
+
            }
-         perform_relocation (inbfd,  i,  data_area, ifile->asymbols);
+         else if (info->relocateable
+                  && (p->type == bfd_section_reloc_link_order
+                      || p->type == bfd_symbol_reloc_link_order))
+           thisrelocs++;
+
+         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 */
+             struct bfd_link_order *l = p;
+             asection *n = clone_section (abfd, cursor, &count);
+             *pp = NULL;       /* Snip off link orders from old section */
+             n->link_order_head = l;   /* attach to new section */
+             pp = &n->link_order_head;
+
+             /* change the size of the original section and
+                update the vma of the new one */
+
+             dump ("before snip", cursor, n);
 
+             n->_raw_size = cursor->_raw_size - l->offset;
+             cursor->_raw_size = l->offset;
 
-         if(bfd_set_section_contents(output_bfd,
-                                     output_section,
-                                     data_area,
-                                     (file_ptr)i->output_offset,
-                                     i->size) == false) 
+             vma += cursor->_raw_size;
+             n->lma = n->vma = vma;
+
+             shift_offset = l->offset;
+
+             /* run down the chain and change the output section to
+                the right one, update the offsets too */
+
+             while (l)
+               {
+                 l->offset -= shift_offset;
+                 if (l->type == bfd_indirect_link_order)
+                   {
+                     l->u.indirect.section->output_section = n;
+                     l->u.indirect.section->output_offset = l->offset;
+                   }
+                 l = l->next;
+               }
+             dump ("after snip", cursor, n);
+             cursor = n;
+             relocs = thisrelocs;
+             lines = thislines;
+           }
+         else
            {
-             info("%F%B error writing section contents of %E\n",
-                  output_bfd);
+             relocs += thisrelocs;
+             lines += thislines;
            }
 
+         first = false;
        }
     }
-    break;
-
- default:
-    /* All the other ones fall through */
-    ;
-
-  }
+  sanity_check (abfd);
 }
-
+/**********************************************************************/
 void
-write_norel()
+ldwrite ()
 {
-  /* Output the text and data segments, relocating as we go.  */
-  lang_for_each_statement(copy_and_relocate);
+  /* 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))
+    {
+      /* 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)
+    {
+      print_symbol_table ();
+      lang_map ();
+    }
 }
 
+/* Print the symbol table.  */
 
-static void read_relocs(abfd, section, symbols)
-bfd *abfd;
-asection *section;
-asymbol **symbols;
+static void
+print_symbol_table ()
 {
-  /* Work out the output section ascociated with this input section */
-  asection *output_section = section->output_section;
-
-  size_t reloc_size = 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;
-  }
+  fprintf (config.map_file, "\n**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);
 }
 
+/* Print information about a file.  */
 
 static void
-write_rel()
+print_file_stuff (f)
+     lang_input_statement_type *f;
 {
-  /*
-     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((size_t)(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);
+  fprintf (config.map_file, "  %s\n", f->filename);
+  if (f->just_syms_flag)
+    {
+      fprintf (config.map_file, " symbols only\n");
+    }
+  else
+    {
+      asection *s;
+      if (true)
+       {
+         for (s = f->the_bfd->sections;
+              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)
+               {
+                 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);
+               }
+           }
+       }
+      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 ();
 }
 
-void
-ldwrite ()
+/* Print a symbol.  */
+
+/*ARGSUSED*/
+static boolean
+print_symbol (p, ignore)
+     struct bfd_link_hash_entry *p;
+     PTR ignore;
 {
-  data_area = (void*) ldmalloc(largest_section);
-  if (config.relocateable_output == true)
+  while (p->type == bfd_link_hash_indirect
+        || p->type == bfd_link_hash_warning)
+    p = p->u.i.link;
+
+  switch (p->type)
     {
-      write_rel();
+    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_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;
+
+       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);
+       if (p->type == bfd_link_hash_defweak)
+         fprintf (config.map_file, " [weak]");
+      }
+      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 ();
     }
-  else 
-    {
-    write_norel();
-  }
-  free(data_area);
-  /* Output the symbol table (both globals and locals).  */
-  ldsym_write ();
 
+  return true;
 }
-    
This page took 0.032344 seconds and 4 git commands to generate.