Discard FDEs for zero-length address ranges.
2016-02-26 Egor Kochetov <egor.kochetov@intel.com> Cary Coutant <ccoutant@gmail.com> gold/ PR gold/19735 * ehframe.h (Cie::fde_encoding): New method. * ehframe.cc (Eh_frame::read_fde): Discard FDEs for zero-length address ranges.
This commit is contained in:
parent
9fde51ed30
commit
fc5a9bd57c
3 changed files with 47 additions and 5 deletions
|
@ -1,3 +1,11 @@
|
|||
2016-02-26 Egor Kochetov <egor.kochetov@intel.com>
|
||||
Cary Coutant <ccoutant@gmail.com>
|
||||
|
||||
PR gold/19735
|
||||
* ehframe.h (Cie::fde_encoding): New method.
|
||||
* ehframe.cc (Eh_frame::read_fde): Discard FDEs for zero-length
|
||||
address ranges.
|
||||
|
||||
2016-02-15 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* testsuite/Makefile.am (x86_64_mov_to_lea5.o): Pass
|
||||
|
|
|
@ -1010,6 +1010,8 @@ Eh_frame::read_fde(Sized_relobj_file<size, big_endian>* object,
|
|||
// pointer to a PC relative offset when generating a shared library.
|
||||
relocs->advance(pfdeend - pcontents);
|
||||
|
||||
// Find the section index for code that this FDE describes.
|
||||
// If we have discarded the section, we can also discard the FDE.
|
||||
unsigned int fde_shndx;
|
||||
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
|
||||
if (symndx >= symbols_size / sym_size)
|
||||
|
@ -1018,13 +1020,40 @@ Eh_frame::read_fde(Sized_relobj_file<size, big_endian>* object,
|
|||
bool is_ordinary;
|
||||
fde_shndx = object->adjust_sym_shndx(symndx, sym.get_st_shndx(),
|
||||
&is_ordinary);
|
||||
bool is_discarded = (is_ordinary
|
||||
&& fde_shndx != elfcpp::SHN_UNDEF
|
||||
&& fde_shndx < object->shnum()
|
||||
&& !object->is_section_included(fde_shndx));
|
||||
|
||||
if (is_ordinary
|
||||
&& fde_shndx != elfcpp::SHN_UNDEF
|
||||
&& fde_shndx < object->shnum()
|
||||
&& !object->is_section_included(fde_shndx))
|
||||
// Fetch the address range field from the FDE. The offset and size
|
||||
// of the field depends on the PC encoding given in the CIE, but
|
||||
// it is always an absolute value. If the address range is 0, this
|
||||
// FDE corresponds to a function that was discarded during optimization
|
||||
// (too late to discard the corresponding FDE).
|
||||
uint64_t address_range = 0;
|
||||
int pc_size = cie->fde_encoding() & 7;
|
||||
if (pc_size == elfcpp::DW_EH_PE_absptr)
|
||||
pc_size = size == 32 ? elfcpp::DW_EH_PE_udata4 : elfcpp::DW_EH_PE_udata8;
|
||||
switch (pc_size)
|
||||
{
|
||||
// This FDE applies to a section which we are discarding. We
|
||||
case elfcpp::DW_EH_PE_udata2:
|
||||
address_range = elfcpp::Swap<16, big_endian>::readval(pfde + 2);
|
||||
break;
|
||||
case elfcpp::DW_EH_PE_udata4:
|
||||
address_range = elfcpp::Swap<32, big_endian>::readval(pfde + 4);
|
||||
break;
|
||||
case elfcpp::DW_EH_PE_udata8:
|
||||
gold_assert(size == 64);
|
||||
address_range = elfcpp::Swap_unaligned<64, big_endian>::readval(pfde + 8);
|
||||
break;
|
||||
default:
|
||||
// All other cases were rejected in Eh_frame::read_cie.
|
||||
gold_unreachable();
|
||||
}
|
||||
|
||||
if (is_discarded || address_range == 0)
|
||||
{
|
||||
// This FDE applies to a discarded function. We
|
||||
// can discard this FDE.
|
||||
object->add_merge_mapping(this, shndx, (pfde - 8) - pcontents,
|
||||
pfdeend - (pfde - 8), -1);
|
||||
|
|
|
@ -323,6 +323,11 @@ class Cie
|
|||
unsigned int addralign, Eh_frame_hdr* eh_frame_hdr,
|
||||
Post_fdes* post_fdes);
|
||||
|
||||
// Return the FDE encoding.
|
||||
unsigned char
|
||||
fde_encoding() const
|
||||
{ return this->fde_encoding_; }
|
||||
|
||||
friend bool operator<(const Cie&, const Cie&);
|
||||
friend bool operator==(const Cie&, const Cie&);
|
||||
|
||||
|
|
Loading…
Reference in a new issue