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.
This commit is contained in:
Cary Coutant 2016-12-12 17:52:09 -08:00
parent 75c6202b1d
commit d81222d386
2 changed files with 42 additions and 3 deletions

View File

@ -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

View File

@ -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;