PR gold/12898
* layout.cc (Layout::segment_precedes): Don't crash if a linker script create indistinguishable segments. (Layout::set_segment_offsets): Use stable_sort when sorting segments. Pass this to Compare_segments constructor. * layout.h (class Layout): Make segment_precedes non-static. (class Compare_segments): Change from struct to class. Add layout_ field. Add constructor. * script-sections.cc (Script_sections::attach_sections_using_phdrs_clause): Rename local orphan to is_orphan. Don't report failure to put empty section in segment. On attachment failure, report name of section, and attach to first PT_LOAD segment.
This commit is contained in:
parent
d555a4fbf3
commit
aecf301fb9
4 changed files with 63 additions and 16 deletions
|
@ -1,3 +1,19 @@
|
||||||
|
2011-06-28 Ian Lance Taylor <iant@google.com>
|
||||||
|
|
||||||
|
PR gold/12898
|
||||||
|
* layout.cc (Layout::segment_precedes): Don't crash if a linker
|
||||||
|
script create indistinguishable segments.
|
||||||
|
(Layout::set_segment_offsets): Use stable_sort when sorting
|
||||||
|
segments. Pass this to Compare_segments constructor.
|
||||||
|
* layout.h (class Layout): Make segment_precedes non-static.
|
||||||
|
(class Compare_segments): Change from struct to class. Add
|
||||||
|
layout_ field. Add constructor.
|
||||||
|
* script-sections.cc
|
||||||
|
(Script_sections::attach_sections_using_phdrs_clause): Rename
|
||||||
|
local orphan to is_orphan. Don't report failure to put empty
|
||||||
|
section in segment. On attachment failure, report name of
|
||||||
|
section, and attach to first PT_LOAD segment.
|
||||||
|
|
||||||
2011-06-28 Ian Lance Taylor <iant@google.com>
|
2011-06-28 Ian Lance Taylor <iant@google.com>
|
||||||
|
|
||||||
PR gold/12934
|
PR gold/12934
|
||||||
|
|
|
@ -2751,7 +2751,7 @@ Layout::create_incremental_info_sections(Symbol_table* symtab)
|
||||||
|
|
||||||
// Return whether SEG1 should be before SEG2 in the output file. This
|
// Return whether SEG1 should be before SEG2 in the output file. This
|
||||||
// is based entirely on the segment type and flags. When this is
|
// is based entirely on the segment type and flags. When this is
|
||||||
// called the segment addresses has normally not yet been set.
|
// called the segment addresses have normally not yet been set.
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Layout::segment_precedes(const Output_segment* seg1,
|
Layout::segment_precedes(const Output_segment* seg1,
|
||||||
|
@ -2877,8 +2877,10 @@ Layout::segment_precedes(const Output_segment* seg1,
|
||||||
return (flags1 & elfcpp::PF_R) == 0;
|
return (flags1 & elfcpp::PF_R) == 0;
|
||||||
|
|
||||||
// We shouldn't get here--we shouldn't create segments which we
|
// We shouldn't get here--we shouldn't create segments which we
|
||||||
// can't distinguish.
|
// can't distinguish. Unless of course we are using a weird linker
|
||||||
gold_unreachable();
|
// script.
|
||||||
|
gold_assert(this->script_options_->saw_phdrs_clause());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increase OFF so that it is congruent to ADDR modulo ABI_PAGESIZE.
|
// Increase OFF so that it is congruent to ADDR modulo ABI_PAGESIZE.
|
||||||
|
@ -2902,9 +2904,11 @@ off_t
|
||||||
Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
|
Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
|
||||||
unsigned int* pshndx)
|
unsigned int* pshndx)
|
||||||
{
|
{
|
||||||
// Sort them into the final order.
|
// Sort them into the final order. We use a stable sort so that we
|
||||||
std::sort(this->segment_list_.begin(), this->segment_list_.end(),
|
// don't randomize the order of indistinguishable segments created
|
||||||
Layout::Compare_segments());
|
// by linker scripts.
|
||||||
|
std::stable_sort(this->segment_list_.begin(), this->segment_list_.end(),
|
||||||
|
Layout::Compare_segments(this));
|
||||||
|
|
||||||
// Find the PT_LOAD segments, and set their addresses and offsets
|
// Find the PT_LOAD segments, and set their addresses and offsets
|
||||||
// and their section's addresses and offsets.
|
// and their section's addresses and offsets.
|
||||||
|
|
|
@ -1052,7 +1052,7 @@ class Layout
|
||||||
place_orphan_sections_in_script();
|
place_orphan_sections_in_script();
|
||||||
|
|
||||||
// Return whether SEG1 comes before SEG2 in the output file.
|
// Return whether SEG1 comes before SEG2 in the output file.
|
||||||
static bool
|
bool
|
||||||
segment_precedes(const Output_segment* seg1, const Output_segment* seg2);
|
segment_precedes(const Output_segment* seg1, const Output_segment* seg2);
|
||||||
|
|
||||||
// Use to save and restore segments during relaxation.
|
// Use to save and restore segments during relaxation.
|
||||||
|
@ -1102,11 +1102,19 @@ class Layout
|
||||||
|
|
||||||
// A comparison class for segments.
|
// A comparison class for segments.
|
||||||
|
|
||||||
struct Compare_segments
|
class Compare_segments
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
Compare_segments(Layout* layout)
|
||||||
|
: layout_(layout)
|
||||||
|
{ }
|
||||||
|
|
||||||
bool
|
bool
|
||||||
operator()(const Output_segment* seg1, const Output_segment* seg2)
|
operator()(const Output_segment* seg1, const Output_segment* seg2)
|
||||||
{ return Layout::segment_precedes(seg1, seg2); }
|
{ return this->layout_->segment_precedes(seg1, seg2); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Layout* layout_;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<Output_section_data*> Output_section_data_list;
|
typedef std::vector<Output_section_data*> Output_section_data_list;
|
||||||
|
|
|
@ -4050,15 +4050,37 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
|
||||||
p != this->sections_elements_->end();
|
p != this->sections_elements_->end();
|
||||||
++p)
|
++p)
|
||||||
{
|
{
|
||||||
bool orphan;
|
bool is_orphan;
|
||||||
String_list* old_phdr_names = phdr_names;
|
String_list* old_phdr_names = phdr_names;
|
||||||
Output_section* os = (*p)->allocate_to_segment(&phdr_names, &orphan);
|
Output_section* os = (*p)->allocate_to_segment(&phdr_names, &is_orphan);
|
||||||
if (os == NULL)
|
if (os == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
elfcpp::Elf_Word seg_flags =
|
||||||
|
Layout::section_flags_to_segment(os->flags());
|
||||||
|
|
||||||
if (phdr_names == NULL)
|
if (phdr_names == NULL)
|
||||||
{
|
{
|
||||||
gold_error(_("allocated section not in any segment"));
|
// Don't worry about empty orphan sections.
|
||||||
|
if (is_orphan && os->current_data_size() > 0)
|
||||||
|
gold_error(_("allocated section %s not in any segment"),
|
||||||
|
os->name());
|
||||||
|
|
||||||
|
// To avoid later crashes drop this section into the first
|
||||||
|
// PT_LOAD segment.
|
||||||
|
for (Phdrs_elements::const_iterator ppe =
|
||||||
|
this->phdrs_elements_->begin();
|
||||||
|
ppe != this->phdrs_elements_->end();
|
||||||
|
++ppe)
|
||||||
|
{
|
||||||
|
Output_segment* oseg = (*ppe)->segment();
|
||||||
|
if (oseg->type() == elfcpp::PT_LOAD)
|
||||||
|
{
|
||||||
|
oseg->add_output_section_to_load(layout, os, seg_flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4073,7 +4095,7 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
|
||||||
// PT_INTERP segment will pick up following orphan sections,
|
// PT_INTERP segment will pick up following orphan sections,
|
||||||
// which does not make sense. If this is not an orphan section,
|
// which does not make sense. If this is not an orphan section,
|
||||||
// we trust the linker script.
|
// we trust the linker script.
|
||||||
if (orphan)
|
if (is_orphan)
|
||||||
{
|
{
|
||||||
// Enable PT_LOAD segments only filtering until we see another
|
// Enable PT_LOAD segments only filtering until we see another
|
||||||
// list of segment names.
|
// list of segment names.
|
||||||
|
@ -4094,9 +4116,6 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
|
||||||
&& r->second->type() != elfcpp::PT_LOAD)
|
&& r->second->type() != elfcpp::PT_LOAD)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
elfcpp::Elf_Word seg_flags =
|
|
||||||
Layout::section_flags_to_segment(os->flags());
|
|
||||||
|
|
||||||
if (r->second->type() != elfcpp::PT_LOAD)
|
if (r->second->type() != elfcpp::PT_LOAD)
|
||||||
r->second->add_output_section_to_nonload(os, seg_flags);
|
r->second->add_output_section_to_nonload(os, seg_flags);
|
||||||
else
|
else
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue