commit dffecd133e0bde443315bbd8b8615752ef3d0ed2 Author: Egor Kochetov Date: Sat Feb 20 14:56:24 2016 +0300 Added filtering of FDEs with empty PC range Change-Id: Ie3e1adf5ad8441015dad1239fb41ffb4e37091a9 Signed-off-by: Egor Kochetov diff --git a/binutils-2.25/gold/ehframe.cc b/binutils-2.25/gold/ehframe.cc index 4f92618..08c5fc8 100644 --- a/binutils-2.25/gold/ehframe.cc +++ b/binutils-2.25/gold/ehframe.cc @@ -656,6 +656,7 @@ Eh_frame::do_add_ehframe_input_section( // Keep track of which CIEs are at which offsets. Offsets_to_cie cies; + int fde_pc_encoding; while (p < pend) { if (pend - p < 4) @@ -697,14 +698,15 @@ Eh_frame::do_add_ehframe_input_section( if (!this->read_cie(object, shndx, symbols, symbols_size, symbol_names, symbol_names_size, pcontents, p, pentend, &relocs, &cies, - new_cies)) + new_cies, fde_pc_encoding)) return false; } else { // FDE. if (!this->read_fde(object, shndx, symbols, symbols_size, - pcontents, id, p, pentend, &relocs, &cies)) + pcontents, id, p, pentend, &relocs, &cies, + fde_pc_encoding)) return false; } @@ -729,7 +731,8 @@ Eh_frame::read_cie(Sized_relobj_file* object, const unsigned char* pcieend, Track_relocs* relocs, Offsets_to_cie* cies, - New_cies* new_cies) + New_cies* new_cies, + int& fde_pc_encoding) { bool mergeable = true; @@ -811,7 +814,7 @@ Eh_frame::read_cie(Sized_relobj_file* object, if (pcieend - p < 1) return false; fde_encoding = *p; - switch (fde_encoding & 7) + switch ((fde_pc_encoding = fde_encoding & 7)) { case elfcpp::DW_EH_PE_absptr: case elfcpp::DW_EH_PE_udata2: @@ -981,7 +984,8 @@ Eh_frame::read_fde(Sized_relobj_file* object, const unsigned char* pfde, const unsigned char* pfdeend, Track_relocs* relocs, - Offsets_to_cie* cies) + Offsets_to_cie* cies, + int fde_pc_encoding) { // OFFSET is the distance between the 4 bytes before PFDE to the // start of the CIE. The offset we recorded for the CIE is 8 bytes @@ -1019,10 +1023,21 @@ Eh_frame::read_fde(Sized_relobj_file* object, fde_shndx = object->adjust_sym_shndx(symndx, sym.get_st_shndx(), &is_ordinary); - if (is_ordinary + bool is_zero_range = false; + switch (fde_pc_encoding) { + case elfcpp::DW_EH_PE_udata2: is_zero_range = *(uint16_t*)(pfde + 2) == 0; break; + case elfcpp::DW_EH_PE_udata4: is_zero_range = *(uint32_t*)(pfde + 4) == 0; break; + case elfcpp::DW_EH_PE_udata8: is_zero_range = *(uint64_t*)(pfde + 8) == 0; break; + default: + // All other cases were rejected in Eh_frame::read_cie. + gold_unreachable(); + } + + if (is_zero_range + || (is_ordinary && fde_shndx != elfcpp::SHN_UNDEF && fde_shndx < object->shnum() - && !object->is_section_included(fde_shndx)) + && !object->is_section_included(fde_shndx))) { // This FDE applies to a section which we are discarding. We // can discard this FDE. diff --git a/binutils-2.25/gold/ehframe.h b/binutils-2.25/gold/ehframe.h index e9c9da8..e50689c 100644 --- a/binutils-2.25/gold/ehframe.h +++ b/binutils-2.25/gold/ehframe.h @@ -470,6 +470,8 @@ class Eh_frame : public Output_section_data New_cies*); // Read a CIE. + // Fill the fde_pc_encoding parameter if it can be parsed. + // Returns false if the CIE is unreadable. template bool read_cie(Sized_relobj_file* object, @@ -483,7 +485,8 @@ class Eh_frame : public Output_section_data const unsigned char* pcieend, Track_relocs* relocs, Offsets_to_cie* cies, - New_cies* new_cies); + New_cies* new_cies, + int& fde_pc_encoding); // Read an FDE. template @@ -497,7 +500,8 @@ class Eh_frame : public Output_section_data const unsigned char* pfde, const unsigned char* pfdeend, Track_relocs* relocs, - Offsets_to_cie* cies); + Offsets_to_cie* cies, + int fde_pc_encoding); // Template version of write function. template