Fix failure in exception_static_test.
Because the __EH_FRAME_BEGIN__ symbol is provided in an empty .eh_frame section in crtbeginT.o, if crt1.o has a non-empty .eh_frame section, we place all optimized .eh_frame sections into the output section ahead of the __EH_FRAME_BEGIN__ symbol, which breaks EH for statically-linked binaries. This patch fixes the problem by delaying the attachment of the optimized .eh_frame sections to the output section until we see the end marker section (or to the end of pass 1 if we never see an end marker). gold/ PR gold/14675 * ehframe.cc (Eh_frame::add_ehframe_input_section): Change return type; return enum indicating whether .eh_frame section is empty, optimizable, unrecognized, or an end marker. Adjust explicit instantiations. * ehframe.h (Eh_frame::Eh_frame_section_disposition): New enum type. (Eh_frame::add_ehframe_input_section): Change return type. * gold.cc (queue_middle_tasks): Call Layout::finalize_eh_frame_section. * layout.cc (Layout::layout_eh_frame): Don't add optimized sections to the .eh_frame output section until we see the end marker. (Layout::finalize_eh_frame_section): New. * layout.h: (Layout::finalize_eh_frame_section): New.
This commit is contained in:
parent
9a9df97001
commit
e16631979e
6 changed files with 92 additions and 41 deletions
|
@ -1,3 +1,17 @@
|
||||||
|
2015-03-09 Cary Coutant <ccoutant@google.com>
|
||||||
|
|
||||||
|
PR gold/14675
|
||||||
|
* ehframe.cc (Eh_frame::add_ehframe_input_section): Change return type;
|
||||||
|
return enum indicating whether .eh_frame section is empty, optimizable,
|
||||||
|
unrecognized, or an end marker. Adjust explicit instantiations.
|
||||||
|
* ehframe.h (Eh_frame::Eh_frame_section_disposition): New enum type.
|
||||||
|
(Eh_frame::add_ehframe_input_section): Change return type.
|
||||||
|
* gold.cc (queue_middle_tasks): Call Layout::finalize_eh_frame_section.
|
||||||
|
* layout.cc (Layout::layout_eh_frame): Don't add optimized sections
|
||||||
|
to the .eh_frame output section until we see the end marker.
|
||||||
|
(Layout::finalize_eh_frame_section): New.
|
||||||
|
* layout.h: (Layout::finalize_eh_frame_section): New.
|
||||||
|
|
||||||
2015-03-05 H.J. Lu <hongjiu.lu@intel.com>
|
2015-03-05 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* output.cc (Relobj::initialize_input_to_output_map<size>):
|
* output.cc (Relobj::initialize_input_to_output_map<size>):
|
||||||
|
|
|
@ -567,7 +567,7 @@ Eh_frame::skip_leb128(const unsigned char** pp, const unsigned char* pend)
|
||||||
// section.
|
// section.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
bool
|
Eh_frame::Eh_frame_section_disposition
|
||||||
Eh_frame::add_ehframe_input_section(
|
Eh_frame::add_ehframe_input_section(
|
||||||
Sized_relobj_file<size, big_endian>* object,
|
Sized_relobj_file<size, big_endian>* object,
|
||||||
const unsigned char* symbols,
|
const unsigned char* symbols,
|
||||||
|
@ -584,7 +584,7 @@ Eh_frame::add_ehframe_input_section(
|
||||||
&contents_len,
|
&contents_len,
|
||||||
false);
|
false);
|
||||||
if (contents_len == 0)
|
if (contents_len == 0)
|
||||||
return false;
|
return EH_EMPTY_SECTION;
|
||||||
|
|
||||||
// If this is the marker section for the end of the data, then
|
// If this is the marker section for the end of the data, then
|
||||||
// return false to force it to be handled as an ordinary input
|
// return false to force it to be handled as an ordinary input
|
||||||
|
@ -592,7 +592,7 @@ Eh_frame::add_ehframe_input_section(
|
||||||
// of unrecognized .eh_frame sections.
|
// of unrecognized .eh_frame sections.
|
||||||
if (contents_len == 4
|
if (contents_len == 4
|
||||||
&& elfcpp::Swap<32, big_endian>::readval(pcontents) == 0)
|
&& elfcpp::Swap<32, big_endian>::readval(pcontents) == 0)
|
||||||
return false;
|
return EH_END_MARKER_SECTION;
|
||||||
|
|
||||||
New_cies new_cies;
|
New_cies new_cies;
|
||||||
if (!this->do_add_ehframe_input_section(object, symbols, symbols_size,
|
if (!this->do_add_ehframe_input_section(object, symbols, symbols_size,
|
||||||
|
@ -609,7 +609,7 @@ Eh_frame::add_ehframe_input_section(
|
||||||
++p)
|
++p)
|
||||||
delete p->first;
|
delete p->first;
|
||||||
|
|
||||||
return false;
|
return EH_UNRECOGNIZED_SECTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we know we are using this section, record any new CIEs
|
// Now that we know we are using this section, record any new CIEs
|
||||||
|
@ -624,7 +624,7 @@ Eh_frame::add_ehframe_input_section(
|
||||||
this->unmergeable_cie_offsets_.push_back(p->first);
|
this->unmergeable_cie_offsets_.push_back(p->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return EH_OPTIMIZABLE_SECTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The bulk of the implementation of add_ehframe_input_section.
|
// The bulk of the implementation of add_ehframe_input_section.
|
||||||
|
@ -1206,7 +1206,7 @@ Eh_frame::do_sized_write(unsigned char* oview)
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_32_LITTLE
|
#ifdef HAVE_TARGET_32_LITTLE
|
||||||
template
|
template
|
||||||
bool
|
Eh_frame::Eh_frame_section_disposition
|
||||||
Eh_frame::add_ehframe_input_section<32, false>(
|
Eh_frame::add_ehframe_input_section<32, false>(
|
||||||
Sized_relobj_file<32, false>* object,
|
Sized_relobj_file<32, false>* object,
|
||||||
const unsigned char* symbols,
|
const unsigned char* symbols,
|
||||||
|
@ -1220,7 +1220,7 @@ Eh_frame::add_ehframe_input_section<32, false>(
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_32_BIG
|
#ifdef HAVE_TARGET_32_BIG
|
||||||
template
|
template
|
||||||
bool
|
Eh_frame::Eh_frame_section_disposition
|
||||||
Eh_frame::add_ehframe_input_section<32, true>(
|
Eh_frame::add_ehframe_input_section<32, true>(
|
||||||
Sized_relobj_file<32, true>* object,
|
Sized_relobj_file<32, true>* object,
|
||||||
const unsigned char* symbols,
|
const unsigned char* symbols,
|
||||||
|
@ -1234,7 +1234,7 @@ Eh_frame::add_ehframe_input_section<32, true>(
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_64_LITTLE
|
#ifdef HAVE_TARGET_64_LITTLE
|
||||||
template
|
template
|
||||||
bool
|
Eh_frame::Eh_frame_section_disposition
|
||||||
Eh_frame::add_ehframe_input_section<64, false>(
|
Eh_frame::add_ehframe_input_section<64, false>(
|
||||||
Sized_relobj_file<64, false>* object,
|
Sized_relobj_file<64, false>* object,
|
||||||
const unsigned char* symbols,
|
const unsigned char* symbols,
|
||||||
|
@ -1248,7 +1248,7 @@ Eh_frame::add_ehframe_input_section<64, false>(
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_64_BIG
|
#ifdef HAVE_TARGET_64_BIG
|
||||||
template
|
template
|
||||||
bool
|
Eh_frame::Eh_frame_section_disposition
|
||||||
Eh_frame::add_ehframe_input_section<64, true>(
|
Eh_frame::add_ehframe_input_section<64, true>(
|
||||||
Sized_relobj_file<64, true>* object,
|
Sized_relobj_file<64, true>* object,
|
||||||
const unsigned char* symbols,
|
const unsigned char* symbols,
|
||||||
|
|
|
@ -359,6 +359,14 @@ extern bool operator==(const Cie&, const Cie&);
|
||||||
class Eh_frame : public Output_section_data
|
class Eh_frame : public Output_section_data
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum Eh_frame_section_disposition
|
||||||
|
{
|
||||||
|
EH_EMPTY_SECTION,
|
||||||
|
EH_UNRECOGNIZED_SECTION,
|
||||||
|
EH_OPTIMIZABLE_SECTION,
|
||||||
|
EH_END_MARKER_SECTION
|
||||||
|
};
|
||||||
|
|
||||||
Eh_frame();
|
Eh_frame();
|
||||||
|
|
||||||
// Record the associated Eh_frame_hdr, if any.
|
// Record the associated Eh_frame_hdr, if any.
|
||||||
|
@ -374,7 +382,7 @@ class Eh_frame : public Output_section_data
|
||||||
// returns whether the section was incorporated into the .eh_frame
|
// returns whether the section was incorporated into the .eh_frame
|
||||||
// data.
|
// data.
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
bool
|
Eh_frame_section_disposition
|
||||||
add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object,
|
add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object,
|
||||||
const unsigned char* symbols,
|
const unsigned char* symbols,
|
||||||
section_size_type symbols_size,
|
section_size_type symbols_size,
|
||||||
|
|
|
@ -492,6 +492,9 @@ queue_middle_tasks(const General_options& options,
|
||||||
if (timer != NULL)
|
if (timer != NULL)
|
||||||
timer->stamp(0);
|
timer->stamp(0);
|
||||||
|
|
||||||
|
// Finalize the .eh_frame section.
|
||||||
|
layout->finalize_eh_frame_section();
|
||||||
|
|
||||||
// Add any symbols named with -u options to the symbol table.
|
// Add any symbols named with -u options to the symbol table.
|
||||||
symtab->add_undefined_symbols_from_command_line(layout);
|
symtab->add_undefined_symbols_from_command_line(layout);
|
||||||
|
|
||||||
|
|
|
@ -1420,15 +1420,21 @@ Layout::layout_eh_frame(Sized_relobj_file<size, big_endian>* object,
|
||||||
|
|
||||||
elfcpp::Elf_Xword orig_flags = os->flags();
|
elfcpp::Elf_Xword orig_flags = os->flags();
|
||||||
|
|
||||||
if (!parameters->incremental()
|
Eh_frame::Eh_frame_section_disposition disp =
|
||||||
&& this->eh_frame_data_->add_ehframe_input_section(object,
|
Eh_frame::EH_UNRECOGNIZED_SECTION;
|
||||||
|
if (!parameters->incremental())
|
||||||
|
{
|
||||||
|
disp = this->eh_frame_data_->add_ehframe_input_section(object,
|
||||||
symbols,
|
symbols,
|
||||||
symbols_size,
|
symbols_size,
|
||||||
symbol_names,
|
symbol_names,
|
||||||
symbol_names_size,
|
symbol_names_size,
|
||||||
shndx,
|
shndx,
|
||||||
reloc_shndx,
|
reloc_shndx,
|
||||||
reloc_type))
|
reloc_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disp == Eh_frame::EH_OPTIMIZABLE_SECTION)
|
||||||
{
|
{
|
||||||
os->update_flags_for_input_section(shdr.get_sh_flags());
|
os->update_flags_for_input_section(shdr.get_sh_flags());
|
||||||
|
|
||||||
|
@ -1440,20 +1446,21 @@ Layout::layout_eh_frame(Sized_relobj_file<size, big_endian>* object,
|
||||||
os->set_order(ORDER_RELRO);
|
os->set_order(ORDER_RELRO);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We found a .eh_frame section we are going to optimize, so now
|
*off = -1;
|
||||||
// we can add the set of optimized sections to the output
|
return os;
|
||||||
// section. We need to postpone adding this until we've found a
|
}
|
||||||
// section we can optimize so that the .eh_frame section in
|
|
||||||
// crtbegin.o winds up at the start of the output section.
|
if (disp == Eh_frame::EH_END_MARKER_SECTION && !this->added_eh_frame_data_)
|
||||||
if (!this->added_eh_frame_data_)
|
|
||||||
{
|
{
|
||||||
|
// We found the end marker section, so now we can add the set of
|
||||||
|
// optimized sections to the output section. We need to postpone
|
||||||
|
// adding this until we've found a section we can optimize so that
|
||||||
|
// the .eh_frame section in crtbeginT.o winds up at the start of
|
||||||
|
// the output section.
|
||||||
os->add_output_section_data(this->eh_frame_data_);
|
os->add_output_section_data(this->eh_frame_data_);
|
||||||
this->added_eh_frame_data_ = true;
|
this->added_eh_frame_data_ = true;
|
||||||
}
|
}
|
||||||
*off = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We couldn't handle this .eh_frame section for some reason.
|
// We couldn't handle this .eh_frame section for some reason.
|
||||||
// Add it as a normal section.
|
// Add it as a normal section.
|
||||||
bool saw_sections_clause = this->script_options_->saw_sections_clause();
|
bool saw_sections_clause = this->script_options_->saw_sections_clause();
|
||||||
|
@ -1464,11 +1471,24 @@ Layout::layout_eh_frame(Sized_relobj_file<size, big_endian>* object,
|
||||||
if ((orig_flags & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR))
|
if ((orig_flags & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR))
|
||||||
!= (os->flags() & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR)))
|
!= (os->flags() & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR)))
|
||||||
os->set_order(this->default_section_order(os, false));
|
os->set_order(this->default_section_order(os, false));
|
||||||
}
|
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Layout::finalize_eh_frame_section()
|
||||||
|
{
|
||||||
|
// If we never found an end marker section, we need to add the
|
||||||
|
// optimized eh sections to the output section now.
|
||||||
|
if (!parameters->incremental()
|
||||||
|
&& this->eh_frame_section_ != NULL
|
||||||
|
&& !this->added_eh_frame_data_)
|
||||||
|
{
|
||||||
|
this->eh_frame_section_->add_output_section_data(this->eh_frame_data_);
|
||||||
|
this->added_eh_frame_data_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create and return the magic .eh_frame section. Create
|
// Create and return the magic .eh_frame section. Create
|
||||||
// .eh_frame_hdr also if appropriate. OBJECT is the object with the
|
// .eh_frame_hdr also if appropriate. OBJECT is the object with the
|
||||||
// input .eh_frame section; it may be NULL.
|
// input .eh_frame section; it may be NULL.
|
||||||
|
|
|
@ -635,6 +635,12 @@ class Layout
|
||||||
unsigned int reloc_shndx, unsigned int reloc_type,
|
unsigned int reloc_shndx, unsigned int reloc_type,
|
||||||
off_t* offset);
|
off_t* offset);
|
||||||
|
|
||||||
|
// After processing all input files, we call this to make sure that
|
||||||
|
// the optimized .eh_frame sections have been added to the output
|
||||||
|
// section.
|
||||||
|
void
|
||||||
|
finalize_eh_frame_section();
|
||||||
|
|
||||||
// Add .eh_frame information for a PLT. The FDE must start with a
|
// Add .eh_frame information for a PLT. The FDE must start with a
|
||||||
// 4-byte PC-relative reference to the start of the PLT, followed by
|
// 4-byte PC-relative reference to the start of the PLT, followed by
|
||||||
// a 4-byte size of PLT.
|
// a 4-byte size of PLT.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue