Protoization.
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 6896b2040188557fe52f5fc6008148a267ad725f..baaf7ed55d9c1145f5897e2d039a8cd0866b90eb 100644 (file)
@@ -30,11 +30,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "ldgram.h"
 #include "ldexp.h"
 #include "ldlang.h"
-#include "ldemul.h"
 #include "ldlex.h"
 #include "ldmisc.h"
 #include "ldctor.h"
 #include "ldfile.h"
+#include "ldemul.h"
 #include "fnmatch.h"
 #include "demangle.h"
 
@@ -58,7 +58,6 @@ static lang_output_section_statement_type *default_common_section;
 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 lang_statement_list_type statement_list;
@@ -166,6 +165,7 @@ static char * get_first_input_target PARAMS ((void));
                                        
 /* EXPORTS */
 lang_output_section_statement_type *abs_output_section;
+lang_statement_list_type lang_output_section_statement;
 lang_statement_list_type *stat_ptr = &statement_list;
 lang_statement_list_type file_chain = { NULL, NULL };
 const char *entry_symbol = NULL;
@@ -682,6 +682,7 @@ lang_output_section_statement_lookup (name)
       lookup = (lang_output_section_statement_type *)
        new_stat (lang_output_section_statement, stat_ptr);
       lookup->region = (lang_memory_region_type *) NULL;
+      lookup->lma_region = (lang_memory_region_type *) NULL;
       lookup->fill = 0;
       lookup->block_value = 1;
       lookup->name = name;
@@ -1195,6 +1196,13 @@ wild_doit (ptr, section, output, file)
       /* If supplied an aligment, then force it.  */
       if (output->section_alignment != -1)
        output->bfd_section->alignment_power = output->section_alignment;
+
+      if (section->flags & SEC_BLOCK)
+        {
+          section->output_section->flags |= SEC_BLOCK;
+          /* FIXME: This value should really be obtained from the bfd... */
+          output->block_value = 128;
+        }
     }
 }
 
@@ -1720,32 +1728,37 @@ open_output (name)
       /* Get the chosen target.  */
       target = bfd_search_for_target (get_target, (void *) output_target);
 
-      if (command_line.endian == ENDIAN_BIG)
-       desired_endian = BFD_ENDIAN_BIG;
-      else
-       desired_endian = BFD_ENDIAN_LITTLE;
-      
-      /* See if the target has the wrong endianness.  This should not happen
-        if the linker script has provided big and little endian alternatives,
-        but some scrips don't do this.  */
-      if (target->byteorder != desired_endian)
+      /* If the target is not supported, we cannot do anything.  */
+      if (target != NULL)
        {
-         /* If it does, then see if the target provides
-            an alternative with the correct endianness.  */
-         if (target->alternative_target != NULL
-             && (target->alternative_target->byteorder == desired_endian))
-           output_target = target->alternative_target->name;
+         if (command_line.endian == ENDIAN_BIG)
+           desired_endian = BFD_ENDIAN_BIG;
          else
+           desired_endian = BFD_ENDIAN_LITTLE;
+         
+         /* See if the target has the wrong endianness.  This should not happen
+            if the linker script has provided big and little endian alternatives,
+            but some scrips don't do this.  */
+         if (target->byteorder != desired_endian)
            {
-             /* Try to find a target as similar as possible to the default
-                target, but which has the desired endian characteristic.  */
-             (void) bfd_search_for_target (closest_target_match, (void *) target);
-             
-             /* Oh dear - we could not find any targets that satisfy our requirements.  */
-             if (winner == NULL)
-               einfo (_("%P: warning: could not find any targets that match endianness requirement\n"));
+             /* If it does, then see if the target provides
+                an alternative with the correct endianness.  */
+             if (target->alternative_target != NULL
+                 && (target->alternative_target->byteorder == desired_endian))
+               output_target = target->alternative_target->name;
              else
-               output_target = winner->name;
+               {
+                 /* Try to find a target as similar as possible to the default
+                    target, but which has the desired endian characteristic.  */
+                 (void) bfd_search_for_target (closest_target_match, (void *) target);
+                 
+                 /* Oh dear - we could not find any targets that satisfy our
+                    requirements.  */
+                 if (winner == NULL)
+                   einfo (_("%P: warning: could not find any targets that match endianness requirement\n"));
+                 else
+                   output_target = winner->name;
+               }
            }
        }
     }
@@ -1863,8 +1876,10 @@ open_input_bfds (s, force)
 
              /* If we are being called from within a group, and this
                  is an archive which has already been searched, then
-                 force it to be researched.  */
+                 force it to be researched unless the whole archive
+                has been loaded already.  */
              if (force
+                 && !s->input_statement.whole_archive
                  && s->input_statement.loaded
                  && bfd_check_format (s->input_statement.the_bfd,
                                       bfd_archive))
@@ -2168,8 +2183,8 @@ print_input_section (in)
 {
   asection *i = in->section;
   bfd_size_type size = i->_cooked_size != 0 ? i->_cooked_size : i->_raw_size;
-  int opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
-                                           ldfile_output_machine);
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine);
   if (size != 0)
     {
       print_space ();
@@ -2235,8 +2250,8 @@ print_data_statement (data)
   bfd_vma addr;
   bfd_size_type size;
   const char *name;
-  int opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
-                                           ldfile_output_machine);
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine);
 
   for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
     print_space ();
@@ -2306,8 +2321,8 @@ print_reloc_statement (reloc)
   int i;
   bfd_vma addr;
   bfd_size_type size;
-  int opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
-                                           ldfile_output_machine); 
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine); 
 
   for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
     print_space ();
@@ -2338,8 +2353,8 @@ print_padding_statement (s)
 {
   int len;
   bfd_vma addr;
-  int opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
-                                           ldfile_output_machine); 
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine); 
 
   minfo (" *fill*");
 
@@ -2555,8 +2570,8 @@ insert_pad (this_ptr, fill, power, output_section_statement, dot)
      inserting a magic 'padding' statement.
      */
 
-  int opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
-                                           ldfile_output_machine); 
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine); 
   unsigned int alignment_needed = align_power (dot, power) - dot;
 
   if (alignment_needed != 0)
@@ -2598,8 +2613,8 @@ size_input_section (this_ptr, output_section_statement, fill, dot, relax)
 {
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
-  int opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
-                                           ldfile_output_machine); 
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine); 
 
   if (is->ifile->just_syms_flag == false)
     {
@@ -2642,7 +2657,7 @@ static void
 lang_check_section_addresses ()
 {
   asection * s;
-  int opb = bfd_octets_per_byte (output_bfd);
+  unsigned opb = bfd_octets_per_byte (output_bfd);
 
   /* Scan all sections in the output list.  */
   for (s = output_bfd->sections; s != NULL; s = s->next)
@@ -2672,8 +2687,8 @@ lang_check_section_addresses ()
             overlapping VMAs but they must have distinct LMAs.  */
          s_start  = bfd_section_lma (output_bfd, s);
          os_start = bfd_section_lma (output_bfd, os);
-         s_end    = s_start  + bfd_section_size (output_bfd, s) - 1;
-         os_end   = os_start + bfd_section_size (output_bfd, os) - 1;
+         s_end    = s_start  + bfd_section_size (output_bfd, s) / opb - 1;
+         os_end   = os_start + bfd_section_size (output_bfd, os) / opb - 1;
          
          /* Look for an overlap.  */
          if ((s_end < os_start) || (s_start > os_end))
@@ -2695,6 +2710,43 @@ _("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
 
 static boolean relax_again;
 
+/* Make sure the new address is within the region.  We explicitly permit the
+   current address to be at the exact end of the region when the address is
+   non-zero, in case the region is at the end of addressable memory and the
+   calculation wraps around.  */ 
+
+static void
+os_region_check (os, region, tree, base)
+  lang_output_section_statement_type *os;
+  struct memory_region_struct *region;
+  etree_type *tree;
+  bfd_vma base;
+{
+  if ((region->current < region->origin
+       || (region->current - region->origin > region->length))
+      && ((region->current != region->origin + region->length)
+           || base == 0))
+    {
+      if (tree != (etree_type *) NULL)
+        {
+          einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
+                 region->current,
+                 os->bfd_section->owner,
+                 os->bfd_section->name,
+                 region->name);
+        }
+      else
+        {
+          einfo (_("%X%P: region %s is full (%B section %s)\n"),
+                 region->name,
+                 os->bfd_section->owner,
+                 os->bfd_section->name);
+        }
+      /* Reset the region pointer.  */
+      region->current = region->origin;
+    }
+}
+
 /* Set the sizes for all the output sections.  */
 
 bfd_vma
@@ -2706,8 +2758,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
      bfd_vma dot;
      boolean relax;
 {
-  int opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
-                                           ldfile_output_machine);
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine);
 
   /* Size up the sections from their constituent parts.  */
   for (; s != (lang_statement_union_type *) NULL; s = s->next)
@@ -2824,8 +2876,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
            
             /* put the section within the requested block size, or align at
                the block boundary */
-           after = ALIGN_N (os->bfd_section->vma,
-                            os->bfd_section->_raw_size / opb,
+           after = ALIGN_N (os->bfd_section->vma
+                            os->bfd_section->_raw_size / opb,
                             /* The coercion here is important, see ld.h.  */
                             (bfd_vma) os->block_value);
 
@@ -2853,37 +2905,35 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
              {
                os->region->current = dot;
                
-               /* Make sure the new address is within the region.  We
-                   explicitly permit the current address to be at the
-                   exact end of the region when the VMA is non-zero,
-                   in case the region is at the end of addressable
-                   memory and the calculation wraps around.  */
-               if ((os->region->current < os->region->origin
-                    || (os->region->current - os->region->origin
-                        > os->region->length))
-                   && ((os->region->current
-                        != os->region->origin + os->region->length)
-                       || os->bfd_section->vma == 0))
-
-                 {
-                   if (os->addr_tree != (etree_type *) NULL)
-                     {
-                       einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
-                              os->region->current,
-                              os->bfd_section->owner,
-                              os->bfd_section->name,
-                              os->region->name);
-                     }
-                   else
-                     {
-                       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 = os->region->origin;
-                 }
+               /* Make sure the new address is within the region.  */
+                os_region_check (os, os->region, os->addr_tree, 
+                                 os->bfd_section->vma);
+
+                /* if there's no load address specified, use the run region as
+                   the load region */
+                if (os->lma_region == NULL && os->load_base == NULL)
+                    os->lma_region = os->region;
+
+                if (os->lma_region != NULL)
+                  {
+                    if (os->load_base != NULL)
+                      {
+                        einfo (_("%X%P: use an absolute load address or a load memory region, not both\n"));
+                      }
+                    else
+                      {
+                        /* don't allocate twice */
+                        if (os->lma_region != os->region)
+                          {
+                            /* set load_base, which will be handled later */
+                            os->load_base = exp_intop (os->lma_region->current);
+                            os->lma_region->current += 
+                              os->bfd_section->_raw_size / opb;
+                            os_region_check (os, os->lma_region, NULL,
+                                             os->bfd_section->lma);
+                          }
+                      }
+                  }
              }
          }
          break;
@@ -2906,6 +2956,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
 
            switch (s->data_statement.type)
              {
+              default:
+                abort();
              case QUAD:
              case SQUAD:
                size = QUAD_SIZE;
@@ -3081,8 +3133,8 @@ lang_do_assignments (s, output_section_statement, fill, dot)
      fill_type fill;
      bfd_vma dot;
 {
-  int opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
-                                           ldfile_output_machine); 
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine); 
 
   for (; s != (lang_statement_union_type *) NULL; s = s->next)
     {
@@ -3108,14 +3160,15 @@ lang_do_assignments (s, output_section_statement, fill, dot)
                dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb;
 
              }
-           if (os->load_base) 
+           if (os->load_base)
              {
                /* If nothing has been placed into the output section then
                   it won't have a bfd_section. */
                if (os->bfd_section) 
                  {
                    os->bfd_section->lma 
-                     = exp_get_abs_int(os->load_base, 0,"load base", lang_final_phase_enum);
+                     = exp_get_abs_int(os->load_base, 0,"load base",
+                                       lang_final_phase_enum);
                  }
              }
          }
@@ -3147,9 +3200,11 @@ lang_do_assignments (s, output_section_statement, fill, dot)
              einfo (_("%F%P: invalid data statement\n"));
          }
           {
-            int size;
+            unsigned int size;
             switch (s->data_statement.type)
               {
+              default:
+                abort();
               case QUAD:
               case SQUAD:
                 size = QUAD_SIZE;
@@ -3269,8 +3324,8 @@ lang_set_startof ()
       h = bfd_link_hash_lookup (link_info.hash, buf, false, false, true);
       if (h != NULL && h->type == bfd_link_hash_undefined)
        {
-          int opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
-                                                   ldfile_output_machine); 
+          unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                                       ldfile_output_machine);
          h->type = bfd_link_hash_defined;
          if (s->_cooked_size != 0)
            h->u.def.value = s->_cooked_size / opb;
@@ -3452,8 +3507,8 @@ lang_one_common (h, info)
   unsigned int power_of_two;
   bfd_vma size;
   asection *section;
-  int opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
-                                           ldfile_output_machine); 
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine); 
 
   if (h->type != bfd_link_hash_common)
     return true;
@@ -3773,7 +3828,7 @@ topower (x)
   return 0;
 }
 
-void
+lang_output_section_statement_type *
 lang_enter_output_section_statement (output_section_statement_name,
                                     address_exp, sectype, block_value,
                                     align, subalign, ebase)
@@ -3821,9 +3876,9 @@ lang_enter_output_section_statement (output_section_statement_name,
                     "section alignment", 0));
 
   os->load_base = ebase;
+  return os;
 }
 
-
 void
 lang_final ()
 {
@@ -4255,13 +4310,22 @@ lang_float (maybe)
 }
 
 void
-lang_leave_output_section_statement (fill, memspec, phdrs)
+lang_leave_output_section_statement (fill, memspec, phdrs, lma_memspec)
      bfd_vma fill;
      const char *memspec;
      struct lang_output_section_phdr_list *phdrs;
+     const char *lma_memspec;
 {
   current_section->fill = fill;
   current_section->region = lang_memory_region_lookup (memspec);
+  if (strcmp (lma_memspec, "*default*") != 0)
+    {
+      current_section->lma_region = lang_memory_region_lookup (lma_memspec);
+      /* if no runtime region has been given, but the load region has been,
+         use the load region */
+      if (strcmp (memspec, "*default*") == 0)
+        current_section->region = lang_memory_region_lookup (lma_memspec);
+    }
   current_section->phdrs = phdrs;
   stat_ptr = &statement_list;
 }
@@ -4640,7 +4704,8 @@ lang_leave_overlay_section (fill, phdrs)
 
   name = current_section->name;
 
-  lang_leave_output_section_statement (fill, "*default*", phdrs);
+  lang_leave_output_section_statement (fill, "*default*", 
+                                       phdrs, "*default*");
 
   /* Define the magic symbols.  */
 
@@ -4670,12 +4735,14 @@ lang_leave_overlay_section (fill, phdrs)
    looks through all the sections in the overlay and sets them.  */
 
 void
-lang_leave_overlay (fill, memspec, phdrs)
+lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
      bfd_vma fill;
      const char *memspec;
      struct lang_output_section_phdr_list *phdrs;
+     const char *lma_memspec;
 {
   lang_memory_region_type *region;
+  lang_memory_region_type *lma_region;
   struct overlay_list *l;
   struct lang_nocrossref *nocrossref;
 
@@ -4684,6 +4751,11 @@ lang_leave_overlay (fill, memspec, phdrs)
   else
     region = lang_memory_region_lookup (memspec);
 
+  if (lma_memspec == NULL)
+    lma_region = NULL;
+  else
+    lma_region = lang_memory_region_lookup (lma_memspec);
+
   nocrossref = NULL;
 
   l = overlay_list;
@@ -4695,6 +4767,8 @@ lang_leave_overlay (fill, memspec, phdrs)
        l->os->fill = fill;
       if (region != NULL && l->os->region == NULL)
        l->os->region = region;
+      if (lma_region != NULL && l->os->lma_region == NULL)
+        l->os->lma_region = lma_region;
       if (phdrs != NULL && l->os->phdrs == NULL)
        l->os->phdrs = phdrs;
 
This page took 0.030172 seconds and 4 git commands to generate.