This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Fix SIZEOF_HEADERS in gold.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8086551f52df808681fa09ca00dfb91e67d8d2ff

commit 8086551f52df808681fa09ca00dfb91e67d8d2ff
Author: Cary Coutant <ccoutant@gmail.com>
Date:   Wed Jun 3 20:30:11 2015 -0700

    Fix SIZEOF_HEADERS in gold.
    
    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.

Diff:
---
 gold/ChangeLog          | 12 ++++++++++++
 gold/script-sections.cc | 24 +++++++++++++++++++++---
 gold/script-sections.h  |  2 ++
 3 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/gold/ChangeLog b/gold/ChangeLog
index f5f3817..8996a97 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -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
diff --git a/gold/script-sections.cc b/gold/script-sections.cc
index 4f29c08..08c31e9 100644
--- a/gold/script-sections.cc
+++ b/gold/script-sections.cc
@@ -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
diff --git a/gold/script-sections.h b/gold/script-sections.h
index 2e07aa2..e247ea5 100644
--- a/gold/script-sections.h
+++ b/gold/script-sections.h
@@ -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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]