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:
Cary Coutant 2016-02-26 07:50:15 -08:00
parent 9fde51ed30
commit fc5a9bd57c
3 changed files with 47 additions and 5 deletions

View file

@ -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> 2016-02-15 H.J. Lu <hongjiu.lu@intel.com>
* testsuite/Makefile.am (x86_64_mov_to_lea5.o): Pass * testsuite/Makefile.am (x86_64_mov_to_lea5.o): Pass

View file

@ -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. // pointer to a PC relative offset when generating a shared library.
relocs->advance(pfdeend - pcontents); 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; unsigned int fde_shndx;
const int sym_size = elfcpp::Elf_sizes<size>::sym_size; const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
if (symndx >= symbols_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; bool is_ordinary;
fde_shndx = object->adjust_sym_shndx(symndx, sym.get_st_shndx(), fde_shndx = object->adjust_sym_shndx(symndx, sym.get_st_shndx(),
&is_ordinary); &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 // Fetch the address range field from the FDE. The offset and size
&& fde_shndx != elfcpp::SHN_UNDEF // of the field depends on the PC encoding given in the CIE, but
&& fde_shndx < object->shnum() // it is always an absolute value. If the address range is 0, this
&& !object->is_section_included(fde_shndx)) // 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. // can discard this FDE.
object->add_merge_mapping(this, shndx, (pfde - 8) - pcontents, object->add_merge_mapping(this, shndx, (pfde - 8) - pcontents,
pfdeend - (pfde - 8), -1); pfdeend - (pfde - 8), -1);

View file

@ -323,6 +323,11 @@ class Cie
unsigned int addralign, Eh_frame_hdr* eh_frame_hdr, unsigned int addralign, Eh_frame_hdr* eh_frame_hdr,
Post_fdes* post_fdes); 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&);
friend bool operator==(const Cie&, const Cie&); friend bool operator==(const Cie&, const Cie&);