* ldlang.c (insert_pad): Make use of an existing pad statement if
authorAlan Modra <amodra@gmail.com>
Sat, 18 Aug 2001 14:54:26 +0000 (14:54 +0000)
committerAlan Modra <amodra@gmail.com>
Sat, 18 Aug 2001 14:54:26 +0000 (14:54 +0000)
available.  Move code calculating alignment, adjusting section
alignment power, and adjusting dot to ..
(size_input_section): .. here.  Remove unused relax param.
(lang_size_sections): Change boolean `relax' param to boolean *.
Adjust call to size_input_section.  Make use of insert_pad to
place pad after the assignment statement.  If relaxing, zap
padding statements.
(reset_memory_regions): Reset output_bfd section sizes too.
(relax_again): Move to..
(lang_process): ..here.  Adjust call to lang_size_sections, and
remove duplicated code.
* ldlang.h (lang_size_sections): Change `relax' param to boolean *.

ld/ChangeLog
ld/ldlang.c
ld/ldlang.h

index b10f2fd3e3f2eabee2f74e85b16aec101d750306..b3c069df4438c0e76d554af40ce338e0a9df878c 100644 (file)
@@ -1,3 +1,19 @@
+2001-08-18  Alan Modra  <amodra@bigpond.net.au>
+
+       * ldlang.c (insert_pad): Make use of an existing pad statement if
+       available.  Move code calculating alignment, adjusting section
+       alignment power, and adjusting dot to ..
+       (size_input_section): .. here.  Remove unused relax param.
+       (lang_size_sections): Change boolean `relax' param to boolean *.
+       Adjust call to size_input_section.  Make use of insert_pad to
+       place pad after the assignment statement.  If relaxing, zap
+       padding statements.
+       (reset_memory_regions): Reset output_bfd section sizes too.
+       (relax_again): Move to..
+       (lang_process): ..here.  Adjust call to lang_size_sections, and
+       remove duplicated code.
+       * ldlang.h (lang_size_sections): Change `relax' param to boolean *.
+
 2001-08-17  Alan Modra  <amodra@bigpond.net.au>
 
        * ld.texinfo: Document that fill values now use the four least
index d9fa38fd347925a415b56a029f942e11b3a56425..905d08c1015daa1b4ce895b3fea3eb691ee1aec9 100644 (file)
@@ -119,12 +119,12 @@ static void print_statement
 static void print_statement_list
   PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *));
 static void print_statements PARAMS ((void));
-static bfd_vma insert_pad
+static void insert_pad
   PARAMS ((lang_statement_union_type **, fill_type,
           unsigned int, asection *, bfd_vma));
 static bfd_vma size_input_section
   PARAMS ((lang_statement_union_type **, lang_output_section_statement_type *,
-          fill_type, bfd_vma, boolean));
+          fill_type, bfd_vma));
 static void lang_finish PARAMS ((void));
 static void ignore_bfd_errors PARAMS ((const char *, ...));
 static void lang_check PARAMS ((void));
@@ -2626,87 +2626,94 @@ dprint_statement (s, n)
   config.map_file = map_save;
 }
 
-static bfd_vma
-insert_pad (this_ptr, fill, power, output_section_statement, dot)
-     lang_statement_union_type **this_ptr;
+static void
+insert_pad (ptr, fill, alignment_needed, output_section, dot)
+     lang_statement_union_type **ptr;
      fill_type fill;
-     unsigned int power;
-     asection *output_section_statement;
+     unsigned int alignment_needed;
+     asection *output_section;
      bfd_vma dot;
 {
-  /* Align this section first to the
-     input sections requirement, then
-     to the output section's requirement.
-     If this alignment is > than any seen before,
-     then record it too. Perform the alignment by
-     inserting a magic 'padding' statement.  */
-
-  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)
+  lang_statement_union_type *pad;
+  size_t ptr_off;
+
+  /* ptr_off is zero, but let's not be too fast and loose with
+     pointers.  */
+  ptr_off = ((char *) &((lang_statement_union_type *) 0)->header.next
+            - (char *) 0);
+  if (ptr != &statement_list.head
+      && ((pad = (lang_statement_union_type *) ((char *) ptr - ptr_off))
+         ->header.type == lang_padding_statement_enum)
+      && pad->padding_statement.output_section == output_section)
     {
-      lang_statement_union_type *new =
-       ((lang_statement_union_type *)
-        stat_alloc (sizeof (lang_padding_statement_type)));
-
-      /* Link into existing chain.  */
-      new->header.next = *this_ptr;
-      *this_ptr = new;
-      new->header.type = lang_padding_statement_enum;
-      new->padding_statement.output_section = output_section_statement;
-      new->padding_statement.output_offset =
-       dot - output_section_statement->vma;
-      new->padding_statement.fill = fill;
-      new->padding_statement.size = alignment_needed * opb;
+      /* Use the existing pad statement.  The above test on output
+        section is probably redundant, but it doesn't hurt to check.  */
     }
-
-  /* Remember the most restrictive alignment.  */
-  if (power > output_section_statement->alignment_power)
+  else
     {
-      output_section_statement->alignment_power = power;
+      /* Make a new padding statement, linked into existing chain.  */
+      pad = ((lang_statement_union_type *)
+            stat_alloc (sizeof (lang_padding_statement_type)));
+      pad->header.next = *ptr;
+      *ptr = pad;
+      pad->header.type = lang_padding_statement_enum;
+      pad->padding_statement.output_section = output_section;
+      pad->padding_statement.fill = fill;
     }
-  output_section_statement->_raw_size += alignment_needed * opb;
-
-  return dot + alignment_needed;
+  pad->padding_statement.output_offset = dot - output_section->vma;
+  pad->padding_statement.size = alignment_needed;
+  output_section->_raw_size += alignment_needed;
 }
 
 /* Work out how much this section will move the dot point.  */
 
 static bfd_vma
-size_input_section (this_ptr, output_section_statement, fill, dot, relax)
+size_input_section (this_ptr, output_section_statement, fill, dot)
      lang_statement_union_type **this_ptr;
      lang_output_section_statement_type *output_section_statement;
      fill_type fill;
      bfd_vma dot;
-     boolean relax ATTRIBUTE_UNUSED;
 {
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
-  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
-                                               ldfile_output_machine);
 
   if (is->ifile->just_syms_flag == false)
     {
+      unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+                                                   ldfile_output_machine);
+      unsigned int alignment_needed;
+      asection *o;
+
+      /* Align this section first to the input sections requirement,
+        then to the output section's requirement.  If this alignment
+        is greater than any seen before, then record it too.  Perform
+        the alignment by inserting a magic 'padding' statement.  */
+
       if (output_section_statement->subsection_alignment != -1)
-       i->alignment_power =
-       output_section_statement->subsection_alignment;
+       i->alignment_power = output_section_statement->subsection_alignment;
+
+      o = output_section_statement->bfd_section;
+      if (o->alignment_power < i->alignment_power)
+       o->alignment_power = i->alignment_power;
 
-      dot = insert_pad (this_ptr, fill, i->alignment_power,
-                       output_section_statement->bfd_section, dot);
+      alignment_needed = align_power (dot, i->alignment_power) - dot;
+
+      if (alignment_needed != 0)
+       {
+         insert_pad (this_ptr, fill, alignment_needed * opb, o, dot);
+         dot += alignment_needed;
+       }
 
       /* Remember where in the output section this input section goes.  */
 
-      i->output_offset = dot - output_section_statement->bfd_section->vma;
+      i->output_offset = dot - o->vma;
 
       /* Mark how big the output section must be to contain this now.  */
       if (i->_cooked_size != 0)
        dot += i->_cooked_size / opb;
       else
        dot += i->_raw_size / opb;
-      output_section_statement->bfd_section->_raw_size =
-       (dot - output_section_statement->bfd_section->vma) * opb;
+      o->_raw_size = (dot - o->vma) * opb;
     }
   else
     {
@@ -2777,11 +2784,6 @@ _("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
     }
 }
 
-/* This variable indicates whether bfd_relax_section should be called
-   again.  */
-
-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
@@ -2828,7 +2830,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
      lang_statement_union_type **prev;
      fill_type fill;
      bfd_vma dot;
-     boolean relax;
+     boolean *relax;
 {
   unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
                                                ldfile_output_machine);
@@ -2947,9 +2949,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                os->bfd_section->output_offset = 0;
              }
 
-           (void) lang_size_sections (os->children.head, os,
-                                      &os->children.head,
-                                      os->fill, dot, relax);
+           lang_size_sections (os->children.head, os, &os->children.head,
+                               os->fill, dot, relax);
 
            /* Put the section within the requested block size, or
               align at the block boundary.  */
@@ -3020,8 +3021,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
          dot = lang_size_sections (constructor_list.head,
                                    output_section_statement,
                                    &s->wild_statement.children.head,
-                                   fill,
-                                   dot, relax);
+                                   fill, dot, relax);
          break;
 
        case lang_data_statement_enum:
@@ -3113,12 +3113,10 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                if (! bfd_relax_section (i->owner, i, &link_info, &again))
                  einfo (_("%P%F: can't relax section: %E\n"));
                if (again)
-                 relax_again = true;
+                 *relax = true;
              }
-           dot = size_input_section (prev,
-                                     output_section_statement,
-                                     output_section_statement->fill,
-                                     dot, relax);
+           dot = size_input_section (prev, output_section_statement,
+                                     output_section_statement->fill, dot);
          }
          break;
        case lang_input_statement_enum:
@@ -3141,31 +3139,22 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
 
            if (newdot != dot)
              {
-               /* The assignment changed dot.  Insert a pad.  */
                if (output_section_statement == abs_output_section)
                  {
                    /* If we don't have an output section, then just adjust
                       the default memory address.  */
                    lang_memory_region_lookup ("*default*")->current = newdot;
                  }
-               else if (!relax)
+               else
                  {
-                   lang_statement_union_type *new =
-                     ((lang_statement_union_type *)
-                      stat_alloc (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) * opb;
-                   output_section_statement->bfd_section->_raw_size +=
-                     new->padding_statement.size;
+                   /* Insert a pad after this statement.  We can't
+                      put the pad before when relaxing, in case the
+                      assignment references dot.  */
+                   insert_pad (&s->header.next, fill, (newdot - dot) * opb,
+                               output_section_statement->bfd_section, dot);
+
+                   /* Don't neuter the pad below when relaxing.  */
+                   s = s->header.next;
                  }
 
                dot = newdot;
@@ -3174,13 +3163,15 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
          break;
 
        case lang_padding_statement_enum:
-         /* If we are relaxing, and this is not the first pass, some
-            padding statements may have been inserted during previous
-            passes.  We may have to move the padding statement to a new
-            location if dot has a different value at this point in this
-            pass than it did at this point in the previous pass.  */
-         s->padding_statement.output_offset =
-           dot - output_section_statement->bfd_section->vma;
+         if (relax)
+           {
+             /* If we are relaxing, and this is not the first pass,
+                we need to allow padding to shrink.  If padding is
+                needed on this pass, it will be added back in.  */
+             s->padding_statement.size = 0;
+             break;
+           }
+
          dot += s->padding_statement.size / opb;
          output_section_statement->bfd_section->_raw_size +=
            s->padding_statement.size;
@@ -3982,6 +3973,7 @@ static void
 reset_memory_regions ()
 {
   lang_memory_region_type *p = lang_memory_region_list;
+  asection *o;
 
   for (p = lang_memory_region_list;
        p != (lang_memory_region_type *) NULL;
@@ -3990,6 +3982,9 @@ reset_memory_regions ()
       p->old_length = (bfd_size_type) (p->current - p->origin);
       p->current = p->origin;
     }
+
+  for (o = output_bfd->sections; o != NULL; o = o->next)
+    o->_raw_size = 0;
 }
 
 /* If the wild pattern was marked KEEP, the member sections
@@ -4148,16 +4143,17 @@ lang_process ()
      section positions, since they will affect SIZEOF_HEADERS.  */
   lang_record_phdrs ();
 
+  /* Size up the sections.  */
+  lang_size_sections (statement_list.head,
+                     abs_output_section,
+                     &statement_list.head, 0, (bfd_vma) 0, NULL);
+
   /* Now run around and relax if we can.  */
   if (command_line.relax)
     {
-      /* First time round is a trial run to get the 'worst case'
-        addresses of the objects if there was no relaxing.  */
-      lang_size_sections (statement_list.head,
-                         abs_output_section,
-                         &(statement_list.head), 0, (bfd_vma) 0, false);
-
       /* Keep relaxing until bfd_relax_section gives up.  */
+      boolean relax_again;
+
       do
        {
          reset_memory_regions ();
@@ -4178,17 +4174,11 @@ lang_process ()
             globals are, so can make better guess.  */
          lang_size_sections (statement_list.head,
                              abs_output_section,
-                             &(statement_list.head), 0, (bfd_vma) 0, true);
+                             &(statement_list.head), 0, (bfd_vma) 0,
+                             &relax_again);
        }
       while (relax_again);
     }
-  else
-    {
-      /* Size up the sections.  */
-      lang_size_sections (statement_list.head,
-                         abs_output_section,
-                         &(statement_list.head), 0, (bfd_vma) 0, false);
-    }
 
   /* See if anything special should be done now we know how big
      everything is.  */
index aa05254c87eb3bec2dab8f994770cb25a9ec1575..28d236c244d4d4f470320aaf4adeec07365f911c 100644 (file)
@@ -441,7 +441,7 @@ extern bfd_vma lang_size_sections
   PARAMS ((lang_statement_union_type *s,
           lang_output_section_statement_type *output_section_statement,
           lang_statement_union_type **prev, fill_type fill,
-          bfd_vma dot, boolean relax));
+          bfd_vma dot, boolean *relax));
 extern void lang_enter_group PARAMS ((void));
 extern void lang_leave_group PARAMS ((void));
 extern void lang_add_section