* ldlang.h (lang_output_section_statement_type): Add update_dot_tree.
authorRichard Sandiford <rdsandiford@googlemail.com>
Tue, 7 May 2002 11:04:54 +0000 (11:04 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Tue, 7 May 2002 11:04:54 +0000 (11:04 +0000)
(lang_enter_overlay): Remove the last two parameters.
(lang_leave_overlay): Take them here instead.
* ldgram.y (memspec_at_opt): Set $$ to null if no region is given.
(section): Pass LMA and crossref flag to lang_leave_overlay rather
than lang_enter_overlay.
* ldlang.c (lang_memory_region_lookup): Return null for null names.
(lang_output_section_statement_lookup): Initialize update_dot_tree.
(lang_size_sections_1): Evaluate it.
(lang_leave_output_section_statement): Rework LMA lookup.
(overlay_lma, overlay_nocrossrefs): Remove.
(lang_enter_overlay): Remove LMA and corssref arguments.
(lang_enter_overlay_section): Don't set the LMA here.
(lang_leave_overlay): Take LMA and crossref arguments.  Move the '.'
assignment to the last section's update_dot_tree.  Unconditionally
use the load and run-time regions specified in the OVERLAY statement.
Likewise the first section's LMA.  Only set the other sections' LMAs
when no load region is given.

ld/ChangeLog
ld/ldgram.y
ld/ldlang.c
ld/ldlang.h

index b9b806a67d2af689835d7a36d1818dbf5b721ee0..93ebd70f4ee5f113418feaf9054f655ac07ef9ad 100644 (file)
@@ -1,3 +1,24 @@
+2002-05-07  Richard Sandiford  <rsandifo@redhat.com>
+
+       * ldlang.h (lang_output_section_statement_type): Add update_dot_tree.
+       (lang_enter_overlay): Remove the last two parameters.
+       (lang_leave_overlay): Take them here instead.
+       * ldgram.y (memspec_at_opt): Set $$ to null if no region is given.
+       (section): Pass LMA and crossref flag to lang_leave_overlay rather
+       than lang_enter_overlay.
+       * ldlang.c (lang_memory_region_lookup): Return null for null names.
+       (lang_output_section_statement_lookup): Initialize update_dot_tree.
+       (lang_size_sections_1): Evaluate it.
+       (lang_leave_output_section_statement): Rework LMA lookup.
+       (overlay_lma, overlay_nocrossrefs): Remove.
+       (lang_enter_overlay): Remove LMA and corssref arguments.
+       (lang_enter_overlay_section): Don't set the LMA here.
+       (lang_leave_overlay): Take LMA and crossref arguments.  Move the '.'
+       assignment to the last section's update_dot_tree.  Unconditionally
+       use the load and run-time regions specified in the OVERLAY statement.
+       Likewise the first section's LMA.  Only set the other sections' LMAs
+       when no load region is given.
+
 2002-05-06  Nick Clifton <nickc@redhat.com>
 
        * po/sv.po: New translation.
index 71da62c86ae62e6bc10c066b5acfc55b4f3dbaa1..3de9326bb8bb1131737d051a5d9d27d7962bf0cb 100644 (file)
@@ -820,7 +820,7 @@ exp :
 
 memspec_at_opt:
                 AT '>' NAME { $$ = $3; }
-        |       { $$ = "*default*"; }
+        |       { $$ = 0; }
         ;
 
 opt_at:
@@ -851,7 +851,7 @@ section:    NAME            { ldlex_expression(); }
                        { ldlex_popstate (); ldlex_script (); }
                '{' 
                        {
-                         lang_enter_overlay ($3, $5, (int) $4);
+                         lang_enter_overlay ($3);
                        }
                overlay_section
                '}'
@@ -859,7 +859,8 @@ section:    NAME            { ldlex_expression(); }
                memspec_opt memspec_at_opt phdr_opt fill_opt
                        {
                          ldlex_popstate ();
-                         lang_leave_overlay ($15, $12, $14, $13);
+                         lang_leave_overlay ($5, (int) $4,
+                                             $15, $12, $14, $13);
                        }
                opt_comma
        |       /* The GROUP case is just enough to support the gcc
index f8c9c44f368ca745acfabeaa1a06c4018f1b96df..054ffc0fa91213305bd26568a932063018695297 100644 (file)
@@ -617,6 +617,10 @@ lang_memory_region_lookup (name)
 {
   lang_memory_region_type *p;
 
+  /* NAME is NULL for LMA memspecs if no region was specified.  */
+  if (name == NULL)
+    return NULL;
+
   for (p = lang_memory_region_list;
        p != (lang_memory_region_type *) NULL;
        p = p->next)
@@ -738,6 +742,7 @@ lang_output_section_statement_lookup (name)
       lookup->subsection_alignment = -1;
       lookup->section_alignment = -1;
       lookup->load_base = (union etree_union *) NULL;
+      lookup->update_dot_tree = NULL;
       lookup->phdrs = NULL;
 
       lang_statement_append (&lang_output_section_statement,
@@ -3009,9 +3014,14 @@ lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax)
            else
              os->bfd_section->_raw_size =
                (after - os->bfd_section->vma) * opb;
+
            dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb;
            os->processed = true;
 
+           if (os->update_dot_tree != 0)
+             exp_fold_tree (os->update_dot_tree, abs_output_section,
+                            lang_allocating_phase_enum, dot, &dot);
+
            /* Update dot in the region ?
               We only do this if the section is going to be allocated,
               since unallocated sections do not contribute to the region's
@@ -4514,14 +4524,13 @@ lang_leave_output_section_statement (fill, memspec, phdrs, 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->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 (current_section->lma_region != 0 && strcmp (memspec, "*default*") == 0)
+    current_section->region = current_section->lma_region;
+
   current_section->phdrs = phdrs;
   stat_ptr = &statement_list;
 }
@@ -4803,12 +4812,6 @@ lang_add_nocrossref (l)
 /* The overlay virtual address.  */
 static etree_type *overlay_vma;
 
-/* The overlay load address.  */
-static etree_type *overlay_lma;
-
-/* Whether nocrossrefs is set for this overlay.  */
-static int overlay_nocrossrefs;
-
 /* An expression for the maximum section size seen so far.  */
 static etree_type *overlay_max;
 
@@ -4824,24 +4827,18 @@ static struct overlay_list *overlay_list;
 /* Start handling an overlay.  */
 
 void
-lang_enter_overlay (vma_expr, lma_expr, nocrossrefs)
+lang_enter_overlay (vma_expr)
      etree_type *vma_expr;
-     etree_type *lma_expr;
-     int nocrossrefs;
 {
   /* The grammar should prevent nested overlays from occurring.  */
-  ASSERT (overlay_vma == NULL
-         && overlay_lma == NULL
-         && overlay_list == NULL
-         && overlay_max == NULL);
+  ASSERT (overlay_vma == NULL && overlay_max == NULL);
 
   overlay_vma = vma_expr;
-  overlay_lma = lma_expr;
-  overlay_nocrossrefs = nocrossrefs;
 }
 
 /* Start a section in an overlay.  We handle this by calling
-   lang_enter_output_section_statement with the correct VMA and LMA.  */
+   lang_enter_output_section_statement with the correct VMA.
+   lang_leave_overlay sets up the LMA and memory regions.  */
 
 void
 lang_enter_overlay_section (name)
@@ -4851,16 +4848,13 @@ lang_enter_overlay_section (name)
   etree_type *size;
 
   lang_enter_output_section_statement (name, overlay_vma, normal_section,
-                                      0, 0, 0, overlay_lma);
+                                      0, 0, 0, 0);
 
-  /* If this is the first section, then base the VMA and LMA of future
+  /* If this is the first section, then base the VMA of future
      sections on this one.  This will work correctly even if `.' is
      used in the addresses.  */
   if (overlay_list == NULL)
-    {
-      overlay_vma = exp_nameop (ADDR, name);
-      overlay_lma = exp_nameop (LOADADDR, name);
-    }
+    overlay_vma = exp_nameop (ADDR, name);
 
   /* Remember the section.  */
   n = (struct overlay_list *) xmalloc (sizeof *n);
@@ -4870,9 +4864,6 @@ lang_enter_overlay_section (name)
 
   size = exp_nameop (SIZEOF, name);
 
-  /* Adjust the LMA for the next section.  */
-  overlay_lma = exp_binop ('+', overlay_lma, size);
-
   /* Arrange to work out the maximum section end address.  */
   if (overlay_max == NULL)
     overlay_max = size;
@@ -4895,8 +4886,10 @@ lang_leave_overlay_section (fill, phdrs)
 
   name = current_section->name;
 
-  lang_leave_output_section_statement (fill, "*default*",
-                                      phdrs, "*default*");
+  /* For now, assume that "*default*" is the run-time memory region and
+     that no load-time region has been specified.  It doesn't really
+     matter what we say here, since lang_leave_overlay will override it.  */
+  lang_leave_output_section_statement (fill, "*default*", phdrs, 0);
 
   /* Define the magic symbols.  */
 
@@ -4926,32 +4919,30 @@ lang_leave_overlay_section (fill, phdrs)
    looks through all the sections in the overlay and sets them.  */
 
 void
-lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
+lang_leave_overlay (lma_expr, nocrossrefs, fill, memspec, phdrs, lma_memspec)
+     etree_type *lma_expr;
+     int nocrossrefs;
      fill_type *fill;
      const char *memspec;
      struct lang_output_section_phdr_list *phdrs;
      const char *lma_memspec;
 {
   lang_memory_region_type *region;
-  lang_memory_region_type *default_region;
   lang_memory_region_type *lma_region;
   struct overlay_list *l;
   struct lang_nocrossref *nocrossref;
 
-  default_region = lang_memory_region_lookup ("*default*");
-
-  if (memspec == NULL)
-    region = NULL;
-  else
-    region = lang_memory_region_lookup (memspec);
-
-  if (lma_memspec == NULL)
-    lma_region = NULL;
-  else
-    lma_region = lang_memory_region_lookup (lma_memspec);
+  region = lang_memory_region_lookup (memspec);
+  lma_region = lang_memory_region_lookup (lma_memspec);
 
   nocrossref = NULL;
 
+  /* After setting the size of the last section, set '.' to end of the
+     overlay region.  */
+  if (overlay_list != NULL)
+    overlay_list->os->update_dot_tree
+      = exp_assop ('=', ".", exp_binop ('+', overlay_vma, overlay_max));
+
   l = overlay_list;
   while (l != NULL)
     {
@@ -4960,28 +4951,24 @@ lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
       if (fill != (fill_type *) 0 && l->os->fill == (fill_type *) 0)
        l->os->fill = fill;
 
-      /* Assign a region to the sections, if one has been specified.
-        Override the assignment of the default section, but not
-        other sections.  */
-      if (region != NULL &&
-         (l->os->region == NULL ||
-          l->os->region == default_region))
-       l->os->region = region;
-
-      /* We only set lma_region for the first overlay section, as
-        subsequent overlay sections will have load_base set relative
-        to the first section.  Also, don't set lma_region if
-        load_base is specified.  FIXME:  There should really be a test
-        that `AT ( LDADDR )' doesn't conflict with `AT >LMA_REGION'
-        rather than letting LDADDR simply override LMA_REGION.  */
-      if (lma_region != NULL && l->os->lma_region == NULL
-         && l->next == NULL && l->os->load_base == NULL)
-       l->os->lma_region = lma_region;
+      l->os->region = region;
+      l->os->lma_region = lma_region;
+
+      /* The first section has the load address specified in the
+        OVERLAY statement.  The rest are worked out from that.
+        The base address is not needed (and should be null) if
+        an LMA region was specified.  */
+      if (l->next == 0)
+       l->os->load_base = lma_expr;
+      else if (lma_region == 0)
+       l->os->load_base = exp_binop ('+',
+                                     exp_nameop (LOADADDR, l->next->os->name),
+                                     exp_nameop (SIZEOF, l->next->os->name));
 
       if (phdrs != NULL && l->os->phdrs == NULL)
        l->os->phdrs = phdrs;
 
-      if (overlay_nocrossrefs)
+      if (nocrossrefs)
        {
          struct lang_nocrossref *nc;
 
@@ -4999,13 +4986,7 @@ lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
   if (nocrossref != NULL)
     lang_add_nocrossref (nocrossref);
 
-  /* Update . for the end of the overlay.  */
-  lang_add_assignment (exp_assop ('=', ".",
-                                 exp_binop ('+', overlay_vma, overlay_max)));
-
   overlay_vma = NULL;
-  overlay_lma = NULL;
-  overlay_nocrossrefs = 0;
   overlay_list = NULL;
   overlay_max = NULL;
 }
index 4e3353ac7fea78b6f7b1907755db5605130b427c..26c4121fa7e5151c7194128353e2c6ae211f5979 100644 (file)
@@ -135,6 +135,12 @@ typedef struct lang_output_section_statement_struct {
 
   union etree_union *load_base;
 
+  /* If non-null, an expression to evaluate after setting the section's
+     size.  The expression is evaluated inside REGION (above) with '.'
+     set to the end of the section.  Used in the last overlay section
+     to move '.' past all the overlaid sections.  */
+  union etree_union *update_dot_tree;
+
   struct lang_output_section_phdr_list *phdrs;
 } lang_output_section_statement_type;
 
@@ -456,13 +462,13 @@ extern void lang_new_phdr
   PARAMS ((const char *, etree_type *, boolean, boolean, etree_type *,
           etree_type *));
 extern void lang_add_nocrossref PARAMS ((struct lang_nocrossref *));
-extern void lang_enter_overlay PARAMS ((etree_type *, etree_type *, int));
+extern void lang_enter_overlay PARAMS ((etree_type *));
 extern void lang_enter_overlay_section PARAMS ((const char *));
 extern void lang_leave_overlay_section
   PARAMS ((fill_type *, struct lang_output_section_phdr_list *));
 extern void lang_leave_overlay
-  PARAMS ((fill_type *, const char *, struct lang_output_section_phdr_list *,
-           const char *));
+  PARAMS ((etree_type *, int, fill_type *, const char *,
+          struct lang_output_section_phdr_list *, const char *));
 
 extern struct bfd_elf_version_tree *lang_elf_version_info;