Fix SIZEOF_HEADERS in gold.
authorCary Coutant <ccoutant@gmail.com>
Thu, 4 Jun 2015 03:30:11 +0000 (20:30 -0700)
committerCary Coutant <ccoutant@gmail.com>
Thu, 4 Jun 2015 03:30:11 +0000 (20:30 -0700)
Gold undercounts the number of program headers it's going to add when
initially evaluating the SIZEOF_HEADERS expression. As a result, scripts
that use it end up skipping a page unnecessarily when the starting address
is too low. The undercounting is because it doesn't count the PT_INTERP
segment.

Then, when finalizing symbols, gold overcounts the program headers: all
segments have already been created, but we still count the headers we
expected to add from the script.

This patch fixes both problems.

gold/
* script-sections.cc (Script_sections::Script_sections): Initialize
segments_created_.
(Script_sections::create_note_and_tls_segments): Set flag when
segments are created.
(Script_sections::expected_segment_count): Count PT_INTERP.
(Script_sections::attach_sections_using_phdrs_clause): Set flag when
segments are created.
* script-sections.h (Script_sections::segments_created_): New data
member.

gold/ChangeLog
gold/script-sections.cc
gold/script-sections.h

index f5f3817..8996a97 100644 (file)
@@ -1,3 +1,15 @@
+2015-06-03  Cary Coutant  <cary@google.com>
+
+       * script-sections.cc (Script_sections::Script_sections): Initialize
+       segments_created_.
+       (Script_sections::create_note_and_tls_segments): Set flag when
+       segments are created.
+       (Script_sections::expected_segment_count): Count PT_INTERP.
+       (Script_sections::attach_sections_using_phdrs_clause): Set flag when
+       segments are created.
+       * script-sections.h (Script_sections::segments_created_): New data
+       member.
+
 2015-06-03  Cary Coutant  <ccoutant@gmail.com>
 
        PR gold/15370
index 4f29c08..08c31e9 100644 (file)
@@ -3200,7 +3200,8 @@ Script_sections::Script_sections()
     data_segment_align_start_(),
     saw_data_segment_align_(false),
     saw_relro_end_(false),
-    saw_segment_start_expression_(false)
+    saw_segment_start_expression_(false),
+    segments_created_(false)
 {
 }
 
@@ -4007,8 +4008,8 @@ Script_sections::create_note_and_tls_segments(
          saw_tls = true;
        }
 
-      // If we are making a shared library, and we see a section named
-      // .interp then put the .interp section in a PT_INTERP segment.
+      // If we see a section named .interp then put the .interp section
+      // in a PT_INTERP segment.
       // This is for GNU ld compatibility.
       if (strcmp((*p)->name(), ".interp") == 0)
        {
@@ -4019,6 +4020,8 @@ Script_sections::create_note_and_tls_segments(
          oseg->add_output_section_to_nonload(*p, seg_flags);
        }
     }
+
+    this->segments_created_ = true;
 }
 
 // Add a program header.  The PHDRS clause is syntactically distinct
@@ -4046,6 +4049,10 @@ Script_sections::add_phdr(const char* name, size_t namelen, unsigned int type,
 size_t
 Script_sections::expected_segment_count(const Layout* layout) const
 {
+  // If we've already created the segments, we won't be adding any more.
+  if (this->segments_created_)
+    return 0;
+
   if (this->saw_phdrs_clause())
     return this->phdrs_elements_->size();
 
@@ -4057,6 +4064,7 @@ Script_sections::expected_segment_count(const Layout* layout) const
 
   bool saw_note = false;
   bool saw_tls = false;
+  bool saw_interp = false;
   for (Layout::Section_list::const_iterator p = sections.begin();
        p != sections.end();
        ++p)
@@ -4080,6 +4088,15 @@ Script_sections::expected_segment_count(const Layout* layout) const
              saw_tls = true;
            }
        }
+      else if (strcmp((*p)->name(), ".interp") == 0)
+       {
+         // There can only be one PT_INTERP segment.
+         if (!saw_interp)
+           {
+             ++ret;
+             saw_interp = true;
+           }
+       }
     }
 
   return ret;
@@ -4108,6 +4125,7 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
        p != this->phdrs_elements_->end();
        ++p)
     name_to_segment[(*p)->name()] = (*p)->create_segment(layout);
+  this->segments_created_ = true;
 
   // Walk through the output sections and attach them to segments.
   // Output sections in the script which do not list segments are
index 2e07aa2..e247ea5 100644 (file)
@@ -319,6 +319,8 @@ class Script_sections
   bool saw_relro_end_;
   // Whether we have seen SEGMENT_START.
   bool saw_segment_start_expression_;
+  // Whether we have created all necessary segments.
+  bool segments_created_;
 };
 
 // Attributes for memory regions.