aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@gmail.com>2016-12-12 17:52:09 -0800
committerCary Coutant <ccoutant@gmail.com>2016-12-12 17:52:53 -0800
commitd81222d3863037a90e0402cf438f7e45600feea2 (patch)
tree7f1c9de2b682bb391df3586758588588d79ca4c1
parent75c6202b1d13b892581e8dd56b8e0664815390c1 (diff)
downloadgdb-d81222d3863037a90e0402cf438f7e45600feea2.zip
gdb-d81222d3863037a90e0402cf438f7e45600feea2.tar.gz
gdb-d81222d3863037a90e0402cf438f7e45600feea2.tar.bz2
Fix edge cases in orphan section placement.
There were still some cases I found where orphan section placement was screwy -- where the script has no output section description for either .data or .bss, a .bss orphan section ends up getting placed before the .data section. In addition, if there is an output section description for a data section not named .data (e.g., .rela.dyn), the orphan .bss gets placed before it. This patch cleans that up, by tracking the last allocated section even as we're adding orphans. I've also improved segment layout in the absence of a PHDRS clause. A zero-length NOBITS section will no longer force a new segment when followed by a PROGBITS section. 2016-12-12 Cary Coutant <ccoutant@gmail.com> gold/ * script-sections.cc (Orphan_section_placement::update_last_alloc): New method. (Orphan_section_placement::find_place): Place orphan .data section after either RODATA or TEXT. (Script_sections::place_orphan): Call update_last_alloc for allocated sections. (Script_sections::create_segments): Improve handling of BSS.
-rw-r--r--gold/ChangeLog10
-rw-r--r--gold/script-sections.cc35
2 files changed, 42 insertions, 3 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index ef0dc13..aeec389 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,13 @@
+2016-12-12 Cary Coutant <ccoutant@gmail.com>
+
+ * script-sections.cc (Orphan_section_placement::update_last_alloc):
+ New method.
+ (Orphan_section_placement::find_place): Place orphan .data section
+ after either RODATA or TEXT.
+ (Script_sections::place_orphan): Call update_last_alloc for allocated
+ sections.
+ (Script_sections::create_segments): Improve handling of BSS.
+
2016-12-13 Alan Modra <amodra@gmail.com>
PR gold/16711
diff --git a/gold/script-sections.cc b/gold/script-sections.cc
index ae81f89..d970e57 100644
--- a/gold/script-sections.cc
+++ b/gold/script-sections.cc
@@ -313,6 +313,10 @@ class Orphan_section_placement
bool
find_place(Output_section*, Elements_iterator** pwhere);
+ // Update PLACE_LAST_ALLOC.
+ void
+ update_last_alloc(Elements_iterator where);
+
// Return the iterator being used for sections at the very end of
// the linker script.
Elements_iterator
@@ -519,6 +523,11 @@ Orphan_section_placement::find_place(Output_section* os,
case PLACE_RODATA:
follow = PLACE_TEXT;
break;
+ case PLACE_DATA:
+ follow = PLACE_RODATA;
+ if (!this->places_[PLACE_RODATA].have_location)
+ follow = PLACE_TEXT;
+ break;
case PLACE_BSS:
follow = PLACE_LAST_ALLOC;
break;
@@ -557,6 +566,20 @@ Orphan_section_placement::find_place(Output_section* os,
return ret;
}
+// Update PLACE_LAST_ALLOC.
+void
+Orphan_section_placement::update_last_alloc(Elements_iterator elem)
+{
+ Elements_iterator prev = elem;
+ --prev;
+ if (this->places_[PLACE_LAST_ALLOC].have_location
+ && this->places_[PLACE_LAST_ALLOC].location == prev)
+ {
+ this->places_[PLACE_LAST_ALLOC].have_location = true;
+ this->places_[PLACE_LAST_ALLOC].location = elem;
+ }
+}
+
// Return the iterator being used for sections at the very end of the
// linker script.
@@ -3617,6 +3640,9 @@ Script_sections::place_orphan(Output_section* os)
Sections_elements::iterator last = osp->last_place();
*where = this->sections_elements_->insert(last, orphan);
}
+
+ if ((os->flags() & elfcpp::SHF_ALLOC) != 0)
+ osp->update_last_alloc(*where);
}
// Set the addresses of all the output sections. Walk through all the
@@ -3926,10 +3952,10 @@ Script_sections::create_segments(Layout* layout, uint64_t dot_alignment)
Output_segment* first_seg = NULL;
Output_segment* current_seg = NULL;
bool is_current_seg_readonly = true;
- Layout::Section_list::iterator plast = sections.end();
uint64_t last_vma = 0;
uint64_t last_lma = 0;
uint64_t last_size = 0;
+ bool in_bss = false;
for (Layout::Section_list::iterator p = sections.begin();
p != sections.end();
++p)
@@ -3956,7 +3982,7 @@ Script_sections::create_segments(Layout* layout, uint64_t dot_alignment)
// skipping a page.
need_new_segment = true;
}
- else if (is_bss_section(*plast) && !is_bss_section(*p))
+ else if (in_bss && !is_bss_section(*p))
{
// A non-BSS section can not follow a BSS section in the
// same segment.
@@ -3988,6 +4014,7 @@ Script_sections::create_segments(Layout* layout, uint64_t dot_alignment)
if (first_seg == NULL)
first_seg = current_seg;
is_current_seg_readonly = true;
+ in_bss = false;
}
current_seg->add_output_section_to_load(layout, *p, seg_flags);
@@ -3995,7 +4022,9 @@ Script_sections::create_segments(Layout* layout, uint64_t dot_alignment)
if (((*p)->flags() & elfcpp::SHF_WRITE) != 0)
is_current_seg_readonly = false;
- plast = p;
+ if (is_bss_section(*p) && size > 0)
+ in_bss = true;
+
last_vma = vma;
last_lma = lma;
last_size = size;