aboutsummaryrefslogtreecommitdiff
path: root/gold/script-sections.cc
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@gmail.com>2015-06-03 20:30:11 -0700
committerCary Coutant <ccoutant@gmail.com>2015-06-03 20:30:11 -0700
commit8086551f52df808681fa09ca00dfb91e67d8d2ff (patch)
tree495eb3d4047371bf419af67f46c65762ca3fd635 /gold/script-sections.cc
parent374082dfab280123f5a54a23b1c1b2cb893b4d2b (diff)
downloadgdb-8086551f52df808681fa09ca00dfb91e67d8d2ff.zip
gdb-8086551f52df808681fa09ca00dfb91e67d8d2ff.tar.gz
gdb-8086551f52df808681fa09ca00dfb91e67d8d2ff.tar.bz2
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.
Diffstat (limited to 'gold/script-sections.cc')
-rw-r--r--gold/script-sections.cc24
1 files changed, 21 insertions, 3 deletions
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