]> Git Repo - binutils.git/blobdiff - ld/ldlang.c
* ldsym.c (write_file_locals): Write BSF_CONSTRUCTOR
[binutils.git] / ld / ldlang.c
index f73f260abf404a0fec68129639f7085abe18b97c..3f286f0e62626f1d2d727955051c9abb19620948 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
+/* Linker command language support.
+   Copyright 1991, 1992 Free Software Foundation, Inc.
 
 This file is part of GLD, the Gnu Linker.
 
@@ -32,8 +33,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "ldindr.h"
 #include "ldctor.h"
 /* FORWARDS */
-PROTO (static void, print_statements, (void));
-PROTO (static void, print_statement, (lang_statement_union_type *,
+static void print_statements PARAMS ((void));
+static void print_statement PARAMS ((lang_statement_union_type *,
                                      lang_output_section_statement_type *));
 
 /* LOCALS */
@@ -60,7 +61,6 @@ static lang_statement_list_type lang_output_section_statement;
 static CONST char *current_target;
 static CONST char *output_target;
 static size_t longest_section_name = 8;
-static asection common_section;
 static section_userdata_type common_section_userdata;
 static lang_statement_list_type statement_list;
 
@@ -94,6 +94,11 @@ extern args_type command_line;
 extern ld_config_type config;
 extern boolean had_script;
 extern boolean write_map;
+extern int g_switch_value;
+
+
+etree_type *base; /* Relocation base - or null */
+
 
 #ifdef __STDC__
 #define cat(a,b) a##b
@@ -107,7 +112,7 @@ 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));
+void lang_add_data PARAMS ((int type, union etree_union * exp));
 
 PTR
 DEFUN (stat_alloc, (size),
@@ -472,6 +477,12 @@ DEFUN (lang_output_section_statement_lookup, (name),
       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);
@@ -611,16 +622,27 @@ DEFUN (wild_doit, (ptr, section, output, file),
     new->section = section;
     new->ifile = file;
     section->output_section = output->bfd_section;
-    section->output_section->flags |= section->flags;
+
+    /* Be selective about what the output section inherits from the
+       input section */
+
+    section->output_section->flags |= section->flags & ~SEC_NEVER_LOAD;
+
     if (!output->loadable) 
     {
-      /* Turn of load flag */
+      /* 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;
+    }
   }
 }
 
@@ -647,9 +669,13 @@ DEFUN (wild_section, (ptr, section, file, output),
        {
          /* 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
        {
@@ -723,6 +749,8 @@ DEFUN (wild, (s, section, file, target, output),
        {
          wild_section (s, section, f, output);
        }
+      /* Once more for the script file */
+      wild_section(s, section, script_file, output);
     }
   else
     {
@@ -777,6 +805,7 @@ DEFUN (open_output, (name),
   bfd_set_arch_mach (output,
                     ldfile_output_architecture,
                     ldfile_output_machine);
+  bfd_set_gp_size (output, g_switch_value);
   return output;
 }
 
@@ -941,13 +970,20 @@ DEFUN_VOID (lang_create_output_section_statements)
 static void
 DEFUN_VOID (lang_init_script_file)
 {
-  script_file = lang_add_input_file ("script file",
+  script_file = lang_add_input_file ("command line",
                                     lang_input_file_is_fake_enum,
                                     (char *) NULL);
-  script_file->the_bfd = bfd_create ("script file", output_bfd);
+  script_file->the_bfd = bfd_create ("command line", 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);
+  script_file->the_bfd->sections = 0;
+
+  /* The user data of a bfd points to the input statement attatched */
+  script_file->the_bfd->usrdata  = (void *)script_file;
+  script_file->common_section =
+   bfd_make_section(script_file->the_bfd,"COMMON");
+
+  abs_output_section =
+   lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
 
   abs_output_section->bfd_section = &bfd_abs_section;
 
@@ -1033,39 +1069,61 @@ DEFUN (print_output_section_statement, (output_section_statement),
   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_size(section->_cooked_size);
-      print_space ();
-      print_alignment (section->alignment_power);
-      print_space ();
+  {
+    print_dot = section->vma;
+    print_space ();
+    print_section ("");
+    print_space ();
+    print_address (section->vma);
+    print_space ();
+    print_size (section->_raw_size);
+    print_space();
+    print_size(section->_cooked_size);
+    print_space ();
+    print_alignment (section->alignment_power);
+    print_space ();
 #if 0
-      fprintf (config.map_file, "%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 ");
+    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
+  {
+    fprintf (config.map_file, "No attached output section");
+  }
+  print_nl ();
+  if (output_section_statement->load_base)
     {
-      fprintf (config.map_file, "No attached output section");
+      int b = exp_get_value_int(output_section_statement->load_base,
+                               0, "output base", lang_final_phase_enum);
+      printf("Output address   %08x\n", b);
     }
-  print_nl ();
+  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);
 
@@ -1348,7 +1406,7 @@ DEFUN (print_statement, (s, os),
        case lang_output_statement_enum:
          fprintf (config.map_file, "OUTPUT(%s %s)\n",
                   s->output_statement.name,
-                  output_target);
+                  output_target ? output_target : "");
          break;
        case lang_input_statement_enum:
          print_input_statement (&s->input_statement);
@@ -1431,6 +1489,10 @@ DEFUN (size_input_section, (this_ptr, output_section_statement, fill,
 
   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);
 
@@ -1495,9 +1557,9 @@ DEFUN (lang_size_sections, (s, output_section_statement, prev, fill,
        bfd_vma after;
        lang_output_section_statement_type *os = &s->output_section_statement;
 
-       /* If this section is never loaded, don't change the size and
-         address.  */
-       if (os->bfd_section->flags & SEC_NEVER_LOAD)
+       /* 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)
@@ -1539,6 +1601,11 @@ DEFUN (lang_size_sections, (s, output_section_statement, prev, fill,
 
         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);
+        }
        }
 
 
@@ -1565,18 +1632,18 @@ DEFUN (lang_size_sections, (s, output_section_statement, prev, fill,
        {
         os->region->current = dot;
         /* Make sure this isn't silly */
-        if (os->region->current >
-            os->region->origin +
-            os->region->length)
-        {
-          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;
+        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;
 
-        }
+          }
 
        }
      }
@@ -1850,16 +1917,18 @@ DEFUN_VOID (lang_relocate_globals)
       }
     if (it != (asymbol *) NULL)
       {
+       asymbol **prev = 0;
        asymbol **ptr = lgs->srefs_chain;;
        if (lgs->flags & SYM_WARNING)
          {
            produce_warnings (lgs, it);
          }
 
-       while (ptr != (asymbol **) NULL)
+       while (ptr != (asymbol **) NULL
+              && ptr != prev)
          {
            asymbol *ref = *ptr;
-
+           prev = ptr;
            *ptr = it;
            ptr = (asymbol **) (ref->udata);
          }
@@ -1928,9 +1997,6 @@ DEFUN_VOID (lang_check)
        file != (lang_statement_union_type *) NULL;
        file = file->input_statement.next)
     {
-      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);
@@ -2025,15 +2091,35 @@ DEFUN_VOID (lang_common)
                    }
                  if (config.sort_common == false || align == power)
                    {
+                     bfd *symbfd;
+
                      /* Change from a common symbol into a definition of
                         a symbol */
                      lgs->sdefs_chain = lgs->scoms_chain;
                      lgs->scoms_chain = (asymbol **) NULL;
                      commons_pending--;
+
                      /* Point to the correct common section */
-                     com->section =
-                       ((lang_input_statement_type *)
-                        (com->the_bfd->usrdata))->common_section;
+                     symbfd = bfd_asymbol_bfd (com);
+                     if (com->section == &bfd_com_section)
+                       com->section =
+                         ((lang_input_statement_type *) symbfd->usrdata)
+                           ->common_section;
+                     else
+                       {
+                         CONST char *name;
+                         asection *newsec;
+
+                         name = bfd_get_section_name (symbfd,
+                                                      com->section);
+                         newsec = bfd_get_section_by_name (symbfd,
+                                                           name);
+                         /* BFD backend must provide this section. */
+                         if (newsec == (asection *) NULL)
+                           einfo ("%P%F: No output section %s", name);
+                         com->section = newsec;
+                       }
+
                      /*  Fix the size of the common section */
 
                      com->section->_raw_size =
@@ -2051,13 +2137,13 @@ DEFUN_VOID (lang_common)
                      com->flags = BSF_EXPORT | BSF_GLOBAL | BSF_OLD_COMMON;
                      com->value = com->section->_raw_size;
 
-                     if (write_map)
+                     if (write_map && config.map_file)
                        {
                          fprintf (config.map_file, "Allocating common %s: %x at %x %s\n",
                                   lgs->name,
                                   (unsigned) size,
                                   (unsigned) com->value,
-                                  com->the_bfd->filename);
+                                  bfd_asymbol_bfd(com)->filename);
                        }
 
                      com->section->_raw_size += size;
@@ -2177,7 +2263,7 @@ DEFUN (lang_set_flags, (ptr, flags),
 
 void
 DEFUN (lang_for_each_file, (func),
-       PROTO (void, (*func), (lang_input_statement_type *)))
+       void (*func) PARAMS ((lang_input_statement_type *)))
 {
   lang_input_statement_type *f;
 
@@ -2192,7 +2278,7 @@ DEFUN (lang_for_each_file, (func),
 
 void
 DEFUN (lang_for_each_input_section, (func),
-       PROTO (void, (*func), (bfd * ab, asection * as)))
+       void (*func) PARAMS ((bfd * ab, asection * as)))
 {
   lang_input_statement_type *f;
 
@@ -2237,21 +2323,38 @@ DEFUN (lang_add_output, (name),
 
 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
 DEFUN (lang_enter_output_section_statement,
        (output_section_statement_name,
        address_exp,
        flags,
-       block_value),
+       block_value, 
+       align, subalign, base),
        char *output_section_statement_name AND
        etree_type * address_exp AND
        int flags AND
-       bfd_vma block_value)
+       bfd_vma block_value AND
+       etree_type *align AND
+       etree_type *subalign AND
+       etree_type *base)
 {
   lang_output_section_statement_type *os;
 
   current_section =
-    os =
+   os =
     lang_output_section_statement_lookup (output_section_statement_name);
 
 
@@ -2263,20 +2366,30 @@ DEFUN (lang_enter_output_section_statement,
 
   if (os->addr_tree ==
       (etree_type *) NULL)
-    {
-      os->addr_tree =
-       address_exp;
-    }
+  {
+    os->addr_tree =
+     address_exp;
+  }
   os->flags = flags;
   if (flags & SEC_NEVER_LOAD)
    os->loadable = 0;
   else
    os->loadable = 1;
-  os->block_value = block_value;
+  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 = base;
 }
 
+
 void
 DEFUN_VOID (lang_final)
 {
@@ -2316,12 +2429,10 @@ DEFUN (create_symbol, (name, flags, section),
 
   /* Add this definition to script file */
   asymbol *def = (asymbol *) bfd_make_empty_symbol (script_file->the_bfd);
-
   def->name = buystring (name);
   def->udata = 0;
   def->flags = flags;
   def->section = section;
-
   *def_ptr = def;
   Q_enter_global_ref (def_ptr, name);
   return def;
@@ -2353,9 +2464,6 @@ DEFUN_VOID (lang_process)
   current_target = default_target;
   lang_for_each_statement (open_input_bfds);
 
-  common_section.userdata = (PTR) & common_section_userdata;
-
-
   /* Run through the contours of the script and attatch input sections
      to the correct output sections
      */
@@ -2684,3 +2792,4 @@ DEFUN (lang_add_output_format, (format),
 {
   output_target = format;
 }
+
This page took 0.043898 seconds and 4 git commands to generate.