PR gold/12571
* options.h (class General_options): Add --ld-generated-unwind-info. * ehframe.cc (Fde::write): Add address parameter. Change all callers. If associated with PLT, fill in address and size. (Cie::set_output_offset): Only add merge mapping if there is an object. (Cie::write): Add address parameter. Change all callers. (Eh_frame::add_ehframe_for_plt): New function. * ehframe.h (class Fde): Update declarations. Move shndx_ and input_offset_ fields into union u_, with new plt field. (Fde::Fde): Adjust for new union field. (Fde::Fde) [Output_data version]: New constructor. (Fde::add_mapping): Only add merge mapping if there is an object. (class Cie): Update declarations. (class Eh_frame): Declare add_ehframe_for_plt. * layout.cc (Layout::layout_eh_frame): Break out code into make_eh_frame_section, and call it. (Layout::make_eh_frame_section): New function. (Layout::add_eh_frame_for_plt): New function. * layout.h (class Layout): Update declarations. * merge.cc (Merge_map::add_mapping): Add assertion. * i386.cc: Include "dwarf.h". (class Output_data_plt_i386): Make first_plt_entry, dyn_first_plt_entry, exec_plt_entry, and dyn_plt_entry const. Add plt_eh_frame_cie_size, plt_eh_frame_fde_size, plt_eh_frame_cie, and plt_eh_frame_fde. (Output_data_plt_i386::Output_data_plt_i386): Align to 16-byte boundary. Call add_eh_frame_for_plt if appropriate. * x86_64.cc: Include "dwarf.h". (class Output_data_plt_x86_64): Align to 16-byte boundary. Make first_plt_entry, plt_entry and tlsdesc_plt_entry const. Add plt_eh_frame_cie_size, plt_eh_frame_fde_size, plt_eh_frame_cie, and plt_eh_frame_fde. (Output_data_plt_x86_64::init): Call add_eh_frame_for_plt if appropriate.
This commit is contained in:
parent
a931db6a07
commit
07a6059735
9 changed files with 408 additions and 106 deletions
|
@ -1,6 +1,6 @@
|
|||
// ehframe.cc -- handle exception frame sections for gold
|
||||
|
||||
// Copyright 2006, 2007, 2008, 2010 Free Software Foundation, Inc.
|
||||
// Copyright 2006, 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
|
||||
// Written by Ian Lance Taylor <iant@google.com>.
|
||||
|
||||
// This file is part of gold.
|
||||
|
@ -321,14 +321,16 @@ Eh_frame_hdr::get_fde_addresses(Output_file* of,
|
|||
|
||||
// Write the FDE to OVIEW starting at OFFSET. CIE_OFFSET is the
|
||||
// offset of the CIE in OVIEW. FDE_ENCODING is the encoding, from the
|
||||
// CIE. ADDRALIGN is the required alignment. Record the FDE pc for
|
||||
// EH_FRAME_HDR. Return the new offset.
|
||||
// CIE. ADDRALIGN is the required alignment. ADDRESS is the virtual
|
||||
// address of OVIEW. Record the FDE pc for EH_FRAME_HDR. Return the
|
||||
// new offset.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
section_offset_type
|
||||
Fde::write(unsigned char* oview, section_offset_type offset,
|
||||
unsigned int addralign, section_offset_type cie_offset,
|
||||
unsigned char fde_encoding, Eh_frame_hdr* eh_frame_hdr)
|
||||
uint64_t address, unsigned int addralign,
|
||||
section_offset_type cie_offset, unsigned char fde_encoding,
|
||||
Eh_frame_hdr* eh_frame_hdr)
|
||||
{
|
||||
gold_assert((offset & (addralign - 1)) == 0);
|
||||
|
||||
|
@ -355,6 +357,24 @@ Fde::write(unsigned char* oview, section_offset_type offset,
|
|||
// will later be applied to the FDE data.
|
||||
memcpy(oview + offset + 8, this->contents_.data(), length);
|
||||
|
||||
// If this FDE is associated with a PLT, fill in the PLT's address
|
||||
// and size.
|
||||
if (this->object_ == NULL)
|
||||
{
|
||||
gold_assert(memcmp(oview + offset + 8, "\0\0\0\0\0\0\0\0", 8) == 0);
|
||||
Output_data* plt = this->u_.from_linker.plt;
|
||||
uint64_t poffset = plt->address() - (address + offset + 8);
|
||||
int32_t spoffset = static_cast<int32_t>(poffset);
|
||||
off_t psize = plt->data_size();
|
||||
uint32_t upsize = static_cast<uint32_t>(psize);
|
||||
if (static_cast<uint64_t>(static_cast<int64_t>(spoffset)) != poffset
|
||||
|| static_cast<off_t>(upsize) != psize)
|
||||
gold_warning(_("overflow in PLT unwind data; "
|
||||
"unwinding through PLT may fail"));
|
||||
elfcpp::Swap<32, big_endian>::writeval(oview + offset + 8, spoffset);
|
||||
elfcpp::Swap<32, big_endian>::writeval(oview + offset + 12, upsize);
|
||||
}
|
||||
|
||||
if (aligned_full_length > length + 8)
|
||||
memset(oview + offset + length + 8, 0, aligned_full_length - (length + 8));
|
||||
|
||||
|
@ -389,8 +409,12 @@ Cie::set_output_offset(section_offset_type output_offset,
|
|||
// Add 4 for length and 4 for zero CIE identifier tag.
|
||||
length += 8;
|
||||
|
||||
merge_map->add_mapping(this->object_, this->shndx_, this->input_offset_,
|
||||
length, output_offset);
|
||||
if (this->object_ != NULL)
|
||||
{
|
||||
// Add a mapping so that relocations are applied correctly.
|
||||
merge_map->add_mapping(this->object_, this->shndx_, this->input_offset_,
|
||||
length, output_offset);
|
||||
}
|
||||
|
||||
length = align_address(length, addralign);
|
||||
|
||||
|
@ -415,7 +439,8 @@ Cie::set_output_offset(section_offset_type output_offset,
|
|||
template<int size, bool big_endian>
|
||||
section_offset_type
|
||||
Cie::write(unsigned char* oview, section_offset_type offset,
|
||||
unsigned int addralign, Eh_frame_hdr* eh_frame_hdr)
|
||||
uint64_t address, unsigned int addralign,
|
||||
Eh_frame_hdr* eh_frame_hdr)
|
||||
{
|
||||
gold_assert((offset & (addralign - 1)) == 0);
|
||||
|
||||
|
@ -448,7 +473,7 @@ Cie::write(unsigned char* oview, section_offset_type offset,
|
|||
for (std::vector<Fde*>::const_iterator p = this->fdes_.begin();
|
||||
p != this->fdes_.end();
|
||||
++p)
|
||||
offset = (*p)->write<size, big_endian>(oview, offset, addralign,
|
||||
offset = (*p)->write<size, big_endian>(oview, offset, address, addralign,
|
||||
cie_offset, fde_encoding,
|
||||
eh_frame_hdr);
|
||||
|
||||
|
@ -994,6 +1019,29 @@ Eh_frame::read_fde(Sized_relobj_file<size, big_endian>* object,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Add unwind information for a PLT.
|
||||
|
||||
void
|
||||
Eh_frame::add_ehframe_for_plt(Output_data* plt, const unsigned char* cie_data,
|
||||
size_t cie_length, const unsigned char* fde_data,
|
||||
size_t fde_length)
|
||||
{
|
||||
Cie cie(NULL, 0, 0, elfcpp::DW_EH_PE_pcrel | elfcpp::DW_EH_PE_sdata4, "",
|
||||
cie_data, cie_length);
|
||||
Cie_offsets::iterator find_cie = this->cie_offsets_.find(&cie);
|
||||
Cie* pcie;
|
||||
if (find_cie != this->cie_offsets_.end())
|
||||
pcie = *find_cie;
|
||||
else
|
||||
{
|
||||
pcie = new Cie(cie);
|
||||
this->cie_offsets_.insert(pcie);
|
||||
}
|
||||
|
||||
Fde* fde = new Fde(plt, fde_data, fde_length);
|
||||
pcie->add_fde(fde);
|
||||
}
|
||||
|
||||
// Return the number of FDEs.
|
||||
|
||||
unsigned int
|
||||
|
@ -1113,18 +1161,19 @@ template<int size, bool big_endian>
|
|||
void
|
||||
Eh_frame::do_sized_write(unsigned char* oview)
|
||||
{
|
||||
uint64_t address = this->address();
|
||||
unsigned int addralign = this->addralign();
|
||||
section_offset_type o = 0;
|
||||
for (Unmergeable_cie_offsets::iterator p =
|
||||
this->unmergeable_cie_offsets_.begin();
|
||||
p != this->unmergeable_cie_offsets_.end();
|
||||
++p)
|
||||
o = (*p)->write<size, big_endian>(oview, o, addralign,
|
||||
o = (*p)->write<size, big_endian>(oview, o, address, addralign,
|
||||
this->eh_frame_hdr_);
|
||||
for (Cie_offsets::iterator p = this->cie_offsets_.begin();
|
||||
p != this->cie_offsets_.end();
|
||||
++p)
|
||||
o = (*p)->write<size, big_endian>(oview, o, addralign,
|
||||
o = (*p)->write<size, big_endian>(oview, o, address, addralign,
|
||||
this->eh_frame_hdr_);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue