Fix corrupted .eh_frame section with LTO and --gc-sections.
When --gc-sections is turned on during an LTO link, the .eh_frame sections from deferred files are processed before those from the replacement files. As a result, the section end-cap from crtendS.o is placed ahead of the .eh_frame data from the replacement files. This patch fixes the bug by skipping the layout of the deferred sections during GC pass 2. gold/ PR gold/17639 * object.cc (Sized_relobj_file): Initialize is_deferred_layout_. (Sized_relobj_file::do_layout): Handle deferred sections properly during GC pass 1. Don't add reloc sections to deferred list twice. * object.h (Sized_relobj_file::is_deferred_layout): New function. (Sized_relobj_file::is_deferred_layout_): New data member.
This commit is contained in:
parent
61e6682207
commit
c924eb67e1
3 changed files with 30 additions and 6 deletions
|
@ -1,3 +1,12 @@
|
||||||
|
2014-11-25 Cary Coutant <ccoutant@google.com>
|
||||||
|
|
||||||
|
PR gold/17639
|
||||||
|
* object.cc (Sized_relobj_file): Initialize is_deferred_layout_.
|
||||||
|
(Sized_relobj_file::do_layout): Handle deferred sections properly
|
||||||
|
during GC pass 1. Don't add reloc sections to deferred list twice.
|
||||||
|
* object.h (Sized_relobj_file::is_deferred_layout): New function.
|
||||||
|
(Sized_relobj_file::is_deferred_layout_): New data member.
|
||||||
|
|
||||||
2014-11-21 H.J. Lu <hongjiu.lu@intel.com>
|
2014-11-21 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
PR gold/17619
|
PR gold/17619
|
||||||
|
|
|
@ -430,6 +430,7 @@ Sized_relobj_file<size, big_endian>::Sized_relobj_file(
|
||||||
kept_comdat_sections_(),
|
kept_comdat_sections_(),
|
||||||
has_eh_frame_(false),
|
has_eh_frame_(false),
|
||||||
discarded_eh_frame_shndx_(-1U),
|
discarded_eh_frame_shndx_(-1U),
|
||||||
|
is_deferred_layout_(false),
|
||||||
deferred_layout_(),
|
deferred_layout_(),
|
||||||
deferred_layout_relocs_(),
|
deferred_layout_relocs_(),
|
||||||
compressed_sections_()
|
compressed_sections_()
|
||||||
|
@ -1430,6 +1431,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
|
||||||
{
|
{
|
||||||
parameters->options().plugins()->add_deferred_layout_object(this);
|
parameters->options().plugins()->add_deferred_layout_object(this);
|
||||||
this->deferred_layout_.reserve(num_sections_to_defer);
|
this->deferred_layout_.reserve(num_sections_to_defer);
|
||||||
|
this->is_deferred_layout_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whether we've seen a .note.GNU-stack section.
|
// Whether we've seen a .note.GNU-stack section.
|
||||||
|
@ -1590,10 +1592,13 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
|
||||||
{
|
{
|
||||||
if (is_pass_one)
|
if (is_pass_one)
|
||||||
{
|
{
|
||||||
|
if (this->is_deferred_layout())
|
||||||
|
out_sections[i] = reinterpret_cast<Output_section*>(2);
|
||||||
|
else
|
||||||
out_sections[i] = reinterpret_cast<Output_section*>(1);
|
out_sections[i] = reinterpret_cast<Output_section*>(1);
|
||||||
out_section_offsets[i] = invalid_address;
|
out_section_offsets[i] = invalid_address;
|
||||||
}
|
}
|
||||||
else if (should_defer_layout)
|
else if (this->is_deferred_layout())
|
||||||
this->deferred_layout_.push_back(Deferred_layout(i, name,
|
this->deferred_layout_.push_back(Deferred_layout(i, name,
|
||||||
pshdrs,
|
pshdrs,
|
||||||
reloc_shndx[i],
|
reloc_shndx[i],
|
||||||
|
@ -1658,11 +1663,12 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defer layout here if input files are claimed by plugins. When gc
|
// Defer layout here if input files are claimed by plugins. When gc
|
||||||
// is turned on this function is called twice. For the second call
|
// is turned on this function is called twice; we only want to do this
|
||||||
// should_defer_layout should be false.
|
// on the first pass.
|
||||||
if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
|
if (!is_pass_two
|
||||||
|
&& this->is_deferred_layout()
|
||||||
|
&& (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
|
||||||
{
|
{
|
||||||
gold_assert(!is_pass_two);
|
|
||||||
this->deferred_layout_.push_back(Deferred_layout(i, name,
|
this->deferred_layout_.push_back(Deferred_layout(i, name,
|
||||||
pshdrs,
|
pshdrs,
|
||||||
reloc_shndx[i],
|
reloc_shndx[i],
|
||||||
|
@ -1764,6 +1770,8 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
|
||||||
Output_section* data_section = out_sections[data_shndx];
|
Output_section* data_section = out_sections[data_shndx];
|
||||||
if (data_section == reinterpret_cast<Output_section*>(2))
|
if (data_section == reinterpret_cast<Output_section*>(2))
|
||||||
{
|
{
|
||||||
|
if (is_pass_two)
|
||||||
|
continue;
|
||||||
// The layout for the data section was deferred, so we need
|
// The layout for the data section was deferred, so we need
|
||||||
// to defer the relocation section, too.
|
// to defer the relocation section, too.
|
||||||
const char* name = pnames + shdr.get_sh_name();
|
const char* name = pnames + shdr.get_sh_name();
|
||||||
|
|
|
@ -2202,6 +2202,10 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
|
||||||
Symbol_value<size>* lv_out,
|
Symbol_value<size>* lv_out,
|
||||||
const Symbol_table* symtab);
|
const Symbol_table* symtab);
|
||||||
|
|
||||||
|
// Return true if the layout for this object was deferred.
|
||||||
|
bool is_deferred_layout() const
|
||||||
|
{ return this->is_deferred_layout_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef typename Sized_relobj<size, big_endian>::Output_sections
|
typedef typename Sized_relobj<size, big_endian>::Output_sections
|
||||||
Output_sections;
|
Output_sections;
|
||||||
|
@ -2740,6 +2744,9 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
|
||||||
// If this object has a GNU style .eh_frame section that is discarded in
|
// If this object has a GNU style .eh_frame section that is discarded in
|
||||||
// output, record the index here. Otherwise it is -1U.
|
// output, record the index here. Otherwise it is -1U.
|
||||||
unsigned int discarded_eh_frame_shndx_;
|
unsigned int discarded_eh_frame_shndx_;
|
||||||
|
// True if the layout of this object was deferred, waiting for plugin
|
||||||
|
// replacement files.
|
||||||
|
bool is_deferred_layout_;
|
||||||
// The list of sections whose layout was deferred.
|
// The list of sections whose layout was deferred.
|
||||||
std::vector<Deferred_layout> deferred_layout_;
|
std::vector<Deferred_layout> deferred_layout_;
|
||||||
// The list of relocation sections whose layout was deferred.
|
// The list of relocation sections whose layout was deferred.
|
||||||
|
|
Loading…
Reference in a new issue