* ldlex.l: Removed duplicate rules.
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 173d1818bb34d6a259a27886a198ed97e9bfccb8..5b1958f528ca331b1ec09edd66d3375ebcc5fba4 100644 (file)
@@ -1,5 +1,6 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
-   
+/* Linker command language support.
+   Copyright 1991, 1992, 1993 Free Software Foundation, Inc.
+
 This file is part of GLD, the Gnu Linker.
 
 GLD is free software; you can redistribute it and/or modify
@@ -16,149 +17,147 @@ 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.4  1991/03/27 02:29:22  steve
- * *** empty log message ***
- *
- * Revision 1.3  1991/03/27  00:52:49  steve
- * *** empty log message ***
- *
- * Revision 1.2  1991/03/22  23:02:34  steve
- * Brought up to sync with Intel again.
- *
- * Revision 1.3  1991/03/16  22:19:21  rich
- * pop
- *
- * Revision 1.2  1991/03/15  18:52:42  rich
- * pop
- *
- * Revision 1.1  1991/03/13  00:48:23  chrisb
- * Initial revision
- *
- * Revision 1.8  1991/03/10  09:31:28  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.7  1991/03/09  03:31:03  sac
- * After a fatal info message, the output file is deleted.
- *
- * Revision 1.6  1991/03/09  03:25:06  sac
- * Added support for LONG, SHORT and BYTE keywords in scripts
- *
- * Revision 1.5  1991/03/06  21:59:31  sac
- * Completed G++ support
- *
- * Revision 1.4  1991/03/06  02:26:02  sac
- * Added support for constructor sections.
- * Remove parsing ambiguity.
- * Lint
- *
- * Revision 1.3  1991/02/22  17:15:01  sac
- * Added RCS keywords and copyrights
- *
-*/
-
-
-
-#include "sysdep.h" 
 #include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
 
 #include "ld.h"
 #include "ldmain.h"
-#include "ldsym.h"
-#include "ldgram.tab.h"
-#include "ldmisc.h"
-#include "ldlang.h"
+#include "ldgram.h"
 #include "ldexp.h"
-#include "ld-emul.h"
+#include "ldlang.h"
+#include "ldemul.h"
 #include "ldlex.h"
+#include "ldmisc.h"
+#include "ldctor.h"
+#include "ldfile.h"
 
-/* EXPORTS */
-
+/* FORWARDS */
+static void print_statements PARAMS ((void));
+static void print_statement PARAMS ((lang_statement_union_type *,
+                                     lang_output_section_statement_type *));
+static lang_statement_union_type *new_statement PARAMS ((enum statement_enum,
+                                                        size_t,
+                                                        lang_statement_list_type*));
 
 
-extern unsigned int undefined_global_sym_count;
+/* LOCALS */
+static struct obstack stat_obstack;
 
-static char *startup_file;
-static lang_input_statement_type *first_file;
-lang_statement_list_type statement_list;
-lang_statement_list_type *stat_ptr = &statement_list;
-lang_statement_list_type lang_output_section_statement;
-lang_statement_list_type input_file_chain;
-lang_statement_list_type file_chain;
-extern char *current_file;
-static boolean placed_commons = false;
+#define obstack_chunk_alloc ldmalloc
+#define obstack_chunk_free free
+static CONST char *startup_file;
+static lang_statement_list_type input_file_chain;
 
-boolean lang_float_flag;
+/* Points to the last statement in the .data section, so we can add
+   stuff to the data section without pain */
+static lang_statement_list_type end_of_data_section_statement_list;
 
+static boolean placed_commons = false;
 static lang_output_section_statement_type *default_common_section;
-
-
-/* FORWARDS */
-PROTO(static void, print_statements,(void));
-PROTO(static void, print_statement,(lang_statement_union_type *,
-                                    lang_output_section_statement_type *));
-
-
+static boolean map_option_f;
+static bfd_vma print_dot;
+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 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 */
+lang_output_section_statement_type *abs_output_section;
+lang_statement_list_type *stat_ptr = &statement_list;
+lang_statement_list_type file_chain =
+{0};
+CONST char *entry_symbol = 0;
+bfd_size_type largest_section = 0;
 boolean lang_has_input_file = false;
-
-
-extern bfd *output_bfd;
-size_t largest_section;
-
-
-extern enum bfd_architecture ldfile_output_architecture;
-extern unsigned long ldfile_output_machine;
-extern char *ldfile_output_machine_name;
-
-
-extern ldsym_type *symbol_head;
-
-bfd_vma print_dot;
-unsigned int commons_pending;
-
-
-
-
-extern args_type command_line;
-extern ld_config_type config;
-
-char *entry_symbol;
-
-
-
-lang_output_section_statement_type *create_object_symbols;
-
-extern boolean had_script;
-static boolean map_option_f;
-
-
 boolean had_output_filename = false;
-extern boolean write_map;
-
-
-
-
-
-
-size_t longest_section_name = 8;
-
+boolean lang_float_flag = false;
+boolean delete_output_file_on_failure = false;
 
-lang_input_statement_type *script_file;
+etree_type *base; /* Relocation base - or null */
 
-section_userdata_type common_section_userdata;
-asection common_section;
 
 #ifdef __STDC__
 #define cat(a,b) a##b
@@ -172,1005 +171,1347 @@ asection common_section;
 
 #define outside_symbol_address(q) ((q)->value +   outside_section_address(q->section))
 
-boolean option_longmap = false;
-
-static void lang_list_init(list)
-lang_statement_list_type *list;
+PTR
+stat_alloc (size)
+     size_t size;
 {
-list->head = (lang_statement_union_type *)NULL;
-list->tail = &list->head;
+  return obstack_alloc (&stat_obstack, size);
 }
 
-static void 
-print_section(name)
-char *name;
+static void
+print_size (value)
+     size_t value;
 {
-  printf("%*s", -longest_section_name, name);
+  fprintf (config.map_file, "%5x", (unsigned) value);
 }
-static void 
-print_space()
+
+static void
+print_alignment (value)
+     unsigned int value;
 {
-  printf(" ");
+  fprintf (config.map_file, "2**%1u", value);
 }
-static void 
-print_nl()
+
+static void
+print_fill (value)
+     fill_type value;
 {
-  printf("\n");
+  fprintf (config.map_file, "%04x", (unsigned) value);
 }
-static void 
-print_address(value)
-bfd_vma value;
+
+static void
+print_section (name)
+     CONST char *name;
 {
-  printf("%8lx", value);
+  fprintf (config.map_file, "%*s", -longest_section_name, name);
 }
-static void 
-print_size(value)
-size_t value;
+
+/*----------------------------------------------------------------------
+  lang_for_each_statement walks the parse tree and calls the provided
+  function for each node
+*/
+
+static void
+lang_for_each_statement_worker (func, s)
+     void (*func) PARAMS ((lang_statement_union_type *));
+     lang_statement_union_type *s;
 {
-  printf("%5x", (unsigned)value);
+  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+    {
+      func (s);
+
+      switch (s->header.type)
+       {
+       case lang_constructors_statement_enum:
+         lang_for_each_statement_worker (func, constructor_list.head);
+         break;
+       case lang_output_section_statement_enum:
+         lang_for_each_statement_worker
+           (func,
+            s->output_section_statement.children.head);
+         break;
+       case lang_wild_statement_enum:
+         lang_for_each_statement_worker
+           (func,
+            s->wild_statement.children.head);
+         break;
+       case lang_data_statement_enum:
+       case lang_object_symbols_statement_enum:
+       case lang_output_statement_enum:
+       case lang_target_statement_enum:
+       case lang_input_section_enum:
+       case lang_input_statement_enum:
+       case lang_assignment_statement_enum:
+       case lang_padding_statement_enum:
+       case lang_address_statement_enum:
+         break;
+       default:
+         FAIL ();
+         break;
+       }
+    }
 }
-static void 
-print_alignment(value)
-unsigned int value;
+
+void
+lang_for_each_statement (func)
+     void (*func) PARAMS ((lang_statement_union_type *));
 {
-  printf("2**%2u",value);
+  lang_for_each_statement_worker (func,
+                                 statement_list.head);
 }
-static void 
-print_fill(value)
-fill_type value;
+
+/*----------------------------------------------------------------------*/
+void
+lang_list_init (list)
+     lang_statement_list_type *list;
 {
-  printf("%04x",(unsigned)value);
+  list->head = (lang_statement_union_type *) NULL;
+  list->tail = &list->head;
 }
 
+/*----------------------------------------------------------------------
+
+  build a new statement node for the parse tree
+
+ */
 
 static
-lang_statement_union_type *new_statement(type, size, list)
-enum statement_enum type;
-size_t size;
-lang_statement_list_type *list;
+lang_statement_union_type *
+new_statement (type, size, list)
+     enum statement_enum type;
+     size_t size;
+     lang_statement_list_type * list;
 {
   lang_statement_union_type *new = (lang_statement_union_type *)
-    ldmalloc(size);
+  stat_alloc (size);
+
   new->header.type = type;
-  new->header.next = (lang_statement_union_type *)NULL;
lang_statement_append(list, new, &new->header.next);
+  new->header.next = (lang_statement_union_type *) NULL;
 lang_statement_append (list, new, &new->header.next);
   return new;
 }
 
+/*
+  Build a new input file node for the language. There are several ways
+  in which we treat an input file, eg, we only look at symbols, or
+  prefix it with a -l etc.
+
+  We can be supplied with requests for input files more than once;
+  they may, for example be split over serveral lines like foo.o(.text)
+  foo.o(.data) etc, so when asked for a file we check that we havn't
+  got it already so we don't duplicate the bfd.
+
+ */
 static lang_input_statement_type *
-new_afile(name, file_type, target)
-char *name;
-lang_input_file_enum_type file_type;
-char *target;
+new_afile (name, file_type, target)
+     CONST char *name;
+     lang_input_file_enum_type file_type;
+     CONST char *target;
 {
-  lang_input_statement_type *p = new_stat(lang_input_statement, 
-                                         stat_ptr);
+
+  lang_input_statement_type *p = new_stat (lang_input_statement,
+                                          stat_ptr);
+
   lang_has_input_file = true;
   p->target = target;
-  switch (file_type) {
-  case  lang_input_file_is_symbols_only_enum:
-    p->filename = name;
-    p->is_archive =false;
-    p->real = true;
-    p->local_sym_name= name;
-    p->just_syms_flag = true;
-    p->search_dirs_flag = false;
-    break;
-  case lang_input_file_is_fake_enum:
-    p->filename = name;
-    p->is_archive =false;
-    p->real = false;
-    p->local_sym_name= name;
-    p->just_syms_flag = false;
-    p->search_dirs_flag =false;
-
-    break;
-  case lang_input_file_is_l_enum:
-    p->is_archive = true;
-    p->filename = name;
-    p->real = true;
-    p->local_sym_name = concat("-l",name,"");
-    p->just_syms_flag = false;
-    p->search_dirs_flag = true;
-    break;
-
-  case lang_input_file_is_search_file_enum:
-  case lang_input_file_is_marker_enum:
-    p->filename = name;
-    p->is_archive =false;
-    p->real = true;
-    p->local_sym_name= name;
-    p->just_syms_flag = false;
-    p->search_dirs_flag =true;
-    break;
-
-
-
-  case lang_input_file_is_file_enum:
-    p->filename = name;
-    p->is_archive =false;
-    p->real = true;
-    p->local_sym_name= name;
-    p->just_syms_flag = false;
-    p->search_dirs_flag =false;
-    break;
-
-
-  default:
-    FAIL();
-  }
-  p->asymbols = (asymbol **)NULL;
-  p->superfile = (lang_input_statement_type *)NULL;
-
-  p->next_real_file = (lang_statement_union_type*)NULL;
-  p->next = (lang_statement_union_type*)NULL;
+  p->complained = false;
+  switch (file_type)
+    {
+    case lang_input_file_is_symbols_only_enum:
+      p->filename = name;
+      p->is_archive = false;
+      p->real = true;
+      p->local_sym_name = name;
+      p->just_syms_flag = true;
+      p->search_dirs_flag = false;
+      break;
+    case lang_input_file_is_fake_enum:
+      p->filename = name;
+      p->is_archive = false;
+      p->real = false;
+      p->local_sym_name = name;
+      p->just_syms_flag = false;
+      p->search_dirs_flag = false;
+      break;
+    case lang_input_file_is_l_enum:
+      p->is_archive = true;
+      p->filename = name;
+      p->real = true;
+      p->local_sym_name = concat ("-l", name, "");
+      p->just_syms_flag = false;
+      p->search_dirs_flag = true;
+      break;
+    case lang_input_file_is_search_file_enum:
+    case lang_input_file_is_marker_enum:
+      p->filename = name;
+      p->is_archive = false;
+      p->real = true;
+      p->local_sym_name = name;
+      p->just_syms_flag = false;
+      p->search_dirs_flag = true;
+      break;
+    case lang_input_file_is_file_enum:
+      p->filename = name;
+      p->is_archive = false;
+      p->real = true;
+      p->local_sym_name = name;
+      p->just_syms_flag = false;
+      p->search_dirs_flag = false;
+      break;
+    default:
+      FAIL ();
+    }
+  p->asymbols = (asymbol **) NULL;
+  p->superfile = (lang_input_statement_type *) NULL;
+  p->next_real_file = (lang_statement_union_type *) NULL;
+  p->next = (lang_statement_union_type *) NULL;
   p->symbol_count = 0;
-  p->common_output_section = (asection *)NULL;
-
-  lang_statement_append(&input_file_chain,
-                       (lang_statement_union_type *)p,
-                       &p->next_real_file);
+  p->common_output_section = (asection *) NULL;
+  p->loaded = false;
+  lang_statement_append (&input_file_chain,
+                        (lang_statement_union_type *) p,
+                        &p->next_real_file);
   return p;
 }
 
 lang_input_statement_type *
-lang_add_input_file(name,
-                   file_type, 
-                   target)
-char *name;
-lang_input_file_enum_type file_type;
-char *target;
+lang_add_input_file (name, file_type, target)
+     CONST char *name;
+     lang_input_file_enum_type file_type;
+     CONST char *target;
 {
   /* Look it up or build a new one */
+  lang_has_input_file = true;
 
+#if 0
   lang_input_statement_type *p;
 
-  for (p = (lang_input_statement_type *)input_file_chain.head;
-       p != (lang_input_statement_type *)NULL;
-       p = (lang_input_statement_type *)(p->next_real_file))
+  for (p = (lang_input_statement_type *) input_file_chain.head;
+       p != (lang_input_statement_type *) NULL;
+       p = (lang_input_statement_type *) (p->next_real_file))
     {
       /* Sometimes we have incomplete entries in here */
-      if (p->filename != (char *)NULL) {
-       if(strcmp(name,p->filename) == 0)  return p;
-      }
-    }
+      if (p->filename != (char *) NULL)
+       {
+         if (strcmp (name, p->filename) == 0)
+           return p;
+       }
 
-  return  new_afile(name, file_type, target);
+    }
+#endif
+  return new_afile (name, file_type, target);
 }
 
-
-
+/* Build enough state so that the parser can build its tree */
 void
-lang_init()
+lang_init ()
 {
+  obstack_begin (&stat_obstack, 1000);
 
-  stat_ptr= &statement_list;
-  lang_list_init(stat_ptr);
-
-  lang_list_init(&input_file_chain);
-  lang_list_init(&lang_output_section_statement);
-  lang_list_init(&file_chain);
-  first_file = lang_add_input_file((char *)NULL, 
-                                  lang_input_file_is_marker_enum,
-                                  (char *)NULL);
+  stat_ptr = &statement_list;
 
-}
+  lang_list_init (stat_ptr);
 
-static void 
-lang_init2()
-{
-  script_file = lang_add_input_file("script file",
-                                   lang_input_file_is_fake_enum,
-                                   (char *)NULL);
-  script_file->the_bfd = bfd_create("script file", output_bfd);
-  script_file->symbol_count = 0;
+  lang_list_init (&input_file_chain);
+  lang_list_init (&lang_output_section_statement);
+  lang_list_init (&file_chain);
+  first_file = lang_add_input_file ((char *) NULL,
+                                   lang_input_file_is_marker_enum,
+                                   (char *) NULL);
+  abs_output_section = lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
 
-  common_section.userdata = &common_section_userdata;
+  abs_output_section->bfd_section = &bfd_abs_section;
 
 }
 
+/*----------------------------------------------------------------------
+ A region is an area of memory declared with the
+ MEMORY {  name:org=exp, len=exp ... }
+ syntax.
 
+ We maintain a list of all the regions here
 
-/*  this function mainains a dictionary of regions. If the *default*
-    region is asked for then a pointer to the first region is
-    returned. If there is no first pointer then one is created 
+ If no regions are specified in the script, then the default is used
+ which is created when looked up to be the entire data space
 */
 
 static lang_memory_region_type *lang_memory_region_list;
 static lang_memory_region_type **lang_memory_region_list_tail = &lang_memory_region_list;
 
 lang_memory_region_type *
-lang_memory_region_lookup(name)
-char *name;
+lang_memory_region_lookup (name)
+     CONST char *CONST name;
 {
 
-    lang_memory_region_type *p  = lang_memory_region_list;
-    for (p = lang_memory_region_list;
-        p != ( lang_memory_region_type *)NULL;
-        p = p->next) {
-       if (strcmp(p->name, name) == 0) {
-           return p;
+  lang_memory_region_type *p = lang_memory_region_list;
+
+  for (p = lang_memory_region_list;
+       p != (lang_memory_region_type *) NULL;
+       p = p->next)
+    {
+      if (strcmp (p->name, name) == 0)
+       {
+         return p;
        }
     }
-    if (strcmp(name,"*default*")==0) {
-       /* This is the default region, dig out first one on the list */
-       if (lang_memory_region_list != (lang_memory_region_type*)NULL){
-           return lang_memory_region_list;
+  if (strcmp (name, "*default*") == 0)
+    {
+      /* This is the default region, dig out first one on the list */
+      if (lang_memory_region_list != (lang_memory_region_type *) NULL)
+       {
+         return lang_memory_region_list;
        }
     }
-    {
-       lang_memory_region_type *new =
-           (lang_memory_region_type *)ldmalloc(sizeof(lang_memory_region_type));
-       new->name = name;
-       new->next = (lang_memory_region_type *)NULL;
+  {
+    lang_memory_region_type *new =
+    (lang_memory_region_type *) stat_alloc ((bfd_size_type) (sizeof (lang_memory_region_type)));
 
-       *lang_memory_region_list_tail = new;
-       lang_memory_region_list_tail = &new->next;
-       new->origin = 0;
-       new->length = ~0;
-       new->current = 0;
-       return new;
-    }
-}
+    new->name = buystring (name);
+    new->next = (lang_memory_region_type *) NULL;
 
+    *lang_memory_region_list_tail = new;
+    lang_memory_region_list_tail = &new->next;
+    new->origin = 0;
+    new->length = ~(bfd_size_type)0;
+    new->current = 0;
+    new->had_full_message = false;
+
+    return new;
+  }
+}
 
 
 lang_output_section_statement_type *
-lang_output_section_find(name)
-char *name;
+lang_output_section_find (name)
+     CONST char *CONST name;
 {
   lang_statement_union_type *u;
   lang_output_section_statement_type *lookup;
 
   for (u = lang_output_section_statement.head;
-       u != (lang_statement_union_type *)NULL;
+       u != (lang_statement_union_type *) NULL;
        u = lookup->next)
     {
       lookup = &u->output_section_statement;
-      if (strcmp(name, lookup->name)==0) {
-       return lookup;
-      }
+      if (strcmp (name, lookup->name) == 0)
+       {
+         return lookup;
+       }
     }
-  return (lang_output_section_statement_type *)NULL;
+  return (lang_output_section_statement_type *) NULL;
 }
 
 lang_output_section_statement_type *
-lang_output_section_statement_lookup(name)
-char *name;
-
+lang_output_section_statement_lookup (name)
+     CONST char *CONST name;
 {
   lang_output_section_statement_type *lookup;
-  lookup =lang_output_section_find(name);
-  if (lookup == (lang_output_section_statement_type *)NULL) {
-    
-    lookup =(lang_output_section_statement_type *)
-      new_stat(lang_output_section_statement, stat_ptr);
-    lookup->region = (lang_memory_region_type *)NULL;
-    lookup->fill = 0;
-    lookup->block_value = 1;
-    lookup->name = name;
-
-    lookup->next = (lang_statement_union_type*)NULL;  
-    lookup->bfd_section = (asection *)NULL;
-    lookup->processed = false;
-    lookup->addr_tree = (etree_type *)NULL;
-    lang_list_init(&lookup->children);
-
-    lang_statement_append(&lang_output_section_statement,
-                         (lang_statement_union_type *)lookup,
-                         &lookup->next);
-  }
-  return lookup;
-}
-
-
 
+  lookup = lang_output_section_find (name);
+  if (lookup == (lang_output_section_statement_type *) NULL)
+    {
 
+      lookup = (lang_output_section_statement_type *)
+       new_stat (lang_output_section_statement, stat_ptr);
+      lookup->region = (lang_memory_region_type *) NULL;
+      lookup->fill = 0;
+      lookup->block_value = 1;
+      lookup->name = name;
+
+      lookup->next = (lang_statement_union_type *) NULL;
+      lookup->bfd_section = (asection *) NULL;
+      lookup->processed = false;
+      lookup->loadable = 1;
+      lookup->addr_tree = (etree_type *) NULL;
+      lang_list_init (&lookup->children);
+
+      lookup->memspec = (CONST char *) NULL;
+      lookup->flags = 0;
+      lookup->subsection_alignment = -1;
+      lookup->section_alignment = -1;
+      lookup->load_base = (union etree_union *) NULL;
+
+      lang_statement_append (&lang_output_section_statement,
+                            (lang_statement_union_type *) lookup,
+                            &lookup->next);
+    }
+  return lookup;
+}
 
+/*ARGSUSED*/
 static void
-  print_flags(outfile, ignore_flags)
-FILE *outfile;
-lang_section_flags_type *ignore_flags;
+print_flags (ignore_flags)
+     int *ignore_flags;
 {
-  fprintf(outfile,"(");
+  fprintf (config.map_file, "(");
 #if 0
-  if (flags->flag_read) fprintf(outfile,"R");
-  if (flags->flag_write) fprintf(outfile,"W");
-  if (flags->flag_executable) fprintf(outfile,"X");
-  if (flags->flag_loadable) fprintf(outfile,"L");
+  if (flags->flag_read)
+    fprintf (outfile, "R");
+  if (flags->flag_write)
+    fprintf (outfile, "W");
+  if (flags->flag_executable)
+    fprintf (outfile, "X");
+  if (flags->flag_loadable)
+    fprintf (outfile, "L");
 #endif
 fprintf(outfile,")");
fprintf (config.map_file, ")");
 }
 
 void
-lang_map(outfile)
-     FILE *outfile;
+lang_map ()
 {
   lang_memory_region_type *m;
-  fprintf(outfile,"**MEMORY CONFIGURATION**\n\n");
 
-  fprintf(outfile,"name\t\torigin\t\tlength\t\tattributes\n");
+  fprintf (config.map_file, "**MEMORY CONFIGURATION**\n\n");
+#ifdef HOST_64_BIT
+  fprintf (config.map_file, "name\t\torigin\t\tlength\t\tattributes\n");
+#else
+  fprintf (config.map_file,
+          "name\t\torigin   length   r_size   c_size    is    attributes\n");
+
+#endif
   for (m = lang_memory_region_list;
-       m != (lang_memory_region_type *)NULL;
-       m = m->next) 
+       m != (lang_memory_region_type *) NULL;
+       m = m->next)
     {
-      fprintf(outfile,"%-16s", m->name);
-
-      fprintf(outfile,"%08lx\t%08lx\t", m->origin, m->length);
-      print_flags(outfile, &m->flags);
-      fprintf(outfile,"\n");
+      fprintf (config.map_file, "%-16s", m->name);
+      print_address (m->origin);
+      print_space ();
+      print_address ((bfd_vma)m->length);
+      print_space ();
+      print_address ((bfd_vma)m->old_length);
+      print_space();
+      print_address (m->current - m->origin);
+      print_space();
+      if (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");
     }
-  fprintf(outfile,"\n\n**LINK EDITOR MEMORY MAP**\n\n");
-  fprintf(outfile,"output\t\tinput\t\tvirtual\n");
-  fprintf(outfile,"section\t\tsection\t\taddress\tsize\n\n");
+  fprintf (config.map_file, "\n\n**LINK EDITOR MEMORY MAP**\n\n");
+  fprintf (config.map_file, "output   input     virtual\n");
+  fprintf (config.map_file, "section  section   address    tsize\n\n");
 
-  print_statements();
+  print_statements ();
 
 }
 
 /*
  *
  */
-static void init_os(s) 
-lang_output_section_statement_type *s;
+static void
+init_os (s)
+     lang_output_section_statement_type * s;
 {
+/*  asection *section = bfd_get_section_by_name(output_bfd, s->name);*/
   section_userdata_type *new =
-    (section_userdata_type *)
-      ldmalloc(sizeof(section_userdata_type));
+  (section_userdata_type *)
+  stat_alloc ((bfd_size_type) (sizeof (section_userdata_type)));
 
-  s->bfd_section = bfd_make_section(output_bfd, s->name);
+  s->bfd_section = bfd_get_section_by_name (output_bfd, s->name);
+  if (s->bfd_section == (asection *) NULL)
+    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",
+            output_bfd->xvec->name, s->name);
+    }
   s->bfd_section->output_section = s->bfd_section;
-  s->bfd_section->flags = SEC_NO_FLAGS;
+/*  s->bfd_section->flags = s->flags;*/
+
   /* We initialize an output sections output offset to minus its own */
   /* vma to allow us to output a section through itself */
   s->bfd_section->output_offset = 0;
-  get_userdata( s->bfd_section) = new;
+  get_userdata (s->bfd_section) = (PTR) new;
+
 }
 
+/***********************************************************************
+  The wild routines.
+
+  These expand statements like *(.text) and foo.o to a list of
+  explicit actions, like foo.o(.text), bar.o(.text) and
+  foo.o(.text,.data) .
+
+  The toplevel routine, wild, takes a statement, section, file and
+  target. If either the section or file is null it is taken to be the
+  wildcard. Seperate lang_input_section statements are created for
+  each part of the expanstion, and placed after the statement provided.
+
+*/
+
 static void
-wild_doit(ptr, section,output, file)
-lang_statement_list_type *ptr;
-asection *section;
-lang_output_section_statement_type *output;
-lang_input_statement_type *file;
-{
-  if(output->bfd_section == (asection *)NULL)
+wild_doit (ptr, section, output, file)
+     lang_statement_list_type * ptr;
+     asection * section;
+     lang_output_section_statement_type * output;
+     lang_input_statement_type * file;
+{
+  if (output->bfd_section == (asection *) NULL)
+  {
+    init_os (output);
+    /* Initialize the vma and size to the existing section.  This will
+       be overriden in lang_size_sections unless SEC_NEVER_LOAD gets
+       set.  */
+    if (section != (asection *) NULL)
     {
-      init_os(output);
+      bfd_set_section_vma (0, output->bfd_section,
+                          bfd_section_vma (0, section));
+      output->bfd_section->_raw_size = section->_raw_size;
     }
+  }
 
-  if (section != (asection *)NULL 
-      && section->output_section == (asection *)NULL) {
+  if (section != (asection *) NULL
+      && section->output_section == (asection *) NULL)
+  {
     /* Add a section reference to the list */
-    lang_input_section_type *new = new_stat(lang_input_section, ptr);
+    lang_input_section_type *new = new_stat (lang_input_section, ptr);
 
     new->section = section;
     new->ifile = file;
     section->output_section = output->bfd_section;
-    section->output_section->flags |= section->flags;
-    if (section->alignment_power > output->bfd_section->alignment_power) {
-       output->bfd_section->alignment_power = section->alignment_power;
-      }
-      
+
+    /* Be selective about what the output section inherits from the
+       input section */
+
+    if ((section->flags & SEC_SHARED_LIBRARY) != 0)
+      section->output_section->flags |= section->flags;
+    else
+      section->output_section->flags |=
+       section->flags & (flagword) (~ SEC_NEVER_LOAD);
+
+    if (!output->loadable) 
+    {
+      /* Turn off load flag */
+      output->bfd_section->flags &= ~SEC_LOAD;
+      output->bfd_section->flags |= SEC_NEVER_LOAD;
+    }
+    if (section->alignment_power > output->bfd_section->alignment_power)
+    {
+      output->bfd_section->alignment_power = section->alignment_power;
+    }
+    /* If supplied an aligmnet, then force it */
+    if (output->section_alignment != -1)
+    {
+      output->bfd_section->alignment_power = output->section_alignment;
+    }
   }
 }
 
 static asection *
-our_bfd_get_section_by_name(abfd, section)
-bfd *abfd;
-char *section;
+our_bfd_get_section_by_name (abfd, section)
+     bfd * abfd;
+     CONST char *section;
 {
-  return bfd_get_section_by_name(abfd, section);
-
+  return bfd_get_section_by_name (abfd, section);
 }
-static void 
-wild_section(ptr, section, file , output)
-lang_wild_statement_type *ptr;
-char *section;
-lang_input_statement_type *file;
-lang_output_section_statement_type *output;
+
+static void
+wild_section (ptr, section, file, output)
+     lang_wild_statement_type * ptr;
+     CONST char *section;
+     lang_input_statement_type * file;
+     lang_output_section_statement_type * output;
 {
   asection *s;
-  if (section == (char *)NULL) {
-    /* Do the creation to all sections in the file */
-    for (s = file->the_bfd->sections; s != (asection *)NULL; s=s->next)  {
-      wild_doit(&ptr->children, s, output, file);
-    }
-  }
-  else {
-    /* Do the creation to the named section only */
-    wild_doit(&ptr->children,
-             our_bfd_get_section_by_name(file->the_bfd, section),
-             output, file);
-  }
-
-
 
+  if (file->just_syms_flag == false)
+    {
+      if (section == (char *) NULL)
+       {
+         /* Do the creation to all sections in the file */
+         for (s = file->the_bfd->sections; s != (asection *) NULL; s = s->next)
+         {
+           /* except for bss */
+           if ((s->flags & SEC_IS_COMMON)  == 0)
+           {
+             wild_doit (&ptr->children, s, output, file);
+           }
+         }
+       }
+      else
+       {
+         /* Do the creation to the named section only */
+         wild_doit (&ptr->children,
+                    our_bfd_get_section_by_name (file->the_bfd, section),
+                    output, file);
+       }
+    }
 }
 
+/* passed a file name (which must have been seen already and added to
+   the statement tree. We will see if it has been opened already and
+   had its symbols read. If not then we'll read it.
 
-
+   Archives are pecuilar here. We may open them once, but if they do
+   not define anything we need at the time, they won't have all their
+   symbols read. If we need them later, we'll have to redo it.
+   */
 static
-lang_input_statement_type *lookup_name(name, target)
-char *name;
-char *target;
+lang_input_statement_type *
+lookup_name (name)
+     CONST char *name;
 {
   lang_input_statement_type *search;
-  for(search = (lang_input_statement_type *)input_file_chain.head;
-      search != (lang_input_statement_type *)NULL;
-      search = (lang_input_statement_type *)search->next_real_file)
+
+  for (search = (lang_input_statement_type *) input_file_chain.head;
+       search != (lang_input_statement_type *) NULL;
+       search = (lang_input_statement_type *) search->next_real_file)
     {
-      if (search->filename == (char *)NULL && name == (char *)NULL) {
+      if (search->filename == (char *) NULL && name == (char *) NULL)
        return search;
-      }
-      if (search->filename != (char *)NULL && name != (char *)NULL) {
-       if (strcmp(search->filename, name) == 0)  {
-         Q_read_file_symbols(search);
-         return search;
-       }
-      }
+      if (search->filename != (char *) NULL
+         && name != (char *) NULL
+         && strcmp (search->filename, name) == 0)
+       break;
+    }
+
+  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;
 
-  /* 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, target);
-  Q_read_file_symbols(search);
   return search;
 }
 
 static void
-
-wild(s, section, file, target, output)
-lang_wild_statement_type *s;
-char *section;
-char *file;
-char *target;
-lang_output_section_statement_type *output;
+wild (s, section, file, target, output)
+     lang_wild_statement_type * s;
+     CONST char *section;
+     CONST char *file;
+     CONST char *target;
+     lang_output_section_statement_type * output;
 {
   lang_input_statement_type *f;
-  if (file == (char *)NULL) {
-    /* Perform the iteration over all files in the list */
-    for (f = (lang_input_statement_type *)file_chain.head;
-        f != (lang_input_statement_type *)NULL;
-        f = (lang_input_statement_type *)f->next) {
-      wild_section(s,  section, f, output);
+
+  if (file == (char *) NULL)
+    {
+      /* Perform the iteration over all files in the list */
+      for (f = (lang_input_statement_type *) file_chain.head;
+          f != (lang_input_statement_type *) NULL;
+          f = (lang_input_statement_type *) f->next)
+       {
+         wild_section (s, section, f, output);
+       }
+    }
+  else
+    {
+      /* Perform the iteration over a single file */
+      wild_section (s, section, lookup_name (file), output);
+    }
+  if (section != (char *) NULL
+      && strcmp (section, "COMMON") == 0
+   && default_common_section == (lang_output_section_statement_type *) NULL)
+    {
+      /* Remember the section that common is going to incase we later
+         get something which doesn't know where to put it */
+      default_common_section = output;
     }
-  }
-  else {
-    /* Perform the iteration over a single file */
-    wild_section( s, section, lookup_name(file, target), output);
-  }
 }
 
 /*
-  read in all the files 
+  read in all the files
   */
-static bfd *   
-open_output(name, target)
-char *name;
-char *target;
-{
-  extern char *output_filename;
-  bfd * output = bfd_openw(name, target);
-  output_filename = name;          
-  if (output == (bfd *)NULL) 
-    {
-      if (bfd_error == invalid_target) {
-       info("%P%F target %s not found\n", target);
-      }
-      info("%P%F problem opening output file %s, %E", name);
-    }
-  
-  output->flags |= D_PAGED;
-  bfd_set_format(output, bfd_object);
-  return output;
-}
-extern char  *default_target;
-static void
-lang_phase_0(sh,target)
-lang_statement_union_type *sh;
-char *target;
+
+static bfd *
+open_output (name)
+     CONST char *name;
 {
-  lang_statement_union_type *s = (lang_statement_union_type *)sh;
-  for (; s != (lang_statement_union_type *)NULL ; s = s->next) 
+  bfd *output;
+
+  if (output_target == (char *) NULL)
     {
-      switch (s->header.type) {
-      case lang_output_section_statement_enum:
-       lang_phase_0(s->output_section_statement.children.head,
-                    target);
-       break;
-      case lang_output_statement_enum:
-#if 1
-       output_bfd = open_output(s->output_statement.name,
-                                target == (char *)NULL ?
-                                default_target : target);
-       ldemul_set_output_arch();
-#endif
-       break;
-      case lang_target_statement_enum:
-       target = s->target_statement.target;
-       break;
-      case lang_wild_statement_enum:
-       /* Maybe we should load the file's symbols */
-       if (s->wild_statement.filename) {
-         (void)  lookup_name(s->wild_statement.filename, target);
-       }
-       break;
-       /* Attatch this to the current output section */
-      case lang_common_statement_enum:
-      case lang_fill_statement_enum:
-      case lang_input_section_enum:
-      case lang_object_symbols_statement_enum:
-      case lang_address_statement_enum:
-      case lang_data_statement_enum:
-       break;
-      case lang_afile_asection_pair_statement_enum:
+      if (current_target != (char *) NULL)
+       output_target = current_target;
+      else
+       output_target = default_target;
+    }
+  output = bfd_openw (name, output_target);
 
-       FAIL();
-       break;
-          
-      case lang_input_statement_enum:
-       if (s->input_statement.real == true) {
-         s->input_statement.target = target;
-         lookup_name(s->input_statement.filename, target);
+  if (output == (bfd *) NULL)
+    {
+      if (bfd_error == invalid_target)
+       {
+         einfo ("%P%F: target %s not found\n", output_target);
        }
-       break;
-      case lang_assignment_statement_enum:
-#if 0
-       (void)    exp_fold_tree(s->assignment_statement.exp,
-                               output_section,
-                               false);
-#endif
-       break;
-
-      case lang_padding_statement_enum:
-       
-       break;
-      }
+      einfo ("%P%F: cannot open output file %s: %E\n", name);
     }
 
-}
+  delete_output_file_on_failure = 1;
 
-/* If there are [COMMONS] statements, put a wild one into the bss section */
+  /*  output->flags |= D_PAGED;*/
 
-static void
-lang_reasonable_defaults()
-{
+  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);
 
-      lang_output_section_statement_lookup(".text");
-      lang_output_section_statement_lookup(".data");
+  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;
+}
 
-  default_common_section = 
-    lang_output_section_statement_lookup(".bss");
 
-  if (placed_commons == false) {
-    lang_wild_statement_type *new =
-      new_stat(lang_wild_statement,
-              &default_common_section->children);
-    new->section_name = "COMMON";
-    new->filename = (char *)NULL;
-    lang_list_init(&new->children);
-  }
 
-}
 
-static void lang()
+static void
+ldlang_open_output (statement)
+     lang_statement_union_type * statement;
 {
-  if (had_script == false) {
-    parse_line(ldemul_get_script());
-  }
+  switch (statement->header.type)
+    {
+    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 && !link_info.relocateable)
+       output_bfd->flags |= D_PAGED;
+      else
+       output_bfd->flags &= ~D_PAGED;
+      if (config.text_read_only)
+       output_bfd->flags |= WP_TEXT;
+      else
+       output_bfd->flags &= ~WP_TEXT;
+      break;
 
-  lang_reasonable_defaults();
-  lang_phase_0(statement_list.head,default_target);
+    case lang_target_statement_enum:
+      current_target = statement->target_statement.target;
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+open_input_bfds (statement)
+     lang_statement_union_type * statement;
+{
+  switch (statement->header.type)
+    {
+      case lang_target_statement_enum:
+      current_target = statement->target_statement.target;
+      break;
+    case lang_wild_statement_enum:
+      /* Maybe we should load the file's symbols */
+      if (statement->wild_statement.filename)
+       {
+         (void) lookup_name (statement->wild_statement.filename);
+       }
+      break;
+    case lang_input_statement_enum:
+      if (statement->input_statement.real == true)
+       {
+         statement->input_statement.target = current_target;
+         lookup_name (statement->input_statement.filename);
+       }
+      break;
+    default:
+      break;
+    }
 }
 
+/* If there are [COMMONS] statements, put a wild one into the bss section */
 
-/* Open input files and attatch to output sections */
 static void
-lang_open_input(s, target, output_section_statement)
-lang_statement_union_type *s;
-char *target;
-lang_output_section_statement_type *output_section_statement;
+lang_reasonable_defaults ()
 {
-  for (; s != (lang_statement_union_type *)NULL ; s = s->next) 
+#if 0
+  lang_output_section_statement_lookup (".text");
+  lang_output_section_statement_lookup (".data");
+
+  default_common_section =
+    lang_output_section_statement_lookup (".bss");
+
+
+  if (placed_commons == false)
     {
-      switch (s->header.type) {
-      case lang_wild_statement_enum:
-       wild(&s->wild_statement, s->wild_statement.section_name,
-            s->wild_statement.filename, target,
-            output_section_statement);
+      lang_wild_statement_type *new =
+      new_stat (lang_wild_statement,
+               &default_common_section->children);
 
-       break;
+      new->section_name = "COMMON";
+      new->filename = (char *) NULL;
+      lang_list_init (&new->children);
+    }
+#endif
 
-      case lang_output_section_statement_enum:
-       lang_open_input(s->output_section_statement.children.head,
-                       target,
-                       &s->output_section_statement);
-       break;
-      case lang_output_statement_enum:
-       break;
-      case lang_target_statement_enum:
-       target = s->target_statement.target;
-       break;
-      case lang_common_statement_enum:
-      case lang_fill_statement_enum:
-      case lang_input_section_enum:
-      case lang_object_symbols_statement_enum:
-      case lang_data_statement_enum:
-       break;
-      case lang_afile_asection_pair_statement_enum:
-       FAIL();
-       break;
+}
 
-      case lang_assignment_statement_enum:
-      case lang_padding_statement_enum:
+/*
+ Add the supplied name to the symbol table as an undefined reference.
+ Remove items from the chain as we open input bfds
+ */
+typedef struct ldlang_undef_chain_list
+{
+  struct ldlang_undef_chain_list *next;
+  char *name;
+}                       ldlang_undef_chain_list_type;
 
-       break;
-      case lang_address_statement_enum:
-       /* Mark the specified section with the supplied address */
+static ldlang_undef_chain_list_type *ldlang_undef_chain_list_head;
+
+void
+ldlang_add_undef (name)
+     CONST char *CONST name;
+{
+  ldlang_undef_chain_list_type *new =
+  (ldlang_undef_chain_list_type
+   *) stat_alloc ((bfd_size_type) (sizeof (ldlang_undef_chain_list_type)));
+
+  new->next = ldlang_undef_chain_list_head;
+  ldlang_undef_chain_list_head = new;
+
+  new->name = buystring (name);
+}
+
+/* Run through the list of undefineds created above and place them
+   into the linker hash table as undefined symbols belonging to the
+   script file.
+*/
+static void
+lang_place_undefineds ()
+{
+  ldlang_undef_chain_list_type *ptr;
+
+  for (ptr = ldlang_undef_chain_list_head;
+       ptr != (ldlang_undef_chain_list_type *) NULL;
+       ptr = ptr->next)
+    {
+      struct bfd_link_hash_entry *h;
+
+      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)
        {
-         lang_output_section_statement_type *os =
-           lang_output_section_statement_lookup
-             (s->address_statement.section_name);
-         os->addr_tree = s->address_statement.address;
+         h->type = bfd_link_hash_undefined;
+         h->u.undef.abfd = NULL;
+         bfd_link_add_undef (link_info.hash, h);
        }
-       break;
-      case lang_input_statement_enum:
-       /* A standard input statement, has no wildcards */
-       /*      Q_read_file_symbols(&s->input_statement);*/
-       break;
-      }
     }
 }
 
+/* Copy important data from out internal form to the bfd way. Also
+   create a section for the dummy file
+ */
 
+static void
+lang_create_output_section_statements ()
+{
+  lang_statement_union_type *os;
 
+  for (os = lang_output_section_statement.head;
+       os != (lang_statement_union_type *) NULL;
+       os = os->output_section_statement.next)
+    {
+      lang_output_section_statement_type *s =
+      &os->output_section_statement;
 
+      init_os (s);
+    }
+
+}
+
+/* Open input files and attatch to output sections */
+static void
+map_input_to_output_sections (s, target, output_section_statement)
+     lang_statement_union_type * s;
+     CONST char *target;
+     lang_output_section_statement_type * output_section_statement;
+{
+  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+    {
+      switch (s->header.type)
+       {
+
+
+       case lang_wild_statement_enum:
+         wild (&s->wild_statement, s->wild_statement.section_name,
+               s->wild_statement.filename, target,
+               output_section_statement);
+
+         break;
+       case lang_constructors_statement_enum:
+         map_input_to_output_sections (constructor_list.head,
+                                       target,
+                                       output_section_statement);
+         break;
+       case lang_output_section_statement_enum:
+         map_input_to_output_sections (s->output_section_statement.children.head,
+                                       target,
+                                       &s->output_section_statement);
+         break;
+       case lang_output_statement_enum:
+         break;
+       case lang_target_statement_enum:
+         target = s->target_statement.target;
+         break;
+       case lang_fill_statement_enum:
+       case lang_input_section_enum:
+       case lang_object_symbols_statement_enum:
+       case lang_data_statement_enum:
+       case lang_assignment_statement_enum:
+       case lang_padding_statement_enum:
+         break;
+       case lang_afile_asection_pair_statement_enum:
+         FAIL ();
+         break;
+       case lang_address_statement_enum:
+         /* Mark the specified section with the supplied address */
+         {
+           lang_output_section_statement_type *os =
+           lang_output_section_statement_lookup
+           (s->address_statement.section_name);
+
+           os->addr_tree = s->address_statement.address;
+           if (os->bfd_section == (asection *) NULL)
+             {
+               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 */
+         break;
+       }
+    }
+}
 
-static void 
-print_output_section_statement(output_section_statement)
-lang_output_section_statement_type *output_section_statement;
+static void
+print_output_section_statement (output_section_statement)
+     lang_output_section_statement_type * output_section_statement;
 {
   asection *section = output_section_statement->bfd_section;
-  print_nl();
-  print_section(output_section_statement->name);
 
-  if (section) {
+  print_nl ();
+  print_section (output_section_statement->name);
+
+
+  if (section)
+  {
     print_dot = section->vma;
+    print_space ();
+    print_section ("");
+    print_space ();
+    print_address (section->vma);
+    print_space ();
+    print_size (section->_raw_size);
     print_space();
-    print_section("");
-    print_space();
-    print_address(section->vma);
-    print_space();
-    print_size(section->size);
-    print_space();
-    print_alignment(section->alignment_power);
-    print_space();
+    print_size(section->_cooked_size);
+    print_space ();
+    print_alignment (section->alignment_power);
+    print_space ();
 #if 0
-    printf("%s flags", output_section_statement->region->name);
-    print_flags(stdout, &output_section_statement->flags);
+    fprintf (config.map_file, "%s flags", output_section_statement->region->name);
+    print_flags (stdout, &output_section_statement->flags);
 #endif
+    if (section->flags & SEC_LOAD)
+     fprintf (config.map_file, "load ");
+    if (section->flags & SEC_ALLOC)
+     fprintf (config.map_file, "alloc ");
+    if (section->flags & SEC_RELOC)
+     fprintf (config.map_file, "reloc ");
+    if (section->flags & SEC_HAS_CONTENTS)
+     fprintf (config.map_file, "contents ");
 
   }
-  else {
-    printf("No attached output section");
+  else
+  {
+    fprintf (config.map_file, "No attached output section");
   }
-  print_nl();
-  print_statement(output_section_statement->children.head,
-                 output_section_statement);
+  print_nl ();
+  if (output_section_statement->load_base)
+    {
+      int b = exp_get_value_int(output_section_statement->load_base,
+                               0, "output base", lang_final_phase_enum);
+      printf("Output address   %08x\n", b);
+    }
+  if (output_section_statement->section_alignment >= 0
+      || output_section_statement->section_alignment >= 0) 
+  {
+    printf("\t\t\t\t\tforced alignment ");
+    if ( output_section_statement->section_alignment >= 0) 
+    {
+      printf("section 2**%d ",output_section_statement->section_alignment );
+    }
+    if ( output_section_statement->subsection_alignment >= 0) 
+    {
+      printf("subsection 2**%d ",output_section_statement->subsection_alignment );
+    }
+  
+    print_nl ();
+  }
+  print_statement (output_section_statement->children.head,
+                  output_section_statement);
 
 }
 
-static void 
-print_assignment(assignment, output_section)
-lang_assignment_statement_type *assignment;
-lang_output_section_statement_type *output_section;
+static void
+print_assignment (assignment, output_section)
+     lang_assignment_statement_type * assignment;
+     lang_output_section_statement_type * output_section;
 {
   etree_value_type result;
-  print_section("");
-  print_space();
-  print_section("");
-  print_space();
-  print_address(print_dot);
-  print_space();
-  result = exp_fold_tree(assignment->exp->assign.src,
-                        output_section,
-                        lang_final_phase_enum,
-                        print_dot,
-                        &print_dot);
-                        
-  if (result.valid) {
-    print_address(result.value);
-  }
-  else 
+
+  print_section ("");
+  print_space ();
+  print_section ("");
+  print_space ();
+  print_address (print_dot);
+  print_space ();
+  result = exp_fold_tree (assignment->exp->assign.src,
+                         output_section,
+                         lang_final_phase_enum,
+                         print_dot,
+                         &print_dot);
+
+  if (result.valid)
     {
-      printf("*undefined*");
+      print_address (result.value);
     }
-  print_space();
-  exp_print_tree(stdout, assignment->exp);
-  printf("\n");
+  else
+    {
+      fprintf (config.map_file, "*undefined*");
+    }
+  print_space ();
+  exp_print_tree (assignment->exp);
+
+  fprintf (config.map_file, "\n");
 }
 
 static void
-print_input_statement(statm)
-lang_input_statement_type *statm;
+print_input_statement (statm)
+     lang_input_statement_type * statm;
 {
-  printf("LOAD %s\n",statm->filename);
+  if (statm->filename != (char *) NULL)
+    {
+      fprintf (config.map_file, "LOAD %s\n", statm->filename);
+    }
 }
 
-static void print_symbol(q)
-asymbol *q;
+/* Print all the defined symbols for the abfd provided by in the supplied
+   section.
+*/
+
+static boolean 
+print_one_symbol (hash_entry, ptr)
+struct  bfd_link_hash_entry *hash_entry;
+PTR ptr;
 {
-  print_section("");
-  printf(" ");
-  print_section("");
-  printf(" ");
-  print_address(outside_symbol_address(q));
-  printf("              %s", q->name ? q->name : " ");
-  print_nl();
+  asection * sec = (asection *)ptr;
+
+  if (hash_entry->type == bfd_link_hash_defined) 
+    {
+      if (sec == hash_entry->u.def.section) {
+       print_section ("");
+       fprintf (config.map_file, " ");
+       print_section ("");
+       fprintf (config.map_file, " ");
+       print_address (hash_entry->u.def.value + outside_section_address (sec));
+       fprintf (config.map_file, "              %s", hash_entry->root.string);
+       print_nl ();
+      }
+    }
 }
-static void 
-print_input_section(in)
-lang_input_section_type *in;
+
+static void
+print_input_section (in)
+     lang_input_section_type * in;
 {
   asection *i = in->section;
+  int size = i->reloc_done ?
+  bfd_get_section_size_after_reloc (i) :
+  bfd_get_section_size_before_reloc (i);
 
-  if(i->size != 0) {
-    print_section("");
-    printf(" ");
-    print_section(i->name);
-    printf(" ");
-    if (i->output_section) {
-      print_address(i->output_section->vma + i->output_offset);
-      printf(" ");
-      print_size(i->size);
-      printf(" ");
-      print_alignment(i->alignment_power);
-      printf(" ");
-      if (in->ifile) {
-       bfd *abfd = in->ifile->the_bfd;
-       printf(" %s ",abfd->xvec->name);
-       if(abfd->my_archive != (bfd *)NULL) {
-         printf("[%s]%s", abfd->my_archive->filename,
-                abfd->filename);
-       }
-       else {
-         printf("%s", abfd->filename);
-       }
-       print_nl();
-
-       /* Find all the symbols in this file defined in this section */
+  if (size != 0)
+    {
+      print_section ("");
+      fprintf (config.map_file, " ");
+      print_section (i->name);
+      fprintf (config.map_file, " ");
+      if (i->output_section)
        {
-         asymbol **p;
-         for (p = in->ifile->asymbols; *p; p++) {
-           asymbol *q = *p;
-       
-           if (bfd_get_section(q) == i && q->flags & BSF_GLOBAL) {
-             print_symbol(q);
-           }
-         }
-       }
-      }
-      else {
-       print_nl();
-      }
+         print_address (i->output_section->vma + i->output_offset);
+         fprintf (config.map_file, " ");
+         print_size (i->_raw_size);
+         fprintf (config.map_file, " ");
+         print_size(i->_cooked_size);
+         fprintf (config.map_file, " ");
+         print_alignment (i->alignment_power);
+         fprintf (config.map_file, " ");
+         if (in->ifile)
+           {
 
+             bfd *abfd = in->ifile->the_bfd;
 
-      print_dot = outside_section_address(i) + i->size;
-    }
-    else {
-      printf("No output section allocated\n");
-    }
-  }
-}
-static void
-print_common_statement()
-{
-  ldsym_type *lgs;
-  print_section("");
-  print_space();
-  print_section(common_section.output_section->name);
-  print_space();
-  print_address(common_section.output_offset +
-               common_section.output_section->vma);
-  print_space();
-  print_size(common_section.size);
-  print_space();
-  printf("(common)");
-  print_nl();
-  /* Print out all the global symbols */
-
-
-  for (lgs = symbol_head; lgs != (ldsym_type *)NULL; lgs =
-       lgs->next) {
-    if (lgs->sdefs_chain) {
-      asymbol *def = *(lgs->sdefs_chain);
-      if (def->section == &common_section) {
-       print_symbol(def);
-      }
-    }
+             if (in->ifile->just_syms_flag == true)
+               {
+                 fprintf (config.map_file, "symbols only ");
+               }
 
-  }
-  print_dot = common_section.output_offset +
-    common_section.output_section->vma + common_section.size;
+             fprintf (config.map_file, " %s ", abfd->xvec->name);
+             if (abfd->my_archive != (bfd *) NULL)
+               {
+                 fprintf (config.map_file, "[%s]%s", abfd->my_archive->filename,
+                          abfd->filename);
+               }
+             else
+               {
+                 fprintf (config.map_file, "%s", abfd->filename);
+               }
+             fprintf (config.map_file, "(overhead %d bytes)", (int) bfd_alloc_size (abfd));
+             print_nl ();
 
+             /* Print all the symbols */
+             bfd_link_hash_traverse (link_info.hash, print_one_symbol, (PTR) i);
+           }
+         else
+           {
+             print_nl ();
+           }
 
+
+         print_dot = outside_section_address (i) + size;
+       }
+      else
+       {
+         fprintf (config.map_file, "No output section allocated\n");
+       }
+    }
 }
+
 static void
-print_fill_statement(fill)
-lang_fill_statement_type *fill;
+print_fill_statement (fill)
+     lang_fill_statement_type * fill;
 {
-  printf("FILL mask ");
-  print_fillfill->fill);
+  fprintf (config.map_file, "FILL mask ");
+  print_fill (fill->fill);
 }
 
 static void
-print_data_statement(data)
-lang_data_statement_type *data;
+print_data_statement (data)
+     lang_data_statement_type * data;
 {
 /*  bfd_vma value; */
-  print_section("");
-  print_space();
-  print_section("");
-  print_space();
-  ASSERT(print_dot == data->output_vma);
-
-  print_address(data->output_vma);
-  print_space();
-  print_address(data->value);
-  print_space();
-  switch (data->type) {
-  case BYTE :
-    printf("BYTE ");
-    print_dot += BYTE_SIZE;
-    break;
-  case SHORT:
-    printf("SHORT ");
-    print_dot += SHORT_SIZE;
-    break;  
-  case LONG:
-    printf("LONG ");
-    print_dot += LONG_SIZE;
-    break;
-  }
+  print_section ("");
+  print_space ();
+  print_section ("");
+  print_space ();
+/*  ASSERT(print_dot == data->output_vma);*/
+
+  print_address (data->output_vma + data->output_section->vma);
+  print_space ();
+  print_address (data->value);
+  print_space ();
+  switch (data->type)
+    {
+    case BYTE:
+      fprintf (config.map_file, "BYTE ");
+      print_dot += BYTE_SIZE;
+      break;
+    case SHORT:
+      fprintf (config.map_file, "SHORT ");
+      print_dot += SHORT_SIZE;
+      break;
+    case LONG:
+      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(stdout, data->exp);
-  
-  printf("\n");
+  exp_print_tree (data->exp);
+
+  fprintf (config.map_file, "\n");
 }
 
 
 static void
-print_padding_statement(s)
-lang_padding_statement_type *s;
-{
-  print_section("");
-  print_space();
-  print_section("*fill*");
-  print_space();
-  print_address(s->output_offset + s->output_section->vma);
-  print_space();
-  print_size(s->size);
-  print_space();
-  print_fill(s->fill);
-  print_nl();
-}
-
-static void print_wild_statement(w,os)
-lang_wild_statement_type *w;
-lang_output_section_statement_type *os;
-{
-  if (w->filename != (char *)NULL) {
-    printf("%s",w->filename);
-  }
-  else {
-    printf("*");
-  }
-  if (w->section_name != (char *)NULL) {
-    printf("(%s)",w->section_name);
-  }
-  else {
-    printf("(*)");
-  }
-  print_nl();
-  print_statement(w->children.head, os);
-
-}
-static void
-print_statement(s, os)
-lang_statement_union_type *s;
-lang_output_section_statement_type *os;
+print_padding_statement (s)
+     lang_padding_statement_type * s;
 {
-  while (s) {
-    switch (s->header.type) {
-    case lang_wild_statement_enum:
-     print_wild_statement(&s->wild_statement, os);
-     break;
-    default:
-     printf("Fail with %d\n",s->header.type);
-      FAIL();
-      break;
-   case lang_address_statement_enum:
-     printf("address\n");
-     break;
-    case lang_common_statement_enum:
-      print_common_statement();
-      break;
-    case lang_object_symbols_statement_enum:
-      printf("object symbols\n");
-      break;
-    case lang_fill_statement_enum:
-      print_fill_statement(&s->fill_statement);
-      break;
-    case lang_data_statement_enum:
-      print_data_statement(&s->data_statement);
-      break;
+  print_section ("");
+  print_space ();
+  print_section ("*fill*");
+  print_space ();
+  print_address (s->output_offset + s->output_section->vma);
+  print_space ();
+  print_size (s->size);
+  print_space ();
+  print_fill (s->fill);
+  print_nl ();
 
+  print_dot = s->output_offset + s->output_section->vma + s->size;
 
-    case lang_input_section_enum:
-      print_input_section(&s->input_section);
-      break;
-    case lang_padding_statement_enum:
-      print_padding_statement(&s->padding_statement);
-      break;
-    case lang_output_section_statement_enum:
-      print_output_section_statement(&s->output_section_statement);
-      break;
-    case lang_assignment_statement_enum:
-      print_assignment(&s->assignment_statement,
-                    os);
-      break;
+}
 
+static void
+print_wild_statement (w, os)
+     lang_wild_statement_type * w;
+     lang_output_section_statement_type * os;
+{
+  fprintf (config.map_file, " from ");
+  if (w->filename != (char *) NULL)
+    {
+      fprintf (config.map_file, "%s", w->filename);
+    }
+  else
+    {
+      fprintf (config.map_file, "*");
+    }
+  if (w->section_name != (char *) NULL)
+    {
+      fprintf (config.map_file, "(%s)", w->section_name);
+    }
+  else
+    {
+      fprintf (config.map_file, "(*)");
+    }
+  print_nl ();
+  print_statement (w->children.head, os);
 
-    case lang_target_statement_enum:
-      printf("TARGET(%s)\n", s->target_statement.target);
-      break;
-    case lang_output_statement_enum:
-      printf("OUTPUT(%s)\n", s->output_statement.name);
-      break;
-    case lang_input_statement_enum:
-      print_input_statement(&s->input_statement);
-      break;
-    case lang_afile_asection_pair_statement_enum:
-      FAIL();
-      break;
+}
+static void
+print_statement (s, os)
+     lang_statement_union_type * s;
+     lang_output_section_statement_type * os;
+{
+  while (s)
+    {
+      switch (s->header.type)
+       {
+         case lang_constructors_statement_enum:
+         fprintf (config.map_file, "constructors:\n");
+         print_statement (constructor_list.head, os);
+         break;
+       case lang_wild_statement_enum:
+         print_wild_statement (&s->wild_statement, os);
+         break;
+       default:
+         fprintf (config.map_file, "Fail with %d\n", s->header.type);
+         FAIL ();
+         break;
+       case lang_address_statement_enum:
+         fprintf (config.map_file, "address\n");
+         break;
+       case lang_object_symbols_statement_enum:
+         fprintf (config.map_file, "object symbols\n");
+         break;
+       case lang_fill_statement_enum:
+         print_fill_statement (&s->fill_statement);
+         break;
+       case lang_data_statement_enum:
+         print_data_statement (&s->data_statement);
+         break;
+       case lang_input_section_enum:
+         print_input_section (&s->input_section);
+         break;
+       case lang_padding_statement_enum:
+         print_padding_statement (&s->padding_statement);
+         break;
+       case lang_output_section_statement_enum:
+         print_output_section_statement (&s->output_section_statement);
+         break;
+       case lang_assignment_statement_enum:
+         print_assignment (&s->assignment_statement,
+                           os);
+         break;
+       case lang_target_statement_enum:
+         fprintf (config.map_file, "TARGET(%s)\n", s->target_statement.target);
+         break;
+       case lang_output_statement_enum:
+         fprintf (config.map_file, "OUTPUT(%s %s)\n",
+                  s->output_statement.name,
+                  output_target ? output_target : "");
+         break;
+       case lang_input_statement_enum:
+         print_input_statement (&s->input_statement);
+         break;
+       case lang_afile_asection_pair_statement_enum:
+         FAIL ();
+         break;
+       }
+      s = s->next;
     }
-    s = s->next;
-  }
 }
 
 
 static void
-print_statements()
+print_statements ()
 {
-  print_statement(statement_list.head,
-                 (lang_output_section_statement_type *)NULL);
+  print_statement (statement_list.head,
+                  abs_output_section);
+
 }
 
 static bfd_vma
-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 
+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
      to the output section's requirement.
-     If this alignment is > than any seen before, 
+     If this alignment is > than any seen before,
      then record it too. Perform the alignment by
      inserting a magic 'padding' statement.
      */
 
-  unsigned int alignment_needed =  align_power(dot, power) - dot;
+  unsigned int alignment_needed = align_power (dot, power) - dot;
 
-  if (alignment_needed != 0) 
+  if (alignment_needed != 0)
     {
-      lang_statement_union_type *new = 
-       (lang_statement_union_type *)
-         ldmalloc(sizeof(lang_padding_statement_type));
+      lang_statement_union_type *new =
+      (lang_statement_union_type *)
+      stat_alloc ((bfd_size_type) (sizeof (lang_padding_statement_type)));
+
       /* Link into existing chain */
       new->header.next = *this_ptr;
       *this_ptr = new;
@@ -1184,726 +1525,739 @@ bfd_vma dot;
 
 
   /* Remember the most restrictive alignment */
-  if (power > output_section_statement->alignment_power) {
-    output_section_statement->alignment_power = power;
-  }
-  output_section_statement->size += alignment_needed;
+  if (power > output_section_statement->alignment_power)
+    {
+      output_section_statement->alignment_power = power;
+    }
+  output_section_statement->_raw_size += alignment_needed;
   return alignment_needed + dot;
 
 }
 
-/*
- size_common runs run though each global symboxl, and works
- out how big the common section will be.
- */
-
-static bfd_vma 
-size_common(output_section_statement, this_ptr, dot)
-lang_output_section_statement_type *output_section_statement;
-lang_statement_union_type **this_ptr;
-bfd_vma dot;
-{
-  extern ldsym_type *symbol_head;
-  ldsym_type *sp;
-  /* Make sure that each symbol is only defined once.
-     Allocate common symbols
-     Make the ref chain point to the defining asymbol.
-     */
-  /* Now, for each symbol, verify that it is defined globally at most once.
-     Put the global value into the symbol entry.
-     Common symbols are allocated here, in the BSS section.
-     Each defined symbol is given a '->defined' field
-     which is the correct N_ code for its definition,
-     except in the case of common symbols with -r.
-     Then make all the references point at the symbol entry
-     instead of being chained together. */
-  
-
-  common_section.name = output_section_statement->bfd_section->name;
-  common_section.output_section = output_section_statement->bfd_section;
-  common_section.output_offset =
-    dot - output_section_statement->bfd_section->vma;
-  if (config.relocateable_output == false ||
-      command_line.force_common_definition== true) {
-    dot = insert_pad(this_ptr,
-                    0x0, 4, output_section_statement->bfd_section, dot);
-
-    for (sp = symbol_head; sp != (ldsym_type *)NULL; sp = sp->next)  
-      {
-       /* Attatch this symbol to the correct output section*/
-
-       /* Allocate as common if wanted */
-
-       if (sp->scoms_chain )
-
-         {
-           unsigned long com = (*(sp->scoms_chain))->value;
-           /* Work out what alignment this common item s
-              hould be put on. Anything < int is int aligned,
-              anything bigger is  self aligned,
-              up to the restriction of the machine */
-
-           unsigned int align = sizeof(int);
-
-           /* Round up size of object to nearest int */
-           com = ALIGN(com, sizeof(int));
-           /* See what alignment is necessary -*/
-           if (com) {          
-             while ((com & align)==0) align <<=1;
-             /* FIXME */
-             if (align > 8)  {
-               align = 8;
-             }
-           }
-           dot =  ALIGN(dot, align);
-               
-
-           /* Transmogrify this from a common symbol
-              into a definition of a symbol in common
-              */
-           sp->sdefs_chain = sp->scoms_chain;
-
-           {
-             asymbol *com_ptr = *(sp->sdefs_chain);
-
-             sp->scoms_chain = (asymbol **)NULL;
-             commons_pending--;
-             /* Assign address, but keep section relative */
-
-             /* Force the symbol to belong in the bss section */
-             com_ptr->flags = BSF_EXPORT | BSF_GLOBAL ;
-             com_ptr->section = &common_section;
-             common_section.size += com;
-             if (write_map) 
-               {
-                 printf ("Allocating common %s: %lx at %lx\n",
-                         sp->name, 
-                         com,
-                         com_ptr->value);
-               }
-             com_ptr->value = common_section.size;
-           }
-         }
-      }
-  }
-  if (dot >
-      (common_section.output_section->vma +
-       common_section.output_section->size)) {
-    common_section.output_section->size =
-      dot - common_section.output_section->vma;
-  }
-  return dot + common_section.size;
-}
-
-static bfd_vma 
-size_input_section( this_ptr, output_section_statement, fill,  dot)
-lang_statement_union_type **this_ptr;
-lang_output_section_statement_type*output_section_statement;
-unsigned short fill;
-bfd_vma dot;
+/* Work out how much this section will move the dot point */
+static bfd_vma
+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;
-           
-  dot =  insert_pad(this_ptr, fill, i->alignment_power,
-                   output_section_statement->bfd_section, dot);
-
-  /* remember the largest size so we can malloc the largest area */
-  /* needed for the output stage */
-  if (i->size > largest_section) {
-    largest_section = i->size;
-  }
 
-  /* Remember where in the output section this input section goes */
-  i->output_offset = dot - output_section_statement->bfd_section->vma;
+  if (is->ifile->just_syms_flag == false)
+    {
+      if (output_section_statement->subsection_alignment != -1)
+       i->alignment_power =
+       output_section_statement->subsection_alignment;
+
+      dot = insert_pad (this_ptr, fill, i->alignment_power,
+                       output_section_statement->bfd_section, dot);
+
+      /* remember the largest size so we can malloc the largest area
+         needed for the output stage. Only remember the size of sections
+         which we will actually allocate  */
+      if ((i->flags & SEC_HAS_CONTENTS) != 0
+         && (bfd_get_section_size_before_reloc (i) > largest_section))
+       {
+         largest_section = bfd_get_section_size_before_reloc (i);
+       }
 
-  /* Mark how big the output section must be to contain this now */
-  dot += i->size;
-  output_section_statement->bfd_section->size =
-    dot - output_section_statement->bfd_section->vma;
+      /* Remember where in the output section this input section goes */
 
+      i->output_offset = dot - output_section_statement->bfd_section->vma;
 
-  return dot ;
+      /* Mark how big the output section must be to contain this now
+        */
+      if (relax)
+       {
+         dot += i->_cooked_size;
+       }
+      else
+       {
+         dot += i->_raw_size;
+       }
+      output_section_statement->bfd_section->_raw_size = dot - output_section_statement->bfd_section->vma;
+    }
+  else
+    {
+      i->output_offset = i->vma - output_section_statement->bfd_section->vma;
+    }
+
+  return dot;
 }
 
+/* Sizing happens in two passes, first pass we allocate worst case
+   stuff. The second pass (if relaxing), we use what we learnt to
+   change the size of some relocs from worst case to better
+   */
+static boolean had_relax;
 
-/* Work out the size of the output sections 
- from the sizes of the input sections */
 static bfd_vma
-lang_size_sections(s, output_section_statement, prev, fill, dot)
-lang_statement_union_type *s;
-lang_output_section_statement_type * output_section_statement;
-lang_statement_union_type **prev;
-unsigned short fill;
-bfd_vma dot;
+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) 
+  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  {
+    switch (s->header.type)
     {
-      switch (s->header.type) {
-      case lang_output_section_statement_enum:
-       {
-         bfd_vma after;
-         lang_output_section_statement_type *os =
-           &(s->output_section_statement);
-         /* The start of a section */
-         
-         if (os->addr_tree == (etree_type *)NULL) {
-           /* No address specified for this section, get one
-              from the region specification
-              */
-             if (os->region == (lang_memory_region_type *)NULL) {
-                 os->region = lang_memory_region_lookup("*default*");
-             }
-             dot = os->region->current;
-         }
-         else {
-           etree_value_type r ;
-           r = exp_fold_tree(os->addr_tree,
-                             (lang_output_section_statement_type *)NULL,
+
+     case lang_output_section_statement_enum:
+     {
+       bfd_vma after;
+       lang_output_section_statement_type *os = &s->output_section_statement;
+
+       /* If this is a shared library section, don't change the size
+         and address.  */
+       if (os->bfd_section->flags & SEC_SHARED_LIBRARY)
+        break;
+
+       if (os->bfd_section == &bfd_abs_section)
+       {
+        /* No matter what happens, an abs section starts at zero */
+        bfd_set_section_vma (0, os->bfd_section, 0);
+       }
+       else
+       {
+        if (os->addr_tree == (etree_type *) NULL)
+        {
+          /* No address specified for this section, get one
+             from the region specification
+             */
+          if (os->region == (lang_memory_region_type *) NULL)
+          {
+            os->region = lang_memory_region_lookup ("*default*");
+          }
+          dot = os->region->current;
+        }
+        else
+        {
+          etree_value_type r;
+
+          r = exp_fold_tree (os->addr_tree,
+                             abs_output_section,
                              lang_allocating_phase_enum,
                              dot, &dot);
-           if (r.valid == false) {
-             info("%F%S: non constant address expression for section %s\n",
-                  os->name);
-           }
-           dot = r.value;
-         }
-         /* The section starts here */
-         /* First, align to what the section needs */
-
-         dot = align_power(dot, os->bfd_section->alignment_power);
-         os->bfd_section->vma = dot;
-         os->bfd_section->output_offset = 0;
-
-         (void)  lang_size_sections(os->children.head, os, &os->children.head,
-                                    os->fill, dot);
-         /* Ignore the size of the input sections, use the vma and size to */
-         /* align against */
+          if (r.valid == false)
+          {
+            einfo ("%F%S: non constant address expression for section %s\n",
+                   os->name);
+          }
+          dot = r.value;
+        }
+        /* The section starts here */
+        /* First, align to what the section needs */
+
+
+        dot = align_power (dot, os->bfd_section->alignment_power);
+        bfd_set_section_vma (0, os->bfd_section, dot);
+        
+        if (os->load_base) {
+          os->bfd_section->lma 
+            = exp_get_value_int(os->load_base, 0,"load base", lang_final_phase_enum);
+        }
+       }
+
+
+       os->bfd_section->output_offset = 0;
+
+       (void) lang_size_sections (os->children.head, os, &os->children.head,
+                                 os->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,
+                       /* 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;
+       os->processed = true;
+
+       /* Replace into region ? */
+       if (os->addr_tree == (etree_type *) NULL
+          && os->region != (lang_memory_region_type *) NULL)
+       {
+        os->region->current = dot;
+        /* Make sure this isn't silly */
+        if (( os->region->current
+              > os->region->origin + os->region->length)
+            || ( os->region->origin > os->region->current ))
+          {
+            einfo ("%X%P: region %s is full (%B section %s)\n",
+                   os->region->name,
+                   os->bfd_section->owner,
+                   os->bfd_section->name);
+            /* Reset the region pointer */
+            os->region->current = 0;
+
+          }
+
+       }
+     }
 
+      break;
+     case lang_constructors_statement_enum:
+      dot = lang_size_sections (constructor_list.head,
+                               output_section_statement,
+                               &s->wild_statement.children.head,
+                               fill,
+                               dot, relax);
+      break;
 
-         after = ALIGN(os->bfd_section->vma +
-                       os->bfd_section->size,
-                       os->block_value) ;
-
-
-         os->bfd_section->size = after - os->bfd_section->vma;
-         dot = os->bfd_section->vma + os->bfd_section->size;
-         os->processed = true;
-
-         /* Replace into region ? */
-         if (os->addr_tree == (etree_type *)NULL 
-             && os->region !=(lang_memory_region_type*)NULL ) {
-           os->region->current = dot;
-         }
-       }
-
-       break;
+     case lang_data_statement_enum:
+     {
+       unsigned int size = 0;
 
-      case lang_data_statement_enum: 
-       {
-       unsigned int size;
-       s->data_statement.output_vma = dot;
-       s->data_statement.output_section =
-         output_section_statement->bfd_section;
+       s->data_statement.output_vma = dot - output_section_statement->bfd_section->vma;
+       s->data_statement.output_section =
+       output_section_statement->bfd_section;
 
-       switch (s->data_statement.type) {
+       switch (s->data_statement.type)
+       {
+        case QUAD:
+        size = QUAD_SIZE;
+        break;
        case LONG:
-         size = LONG_SIZE;
-         break;
+        size = LONG_SIZE;
+        break;
        case SHORT:
-         size = SHORT_SIZE;
-         break;
+        size = SHORT_SIZE;
+        break;
        case BYTE:
-         size = BYTE_SIZE;
-         break;
+        size = BYTE_SIZE;
+        break;
 
-       }
-       dot += size;
-       output_section_statement->bfd_section->size += size;
-      }
-       break;
+       }
+       dot += size;
+       output_section_statement->bfd_section->_raw_size += size;
+     }
+      break;
 
-      case lang_wild_statement_enum:
+     case lang_wild_statement_enum:
 
-       dot =   lang_size_sections(s->wild_statement.children.head,
-                                  output_section_statement,
-                                  &s->wild_statement.children.head,
+      dot = lang_size_sections (s->wild_statement.children.head,
+                               output_section_statement,
+                               &s->wild_statement.children.head,
 
-                                  fill, dot);
+                               fill, dot, relax);
 
-       break;
+      break;
 
-      case lang_object_symbols_statement_enum:
-       create_object_symbols = output_section_statement;
-       break;
-      case lang_output_statement_enum:
+     case lang_object_symbols_statement_enum:
+      link_info.create_object_symbols_section =
+       output_section_statement->bfd_section;
+      break;
+     case lang_output_statement_enum:
+     case lang_target_statement_enum:
+      break;
+     case lang_input_section_enum:
+      if (relax)
+      {
+       lang_input_section_type *is;
+       asection *i;
 
-      case lang_target_statement_enum:
-       break;
-      case lang_common_statement_enum:
-       dot =   size_common(output_section_statement, prev, dot);
+       is = &(*prev)->input_section;
+       i = is->section;
 
-       break;
+       /* 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;
+         }
 
-      case lang_input_section_enum:
-       dot =   size_input_section(prev,
-                                  output_section_statement,
-                                  output_section_statement->fill, dot);
-       break;
-      case lang_input_statement_enum:
-       break;
-      case lang_fill_statement_enum:
-       fill = s->fill_statement.fill;
-       break;
-      case lang_assignment_statement_enum:
-       {
-         bfd_vma newdot = dot;
-         exp_fold_tree(s->assignment_statement.exp,
-                       output_section_statement,
-                       lang_allocating_phase_enum,
-                       dot,
-                       &newdot);
-
-         if (newdot != dot) 
-           /* We've been moved ! so insert a pad */
-           {
-             lang_statement_union_type *new = 
-               (lang_statement_union_type *)
-                 ldmalloc(sizeof(lang_padding_statement_type));
-             /* Link into existing chain */
-             new->header.next = *prev;
-             *prev = new;
-             new->header.type = lang_padding_statement_enum;
-             new->padding_statement.output_section =
-               output_section_statement->bfd_section;
-             new->padding_statement.output_offset =
-               dot - output_section_statement->bfd_section->vma;
-             new->padding_statement.fill = fill;
-             new->padding_statement.size = newdot - dot;
-             output_section_statement->bfd_section->size +=
-               new->padding_statement.size;
-             dot =   newdot;
-           }
-       }
+       if (bfd_relax_section (i->owner, i, &link_info, is->ifile->asymbols))
+         had_relax = true;
+      }
+      else  {
+       (*prev)->input_section.section->_cooked_size = 
+        (*prev)->input_section.section->_raw_size ;
 
-       break;
-      case lang_padding_statement_enum:
-       FAIL();
-       break;
-      default:
-       FAIL();
-       break;
-      case lang_address_statement_enum:
-       break;
       }
-      prev = &s->header.next;      
+      dot = size_input_section (prev,
+                               output_section_statement,
+                               output_section_statement->fill,
+                               dot, relax);
+      break;
+     case lang_input_statement_enum:
+      break;
+     case lang_fill_statement_enum:
+      s->fill_statement.output_section = output_section_statement->bfd_section;
+
+      fill = s->fill_statement.fill;
+      break;
+     case lang_assignment_statement_enum:
+     {
+       bfd_vma newdot = dot;
+
+       exp_fold_tree (s->assignment_statement.exp,
+                     output_section_statement,
+                     lang_allocating_phase_enum,
+                     dot,
+                     &newdot);
+
+       if (newdot != dot && !relax)
+       /* We've been moved ! so insert a pad */
+       {
+        lang_statement_union_type *new =
+         (lang_statement_union_type *)
+          stat_alloc ((bfd_size_type) (sizeof (lang_padding_statement_type)));
+
+        /* Link into existing chain */
+        new->header.next = *prev;
+        *prev = new;
+        new->header.type = lang_padding_statement_enum;
+        new->padding_statement.output_section =
+         output_section_statement->bfd_section;
+        new->padding_statement.output_offset =
+         dot - output_section_statement->bfd_section->vma;
+        new->padding_statement.fill = fill;
+        new->padding_statement.size = newdot - dot;
+        output_section_statement->bfd_section->_raw_size +=
+         new->padding_statement.size;
+        dot = newdot;
+       }
+     }
+
+      break;
+     default:
+      FAIL ();
+      break;
+      /* This can only get here when relaxing is turned on */
+     case lang_padding_statement_enum:
+
+     case lang_address_statement_enum:
+      break;
     }
+    prev = &s->header.next;
+  }
   return dot;
 }
 
-
 static bfd_vma
-lang_do_assignments(s, output_section_statement, fill, dot)
-lang_statement_union_type *s;
-lang_output_section_statement_type * output_section_statement;
-unsigned short fill;
-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) 
+  for (; s != (lang_statement_union_type *) NULL; s = s->next)
     {
-      switch (s->header.type) {
-      case lang_output_section_statement_enum:
+      switch (s->header.type)
        {
-         lang_output_section_statement_type *os =
+       case lang_constructors_statement_enum:
+         dot = lang_do_assignments (constructor_list.head,
+                                    output_section_statement,
+                                    fill,
+                                    dot);
+         break;
+
+       case lang_output_section_statement_enum:
+         {
+           lang_output_section_statement_type *os =
            &(s->output_section_statement);
-         dot = os->bfd_section->vma;
-         (void) lang_do_assignments(os->children.head, os, os->fill, dot);
-         dot = os->bfd_section->vma + os->bfd_section->size;
-       }
-       break;
-      case lang_wild_statement_enum:
 
-       dot = lang_do_assignments(s->wild_statement.children.head,
-                                   output_section_statement,
-                                   fill, dot);
+           dot = os->bfd_section->vma;
+           (void) lang_do_assignments (os->children.head, os, os->fill, dot);
+           dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+         }
+         break;
+       case lang_wild_statement_enum:
 
-       break;
+         dot = lang_do_assignments (s->wild_statement.children.head,
+                                    output_section_statement,
+                                    fill, dot);
 
-      case lang_object_symbols_statement_enum:
-      case lang_output_statement_enum:
-      case lang_target_statement_enum:
-      case lang_common_statement_enum:
-       break;
-      case lang_data_statement_enum:
-       {
-         etree_value_type value ;
-         value =   exp_fold_tree(s->data_statement.exp,
-                                 0, lang_final_phase_enum, dot, &dot);
-         s->data_statement.value = value.value;
-         if (value.valid == false) info("%F%P: Invalid data statement\n");
-       }
-       switch (s->data_statement.type) {
-       case LONG:
-         dot += LONG_SIZE;
          break;
-       case SHORT:
-         dot += SHORT_SIZE;
+
+       case lang_object_symbols_statement_enum:
+       case lang_output_statement_enum:
+       case lang_target_statement_enum:
+#if 0
+       case lang_common_statement_enum:
+#endif
          break;
-       case BYTE:
-         dot += BYTE_SIZE;
+       case lang_data_statement_enum:
+         {
+           etree_value_type value;
+
+           value = exp_fold_tree (s->data_statement.exp,
+                                  abs_output_section,
+                                  lang_final_phase_enum, dot, &dot);
+           s->data_statement.value = value.value;
+           if (value.valid == false)
+             einfo ("%F%P: invalid data statement\n");
+         }
+         switch (s->data_statement.type)
+           {
+           case QUAD:
+             dot += QUAD_SIZE;
+             break;
+           case LONG:
+             dot += LONG_SIZE;
+             break;
+           case SHORT:
+             dot += SHORT_SIZE;
+             break;
+           case BYTE:
+             dot += BYTE_SIZE;
+             break;
+           }
          break;
-       }
-       break;
-      case lang_input_section_enum:
-       {
-         asection *in =    s->input_section.section;
-         dot += in->size;
-       }
-       break;
-
-      case lang_input_statement_enum:
-       break;
-      case lang_fill_statement_enum:
-       fill = s->fill_statement.fill;
-       break;
-      case lang_assignment_statement_enum:
-       {
-         exp_fold_tree(s->assignment_statement.exp,
-                       output_section_statement,
-                       lang_final_phase_enum,
-                       dot,
-                       &dot);
-       }
-
-       break;
-      case lang_padding_statement_enum:
-       dot += s->padding_statement.size;
-       break;
-      default:
-       FAIL();
-       break;
-      case lang_address_statement_enum:
-       break;
-      }
-
-    }
-  return dot;
-}
-
+       case lang_input_section_enum:
+         {
+           asection *in = s->input_section.section;
 
+           dot += bfd_get_section_size_before_reloc (in);
+         }
+         break;
 
-static void lang_relocate_globals() 
-{ 
+       case lang_input_statement_enum:
+         break;
+       case lang_fill_statement_enum:
+         fill = s->fill_statement.fill;
+         break;
+       case lang_assignment_statement_enum:
+         {
+           exp_fold_tree (s->assignment_statement.exp,
+                          output_section_statement,
+                          lang_final_phase_enum,
+                          dot,
+                          &dot);
+         }
 
-  /*
-     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.
-     */
+         break;
+       case lang_padding_statement_enum:
+         dot += s->padding_statement.size;
+         break;
+       default:
+         FAIL ();
+         break;
+       case lang_address_statement_enum:
+         break;
+       }
 
-  FOR_EACH_LDSYM(lgs) {
-    asymbol *it;
-    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 {
-      FAIL();
-    }
-    if (it != (asymbol *)NULL)
-      {
-       asymbol **ptr= lgs->srefs_chain;
-
-       while (ptr != (asymbol **)NULL) {
-         asymbol *ref = *ptr;
-         *ptr = it;
-         ptr = (asymbol **)(ref->udata);
-       }
-      }
-  }
+  return dot;
 }
 
-
-
-/* now that all the jiggery pokery is finished, copy important data from
- * out internal form to the bfd way. Also create a section
- * for each dummy file
- */
-
 static void
-lang_create_output_section_statements()
+lang_finish ()
 {
-  lang_statement_union_type*os;
-  for (os = lang_output_section_statement.head;
-       os != (lang_statement_union_type*)NULL;
-       os = os->output_section_statement.next) {
-    lang_output_section_statement_type *s =
-      &os->output_section_statement;
-    init_os(s);
-  }
-  script_file->the_bfd->sections = output_bfd->sections;
-}
+  struct bfd_link_hash_entry *h;
+  boolean warn = link_info.relocateable ? false : true;
 
-static void
-lang_finish()
-{
-  ldsym_type *lgs;
+  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;
+    }
 
-  if (entry_symbol == (char *)NULL) {
-    /* No entry has been specified, look for start */
-    entry_symbol = "start";
-  }
-  lgs = ldsym_get_soft(entry_symbol);
-  if (lgs && lgs->sdefs_chain) {
-    asymbol *sy = *(lgs->sdefs_chain);
-    /* We can set the entry address*/
-    bfd_set_start_address(output_bfd,
-                         outside_symbol_address(sy));
+  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)
+    {
+      bfd_vma val;
+
+      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
+    {
+      asection *ts;
 
-  }
-  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) {
-      bfd_set_start_address(output_bfd, ts->vma);
+      /* 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 */
 /* ldfile_output_machine_name */
 static void
-lang_check()
+lang_check ()
 {
   lang_statement_union_type *file;
+  bfd *input_bfd;
+  unsigned long input_machine;
+  enum bfd_architecture input_architecture;
+  CONST bfd_arch_info_type *compatible;
 
-  
   for (file = file_chain.head;
-       file != (lang_statement_union_type *)NULL;
-       file=file->input_statement.next) 
+       file != (lang_statement_union_type *) NULL;
+       file = file->input_statement.next)
     {
-      /* Inspect the architecture and ensure we're linking like
-        with like
-        */
-
-      if (bfd_arch_compatible( file->input_statement.the_bfd,
-                             output_bfd,
-                             &ldfile_output_architecture,
-                             &ldfile_output_machine)) {
-       bfd_set_arch_mach(output_bfd,
-                         ldfile_output_architecture, ldfile_output_machine);
-      }
-      else {
-       enum bfd_architecture this_architecture =
-         bfd_get_architecture(file->input_statement.the_bfd);
-       unsigned long this_machine =
-         bfd_get_machine(file->input_statement.the_bfd);
-       
-       info("%I: architecture %s",
-            file,
-            bfd_printable_arch_mach(this_architecture, this_machine));
-       info(" incompatible with output %s\n",
-            bfd_printable_arch_mach(ldfile_output_architecture,
-                                    ldfile_output_machine));
-       ldfile_output_architecture = this_architecture;
-       ldfile_output_machine = this_machine;
-       bfd_set_arch_mach(output_bfd,
-                         ldfile_output_architecture,
-                         ldfile_output_machine);
-
-
-      }
-    }
-}
+      input_bfd = file->input_statement.the_bfd;
 
+      input_machine = bfd_get_mach (input_bfd);
+      input_architecture = bfd_get_arch (input_bfd);
 
-/*
- * run through all the global common symbols and tie them 
- * to the output section requested.
- */
 
-static void
-lang_common()
-{
-  ldsym_type *lgs;
-  if (config.relocateable_output == false ||
-      command_line.force_common_definition== true) {
-    for (lgs = symbol_head;
-        lgs != (ldsym_type *)NULL;
-        lgs=lgs->next)
-      {
-       asymbol *com ;
-       size_t size;
-       size_t align;
-       if (lgs->scoms_chain != (asymbol **)NULL) {
-
-         com = *(lgs->scoms_chain);
-         size = com->value;
-         align = sizeof(int);
-         /* Round up size of object to nearest int */
-         size = ALIGN(size, sizeof(int));
-         /* Force alignment */
-         if (size) {
-           while ((size & align)==0) align<<=1;
-           if (align > 8) {
-             align = 8;
-           }
-         }
-         /* 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 */
-         com->section =
-           ((lang_input_statement_type *)
-            (com->the_bfd->usrdata))->common_section;
-         /*  Fix the size of the common section */
+      /* Inspect the architecture and ensure we're linking like with
+         like */
 
+      compatible = bfd_arch_get_compatible (input_bfd,
+                                           output_bfd);
+      if (compatible)
+       {
+         ldfile_output_machine = compatible->mach;
+         ldfile_output_architecture = compatible->arch;
+       }
+      else
+       {
 
-         com->flags = BSF_EXPORT | BSF_GLOBAL;
+         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));
 
-         if (write_map) 
-           {
-             printf ("Allocating common %s: %x at %x\n",
-                     lgs->name, 
-                     (unsigned) size,
-                     (unsigned)  com->section->size);
-           }
-         com->value = com->section->size;
-         com->section->size += size;
+         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 the input files and ensure that every input 
-section has somewhere to go. If one is found without
-a destination then create an input request and place it
-into the statement tree.
-*/
+/* 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_place_orphans()
+static void
+lang_common ()
 {
-  lang_input_statement_type *file;
-  for (file = (lang_input_statement_type*)file_chain.head;
-       file != (lang_input_statement_type*)NULL;
-       file = (lang_input_statement_type*)file->next) {
-    asection *s;  
-    for (s = file->the_bfd->sections;
-        s != (asection *)NULL;
-        s = s->next) {
-      if ( s->output_section == (asection *)NULL) {
-       /* This section of the file is not attatched, root
-          around for a sensible place for it to go */
-
-       if (file->common_section == s) {
-         /* This is a lonely common section which must
-            have come from an archive. We attatch to the
-            section with the wildcard  */
-         wild_doit(&default_common_section->children, s, 
-                   default_common_section, file);        
-       }
-       else {
-         lang_output_section_statement_type *os = 
-           lang_output_section_statement_lookup(s->name);
+  if (link_info.relocateable
+      && ! command_line.force_common_definition)
+    return;
 
-         wild_doit(&os->children, s, os, file);
-       }
-      }
-    }
+  if (! config.sort_common)
+    bfd_link_hash_traverse (link_info.hash, lang_one_common, (PTR) NULL);
+  else
+    {
+      unsigned int power;
 
-  }
+      for (power = 1; power <= 16; power <<= 1)
+       bfd_link_hash_traverse (link_info.hash, lang_one_common,
+                               (PTR) &power);
+    }
 }
 
+/* Place one common symbol in the correct section.  */
 
-/*
- * phase_2
- *
- * peformed after every file has been opened and symbols read
- */
-static void
-lang_phase_2()
+static boolean
+lang_one_common (h, info)
+     struct bfd_link_hash_entry *h;
+     PTR info;
 {
-  lang_init2();
-  lang_create_output_section_statements();
-  lang_open_input(statement_list.head, (char *)NULL, 
-                 ( lang_output_section_statement_type *)NULL);
-  lang_place_orphans();
-  lang_common();
+  unsigned int power_of_two;
+  bfd_vma size;
+  size_t align;
+  asection *section;
 
-  ldemul_before_allocation();
+  if (h->type != bfd_link_hash_common)
+    return true;
 
-  lang_size_sections(statement_list.head,
-                    (lang_output_section_statement_type *)NULL,
-                    &(statement_list.head), 0, (bfd_vma)0);
-  ldemul_after_allocation();
-  /* Do it once again now that we know the sizes of everything */
+  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;
 
-  lang_do_assignments(statement_list.head,
-                     (lang_output_section_statement_type *)NULL,
-                     0, (bfd_vma)0);
+  section = h->u.c.section;
 
+  /* Increase the size of the section.  */
+  section->_raw_size = ALIGN_N (section->_raw_size, align);
 
+  /* Adjust the alignment if necessary.  */
+  if (power_of_two > section->alignment_power)
+    section->alignment_power = power_of_two;
 
-  lang_check();
+  /* 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;
 
-  lang_relocate_globals();
+  /* 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);
 
-  lang_finish();
+  return true;
 }
 
+/*
+run through the input files and ensure that every input
+section has somewhere to go. If one is found without
+a destination then create an input request and place it
+into the statement tree.
+*/
+
+static void
+lang_place_orphans ()
+{
+  lang_input_statement_type *file;
+
+  for (file = (lang_input_statement_type *) file_chain.head;
+       file != (lang_input_statement_type *) NULL;
+       file = (lang_input_statement_type *) file->next)
+    {
+      asection *s;
+
+      for (s = file->the_bfd->sections;
+          s != (asection *) NULL;
+          s = s->next)
+       {
+         if (s->output_section == (asection *) NULL)
+           {
+             /* This section of the file is not attatched, root
+                around for a sensible place for it to go */
+
+             if (file->common_section == s)
+               {
+                 /* This is a lonely common section which must
+                    have come from an archive. We attatch to the
+                    section with the wildcard  */
+                 if (! link_info.relocateable
+                     && ! command_line.force_common_definition)
+                   {
+                     if (default_common_section ==
+                         (lang_output_section_statement_type *) NULL)
+                       {
+                         info_msg ("%P: no [COMMON] command, defaulting to .bss\n");
+
+                         default_common_section =
+                           lang_output_section_statement_lookup (".bss");
+
+                       }
+                     wild_doit (&default_common_section->children, s,
+                                default_common_section, file);
+                   }
+               }
+             else
+               {
+                 lang_output_section_statement_type *os =
+                 lang_output_section_statement_lookup (s->name);
 
+                 wild_doit (&os->children, s, os, file);
+               }
+           }
+       }
+    }
+}
 
 
 void
-lang_set_flags(ptr, flags)
-lang_section_flags_type *ptr;
-char *flags;
-{
-  boolean state = true;
-  ptr->flag_read = false;
-  ptr->flag_write = false;
-  ptr->flag_executable = false;
-  ptr->flag_loadable= false;
+lang_set_flags (ptr, flags)
+     int *ptr;
+     CONST char *flags;
+{
+  boolean state = false;
+
+  *ptr = 0;
   while (*flags)
     {
-      if (*flags == '!') {
-       state = false;
-       flags++;
-      }
-      else state = true;
-      switch (*flags) {
-      case 'R':
-       ptr->flag_read = state; 
-       break;
-      case 'W':
-       ptr->flag_write = state; 
-       break;
-      case 'X':
-       ptr->flag_executable= state;
-       break;
-      case 'L':
-       ptr->flag_loadable= state;
-       break;
-      default:
-       info("%P%F illegal syntax in flags\n");
-       break;
-      }
+      if (*flags == '!')
+       {
+         state = false;
+         flags++;
+       }
+      else
+       state = true;
+      switch (*flags)
+       {
+       case 'R':
+         /*      ptr->flag_read = state; */
+         break;
+       case 'W':
+         /*      ptr->flag_write = state; */
+         break;
+       case 'X':
+         /*      ptr->flag_executable= state;*/
+         break;
+       case 'L':
+       case 'I':
+         /*      ptr->flag_loadable= state;*/
+         break;
+       default:
+         einfo ("%P%F: invalid syntax in flags\n");
+         break;
+       }
       flags++;
     }
 }
@@ -1911,76 +2265,115 @@ char *flags;
 
 
 void
-lang_for_each_file(func)
-void (*func)();
+lang_for_each_file (func)
+     void (*func) PARAMS ((lang_input_statement_type *));
 {
   lang_input_statement_type *f;
-  for (f = (lang_input_statement_type *)file_chain.head; 
-       f != (lang_input_statement_type *)NULL;
-       f = (lang_input_statement_type *)f->next)  
+
+  for (f = (lang_input_statement_type *) file_chain.head;
+       f != (lang_input_statement_type *) NULL;
+       f = (lang_input_statement_type *) f->next)
     {
-      func(f);
+      func (f);
     }
 }
 
+#if 0
+
+/* Not used.  */
 
 void
-lang_for_each_input_section(func)
-void (*func)();
+lang_for_each_input_section (func)
+     void (*func) PARAMS ((bfd * ab, asection * as));
 {
   lang_input_statement_type *f;
-  for (f = (lang_input_statement_type *)file_chain.head; 
-       f != (lang_input_statement_type *)NULL;
-       f = (lang_input_statement_type *)f->next)  
+
+  for (f = (lang_input_statement_type *) file_chain.head;
+       f != (lang_input_statement_type *) NULL;
+       f = (lang_input_statement_type *) f->next)
     {
       asection *s;
+
       for (s = f->the_bfd->sections;
-          s != (asection *)NULL;
-          s = s->next) {
-       func(f->the_bfd, s);
-      }
+          s != (asection *) NULL;
+          s = s->next)
+       {
+         func (f->the_bfd, s);
+       }
     }
 }
 
+#endif
 
-
-void 
-ldlang_add_file(entry)
-lang_input_statement_type *entry;
+void
+ldlang_add_file (entry)
+     lang_input_statement_type * entry;
 {
-  lang_has_input_file = true;
-  lang_statement_append(&file_chain,
-                       (lang_statement_union_type *)entry,
-                       &entry->next);
-}
+  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)
-char *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;
+{
+  unsigned  int i = 1;
+  int l;
+  if (x < 0) return -1;
+  for (l = 0; l < 32; l++) 
+  {
+    if (i >= x) return l;
+    i<<=1;
+  }
+  return 0;
+}
 void
-lang_enter_output_section_statement(output_section_statement_name,
-address_exp,
-block_value)
-char *output_section_statement_name;
-etree_type *address_exp;
-bfd_vma block_value;
+lang_enter_output_section_statement (output_section_statement_name,
+                                    address_exp, flags, block_value,
+                                    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 *ebase;
 {
   lang_output_section_statement_type *os;
-  current_section = 
-    os =
-      lang_output_section_statement_lookup(output_section_statement_name);
+
+  current_section =
+   os =
+    lang_output_section_statement_lookup (output_section_statement_name);
+
 
 
   /* Add this statement to tree */
@@ -1989,179 +2382,326 @@ bfd_vma block_value;
   /* Make next things chain into subchain of this */
 
   if (os->addr_tree ==
-      (etree_type *)NULL) {
+      (etree_type *) NULL)
+  {
     os->addr_tree =
-      address_exp;
+     address_exp;
   }
-  os->block_value = block_value;
-  stat_ptr = & os->children;
+  os->flags = flags;
+  if (flags & SEC_NEVER_LOAD)
+   os->loadable = 0;
+  else
+   os->loadable = 1;
+  os->block_value = block_value ? block_value : 1;
+  stat_ptr = &os->children;
+
+  os->subsection_alignment = topower(
+   exp_get_value_int(subalign, -1,
+                    "subsection alignment",
+                    0));
+  os->section_alignment = topower(
+   exp_get_value_int(align, -1,
+                    "section alignment", 0));
 
+  os->load_base = ebase;
 }
 
 
-void 
-lang_final()
+void
+lang_final ()
 {
-  if (had_output_filename == false) {
-    lang_add_output("a.out");
-  }
+  lang_output_statement_type *new =
+    new_stat (lang_output_statement, stat_ptr);
+
+  new->name = output_filename;
+}
 
+/* Reset the current counters in the regions */
+static void
+reset_memory_regions ()
+{
+  lang_memory_region_type *p = lang_memory_region_list;
 
+  for (p = lang_memory_region_list;
+       p != (lang_memory_region_type *) NULL;
+       p = p->next)
+    {
+      p->old_length = (bfd_size_type) (p->current - p->origin);
+      p->current = p->origin;
+    }
 }
 
+void
+lang_process ()
+{
+  lang_reasonable_defaults ();
+  current_target = default_target;
 
+  lang_for_each_statement (ldlang_open_output);        /* Open the output file */
+  /* For each output section statement, create a section in the output
+     file */
+  lang_create_output_section_statements ();
 
+  ldemul_create_output_section_statements ();
 
+  /* Add to the hash table all undefineds on the command line */
+  lang_place_undefineds ();
 
-asymbol *create_symbol(name, flags, section)
-char *name;
-flagword flags;
-asection *section;
-{
-  extern lang_input_statement_type *script_file;
-  asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **));
-  /* Add this definition to script file */
-  asymbol *def =  (asymbol  *)bfd_make_empty_symbol(script_file->the_bfd);
-  def->name = name;
-  def->udata = 0;
-  def->flags = flags;
-  def->section = section;
+  /* Create a bfd for each input file */
+  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
+     */
+  map_input_to_output_sections (statement_list.head, (char *) NULL,
+                               (lang_output_section_statement_type *) NULL);
+
+
+  /* Find any sections not attatched explicitly and handle them */
+  lang_place_orphans ();
+
+  /* Size up the common data */
+  lang_common ();
+
+  ldemul_before_allocation ();
+
+
+#if 0
+  had_relax = true;
+  while (had_relax)
+    {
+
+      had_relax = false;
+
+      lang_size_sections (statement_list.head,
+                         (lang_output_section_statement_type *) NULL,
+                         &(statement_list.head), 0, (bfd_vma) 0, true);
+      /* FIXME. Until the code in relax is fixed so that it only reads in
+         stuff once, we cant iterate since there is no way for the linker to
+         know what has been patched and what hasn't */
+      break;
+
+    }
+#endif
+
+  /* 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.  */
+      lang_size_sections (statement_list.head,
+                         (lang_output_section_statement_type *) NULL,
+                         &(statement_list.head), 0, (bfd_vma) 0, false);
+
+
+      reset_memory_regions ();
+
+      /* 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.  */
+      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.  */
+      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.  */
+  ldemul_after_allocation ();
+
+  /* Do all the assignments, now that we know the final restingplaces
+     of all the symbols */
+
+  lang_do_assignments (statement_list.head,
+                      abs_output_section,
+                      (fill_type) 0, (bfd_vma) 0);
+
+  /* Make sure that we're not mixing architectures */
+
+  lang_check ();
+
+  /* Final stuffs */
 
-  *def_ptr = def;
-  Q_enter_global_ref(def_ptr);
-  return def;
+  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 ();
 }
 
+/* EXPORTED TO YACC */
 
 void
-lang_process()
+lang_add_wild (section_name, filename)
+     CONST char *CONST section_name;
+     CONST char *CONST filename;
 {
-  lang();
-  lang_phase_2();
-}
+  lang_wild_statement_type *new = new_stat (lang_wild_statement,
+                                           stat_ptr);
 
+  if (section_name != (char *) NULL && strcmp (section_name, "COMMON") == 0)
+    {
+      placed_commons = true;
+    }
+  if (filename != (char *) NULL)
+    {
+      lang_has_input_file = true;
+    }
+  new->section_name = section_name;
+  new->filename = filename;
+  lang_list_init (&new->children);
+}
 
-/* EXPORTED TO YACC */
 void
-lang_section_start(name, address)
-char *name;
-etree_type *address;
+lang_section_start (name, address)
+     CONST char *name;
+     etree_type * address;
 {
-  lang_address_statement_type *ad =new_stat(lang_address_statement, stat_ptr);
+  lang_address_statement_type *ad = new_stat (lang_address_statement, stat_ptr);
+
   ad->section_name = name;
   ad->address = address;
 }
-void lang_add_entry(name)
-char *name;
+
+void
+lang_add_entry (name)
+     CONST char *name;
 {
   entry_symbol = name;
 }
 
 void
-lang_add_target(name)
-char *name;
+lang_add_target (name)
+     CONST char *name;
 {
-  lang_target_statement_type *new = new_stat(lang_target_statement,
-                                           stat_ptr);
+  lang_target_statement_type *new = new_stat (lang_target_statement,
+                                             stat_ptr);
+
   new->target = name;
 
 }
+
 void
-lang_add_wild(section_name, filename)
-char *section_name;
-char *filename;
+lang_add_map (name)
+     CONST char *name;
 {
-  lang_wild_statement_type *new = new_stat(lang_wild_statement,
-                                          stat_ptr);
-
-  if (section_name != (char *)NULL && strcmp(section_name,"COMMON") == 0)
+  while (*name)
     {
-      placed_commons = true;
+      switch (*name)
+       {
+         case 'F':
+         map_option_f = true;
+         break;
+       }
+      name++;
     }
-  new->section_name = section_name;
-  new->filename = filename;
-  lang_list_init(&new->children);
 }
 
 void
-lang_add_map(name)
-char *name;
+lang_add_fill (exp)
+     int exp;
 {
-  while (*name) {
-    switch (*name) {
-    case 'F':
-      map_option_f = true;
-      break;
-    }
-    name++;
-  }
-}
+  lang_fill_statement_type *new = new_stat (lang_fill_statement,
+                                           stat_ptr);
 
-void lang_add_fill(exp)
-int exp;
-{
-  lang_fill_statement_type *new =   new_stat(lang_fill_statement, 
-                                             stat_ptr);
   new->fill = exp;
 }
 
-void lang_add_data(type, exp)
-int type;
-union etree_union *exp;
+void
+lang_add_data (type, exp)
+     int type;
+     union etree_union *exp;
 {
 
lang_data_statement_type *new = new_stat(lang_data_statement,
 lang_data_statement_type *new = new_stat (lang_data_statement,
                                            stat_ptr);
- new->exp = exp;
- new->type = type;
+
+  new->exp = exp;
+  new->type = type;
 
 }
+
 void
-lang_add_assignment(exp)
-etree_type *exp;
+lang_add_assignment (exp)
+     etree_type * exp;
 {
-  lang_assignment_statement_type *new = new_stat(lang_assignment_statement,
-                                           stat_ptr);
+  lang_assignment_statement_type *new = new_stat (lang_assignment_statement,
+                                                 stat_ptr);
+
   new->exp = exp;
 }
 
 void
-lang_add_attribute(attribute)
-enum statement_enum attribute;
+lang_add_attribute (attribute)
+     enum statement_enum attribute;
 {
-  new_statement(attribute, sizeof(lang_statement_union_type),stat_ptr);
+  new_statement (attribute, sizeof (lang_statement_union_type), stat_ptr);
 }
 
-
-
-void 
-lang_startup(name)
-char *name;
+void
+lang_startup (name)
+     CONST char *name;
 {
-  if (startup_file != (char *)NULL) {
-   info("%P%FMultiple STARTUP files\n");
-  }
+  if (startup_file != (char *) NULL)
+    {
+      einfo ("%P%Fmultiple STARTUP files\n");
+    }
   first_file->filename = name;
   first_file->local_sym_name = name;
 
-  startup_file= name;
+  startup_file = name;
 }
-void 
-lang_float(maybe)
-boolean maybe;
+
+void
+lang_float (maybe)
+     boolean maybe;
 {
   lang_float_flag = maybe;
 }
 
-void 
-lang_leave_output_section_statement(fill, memspec)
-bfd_vma fill;
-char *memspec;
+void
+lang_leave_output_section_statement (fill, memspec)
+     bfd_vma fill;
+     CONST char *memspec;
 {
   current_section->fill = fill;
-  current_section->region = lang_memory_region_lookup(memspec);
+  current_section->region = lang_memory_region_lookup (memspec);
   stat_ptr = &statement_list;
+
+  /* We remember if we are closing a .data section, since we use it to
+     store constructors in */
+  if (strcmp (current_section->name, ".data") == 0)
+    {
+      end_of_data_section_statement_list = statement_list;
+
+    }
 }
+
 /*
  Create an absolute symbol with the given name with the value of the
  address of first byte of the section named.
@@ -2169,25 +2709,31 @@ char *memspec;
  If the symbol already exists, then do nothing.
 */
 void
-lang_abs_symbol_at_beginning_of(section, name)
-char *section;
-char *name;
-{
-  if (ldsym_undefined(name)) {
-    extern bfd *output_bfd;
-    extern asymbol *create_symbol();
-    asection *s = bfd_get_section_by_name(output_bfd, section);
-    asymbol *def = create_symbol(name,
-                                BSF_GLOBAL | BSF_EXPORT |
-                                BSF_ABSOLUTE,
-                                (asection *)NULL);
-    if (s != (asection *)NULL) {
-      def->value = s->vma;
-    }
-    else {
-      def->value = 0;
+lang_abs_symbol_at_beginning_of (secname, name)
+     const char *secname;
+     const char *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 *sec;
+
+      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
+       h->u.def.value = bfd_get_section_vma (output_bfd, sec);
+
+      h->u.def.section = &bfd_abs_section;
     }
-  }
 }
 
 /*
@@ -2197,82 +2743,50 @@ char *name;
  If the symbol already exists, then do nothing.
 */
 void
-lang_abs_symbol_at_end_of(section, name)
-char *section;
-char *name;
-{
-  if (ldsym_undefined(name)){
-    extern bfd *output_bfd;
-    extern asymbol *create_symbol();
-    asection *s = bfd_get_section_by_name(output_bfd, section);
-    /* Add a symbol called _end */
-    asymbol *def = create_symbol(name,
-                                BSF_GLOBAL | BSF_EXPORT |
-                                BSF_ABSOLUTE,
-                                (asection *)NULL);
-    if (s != (asection *)NULL) {
-      def->value = s->vma + s->size;
-    }
-    else {
-      def->value = 0;
-    }
-  }
-}
-
-void 
-lang_statement_append(list, element, field)
-lang_statement_list_type *list;
-lang_statement_union_type *element;
-lang_statement_union_type **field;
+lang_abs_symbol_at_end_of (secname, name)
+     const char *secname;
+     const char *name;
 {
-  *(list->tail) = element;
-  list->tail = field;
-}
+  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");
 
-static void 
-lang_for_each_statement_worker(func,  s)
-void (*func)();
-lang_statement_union_type *s;
-{
-  for (; s != (lang_statement_union_type *)NULL ; s = s->next) 
+  if (h->type == bfd_link_hash_new
+      || h->type == bfd_link_hash_undefined)
     {
-      func(s);
+      asection *sec;
 
-      switch (s->header.type) {
-      case lang_output_section_statement_enum:
-       lang_for_each_statement_worker
-         (func, 
-          s->output_section_statement.children.head);
-       break;
-      case lang_wild_statement_enum:
-       lang_for_each_statement_worker
-         (func, 
-          s->wild_statement.children.head);
-       break;
-      case lang_data_statement_enum:
-      case lang_object_symbols_statement_enum:
-      case lang_output_statement_enum:
-      case lang_target_statement_enum:
-      case lang_common_statement_enum:
-      case lang_input_section_enum:
-      case lang_input_statement_enum:
-      case lang_fill_statement_enum:
-      case lang_assignment_statement_enum:
-      case lang_padding_statement_enum:
-      case lang_address_statement_enum:
-       break;
-      default:
-       FAIL();
-       break;
-      }
+      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
+       h->u.def.value = (bfd_get_section_vma (output_bfd, sec)
+                         + bfd_section_size (output_bfd, sec));
+
+      h->u.def.section = &bfd_abs_section;
     }
 }
 
-void lang_for_each_statement(func)
-void (*func)();
+void
+lang_statement_append (list, element, field)
+     lang_statement_list_type * list;
+     lang_statement_union_type * element;
+     lang_statement_union_type ** field;
 {
-  lang_for_each_statement_worker(func,
-                                statement_list.head);
+  *(list->tail) = element;
+  list->tail = field;
+}
 
+/* Set the output format type.  -oformat overrides scripts.  */
+void
+lang_add_output_format (format, from_script)
+     CONST char *format;
+     int from_script;
+{
+  if (output_target == NULL || !from_script)
+    output_target = format;
 }
This page took 0.065204 seconds and 4 git commands to generate.