diff options
author | Cary Coutant <ccoutant@gmail.com> | 2015-06-03 20:30:11 -0700 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2015-06-03 20:30:11 -0700 |
commit | 8086551f52df808681fa09ca00dfb91e67d8d2ff (patch) | |
tree | 495eb3d4047371bf419af67f46c65762ca3fd635 /gold/script-sections.cc | |
parent | 374082dfab280123f5a54a23b1c1b2cb893b4d2b (diff) | |
download | fsf-binutils-gdb-8086551f52df808681fa09ca00dfb91e67d8d2ff.zip fsf-binutils-gdb-8086551f52df808681fa09ca00dfb91e67d8d2ff.tar.gz fsf-binutils-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.cc | 24 |
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 |