This is the mail archive of the
binutils-cvs@sourceware.org
mailing list for the binutils project.
[binutils-gdb] Fix SIZEOF_HEADERS in gold.
- From: Cary Coutant <ccoutant at sourceware dot org>
- To: bfd-cvs at sourceware dot org
- Date: 4 Jun 2015 03:32:42 -0000
- Subject: [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.