Replace MINUS_G by CFLAGS.
[deliverable/binutils-gdb.git] / ld / ldlang.c
index b124ac76dc72107c3aa716ea4a8e9c41a4eee732..191dd484814de38f0fe0623996d186daef6c80e3 100644 (file)
@@ -20,21 +20,21 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  *
 */
 
-
-
-#include "sysdep.h" 
 #include "bfd.h"
+#include "sysdep.h" 
 
 #include "ld.h"
 #include "ldmain.h"
 #include "ldsym.h"
-#include "ldgram.tab.h"
-#include "ldmisc.h"
+#include "ldgram.h"
+#include "ldwarn.h"
 #include "ldlang.h"
 #include "ldexp.h"
-#include "ld-emul.h"
+#include "ldemul.h"
 #include "ldlex.h"
-
+#include "ldmisc.h"
+#include "ldindr.h"
+#include "ldctor.h"
 /* FORWARDS */
 PROTO(static void, print_statements,(void));
 PROTO(static void, print_statement,(lang_statement_union_type *,
@@ -44,6 +44,14 @@ PROTO(static void, print_statement,(lang_statement_union_type *,
 /* LOCALS */
 static CONST  char *startup_file;
 static lang_statement_list_type input_file_chain;
+
+/* 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;
+
+/* List of statements needed to handle constructors */
+extern lang_statement_list_type constructor_list;
+
 static boolean placed_commons = false;
 static lang_output_section_statement_type *default_common_section;
 static boolean map_option_f;
@@ -56,14 +64,16 @@ static size_t longest_section_name = 8;
 static asection common_section;
 static section_userdata_type common_section_userdata;
 static lang_statement_list_type statement_list;
-/* EXPORTS */
 
+/* EXPORTS */
+boolean relaxing;
+lang_output_section_statement_type *abs_output_section;
 lang_statement_list_type *stat_ptr = &statement_list;
 lang_input_statement_type *script_file = 0;
 boolean option_longmap = false;
 lang_statement_list_type file_chain = {0};
 CONST char *entry_symbol = 0;
-size_t largest_section = 0;
+bfd_size_type largest_section = 0;
 boolean lang_has_input_file = false;
 lang_output_section_statement_type *create_object_symbols = 0;
 boolean had_output_filename = false;
@@ -97,7 +107,34 @@ extern boolean write_map;
 
 #define outside_symbol_address(q) ((q)->value +   outside_section_address(q->section))
 
+void EXFUN(lang_add_data,( int type ,   union etree_union *exp));
+
+static void 
+DEFUN(print_size,(value),
+      size_t value)
+{
+  fprintf(config.map_file, "%5x", (unsigned)value);
+}
+static void 
+DEFUN(print_alignment,(value),
+      unsigned int value)
+{
+  fprintf(config.map_file, "2**%1u",value);
+}
+static void 
+DEFUN(print_fill,(value),
+      fill_type value)
+{
+  fprintf(config.map_file, "%04x",(unsigned)value);
+}
+
 
+static void 
+DEFUN(print_section,(name),
+      CONST char *CONST name)
+{
+  fprintf(config.map_file, "%*s", -longest_section_name, name);
+}
 
 /*----------------------------------------------------------------------
   lang_for_each_statement walks the parse tree and calls the provided
@@ -114,6 +151,9 @@ DEFUN(lang_for_each_statement_worker,(func,  s),
        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, 
@@ -150,7 +190,7 @@ DEFUN(lang_for_each_statement,(func),
                                 statement_list.head);
 }
 /*----------------------------------------------------------------------*/
-static void 
+void 
 DEFUN(lang_list_init,(list),
       lang_statement_list_type *list)
 {
@@ -158,51 +198,6 @@ list->head = (lang_statement_union_type *)NULL;
 list->tail = &list->head;
 }
 
-/*----------------------------------------------------------------------
-  Functions to print the link map 
- */
-
-static void 
-DEFUN(print_section,(name),
-      CONST char *CONST name)
-{
-  printf("%*s", -longest_section_name, name);
-}
-static void 
-DEFUN_VOID(print_space)
-{
-  printf(" ");
-}
-static void 
-DEFUN_VOID(print_nl)
-{
-  printf("\n");
-}
-static void 
-DEFUN(print_address,(value),
-      bfd_vma value)
-{
-  printf("%8lx", value);
-}
-static void 
-DEFUN(print_size,(value),
-      size_t value)
-{
-  printf("%5x", (unsigned)value);
-}
-static void 
-DEFUN(print_alignment,(value),
-      unsigned int value)
-{
-  printf("2**%2u",value);
-}
-
-static void 
-DEFUN(print_fill,(value),
-      fill_type value)
-{
-  printf("%04x",(unsigned)value);
-}
 
 /*----------------------------------------------------------------------
   
@@ -214,7 +209,7 @@ static
 lang_statement_union_type*
 DEFUN(new_statement,(type, size, list),
       enum statement_enum type AND
-      size_t size AND
+      bfd_size_type size AND
       lang_statement_list_type *list)
 {
   lang_statement_union_type *new = (lang_statement_union_type *)
@@ -307,9 +302,9 @@ DEFUN(new_afile, (name, file_type, target),
 
 lang_input_statement_type *
 DEFUN(lang_add_input_file,(name, file_type, target),
-      char *name AND
+     CONST char *name AND
       lang_input_file_enum_type file_type AND
-      char *target)
+     CONST char *target)
 {
   /* Look it up or build a new one */
   lang_has_input_file = true;
@@ -345,6 +340,10 @@ DEFUN_VOID(lang_init)
   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);
+
+abs_output_section->bfd_section = &bfd_abs_section;
+
 }
 
 
@@ -383,7 +382,7 @@ DEFUN(lang_memory_region_lookup,(name),
   }
     {
       lang_memory_region_type *new =
-       (lang_memory_region_type *)ldmalloc(sizeof(lang_memory_region_type));
+       (lang_memory_region_type *)ldmalloc((bfd_size_type)(sizeof(lang_memory_region_type)));
       new->name = buystring(name);
       new->next = (lang_memory_region_type *)NULL;
 
@@ -392,6 +391,8 @@ DEFUN(lang_memory_region_lookup,(name),
       new->origin = 0;
       new->length = ~0;
       new->current = 0;
+      new->had_full_message = false;
+      
       return new;
     }
 }
@@ -447,43 +448,46 @@ DEFUN(lang_output_section_statement_lookup,(name),
 
 
 
-
+/*ARGSUSED*/
 static void
-DEFUN(print_flags, (outfile, ignore_flags),
-      FILE *outfile AND
-      lang_section_flags_type *ignore_flags)
+DEFUN(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");
 #endif
-  fprintf(outfile,")");
+  fprintf(config.map_file, ")");
 }
 
 void
-DEFUN(lang_map,(outfile),
-      FILE *outfile)
+DEFUN_VOID(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\t\tattributes\n");
+#endif
   for (m = lang_memory_region_list;
        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(m->length);
+      print_space();
+      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();
 
@@ -496,17 +500,26 @@ static void
 DEFUN(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));
-
-  s->bfd_section = bfd_make_section(output_bfd, s->name);
+   (section_userdata_type *)
+    ldmalloc((bfd_size_type)(sizeof(section_userdata_type)));
+
+  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;
+
 }
 
 /***********************************************************************
@@ -674,12 +687,12 @@ DEFUN(open_output,(name),
   if (output == (bfd *)NULL) 
       {
        if (bfd_error == invalid_target) {
-         info("%P%F target %s not found\n", output_target);
+         einfo("%P%F target %s not found\n", output_target);
        }
-       info("%P%F problem opening output file %s, %E", name);
+       einfo("%P%F problem opening output file %s, %E", name);
       }
   
-  output->flags |= D_PAGED;
+/*  output->flags |= D_PAGED;*/
   bfd_set_format(output, bfd_object);
   return output;
 }
@@ -696,6 +709,14 @@ DEFUN(ldlang_open_output,(statement),
       case  lang_output_statement_enum:
        output_bfd = open_output(statement->output_statement.name);
        ldemul_set_output_arch();
+       if (config.magic_demand_paged && !config.relocateable_output)
+         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;
 
       case lang_target_statement_enum:
@@ -738,6 +759,9 @@ DEFUN(open_input_bfds,(statement),
 static void
 lang_reasonable_defaults()
 {
+
+
+  
 #if 0
       lang_output_section_statement_lookup(".text");
       lang_output_section_statement_lookup(".data");
@@ -762,8 +786,8 @@ lang_reasonable_defaults()
  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 {
-  struct ldlang_undef_chain_list_struct *next;
+typedef struct ldlang_undef_chain_list {
+  struct ldlang_undef_chain_list *next;
   char *name;
 } ldlang_undef_chain_list_type;
 
@@ -775,7 +799,7 @@ DEFUN(ldlang_add_undef,(name),
 {
   ldlang_undef_chain_list_type *new =
     (ldlang_undef_chain_list_type
-     *)ldmalloc(sizeof(ldlang_undef_chain_list_type));
+     *)ldmalloc((bfd_size_type)(sizeof(ldlang_undef_chain_list_type)));
 
   new->next = ldlang_undef_chain_list_head;
   ldlang_undef_chain_list_head = new;
@@ -793,12 +817,11 @@ DEFUN_VOID(lang_place_undefineds)
   while (ptr != (ldlang_undef_chain_list_type*)NULL) {
     ldsym_type *sy = ldsym_get(ptr->name);
     asymbol *def;
-    asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **));
+    asymbol **def_ptr = (asymbol **)ldmalloc((bfd_size_type)(sizeof(asymbol **)));
     def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd);
     *def_ptr= def;
     def->name = ptr->name;
-    def->flags = BSF_UNDEFINED;
-    def->section = (asection *)NULL;
+    def->section = &bfd_und_section;
     Q_enter_global_ref(def_ptr);
     ptr = ptr->next;
   }
@@ -833,6 +856,10 @@ DEFUN_VOID(lang_init_script_file)
   script_file->the_bfd = bfd_create("script file", output_bfd);
   script_file->symbol_count = 0;
   script_file->the_bfd->sections = output_bfd->sections;
+abs_output_section = lang_output_section_statement_lookup(BFD_ABS_SECTION_NAME);
+
+abs_output_section->bfd_section = &bfd_abs_section;
+
 }
 
 
@@ -848,13 +875,19 @@ DEFUN(map_input_to_output_sections,(s, target, 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,
@@ -882,6 +915,10 @@ DEFUN(map_input_to_output_sections,(s, target, output_section_statement),
            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 can't set the address of undefined section %s\n",
+                 s->address_statement.section_name);
+         }
        }
        break;
       case lang_input_statement_enum:
@@ -911,18 +948,26 @@ DEFUN(print_output_section_statement,(output_section_statement),
     print_space();
     print_address(section->vma);
     print_space();
-    print_size(section->size);
+    print_size(bfd_get_section_size_before_reloc(section));
     print_space();
     print_alignment(section->alignment_power);
     print_space();
 #if 0
-    printf("%s flags", output_section_statement->region->name);
+    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");
+    fprintf(config.map_file, "No attached output section");
   }
   print_nl();
   print_statement(output_section_statement->children.head,
@@ -953,11 +998,12 @@ DEFUN(print_assignment,(assignment, output_section),
   }
   else 
       {
-       printf("*undefined*");
+       fprintf(config.map_file, "*undefined*");
       }
   print_space();
-  exp_print_tree(stdout, assignment->exp);
-  printf("\n");
+  exp_print_tree(assignment->exp);
+  
+  fprintf(config.map_file, "\n");
 }
 
 static void
@@ -965,7 +1011,7 @@ DEFUN(print_input_statement,(statm),
       lang_input_statement_type *statm)
 {
   if (statm->filename != (char *)NULL) {
-    printf("LOAD %s\n",statm->filename);
+    fprintf(config.map_file, "LOAD %s\n",statm->filename);
   }
 }
 
@@ -974,11 +1020,11 @@ DEFUN(print_symbol,(q),
       asymbol *q)
 {
   print_section("");
-  printf(" ");
+  fprintf(config.map_file, " ");
   print_section("");
-  printf(" ");
+  fprintf(config.map_file, " ");
   print_address(outside_symbol_address(q));
-  printf("              %s", q->name ? q->name : " ");
+  fprintf(config.map_file, "              %s", q->name ? q->name : " ");
   print_nl();
 }
 
@@ -987,35 +1033,39 @@ DEFUN(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) {
+  if(size != 0) {
     print_section("");
-    printf(" ");
+    fprintf(config.map_file, " ");
     print_section(i->name);
-    printf(" ");
+    fprintf(config.map_file, " ");
     if (i->output_section) {
       print_address(i->output_section->vma + i->output_offset);
-      printf(" ");
-      print_size(i->size);
-      printf(" ");
+      fprintf(config.map_file, " ");
+      print_size(size);
+      fprintf(config.map_file, " ");
       print_alignment(i->alignment_power);
-      printf(" ");
+      fprintf(config.map_file, " ");
       if (in->ifile) {
 
        bfd *abfd = in->ifile->the_bfd;
        if (in->ifile->just_syms_flag == true) {
-         printf("symbols only ");
+         fprintf(config.map_file, "symbols only ");
        }
 
-       printf(" %s ",abfd->xvec->name);
+       fprintf(config.map_file, " %s ",abfd->xvec->name);
        if(abfd->my_archive != (bfd *)NULL) {
-         printf("[%s]%s", abfd->my_archive->filename,
+         fprintf(config.map_file, "[%s]%s", abfd->my_archive->filename,
                 abfd->filename);
        }
        else {
-         printf("%s", abfd->filename);
+         fprintf(config.map_file, "%s", abfd->filename);
        }
-       printf("(%d bytes)", bfd_alloc_size(abfd));
+       fprintf(config.map_file, "(overhead %d bytes)", (int)bfd_alloc_size(abfd));
        print_nl();
 
        /* Find all the symbols in this file defined in this section */
@@ -1035,10 +1085,10 @@ DEFUN(print_input_section,(in),
       }
 
 
-      print_dot = outside_section_address(i) + i->size;
+      print_dot = outside_section_address(i) + size;
     }
     else {
-      printf("No output section allocated\n");
+      fprintf(config.map_file, "No output section allocated\n");
     }
   }
 }
@@ -1047,7 +1097,7 @@ static void
 DEFUN(print_fill_statement,(fill),
       lang_fill_statement_type *fill)
 {
-  printf("FILL mask ");
+  fprintf(config.map_file, "FILL mask ");
   print_fill( fill->fill);
 }
 
@@ -1060,30 +1110,30 @@ DEFUN(print_data_statement,(data),
   print_space();
   print_section("");
   print_space();
-  ASSERT(print_dot == data->output_vma);
+/*  ASSERT(print_dot == data->output_vma);*/
 
-  print_address(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 :
-    printf("BYTE ");
+    fprintf(config.map_file, "BYTE ");
     print_dot += BYTE_SIZE;
     break;
   case SHORT:
-    printf("SHORT ");
+    fprintf(config.map_file, "SHORT ");
     print_dot += SHORT_SIZE;
     break;  
   case LONG:
-    printf("LONG ");
+    fprintf(config.map_file, "LONG ");
     print_dot += LONG_SIZE;
     break;
   }
 
-  exp_print_tree(stdout, data->exp);
+  exp_print_tree(data->exp);
   
-  printf("\n");
+  fprintf(config.map_file, "\n");
 }
 
 
@@ -1101,6 +1151,9 @@ DEFUN(print_padding_statement,(s),
   print_space();
   print_fill(s->fill);
   print_nl();
+
+  print_dot = s->output_offset + s->output_section->vma + s->size;
+
 }
 
 static void 
@@ -1108,17 +1161,18 @@ DEFUN(print_wild_statement,(w,os),
       lang_wild_statement_type *w AND
       lang_output_section_statement_type *os)
 {
+  fprintf(config.map_file, " from ");
   if (w->filename != (char *)NULL) {
-    printf("%s",w->filename);
+    fprintf(config.map_file, "%s",w->filename);
   }
   else {
-    printf("*");
+    fprintf(config.map_file, "*");
   }
   if (w->section_name != (char *)NULL) {
-    printf("(%s)",w->section_name);
+    fprintf(config.map_file, "(%s)",w->section_name);
   }
   else {
-    printf("(*)");
+    fprintf(config.map_file, "(*)");
   }
   print_nl();
   print_statement(w->children.head, os);
@@ -1129,60 +1183,64 @@ DEFUN(print_statement,(s, os),
       lang_statement_union_type *s AND
       lang_output_section_statement_type *os)
 {
-  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;
-      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;
-    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:
-      printf("TARGET(%s)\n", s->target_statement.target);
-      break;
-    case lang_output_statement_enum:
-      printf("OUTPUT(%s %s)\n",
-            s->output_statement.name,
-            output_target);
-      break;
-    case lang_input_statement_enum:
-      print_input_statement(&s->input_statement);
-      break;
-    case lang_afile_asection_pair_statement_enum:
-      FAIL();
-      break;
+    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;
+           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);
+           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;
-  }
 }
 
 
@@ -1190,7 +1248,8 @@ static void
 DEFUN_VOID(print_statements)
 {
   print_statement(statement_list.head,
-                 (lang_output_section_statement_type *)NULL);
+                 abs_output_section);
+  
 }
 
 static bfd_vma
@@ -1215,7 +1274,7 @@ DEFUN(insert_pad,(this_ptr, fill, power, output_section_statement, dot),
     {
       lang_statement_union_type *new = 
        (lang_statement_union_type *)
-         ldmalloc(sizeof(lang_padding_statement_type));
+         ldmalloc((bfd_size_type)(sizeof(lang_padding_statement_type)));
       /* Link into existing chain */
       new->header.next = *this_ptr;
       *this_ptr = new;
@@ -1232,7 +1291,7 @@ DEFUN(insert_pad,(this_ptr, fill, power, output_section_statement, dot),
   if (power > output_section_statement->alignment_power) {
     output_section_statement->alignment_power = power;
   }
-  output_section_statement->size += alignment_needed;
+  output_section_statement->_raw_size += alignment_needed;
   return alignment_needed + dot;
 
 }
@@ -1252,10 +1311,13 @@ DEFUN(size_input_section, (this_ptr, output_section_statement, fill,  dot),
     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 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 | SEC_LOAD)) == (SEC_HAS_CONTENTS | SEC_LOAD))
+       && (bfd_get_section_size_before_reloc(i) > largest_section)) {
+      largest_section = bfd_get_section_size_before_reloc(i);
     }
 
     /* Remember where in the output section this input section goes */
@@ -1263,8 +1325,8 @@ DEFUN(size_input_section, (this_ptr, output_section_statement, fill,  dot),
     i->output_offset = dot - output_section_statement->bfd_section->vma;
 
     /* Mark how big the output section must be to contain this now */
-    dot += i->size;
-    output_section_statement->bfd_section->size =
+    dot += bfd_get_section_size_before_reloc(i);
+output_section_statement->bfd_section->_raw_size =
       dot - output_section_statement->bfd_section->vma;
   }
   else
@@ -1276,172 +1338,222 @@ DEFUN(size_input_section, (this_ptr, output_section_statement, fill,  dot),
 }
 
 
-/* Work out the size of the output sections 
- from the sizes of the input sections */
+/* 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;
+
 static bfd_vma
-DEFUN(lang_size_sections,(s, output_section_statement, prev, fill, dot),
+DEFUN(lang_size_sections,(s, output_section_statement, prev, fill,
+                         dot, relax),
       lang_statement_union_type *s AND
       lang_output_section_statement_type * output_section_statement AND
       lang_statement_union_type **prev AND
       unsigned short fill AND
-      bfd_vma dot)
+      bfd_vma dot AND
+      boolean relax)
 {
   /* Size up the sections from their constituent parts */
   for (; s != (lang_statement_union_type *)NULL ; s = s->next) 
-      {
-       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 */
+  {
+    switch (s->header.type) {
          
-             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,
-                                 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 */
+      case lang_output_section_statement_enum:
+      {
+       bfd_vma after;
+       lang_output_section_statement_type *os =&(s->output_section_statement);
 
-             dot = align_power(dot, os->bfd_section->alignment_power);
-             os->bfd_section->vma = dot;
-             os->bfd_section->output_offset = 0;
+       if (os->bfd_section == &bfd_abs_section)
+       {
+         /* No matter what happens, an abs section starts at zero */
+         os->bfd_section->vma = 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) 
+           {
+             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 */
 
-             (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 */
 
+         dot = align_power(dot, os->bfd_section->alignment_power);
+         os->bfd_section->vma = dot;
+       }
+       
+       
+       os->bfd_section->output_offset = 0;
 
-             after = ALIGN(os->bfd_section->vma +
-                           os->bfd_section->size,
-                           os->block_value) ;
+       (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 */
 
 
-             os->bfd_section->size = after - os->bfd_section->vma;
-             dot = os->bfd_section->vma + os->bfd_section->size;
-             os->processed = true;
+       after = ALIGN(os->bfd_section->vma +
+                     os->bfd_section->_raw_size,
+                     os->block_value) ;
 
-             /* Replace into region ? */
-             if (os->addr_tree == (etree_type *)NULL 
-                 && os->region !=(lang_memory_region_type*)NULL ) {
-               os->region->current = dot;
-             }
-           }
 
-         break;
+       os->bfd_section->_raw_size = after - os->bfd_section->vma;
+       dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+       os->processed = true;
 
-       case lang_data_statement_enum: 
+       /* 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) 
            {
-             unsigned int size;
-             s->data_statement.output_vma = dot;
-             s->data_statement.output_section =
-               output_section_statement->bfd_section;
-
-             switch (s->data_statement.type) {
-             case LONG:
-               size = LONG_SIZE;
-               break;
-             case SHORT:
-               size = SHORT_SIZE;
-               break;
-             case BYTE:
-               size = BYTE_SIZE;
-               break;
+             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;
 
-             }
-             dot += size;
-             output_section_statement->bfd_section->size += size;
            }
-         break;
+               
+         }
+      }
 
-       case lang_wild_statement_enum:
+       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;
+                                     
+      case lang_data_statement_enum: 
+      {
+       unsigned int size = 0;
+       s->data_statement.output_vma = dot - output_section_statement->bfd_section->vma;
+       s->data_statement.output_section =
+        output_section_statement->bfd_section;
 
-         dot = lang_size_sections(s->wild_statement.children.head,
+       switch (s->data_statement.type) {
+         case LONG:
+           size = LONG_SIZE;
+           break;
+         case SHORT:
+           size = SHORT_SIZE;
+           break;
+         case BYTE:
+           size = BYTE_SIZE;
+           break;
+
+         }
+       dot += size;
+       output_section_statement->bfd_section->_raw_size += size;
+      }
+       break;
+
+      case lang_wild_statement_enum:
+
+       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_target_statement_enum:
-         break;
-       case lang_input_section_enum:
-         dot = size_input_section(prev,
+      case lang_object_symbols_statement_enum:
+       create_object_symbols = output_section_statement;
+       break;
+      case lang_output_statement_enum:
+      case lang_target_statement_enum:
+       break;
+      case lang_input_section_enum:
+       if (relax)
+       {
+         relaxing = true;
+  
+
+         had_relax |=  relax_section(prev);
+         relaxing = false;
+  
+       }
+
+       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;
-                 }
-           }
-
-         break;
-       case lang_padding_statement_enum:
-         FAIL();
-         break;
-       default:
-         FAIL();
-         break;
-       case lang_address_statement_enum:
-         break;
+       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 && !relax) 
+        /* We've been moved ! so insert a pad */
+       {
+         lang_statement_union_type *new = 
+          (lang_statement_union_type *)
+           ldmalloc((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;
        }
-       prev = &s->header.next;      
       }
+
+       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;
 }
 
@@ -1457,13 +1569,20 @@ DEFUN(lang_do_assignments,(s, output_section_statement, fill, dot),
   for (; s != (lang_statement_union_type *)NULL ; s = s->next) 
     {
       switch (s->header.type) {
+      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;
+         dot = os->bfd_section->vma + os->bfd_section->_raw_size;
        }
        break;
       case lang_wild_statement_enum:
@@ -1485,9 +1604,10 @@ DEFUN(lang_do_assignments,(s, output_section_statement, fill, dot),
        {
          etree_value_type value ;
          value =   exp_fold_tree(s->data_statement.exp,
-                                 0, lang_final_phase_enum, dot, &dot);
+                                 abs_output_section,
+                                 lang_final_phase_enum, dot, &dot);
          s->data_statement.value = value.value;
-         if (value.valid == false) info("%F%P: Invalid data statement\n");
+         if (value.valid == false) einfo("%F%P: Invalid data statement\n");
        }
        switch (s->data_statement.type) {
        case LONG:
@@ -1504,7 +1624,7 @@ DEFUN(lang_do_assignments,(s, output_section_statement, fill, dot),
       case lang_input_section_enum:
        {
          asection *in =    s->input_section.section;
-         dot += in->size;
+         dot += bfd_get_section_size_before_reloc(in);
        }
        break;
 
@@ -1569,7 +1689,11 @@ DEFUN_VOID(lang_relocate_globals)
     }
     if (it != (asymbol *)NULL)
        {
-         asymbol **ptr= lgs->srefs_chain;
+         asymbol **ptr = lgs->srefs_chain;;
+         if (lgs->flags & SYM_WARNING) 
+             {
+               produce_warnings(lgs, it);
+             }
 
          while (ptr != (asymbol **)NULL) {
            asymbol *ref = *ptr;
@@ -1617,60 +1741,71 @@ DEFUN_VOID(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) 
       {
-       /* 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);
+       unsigned long ldfile_new_output_machine = 0;
+       enum bfd_architecture ldfile_new_output_architecture = bfd_arch_unknown;
 
+       input_bfd = file->input_statement.the_bfd;
+
+       input_machine = bfd_get_mach(input_bfd);
+       input_architecture = bfd_get_arch(input_bfd);  
+
+       /* 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
+           {
+
+             info("%P: warning, %s architecture of input file `%B' incompatible with %s output\n",
+                  bfd_printable_name(input_bfd), input_bfd,
+                  bfd_printable_name(output_bfd));
+
+             bfd_set_arch_mach(output_bfd,
+                               ldfile_new_output_architecture,
+                               ldfile_new_output_machine);
+           }
 
-       }
       }
 }
 
 
 /*
  * run through all the global common symbols and tie them 
- * to the output section requested.
- */
+ * to the output section requested. 
+ *
+ As an experiment we do this 4 times, once for all the byte sizes,
+ then all the two  bytes, all the four bytes and then everything else
+  */
 
 static void
 DEFUN_VOID(lang_common)
 {
   ldsym_type *lgs;
+  size_t power;
   if (config.relocateable_output == false ||
       command_line.force_common_definition== true) {
-    for (lgs = symbol_head;
-        lgs != (ldsym_type *)NULL;
-        lgs=lgs->next)
+    for (power = 1; (config.sort_common == true && power == 1) || (power <= 16); power <<=1) {
+      for (lgs = symbol_head;
+          lgs != (ldsym_type *)NULL;
+          lgs=lgs->next)
        {
          asymbol *com ;
          unsigned  int power_of_two;
@@ -1706,44 +1841,48 @@ DEFUN_VOID(lang_common)
              align = 16;
              break;
            }
+           if (config.sort_common == false || align == power) {
+             /* 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 */
+
+              com->section->_raw_size =
+               ALIGN(com->section->_raw_size, align);
+
+             /* Remember if this is the biggest alignment ever seen */
+             if (power_of_two > com->section->alignment_power) {
+               com->section->alignment_power = power_of_two;
+             }
 
+             /* Symbol stops being common and starts being global, but
+                we remember that it was common once. */
 
-           /* 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 */
-           com->section->size = ALIGN(com->section->size, align);
-
-           /* Remember if this is the biggest alignment ever seen */
-           if (power_of_two > com->section->alignment_power) {
-             com->section->alignment_power = power_of_two;
-           }
-
-           /* Symbol stops being common and starts being global, but
-              we remember that it was common once. */
-
-           com->flags = BSF_EXPORT | BSF_GLOBAL | BSF_OLD_COMMON;
-
+             com->flags = BSF_EXPORT | BSF_GLOBAL | BSF_OLD_COMMON;
+             com->value = com->section->_raw_size;
 
-           if (write_map) 
+             if (write_map) 
                {
-                 printf ("Allocating common %s: %x at %x\n",
+                 fprintf (config.map_file, "Allocating common %s: %x at %x %s\n",
                          lgs->name, 
                          (unsigned) size,
-                         (unsigned)  com->section->size);
+                         (unsigned) com->value,
+                         com->the_bfd->filename);
                }
-           com->value = com->section->size;
-           com->section->size += size;
 
+             com->section->_raw_size += size;
 
+           }
          }
+
        }
+    }
   }
 
 
@@ -1803,14 +1942,11 @@ DEFUN_VOID(lang_place_orphans)
 
 void
 DEFUN(lang_set_flags,(ptr, flags),
-      lang_section_flags_type *ptr AND
+      int  *ptr AND
       CONST char *flags)
 {
   boolean state = true;
-  ptr->flag_read = false;
-  ptr->flag_write = false;
-  ptr->flag_executable = false;
-  ptr->flag_loadable= false;
+*ptr= 0;
   while (*flags)
       {
        if (*flags == '!') {
@@ -1820,19 +1956,20 @@ DEFUN(lang_set_flags,(ptr, flags),
        else state = true;
        switch (*flags) {
        case 'R':
-         ptr->flag_read = state; 
+/*       ptr->flag_read = state; */
          break;
        case 'W':
-         ptr->flag_write = state; 
+/*       ptr->flag_write = state; */
          break;
        case 'X':
-         ptr->flag_executable= state;
+/*       ptr->flag_executable= state;*/
          break;
        case 'L':
-         ptr->flag_loadable= state;
+       case 'I':
+/*       ptr->flag_loadable= state;*/
          break;
        default:
-         info("%P%F illegal syntax in flags\n");
+         einfo("%P%F illegal syntax in flags\n");
          break;
        }
        flags++;
@@ -1904,9 +2041,11 @@ void
 DEFUN(lang_enter_output_section_statement,
       (output_section_statement_name,
        address_exp,
+       flags,
        block_value),
       char *output_section_statement_name AND
       etree_type *address_exp AND
+      int flags AND
       bfd_vma block_value)
 {
   lang_output_section_statement_type *os;
@@ -1914,7 +2053,8 @@ DEFUN(lang_enter_output_section_statement,
     os =
       lang_output_section_statement_lookup(output_section_statement_name);
 
-
+  
+  
   /* Add this statement to tree */
   /*  add_statement(lang_output_section_statement_enum,
       output_section_statement);*/
@@ -1925,6 +2065,7 @@ DEFUN(lang_enter_output_section_statement,
     os->addr_tree =
       address_exp;
   }
+  os->flags = flags;
   os->block_value = block_value;
   stat_ptr = & os->children;
 
@@ -1935,12 +2076,25 @@ void
 DEFUN_VOID(lang_final)
 {
   if (had_output_filename == false) {
-    lang_add_output("a.out");
+    extern CONST char *output_filename;
+    lang_add_output(output_filename);
   }
 }
 
 
 
+/* Reset the current counters in the regions */
+static void
+ DEFUN_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->current = p->origin;
+  }
+}
 
 
 asymbol *
@@ -1950,7 +2104,7 @@ DEFUN(create_symbol,(name, flags, section),
       asection *section)
 {
   extern lang_input_statement_type *script_file;
-  asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **));
+  asymbol **def_ptr = (asymbol **)ldmalloc((bfd_size_type)(sizeof(asymbol **)));
   /* Add this definition to script file */
   asymbol *def =  (asymbol  *)bfd_make_empty_symbol(script_file->the_bfd);
   def->name = buystring(name);
@@ -1964,12 +2118,14 @@ DEFUN(create_symbol,(name, flags, section),
 }
 
 
+
 void
 DEFUN_VOID(lang_process)
 {               
+
   if (had_script == false) {
-    parse_line(ldemul_get_script());
-  }
+      parse_line(ldemul_get_script(),1);
+    }
   lang_reasonable_defaults();
   current_target = default_target;
 
@@ -1988,14 +2144,17 @@ DEFUN_VOID(lang_process)
   current_target = default_target;
   lang_for_each_statement(open_input_bfds);
 
-  common_section.userdata = &common_section_userdata;
+  common_section.userdata = (PTR)&common_section_userdata;
+
 
   /* Run through the contours of the script and attatch input sections
      to the correct output sections 
      */
+  find_constructors();
   map_input_to_output_sections(statement_list.head, (char *)NULL, 
                               ( lang_output_section_statement_type *)NULL);
 
+
   /* Find any sections not attatched explicitly and handle them */
   lang_place_orphans();
 
@@ -2004,10 +2163,42 @@ DEFUN_VOID(lang_process)
 
   ldemul_before_allocation();
 
+
   /* Size up the sections */
   lang_size_sections(statement_list.head,
-                    (lang_output_section_statement_type *)NULL,
-                    &(statement_list.head), 0, (bfd_vma)0);
+                    abs_output_section,
+                    &(statement_list.head), 0, (bfd_vma)0, false);
+
+
+  /* Now run around and relax if we can */
+  if (command_line.relax) 
+  {
+    reset_memory_regions();
+
+  /* Move the global symbols around */
+  lang_relocate_globals();
+    
+    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;
+      
+    }
+    
+    
+
+
+  }
+  
 
   /* See if anything special should be done now we know how big
      everything is */
@@ -2017,16 +2208,17 @@ DEFUN_VOID(lang_process)
      of all the symbols */
 
   lang_do_assignments(statement_list.head,
-                     (lang_output_section_statement_type *)NULL,
+                     abs_output_section,
                      0, (bfd_vma)0);
 
-  /* Make sure that we're not mixing architectures */
-
-  lang_check();
 
   /* Move the global symbols around */
   lang_relocate_globals();
 
+  /* Make sure that we're not mixing architectures */
+
+  lang_check();
+
   /* Final stuffs */
   lang_finish();
 }
@@ -2141,7 +2333,7 @@ DEFUN(lang_startup,(name),
       CONST char *name)
 {
   if (startup_file != (char *)NULL) {
-   info("%P%FMultiple STARTUP files\n");
+   einfo("%P%FMultiple STARTUP files\n");
   }
   first_file->filename = name;
   first_file->local_sym_name = name;
@@ -2163,6 +2355,13 @@ DEFUN(lang_leave_output_section_statement,(fill, memspec),
   current_section->fill = fill;
   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
@@ -2176,13 +2375,12 @@ DEFUN(lang_abs_symbol_at_beginning_of,(section, name),
       CONST 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);
+                                BSF_GLOBAL | BSF_EXPORT ,
+                                &bfd_abs_section);
+    
+
     if (s != (asection *)NULL) {
       def->value = s->vma;
     }
@@ -2204,16 +2402,14 @@ DEFUN(lang_abs_symbol_at_end_of,(section, name),
       CONST 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);
+                                BSF_GLOBAL | BSF_EXPORT ,
+                                &bfd_abs_section);
+
     if (s != (asection *)NULL) {
-      def->value = s->vma + s->size;
+      def->value = s->vma + s->_raw_size;
     }
     else {
       def->value = 0;
This page took 0.044377 seconds and 4 git commands to generate.