Tue Jan 25 19:54:19 1994 Stan Shebs (shebs@andros.cygnus.com)
[deliverable/binutils-gdb.git] / ld / ldlang.c
index b53a2fab3d92c2501c75effed8bc023aa7c3cec9..aacff4b704105e358fe6514caafe3d7a49a9255b 100644 (file)
@@ -1,5 +1,5 @@
 /* Linker command language support.
-   Copyright 1991, 1992 Free Software Foundation, Inc.
+   Copyright 1991, 1992, 1993 Free Software Foundation, Inc.
 
 This file is part of GLD, the Gnu Linker.
 
@@ -19,19 +19,19 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
+#include "bfdlink.h"
 
 #include "ld.h"
 #include "ldmain.h"
-#include "ldsym.h"
 #include "ldgram.h"
-#include "ldwarn.h"
-#include "ldlang.h"
 #include "ldexp.h"
+#include "ldlang.h"
 #include "ldemul.h"
 #include "ldlex.h"
 #include "ldmisc.h"
-#include "ldindr.h"
 #include "ldctor.h"
+#include "ldfile.h"
+
 /* FORWARDS */
 static void print_statements PARAMS ((void));
 static void print_statement PARAMS ((lang_statement_union_type *,
@@ -53,9 +53,6 @@ static lang_statement_list_type input_file_chain;
    stuff to the data section without pain */
 static lang_statement_list_type end_of_data_section_statement_list;
 
-/* List of statements needed to handle constructors */
-extern lang_statement_list_type constructor_list;
-
 static boolean placed_commons = false;
 static lang_output_section_statement_type *default_common_section;
 static boolean map_option_f;
@@ -64,42 +61,100 @@ static lang_input_statement_type *first_file;
 static lang_statement_list_type lang_output_section_statement;
 static CONST char *current_target;
 static CONST char *output_target;
-static size_t longest_section_name = 8;
-static section_userdata_type common_section_userdata;
+static int longest_section_name = 8;
 static lang_statement_list_type statement_list;
 
+static void print_size PARAMS ((size_t value));
+static void print_alignment PARAMS ((unsigned int value));
+static void print_fill PARAMS ((fill_type value));
+static void print_section PARAMS ((const char *name));
+static void lang_for_each_statement_worker
+  PARAMS ((void (*func) (lang_statement_union_type *),
+          lang_statement_union_type *s));
+static lang_input_statement_type *new_afile
+  PARAMS ((const char *name, lang_input_file_enum_type file_type,
+          const char *target));
+static void print_flags PARAMS ((int *ignore_flags));
+static void init_os PARAMS ((lang_output_section_statement_type *s));
+static void wild_doit PARAMS ((lang_statement_list_type *ptr,
+                              asection *section,
+                              lang_output_section_statement_type *output,
+                              lang_input_statement_type *file));
+static asection *our_bfd_get_section_by_name PARAMS ((bfd *abfd,
+                                                     const char *section));
+static void wild_section PARAMS ((lang_wild_statement_type *ptr,
+                                 const char *section,
+                                 lang_input_statement_type *file,
+                                 lang_output_section_statement_type *output));
+static lang_input_statement_type *lookup_name PARAMS ((const char *name));
+static void wild PARAMS ((lang_wild_statement_type *s,
+                         const char *section, const char *file,
+                         const char *target,
+                         lang_output_section_statement_type *output));
+static bfd *open_output PARAMS ((const char *name));
+static void ldlang_open_output PARAMS ((lang_statement_union_type *statement));
+static void open_input_bfds PARAMS ((lang_statement_union_type *statement));
+static void lang_reasonable_defaults PARAMS ((void));
+static void lang_place_undefineds PARAMS ((void));
+static void lang_create_output_section_statements PARAMS ((void));
+static void map_input_to_output_sections
+  PARAMS ((lang_statement_union_type *s,
+          const char *target,
+          lang_output_section_statement_type *output_section_statement));
+static void print_output_section_statement
+  PARAMS ((lang_output_section_statement_type *output_section_statement));
+static void print_assignment
+  PARAMS ((lang_assignment_statement_type *assignment,
+          lang_output_section_statement_type *output_section));
+static void print_input_statement PARAMS ((lang_input_statement_type *statm));
+static void print_symbol PARAMS ((asymbol *q));
+static void print_input_section PARAMS ((lang_input_section_type *in));
+static void print_fill_statement PARAMS ((lang_fill_statement_type *fill));
+static void print_data_statement PARAMS ((lang_data_statement_type *data));
+static void print_padding_statement PARAMS ((lang_padding_statement_type *s));
+static void print_wild_statement
+  PARAMS ((lang_wild_statement_type *w,
+          lang_output_section_statement_type *os));
+static void print_statement PARAMS ((lang_statement_union_type *s,
+                                    lang_output_section_statement_type *os));
+static void print_statements PARAMS ((void));
+static bfd_vma insert_pad PARAMS ((lang_statement_union_type **this_ptr,
+                                  fill_type fill, unsigned int power,
+                                  asection *output_section_statement,
+                                  bfd_vma dot));
+static bfd_vma size_input_section
+  PARAMS ((lang_statement_union_type **this_ptr,
+          lang_output_section_statement_type *output_section_statement,
+          fill_type fill, bfd_vma dot, boolean relax));
+static bfd_vma lang_size_sections
+  PARAMS ((lang_statement_union_type *s,
+          lang_output_section_statement_type *output_section_statement,
+          lang_statement_union_type **prev, fill_type fill,
+          bfd_vma dot, boolean relax));
+static bfd_vma lang_do_assignments
+  PARAMS ((lang_statement_union_type * s,
+          lang_output_section_statement_type *output_section_statement,
+          fill_type fill,
+          bfd_vma dot));
+static void lang_finish PARAMS ((void));
+static void lang_check PARAMS ((void));
+static void lang_common PARAMS ((void));
+static boolean lang_one_common PARAMS ((struct bfd_link_hash_entry *, PTR));
+static void lang_place_orphans PARAMS ((void));
+static int topower PARAMS ((int));
+static void reset_memory_regions PARAMS ((void));
+
 /* EXPORTS */
-boolean relaxing;
 lang_output_section_statement_type *abs_output_section;
 lang_statement_list_type *stat_ptr = &statement_list;
-lang_input_statement_type *script_file = 0;
-boolean option_longmap = false;
 lang_statement_list_type file_chain =
 {0};
 CONST char *entry_symbol = 0;
 bfd_size_type largest_section = 0;
 boolean lang_has_input_file = false;
-lang_output_section_statement_type *create_object_symbols = 0;
 boolean had_output_filename = false;
 boolean lang_float_flag = false;
-
-/* IMPORTS */
-extern char *default_target;
-
-extern unsigned int undefined_global_sym_count;
-extern char *current_file;
-extern bfd *output_bfd;
-extern enum bfd_architecture ldfile_output_architecture;
-extern unsigned long ldfile_output_machine;
-extern char *ldfile_output_machine_name;
-extern ldsym_type *symbol_head;
-extern unsigned int commons_pending;
-extern args_type command_line;
-extern ld_config_type config;
-extern boolean had_script;
-extern boolean write_map;
-extern int g_switch_value;
-
+boolean delete_output_file_on_failure = false;
 
 etree_type *base; /* Relocation base - or null */
 
@@ -116,37 +171,37 @@ etree_type *base; /* Relocation base - or null */
 
 #define outside_symbol_address(q) ((q)->value +   outside_section_address(q->section))
 
-void lang_add_data PARAMS ((int type, union etree_union * exp));
-
 PTR
 stat_alloc (size)
      size_t size;
 {
   return obstack_alloc (&stat_obstack, size);
 }
+
 static void
 print_size (value)
      size_t value;
 {
   fprintf (config.map_file, "%5x", (unsigned) value);
 }
+
 static void
 print_alignment (value)
      unsigned int value;
 {
   fprintf (config.map_file, "2**%1u", value);
 }
+
 static void
-DEFUN (print_fill, (value),
-     fill_type value)
+print_fill (value)
+     fill_type value;
 {
   fprintf (config.map_file, "%04x", (unsigned) value);
 }
 
-
 static void
 print_section (name)
-     CONST char *CONST name;
+     CONST char *name;
 {
   fprintf (config.map_file, "%*s", -longest_section_name, name);
 }
@@ -158,7 +213,7 @@ print_section (name)
 
 static void
 lang_for_each_statement_worker (func, s)
-     void (*func) ();
+     void (*func) PARAMS ((lang_statement_union_type *));
      lang_statement_union_type *s;
 {
   for (; s != (lang_statement_union_type *) NULL; s = s->next)
@@ -199,7 +254,7 @@ lang_for_each_statement_worker (func, s)
 
 void
 lang_for_each_statement (func)
-     void (*func) ();
+     void (*func) PARAMS ((lang_statement_union_type *));
 {
   lang_for_each_statement_worker (func,
                                  statement_list.head);
@@ -249,9 +304,9 @@ new_statement (type, size, list)
  */
 static lang_input_statement_type *
 new_afile (name, file_type, target)
-     CONST char *CONST name;
-     CONST lang_input_file_enum_type file_type;
-     CONST char *CONST target;
+     CONST char *name;
+     lang_input_file_enum_type file_type;
+     CONST char *target;
 {
 
   lang_input_statement_type *p = new_stat (lang_input_statement,
@@ -312,6 +367,7 @@ new_afile (name, file_type, target)
   p->next = (lang_statement_union_type *) NULL;
   p->symbol_count = 0;
   p->common_output_section = (asection *) NULL;
+  p->loaded = false;
   lang_statement_append (&input_file_chain,
                         (lang_statement_union_type *) p,
                         &p->next_real_file);
@@ -326,6 +382,7 @@ lang_add_input_file (name, file_type, target)
 {
   /* Look it up or build a new one */
   lang_has_input_file = true;
+
 #if 0
   lang_input_statement_type *p;
 
@@ -345,19 +402,6 @@ lang_add_input_file (name, file_type, target)
   return new_afile (name, file_type, target);
 }
 
-void
-lang_add_keepsyms_file (filename)
-     CONST char *filename;
-{
-  extern strip_symbols_type strip_symbols;
-  if (keepsyms_file != 0)
-    info ("%X%P error: duplicated keep-symbols-file value\n");
-  keepsyms_file = filename;
-  if (strip_symbols != STRIP_NONE)
-    info ("%P `-keep-only-symbols-file' overrides `-s' and `-S'\n");
-  strip_symbols = STRIP_SOME;
-}
-
 /* Build enough state so that the parser can build its tree */
 void
 lang_init ()
@@ -540,7 +584,8 @@ lang_map ()
       print_address (m->current - m->origin);
       print_space();
       if (m->old_length)
-       fprintf(config.map_file," %2d%%  ", ( m->current - m->origin) * 100 / m->old_length);
+       fprintf (config.map_file, " %2d%%  ",
+               (int) ((m->current - m->origin) * 100 / m->old_length));
       print_flags (&m->flags);
       fprintf (config.map_file, "\n");
     }
@@ -569,7 +614,7 @@ init_os (s)
     s->bfd_section = bfd_make_section (output_bfd, s->name);
   if (s->bfd_section == (asection *) NULL)
     {
-      einfo ("%P%F output format %s cannot represent section called %s\n",
+      einfo ("%P%F: output format %s cannot represent section called %s\n",
             output_bfd->xvec->name, s->name);
     }
   s->bfd_section->output_section = s->bfd_section;
@@ -633,7 +678,8 @@ wild_doit (ptr, section, output, file)
     if ((section->flags & SEC_SHARED_LIBRARY) != 0)
       section->output_section->flags |= section->flags;
     else
-      section->output_section->flags |= section->flags & ~SEC_NEVER_LOAD;
+      section->output_section->flags |=
+       section->flags & (flagword) (~ SEC_NEVER_LOAD);
 
     if (!output->loadable) 
     {
@@ -705,7 +751,7 @@ wild_section (ptr, section, file, output)
 static
 lang_input_statement_type *
 lookup_name (name)
-     CONST char *CONST name;
+     CONST char *name;
 {
   lang_input_statement_type *search;
 
@@ -714,35 +760,62 @@ lookup_name (name)
        search = (lang_input_statement_type *) search->next_real_file)
     {
       if (search->filename == (char *) NULL && name == (char *) NULL)
-       {
-         return search;
-       }
-      if (search->filename != (char *) NULL && name != (char *) NULL)
-       {
-         if (strcmp (search->filename, name) == 0)
-           {
-             ldmain_open_file_read_symbol (search);
-             return search;
-           }
-       }
+       return search;
+      if (search->filename != (char *) NULL
+         && name != (char *) NULL
+         && strcmp (search->filename, name) == 0)
+       break;
     }
 
-  /* There isn't an afile entry for this file yet, this must be
-     because the name has only appeared inside a load script and not
-     on the command line  */
-  search = new_afile (name, lang_input_file_is_file_enum, default_target);
-  ldmain_open_file_read_symbol (search);
-  return search;
+  if (search == (lang_input_statement_type *) NULL)
+    {
+      /* There isn't an afile entry for this file yet, this must be
+        because the name has only appeared inside a load script and
+        not on the command line */
+      search = new_afile (name, lang_input_file_is_file_enum, default_target);
+    }
+
+  /* If we have already added this file, or this file is not real
+     (FIXME: can that ever actually happen?) or the name is NULL
+     (FIXME: can that ever actually happen?) don't add this file.  */
+  if (search->loaded
+      || ! search->real
+      || search->filename == (const char *) NULL)
+    return search;
+
+  ldfile_open_file (search);
+
+  if (bfd_check_format (search->the_bfd, bfd_object))
+    {
+      ldlang_add_file (search);
+      if (trace_files || trace_file_tries)
+       info_msg ("%I\n", search);
+    }
+  else if (bfd_check_format (search->the_bfd, bfd_archive))
+    {
+      /* There is nothing to do here; the add_symbols routine will
+        call ldlang_add_file (via the add_archive_element callback)
+        for each element of the archive which is used.  */
+    }
+  else
+    einfo ("%F%B: file not recognized: %E\n", search->the_bfd);
 
+  bfd_set_gp_size (search->the_bfd, g_switch_value);
 
+  if (bfd_link_add_symbols (search->the_bfd, &link_info) == false)
+    einfo ("%F%B: could not read symbols: %E\n", search->the_bfd);
+
+  search->loaded = true;
+
+  return search;
 }
 
 static void
 wild (s, section, file, target, output)
      lang_wild_statement_type * s;
-     CONST char *CONST section;
-     CONST char *CONST file;
-     CONST char *CONST target;
+     CONST char *section;
+     CONST char *file;
+     CONST char *target;
      lang_output_section_statement_type * output;
 {
   lang_input_statement_type *f;
@@ -756,8 +829,6 @@ wild (s, section, file, target, output)
        {
          wild_section (s, section, f, output);
        }
-      /* Once more for the script file */
-      wild_section(s, section, script_file, output);
     }
   else
     {
@@ -777,14 +848,11 @@ wild (s, section, file, target, output)
 /*
   read in all the files
   */
+
 static bfd *
 open_output (name)
-     CONST char *CONST name;
+     CONST char *name;
 {
-  extern unsigned long ldfile_output_machine;
-  extern enum bfd_architecture ldfile_output_architecture;
-
-  extern CONST char *output_filename;
   bfd *output;
 
   if (output_target == (char *) NULL)
@@ -795,23 +863,31 @@ open_output (name)
        output_target = default_target;
     }
   output = bfd_openw (name, output_target);
-  output_filename = name;
 
   if (output == (bfd *) NULL)
     {
       if (bfd_error == invalid_target)
        {
-         einfo ("%P%F target %s not found\n", output_target);
+         einfo ("%P%F: target %s not found\n", output_target);
        }
-      einfo ("%P%F problem opening output file %s, %E\n", name);
+      einfo ("%P%F: cannot open output file %s: %E\n", name);
     }
 
+  delete_output_file_on_failure = 1;
+
   /*  output->flags |= D_PAGED;*/
 
-  bfd_set_format (output, bfd_object);
-  bfd_set_arch_mach (output,
-                    ldfile_output_architecture,
-                    ldfile_output_machine);
+  if (! bfd_set_format (output, bfd_object))
+    einfo ("%P%F:%s: can not make object file: %E\n", name);
+  if (! bfd_set_arch_mach (output,
+                          ldfile_output_architecture,
+                          ldfile_output_machine))
+    einfo ("%P%F:%s: can not set architecture: %E\n", name);
+
+  link_info.hash = bfd_link_hash_table_create (output);
+  if (link_info.hash == (struct bfd_link_hash_table *) NULL)
+    einfo ("%P%F: can not create link hash table: %E\n");
+
   bfd_set_gp_size (output, g_switch_value);
   return output;
 }
@@ -825,10 +901,11 @@ ldlang_open_output (statement)
 {
   switch (statement->header.type)
     {
-      case lang_output_statement_enum:
+    case lang_output_statement_enum:
+      ASSERT (output_bfd == (bfd *) NULL);
       output_bfd = open_output (statement->output_statement.name);
       ldemul_set_output_arch ();
-      if (config.magic_demand_paged && !config.relocateable_output)
+      if (config.magic_demand_paged && !link_info.relocateable)
        output_bfd->flags |= D_PAGED;
       else
        output_bfd->flags &= ~D_PAGED;
@@ -879,9 +956,6 @@ open_input_bfds (statement)
 static void
 lang_reasonable_defaults ()
 {
-
-
-
 #if 0
   lang_output_section_statement_lookup (".text");
   lang_output_section_statement_lookup (".data");
@@ -937,19 +1011,23 @@ ldlang_add_undef (name)
 static void
 lang_place_undefineds ()
 {
-  ldlang_undef_chain_list_type *ptr = ldlang_undef_chain_list_head;
+  ldlang_undef_chain_list_type *ptr;
 
-  while (ptr != (ldlang_undef_chain_list_type *) NULL)
+  for (ptr = ldlang_undef_chain_list_head;
+       ptr != (ldlang_undef_chain_list_type *) NULL;
+       ptr = ptr->next)
     {
-      asymbol *def;
-      asymbol **def_ptr = (asymbol **) stat_alloc ((bfd_size_type) (sizeof (asymbol **)));
+      struct bfd_link_hash_entry *h;
 
-      def = (asymbol *) bfd_make_empty_symbol (script_file->the_bfd);
-      *def_ptr = def;
-      def->name = ptr->name;
-      def->section = &bfd_und_section;
-      Q_enter_global_ref (def_ptr, ptr->name);
-      ptr = ptr->next;
+      h = bfd_link_hash_lookup (link_info.hash, ptr->name, true, false, true);
+      if (h == (struct bfd_link_hash_entry *) NULL)
+       einfo ("%P%F: bfd_link_hash_lookup failed: %E");
+      if (h->type == bfd_link_hash_new)
+       {
+         h->type = bfd_link_hash_undefined;
+         h->u.undef.abfd = NULL;
+         bfd_link_add_undef (link_info.hash, h);
+       }
     }
 }
 
@@ -974,28 +1052,6 @@ lang_create_output_section_statements ()
 
 }
 
-static void
-lang_init_script_file ()
-{
-  script_file = lang_add_input_file ("command line",
-                                    lang_input_file_is_fake_enum,
-                                    (char *) NULL);
-  script_file->the_bfd = bfd_create ("command line", output_bfd);
-  script_file->symbol_count = 0;
-  script_file->the_bfd->sections = 0;
-
-  /* The user data of a bfd points to the input statement attatched */
-  script_file->the_bfd->usrdata  = (void *)script_file;
-  script_file->common_section =
-   bfd_make_section(script_file->the_bfd,"COMMON");
-
-  abs_output_section =
-   lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
-
-  abs_output_section->bfd_section = &bfd_abs_section;
-
-}
-
 /* Open input files and attatch to output sections */
 static void
 map_input_to_output_sections (s, target, output_section_statement)
@@ -1050,23 +1106,18 @@ map_input_to_output_sections (s, target, output_section_statement)
            os->addr_tree = s->address_statement.address;
            if (os->bfd_section == (asection *) NULL)
              {
-               einfo ("%P%F can't set the address of undefined section %s\n",
+               einfo ("%P%F: cannot set the address of undefined section %s\n",
                       s->address_statement.section_name);
              }
          }
          break;
        case lang_input_statement_enum:
          /* A standard input statement, has no wildcards */
-         /*    ldmain_open_file_read_symbol(&s->input_statement);*/
          break;
        }
     }
 }
 
-
-
-
-
 static void
 print_output_section_statement (output_section_statement)
      lang_output_section_statement_type * output_section_statement;
@@ -1189,6 +1240,8 @@ print_symbol (q)
   fprintf (config.map_file, " ");
   print_address (outside_symbol_address (q));
   fprintf (config.map_file, "              %s", q->name ? q->name : " ");
+  if (q->flags & BSF_WEAK)
+    fprintf (config.map_file, " *weak*");
   print_nl ();
 }
 
@@ -1250,7 +1303,8 @@ print_input_section (in)
                    {
                      asymbol *q = *p;
 
-                     if (bfd_get_section (q) == i && q->flags & BSF_GLOBAL)
+                     if (bfd_get_section (q) == i
+                         && (q->flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
                        {
                          print_symbol (q);
                        }
@@ -1309,6 +1363,10 @@ print_data_statement (data)
       fprintf (config.map_file, "LONG ");
       print_dot += LONG_SIZE;
       break;
+    case QUAD:
+      fprintf (config.map_file, "QUAD ");
+      print_dot += QUAD_SIZE;
+      break;
     }
 
   exp_print_tree (data->exp);
@@ -1436,12 +1494,12 @@ print_statements ()
 }
 
 static bfd_vma
-DEFUN (insert_pad, (this_ptr, fill, power, output_section_statement, dot),
-     lang_statement_union_type ** this_ptr AND
-     fill_type fill AND
-     unsigned int power AND
-     asection * output_section_statement AND
-     bfd_vma dot)
+insert_pad (this_ptr, fill, power, output_section_statement, dot)
+     lang_statement_union_type ** this_ptr;
+     fill_type fill;
+     unsigned int power;
+     asection * output_section_statement;
+     bfd_vma dot;
 {
   /* Align this section first to the
      input sections requirement, then
@@ -1483,12 +1541,12 @@ DEFUN (insert_pad, (this_ptr, fill, power, output_section_statement, dot),
 
 /* Work out how much this section will move the dot point */
 static bfd_vma
-DEFUN (size_input_section, (this_ptr, output_section_statement, fill, dot, relax),
-     lang_statement_union_type ** this_ptr AND
-     lang_output_section_statement_type * output_section_statement AND
-     unsigned short fill AND
-     bfd_vma dot AND
-     boolean relax)
+size_input_section (this_ptr, output_section_statement, fill, dot, relax)
+     lang_statement_union_type ** this_ptr;
+     lang_output_section_statement_type * output_section_statement;
+     fill_type fill;
+     bfd_vma dot;
+     boolean relax;
 {
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
@@ -1542,13 +1600,13 @@ DEFUN (size_input_section, (this_ptr, output_section_statement, fill, dot, relax
 static boolean had_relax;
 
 static bfd_vma
-DEFUN (lang_size_sections, (s, output_section_statement, prev, fill, dot, relax),
-     lang_statement_union_type * s AND
-     lang_output_section_statement_type * output_section_statement AND
-     lang_statement_union_type ** prev AND
-     unsigned short fill AND
-     bfd_vma dot AND
-     boolean relax)
+lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
+     lang_statement_union_type * s;
+     lang_output_section_statement_type * output_section_statement;
+     lang_statement_union_type ** prev;
+     fill_type fill;
+     bfd_vma dot;
+     boolean relax;
 {
   /* Size up the sections from their constituent parts */
   for (; s != (lang_statement_union_type *) NULL; s = s->next)
@@ -1620,11 +1678,10 @@ DEFUN (lang_size_sections, (s, output_section_statement, prev, fill, dot, relax)
        /* Ignore the size of the input sections, use the vma and size to */
        /* align against */
 
-
        after = ALIGN_N (os->bfd_section->vma +
-                     os->bfd_section->_raw_size,
-                     os->block_value);
-
+                       os->bfd_section->_raw_size,
+                       /* The coercion here is important, see ld.h.  */
+                       (bfd_vma) os->block_value);
 
        os->bfd_section->_raw_size = after - os->bfd_section->vma;
        dot = os->bfd_section->vma + os->bfd_section->_raw_size;
@@ -1640,7 +1697,7 @@ DEFUN (lang_size_sections, (s, output_section_statement, prev, fill, dot, relax)
               > os->region->origin + os->region->length)
             || ( os->region->origin > os->region->current ))
           {
-            einfo ("%X%P: Region %s is full (%B section %s)\n",
+            einfo ("%X%P: region %s is full (%B section %s)\n",
                    os->region->name,
                    os->bfd_section->owner,
                    os->bfd_section->name);
@@ -1671,6 +1728,9 @@ DEFUN (lang_size_sections, (s, output_section_statement, prev, fill, dot, relax)
 
        switch (s->data_statement.type)
        {
+        case QUAD:
+        size = QUAD_SIZE;
+        break;
        case LONG:
         size = LONG_SIZE;
         break;
@@ -1698,7 +1758,8 @@ DEFUN (lang_size_sections, (s, output_section_statement, prev, fill, dot, relax)
       break;
 
      case lang_object_symbols_statement_enum:
-      create_object_symbols = output_section_statement;
+      link_info.create_object_symbols_section =
+       output_section_statement->bfd_section;
       break;
      case lang_output_statement_enum:
      case lang_target_statement_enum:
@@ -1706,12 +1767,35 @@ DEFUN (lang_size_sections, (s, output_section_statement, prev, fill, dot, relax)
      case lang_input_section_enum:
       if (relax)
       {
-       relaxing = true;
+       lang_input_section_type *is;
+       asection *i;
 
-       if( relax_section (prev))
-        had_relax = true;
-       relaxing = false;
+       is = &(*prev)->input_section;
+       i = is->section;
 
+       /* FIXME: The interface to bfd_relax_section should be changed
+          to not require the generic symbols to be read.  Changing
+          this would require changing both b_out_relax_section and
+          bfd_coff_relax16_section.  */
+       if (is->ifile->asymbols == (asymbol **) NULL)
+         {
+           unsigned int symsize;
+
+           symsize = get_symtab_upper_bound (i->owner);
+           is->ifile->asymbols = (asymbol **) ldmalloc (symsize);
+           is->ifile->symbol_count =
+             bfd_canonicalize_symtab (i->owner, is->ifile->asymbols);
+
+           /* The generic linker code in BFD requires that these
+              symbols be stored in the outsymbols and symcount
+              fields.  When the bfd_relax_section is interface is
+              fixed this should also be fixed.  */
+           i->owner->outsymbols = is->ifile->asymbols;
+           i->owner->symcount = is->ifile->symbol_count;
+         }
+
+       if (bfd_relax_section (i->owner, i, &link_info, is->ifile->asymbols))
+         had_relax = true;
       }
       else  {
        (*prev)->input_section.section->_cooked_size = 
@@ -1779,13 +1863,12 @@ DEFUN (lang_size_sections, (s, output_section_statement, prev, fill, dot, relax)
 }
 
 static bfd_vma
-DEFUN (lang_do_assignments, (s, output_section_statement, fill, dot),
-     lang_statement_union_type * s AND
-     lang_output_section_statement_type * output_section_statement AND
-     unsigned short fill AND
-     bfd_vma dot)
+lang_do_assignments (s, output_section_statement, fill, dot)
+     lang_statement_union_type * s;
+     lang_output_section_statement_type * output_section_statement;
+     fill_type fill;
+     bfd_vma dot;
 {
-
   for (; s != (lang_statement_union_type *) NULL; s = s->next)
     {
       switch (s->header.type)
@@ -1831,10 +1914,13 @@ DEFUN (lang_do_assignments, (s, output_section_statement, fill, dot),
                                   lang_final_phase_enum, dot, &dot);
            s->data_statement.value = value.value;
            if (value.valid == false)
-             einfo ("%F%P: Invalid data statement\n");
+             einfo ("%F%P: invalid data statement\n");
          }
          switch (s->data_statement.type)
            {
+           case QUAD:
+             dot += QUAD_SIZE;
+             break;
            case LONG:
              dot += LONG_SIZE;
              break;
@@ -1883,110 +1969,56 @@ DEFUN (lang_do_assignments, (s, output_section_statement, fill, dot),
   return dot;
 }
 
-
-
-static void
-lang_relocate_globals ()
-{
-  /*
-    Each ldsym_type maintains a chain of pointers to asymbols which
-    references the definition.  Replace each pointer to the referenence
-    with a pointer to only one place, preferably the definition. If
-    the defintion isn't available then the common symbol, and if
-    there isn't one of them then choose one reference.
-    */
-
-  FOR_EACH_LDSYM (lgs)
-  {
-    asymbol *it;
-
-    /* Skip indirect symbols.  */
-    if (lgs->flags & SYM_INDIRECT)
-      continue;
-
-    if (lgs->sdefs_chain)
-      {
-       it = *(lgs->sdefs_chain);
-      }
-    else if (lgs->scoms_chain != (asymbol **) NULL)
-      {
-       it = *(lgs->scoms_chain);
-      }
-    else if (lgs->srefs_chain != (asymbol **) NULL)
-      {
-       it = *(lgs->srefs_chain);
-      }
-    else
-      {
-       /* This can happen when the command line asked for a symbol to
-          be -u */
-       it = (asymbol *) NULL;
-      }
-    if (it != (asymbol *) NULL)
-      {
-       asymbol **prev = 0;
-       asymbol **ptr = lgs->srefs_chain;;
-       if (lgs->flags & SYM_WARNING)
-         {
-           produce_warnings (lgs, it);
-         }
-
-       while (ptr != (asymbol **) NULL
-              && ptr != prev)
-         {
-           asymbol *ref = *ptr;
-           prev = ptr;
-           *ptr = it;
-           ptr = (asymbol **) (ref->udata);
-         }
-      }
-  }
-}
-
-
-
 static void
 lang_finish ()
 {
-  ldsym_type *lgs;
-  int warn = config.relocateable_output != true;
-  if (entry_symbol == (char *) NULL)
-  {
-    /* No entry has been specified, look for start, but don't warn */
-    entry_symbol = "start";
-    warn =0;
-  }
-  lgs = ldsym_get_soft (entry_symbol);
-  if (lgs && lgs->sdefs_chain)
-  {
-    asymbol *sy = *(lgs->sdefs_chain);
+  struct bfd_link_hash_entry *h;
+  boolean warn = link_info.relocateable ? false : true;
 
-    /* We can set the entry address*/
-    bfd_set_start_address (output_bfd,
-                          outside_symbol_address (sy));
+  if (entry_symbol == (char *) NULL)
+    {
+      /* No entry has been specified.  Look for start, but don't warn
+        if we don't find it.  */
+      entry_symbol = "start";
+      warn = false;
+    }
 
-  }
-  else
-  {
-    /* Can't find anything reasonable,
-       use the first address in the text section
-       */
-    asection *ts = bfd_get_section_by_name (output_bfd, ".text");
-    if (ts)
+  h = bfd_link_hash_lookup (link_info.hash, entry_symbol, false, false, true);
+  if (h != (struct bfd_link_hash_entry *) NULL
+      && h->type == bfd_link_hash_defined)
     {
-      if (warn)
-       einfo ("%P: Warning, can't find entry symbol %s, defaulting to %V\n",
-             entry_symbol, ts->vma);
+      bfd_vma val;
 
-      bfd_set_start_address (output_bfd, ts->vma);
+      val = (h->u.def.value
+            + bfd_get_section_vma (output_bfd,
+                                   h->u.def.section->output_section)
+            + h->u.def.section->output_offset);
+      if (! bfd_set_start_address (output_bfd, val))
+       einfo ("%P%F:%s: can't set start address\n", entry_symbol);
     }
-    else 
+  else
     {
-      if (warn)
-       einfo ("%P: Warning, can't find entry symbol %s, not setting start address\n",
-             entry_symbol);
+      asection *ts;
+
+      /* Can't find the entry symbol.  Use the first address in the
+        text section.  */
+      ts = bfd_get_section_by_name (output_bfd, ".text");
+      if (ts != (asection *) NULL)
+       {
+         if (warn)
+           einfo ("%P: warning: cannot find entry symbol %s; defaulting to %V\n",
+                  entry_symbol, bfd_get_section_vma (output_bfd, ts));
+         if (! bfd_set_start_address (output_bfd,
+                                      bfd_get_section_vma (output_bfd, ts)))
+           einfo ("%P%F: can't set start address\n");
+       }
+      else
+       {
+         if (warn)
+           einfo ("%P: warning: cannot find entry symbol %s; not setting start address\n",
+                  entry_symbol);
+       }
     }
-  }
 }
 
 /* By now we know the target architecture, and we may have an */
@@ -2024,145 +2056,114 @@ lang_check ()
       else
        {
 
-         info ("%P: warning, %s architecture of input file `%B' incompatible with %s output\n",
+         einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
                bfd_printable_name (input_bfd), input_bfd,
                bfd_printable_name (output_bfd));
 
-         bfd_set_arch_mach (output_bfd,
-                            input_architecture,
-                            input_machine);
+         if (! bfd_set_arch_mach (output_bfd,
+                                  input_architecture,
+                                  input_machine))
+           einfo ("%P%F:%s: can't set architecture: %E\n",
+                  bfd_get_filename (output_bfd));
        }
 
     }
 }
 
-/*
- * run through all the global common symbols and tie them
- * to the output section requested.
- *
- As an experiment we do this 4 times, once for all the byte sizes,
- then all the two  bytes, all the four bytes and then everything else
-  */
+/* Look through all the global common symbols and attach them to the
+   correct section.  The -sort-common command line switch may be used
+   to roughly sort the entries by size.  */
 
 static void
 lang_common ()
 {
-  ldsym_type *lgs;
-  size_t power;
+  if (link_info.relocateable
+      && ! command_line.force_common_definition)
+    return;
 
-  if (config.relocateable_output == false ||
-      command_line.force_common_definition == true)
+  if (! config.sort_common)
+    bfd_link_hash_traverse (link_info.hash, lang_one_common, (PTR) NULL);
+  else
     {
-      for (power = 1; (config.sort_common == true && power == 1) || (power <= 16); power <<= 1)
-       {
-         for (lgs = symbol_head;
-              lgs != (ldsym_type *) NULL;
-              lgs = lgs->next)
-           {
-             asymbol *com;
-             unsigned int power_of_two;
-             size_t size;
-             size_t align;
+      unsigned int power;
 
-             if (lgs->scoms_chain != (asymbol **) NULL)
-               {
-                 com = *(lgs->scoms_chain);
-                 size = com->value;
-                 switch (size)
-                   {
-                   case 0:
-                   case 1:
-                     align = 1;
-                     power_of_two = 0;
-                     break;
-                   case 2:
-                     power_of_two = 1;
-                     align = 2;
-                     break;
-                   case 3:
-                   case 4:
-                     power_of_two = 2;
-                     align = 4;
-                     break;
-                   case 5:
-                   case 6:
-                   case 7:
-                   case 8:
-                     power_of_two = 3;
-                     align = 8;
-                     break;
-                   default:
-                     power_of_two = 4;
-                     align = 16;
-                     break;
-                   }
-                 if (config.sort_common == false || align == power)
-                   {
-                     bfd *symbfd;
-
-                     /* Change from a common symbol into a definition of
-                        a symbol */
-                     lgs->sdefs_chain = lgs->scoms_chain;
-                     lgs->scoms_chain = (asymbol **) NULL;
-                     commons_pending--;
-
-                     /* Point to the correct common section */
-                     symbfd = bfd_asymbol_bfd (com);
-                     if (com->section == &bfd_com_section)
-                       com->section =
-                         ((lang_input_statement_type *) symbfd->usrdata)
-                           ->common_section;
-                     else
-                       {
-                         CONST char *name;
-                         asection *newsec;
-
-                         name = bfd_get_section_name (symbfd,
-                                                      com->section);
-                         newsec = bfd_get_section_by_name (symbfd,
-                                                           name);
-                         /* BFD backend must provide this section. */
-                         if (newsec == (asection *) NULL)
-                           einfo ("%P%F: No output section %s", name);
-                         com->section = newsec;
-                       }
+      for (power = 1; power <= 16; power <<= 1)
+       bfd_link_hash_traverse (link_info.hash, lang_one_common,
+                               (PTR) &power);
+    }
+}
 
-                     /*  Fix the size of the common section */
+/* Place one common symbol in the correct section.  */
 
-                     com->section->_raw_size =
-                       ALIGN_N (com->section->_raw_size, align);
+static boolean
+lang_one_common (h, info)
+     struct bfd_link_hash_entry *h;
+     PTR info;
+{
+  unsigned int power_of_two;
+  bfd_vma size;
+  size_t align;
+  asection *section;
 
-                     /* Remember if this is the biggest alignment ever seen */
-                     if (power_of_two > com->section->alignment_power)
-                       {
-                         com->section->alignment_power = power_of_two;
-                       }
+  if (h->type != bfd_link_hash_common)
+    return true;
 
-                     /* Symbol stops being common and starts being global, but
-                        we remember that it was common once. */
+  size = h->u.c.size;
+  switch (size)
+    {
+    case 0:
+    case 1:
+      power_of_two = 0;
+      align = 1;
+      break;
+    case 2:
+      power_of_two = 1;
+      align = 2;
+      break;
+    case 3:
+    case 4:
+      power_of_two = 2;
+      align = 4;
+      break;
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+      power_of_two = 3;
+      align = 8;
+      break;
+    default:
+      power_of_two = 4;
+      align = 16;
+      break;
+    }
+             
+  if (config.sort_common && align != *(unsigned int *) info)
+    return true;
 
-                     com->flags = BSF_EXPORT | BSF_GLOBAL | BSF_OLD_COMMON;
-                     com->value = com->section->_raw_size;
+  section = h->u.c.section;
 
-                     if (write_map && config.map_file)
-                       {
-                         fprintf (config.map_file, "Allocating common %s: %x at %x %s\n",
-                                  lgs->name,
-                                  (unsigned) size,
-                                  (unsigned) com->value,
-                                  bfd_asymbol_bfd(com)->filename);
-                       }
+  /* Increase the size of the section.  */
+  section->_raw_size = ALIGN_N (section->_raw_size, align);
 
-                     com->section->_raw_size += size;
+  /* Adjust the alignment if necessary.  */
+  if (power_of_two > section->alignment_power)
+    section->alignment_power = power_of_two;
 
-                   }
-               }
+  /* Change the symbol from common to defined.  */
+  h->type = bfd_link_hash_defined;
+  h->u.def.section = section;
+  h->u.def.value = section->_raw_size;
 
-           }
-       }
-    }
+  /* Increase the size of the section.  */
+  section->_raw_size += size;
 
+  if (write_map && config.map_file != NULL)
+    fprintf (config.map_file, "Allocating common %s: %lx at %lx %s\n",
+            h->root.string, (unsigned long) size,
+            (unsigned long) h->u.def.value, section->owner->filename);
 
+  return true;
 }
 
 /*
@@ -2197,13 +2198,13 @@ lang_place_orphans ()
                  /* This is a lonely common section which must
                     have come from an archive. We attatch to the
                     section with the wildcard  */
-                 if (config.relocateable_output != true
-                     && command_line.force_common_definition == false)
+                 if (! link_info.relocateable
+                     && ! command_line.force_common_definition)
                    {
                      if (default_common_section ==
                          (lang_output_section_statement_type *) NULL)
                        {
-                         info ("%P: No [COMMON] command, defaulting to .bss\n");
+                         info_msg ("%P: no [COMMON] command, defaulting to .bss\n");
 
                          default_common_section =
                            lang_output_section_statement_lookup (".bss");
@@ -2259,7 +2260,7 @@ lang_set_flags (ptr, flags)
          /*      ptr->flag_loadable= state;*/
          break;
        default:
-         einfo ("%P%F illegal syntax in flags\n");
+         einfo ("%P%F: invalid syntax in flags\n");
          break;
        }
       flags++;
@@ -2282,6 +2283,9 @@ lang_for_each_file (func)
     }
 }
 
+#if 0
+
+/* Not used.  */
 
 void
 lang_for_each_input_section (func)
@@ -2304,34 +2308,48 @@ lang_for_each_input_section (func)
     }
 }
 
-
+#endif
 
 void
 ldlang_add_file (entry)
      lang_input_statement_type * entry;
 {
+  bfd **pp;
 
   lang_statement_append (&file_chain,
                         (lang_statement_union_type *) entry,
                         &entry->next);
+
+  /* The BFD linker needs to have a list of all input BFDs involved in
+     a link.  */
+  ASSERT (entry->the_bfd->link_next == (bfd *) NULL);
+  ASSERT (entry->the_bfd != output_bfd);
+  for (pp = &link_info.input_bfds;
+       *pp != (bfd *) NULL;
+       pp = &(*pp)->link_next)
+    ;
+  *pp = entry->the_bfd;
+  entry->the_bfd->usrdata = (PTR) entry;
 }
 
 void
-lang_add_output (name)
+lang_add_output (name, from_script)
      CONST char *name;
+     int from_script;
 {
-  lang_output_statement_type *new = new_stat (lang_output_statement,
-                                             stat_ptr);
-
-  new->name = name;
-  had_output_filename = true;
+  /* Make -o on command line override OUTPUT in script.  */
+  if (had_output_filename == false || !from_script)
+    {
+      output_filename = name;
+      had_output_filename = true;
+    }
 }
 
 
 static lang_output_section_statement_type *current_section;
 
 static int topower(x)
- int x;
    int x;
 {
   unsigned  int i = 1;
   int l;
@@ -2346,14 +2364,14 @@ static int topower(x)
 void
 lang_enter_output_section_statement (output_section_statement_name,
                                     address_exp, flags, block_value,
-                                    align, subalign, base)
-     char *output_section_statement_name;
+                                    align, subalign, ebase)
+     const char *output_section_statement_name;
      etree_type * address_exp;
      int flags;
      bfd_vma block_value;
      etree_type *align;
      etree_type *subalign;
-     etree_type *base;
+     etree_type *ebase;
 {
   lang_output_section_statement_type *os;
 
@@ -2390,19 +2408,17 @@ lang_enter_output_section_statement (output_section_statement_name,
    exp_get_value_int(align, -1,
                     "section alignment", 0));
 
-  os->load_base = base;
+  os->load_base = ebase;
 }
 
 
 void
 lang_final ()
 {
-  if (had_output_filename == false)
-    {
-      extern CONST char *output_filename;
+  lang_output_statement_type *new =
+    new_stat (lang_output_statement, stat_ptr);
 
-      lang_add_output (output_filename);
-    }
+  new->name = output_filename;
 }
 
 /* Reset the current counters in the regions */
@@ -2420,43 +2436,9 @@ reset_memory_regions ()
     }
 }
 
-
-
-asymbol *
-DEFUN (create_symbol, (name, flags, section),
-     CONST char *name AND
-     flagword flags AND
-     asection * section)
-{
-  extern lang_input_statement_type *script_file;
-  asymbol **def_ptr = (asymbol **) stat_alloc ((bfd_size_type) (sizeof (asymbol **)));
-
-  /* Add this definition to script file */
-  asymbol *def = (asymbol *) bfd_make_empty_symbol (script_file->the_bfd);
-  def->name = buystring (name);
-  def->udata = 0;
-  def->flags = flags;
-  def->section = section;
-  *def_ptr = def;
-  Q_enter_global_ref (def_ptr, name);
-  return def;
-}
-
 void
 lang_process ()
 {
-  if (had_script == false)
-    {
-      /* Read the emulation's appropriate default script.  */
-      char *scriptname = ldemul_get_script ();
-      size_t size = strlen (scriptname) + 13;
-      char *buf = (char *) ldmalloc(size);
-
-      sprintf (buf, "-Tldscripts/%s", scriptname);
-      parse_line (buf, 0);
-      free (buf);
-    }
-
   lang_reasonable_defaults ();
   current_target = default_target;
 
@@ -2465,8 +2447,7 @@ lang_process ()
      file */
   lang_create_output_section_statements ();
 
-  /* Create a dummy bfd for the script */
-  lang_init_script_file ();
+  ldemul_create_output_section_statements ();
 
   /* Add to the hash table all undefineds on the command line */
   lang_place_undefineds ();
@@ -2475,10 +2456,13 @@ lang_process ()
   current_target = default_target;
   lang_for_each_statement (open_input_bfds);
 
+  /* Build all sets based on the information gathered from the input
+     files.  */
+  ldctor_build_sets ();
+
   /* Run through the contours of the script and attatch input sections
      to the correct output sections
      */
-  find_constructors ();
   map_input_to_output_sections (statement_list.head, (char *) NULL,
                                (lang_output_section_statement_type *) NULL);
 
@@ -2513,50 +2497,38 @@ lang_process ()
   /* Now run around and relax if we can */
   if (command_line.relax)
     {
-      /* First time round is a trial run to get the 'worst case' addresses of the
-         objects if there was no relaxing */
+      /* First time round is a trial run to get the 'worst case'
+        addresses of the objects if there was no relaxing.  */
       lang_size_sections (statement_list.head,
                          (lang_output_section_statement_type *) NULL,
                          &(statement_list.head), 0, (bfd_vma) 0, false);
 
 
+      reset_memory_regions ();
 
-  /* Move the global symbols around so the second pass of relaxing can
-     see them */
-  lang_relocate_globals ();
-
-  reset_memory_regions ();
-
-  /* Do all the assignments, now that we know the final restingplaces
-     of all the symbols */
-
-  lang_do_assignments (statement_list.head,
-                      abs_output_section,
-                      0, (bfd_vma) 0);
+      /* Do all the assignments, now that we know the final resting
+        places of all the symbols.  */
 
+      lang_do_assignments (statement_list.head,
+                          abs_output_section,
+                          (fill_type) 0, (bfd_vma) 0);
 
       /* Perform another relax pass - this time we know where the
-        globals are, so can make better guess */
+        globals are, so can make better guess */
       lang_size_sections (statement_list.head,
                          (lang_output_section_statement_type *) NULL,
                          &(statement_list.head), 0, (bfd_vma) 0, true);
-
-
-
     }
-
   else
     {
-      /* Size up the sections */
+      /* Size up the sections */
       lang_size_sections (statement_list.head,
                          abs_output_section,
                          &(statement_list.head), 0, (bfd_vma) 0, false);
-
     }
 
-
   /* See if anything special should be done now we know how big
-     everything is */
+     everything is */
   ldemul_after_allocation ();
 
   /* Do all the assignments, now that we know the final restingplaces
@@ -2564,17 +2536,26 @@ lang_process ()
 
   lang_do_assignments (statement_list.head,
                       abs_output_section,
-                      0, (bfd_vma) 0);
-
-
-  /* Move the global symbols around */
-  lang_relocate_globals ();
+                      (fill_type) 0, (bfd_vma) 0);
 
   /* Make sure that we're not mixing architectures */
 
   lang_check ();
 
   /* Final stuffs */
+
+  ldemul_finish ();
+
+#if 0
+  /* DO NOT REENABLE THIS CALL.  IF THIS CALL IS MADE, THE SUN4 LINKER
+     CAN NOT BOOTSTRAP!!  No, I don't know why, but don't change it
+     unless you fix it.  */
+  /* Size up the sections.  */
+  lang_size_sections (statement_list.head,
+                     abs_output_section,
+                     &(statement_list.head), 0, (bfd_vma) 0, false);
+#endif
+
   lang_finish ();
 }
 
@@ -2693,7 +2674,7 @@ lang_startup (name)
 {
   if (startup_file != (char *) NULL)
     {
-      einfo ("%P%FMultiple STARTUP files\n");
+      einfo ("%P%Fmultiple STARTUP files\n");
     }
   first_file->filename = name;
   first_file->local_sym_name = name;
@@ -2733,25 +2714,30 @@ lang_leave_output_section_statement (fill, memspec)
  If the symbol already exists, then do nothing.
 */
 void
-lang_abs_symbol_at_beginning_of (section, name)
-     CONST char *section;
-     CONST char *name;
+lang_abs_symbol_at_beginning_of (secname, name)
+     const char *secname;
+     const char *name;
 {
-  if (ldsym_undefined (name))
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_link_hash_lookup (link_info.hash, name, true, true, true);
+  if (h == (struct bfd_link_hash_entry *) NULL)
+    einfo ("%P%F: bfd_link_hash_lookup failed: %E\n");
+
+  if (h->type == bfd_link_hash_new
+      || h->type == bfd_link_hash_undefined)
     {
-      asection *s = bfd_get_section_by_name (output_bfd, section);
-      asymbol *def = create_symbol (name,
-                                   BSF_GLOBAL | BSF_EXPORT,
-                                   &bfd_abs_section);
+      asection *sec;
 
-      if (s != (asection *) NULL)
-       {
-         def->value = s->vma;
-       }
+      h->type = bfd_link_hash_defined;
+
+      sec = bfd_get_section_by_name (output_bfd, secname);
+      if (sec == (asection *) NULL)
+       h->u.def.value = 0;
       else
-       {
-         def->value = 0;
-       }
+       h->u.def.value = bfd_get_section_vma (output_bfd, sec);
+
+      h->u.def.section = &bfd_abs_section;
     }
 }
 
@@ -2762,27 +2748,31 @@ lang_abs_symbol_at_beginning_of (section, name)
  If the symbol already exists, then do nothing.
 */
 void
-lang_abs_symbol_at_end_of (section, name)
-     CONST char *section;
-     CONST char *name;
+lang_abs_symbol_at_end_of (secname, name)
+     const char *secname;
+     const char *name;
 {
-  if (ldsym_undefined (name))
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_link_hash_lookup (link_info.hash, name, true, true, true);
+  if (h == (struct bfd_link_hash_entry *) NULL)
+    einfo ("%P%F: bfd_link_hash_lookup failed: %E\n");
+
+  if (h->type == bfd_link_hash_new
+      || h->type == bfd_link_hash_undefined)
     {
-      asection *s = bfd_get_section_by_name (output_bfd, section);
+      asection *sec;
 
-      /* Add a symbol called _end */
-      asymbol *def = create_symbol (name,
-                                   BSF_GLOBAL | BSF_EXPORT,
-                                   &bfd_abs_section);
+      h->type = bfd_link_hash_defined;
 
-      if (s != (asection *) NULL)
-       {
-         def->value = s->vma + s->_raw_size;
-       }
+      sec = bfd_get_section_by_name (output_bfd, secname);
+      if (sec == (asection *) NULL)
+       h->u.def.value = 0;
       else
-       {
-         def->value = 0;
-       }
+       h->u.def.value = (bfd_get_section_vma (output_bfd, sec)
+                         + bfd_section_size (output_bfd, sec));
+
+      h->u.def.section = &bfd_abs_section;
     }
 }
 
@@ -2802,6 +2792,6 @@ lang_add_output_format (format, from_script)
      CONST char *format;
      int from_script;
 {
-  if (!from_script || output_target == NULL)
+  if (output_target == NULL || !from_script)
     output_target = format;
 }
This page took 0.042685 seconds and 4 git commands to generate.