From 43679a61031608451d20ee2a19aa6808162690fa Mon Sep 17 00:00:00 2001 From: Matthias Maennich Date: Mon, 21 Oct 2019 17:09:49 +0100 Subject: [PATCH] dwarf-reader: refactor try_reading_first_ksymtab_entry_using{pre,}_v4_19_format Avoid code duplication and increase maintainebility of these helper functions. As their only difference was the application of position relative relocations, consolidate them and add a flag for exactly this feature. This is purely stylistic and not changing functionality. * src/abg-dwarf-reader.cc(try_reading_first_ksymtab_entry): New function to consolidate functionality for try_reading_first_ksymtab_entry_using_{pre,}v4_19_format functions. (try_reading_first_ksymtab_entry_using_v4_19_format, try_reading_first_ksymtab_entry_using_pre_v4_19_format): refactor to use try_reading_first_ksymtab_entry Signed-off-by: Matthias Maennich Signed-off-by: Dodji Seketeli --- src/abg-dwarf-reader.cc | 101 ++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 41 deletions(-) diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc index 1ae0ed70..278cb5c0 100644 --- a/src/abg-dwarf-reader.cc +++ b/src/abg-dwarf-reader.cc @@ -7588,67 +7588,86 @@ public: return true; } + /// Try reading the first __ksymtab section entry. + /// + /// We lookup the symbol from the raw section passed as an argument. For + /// that, consider endianess and adjust for potential Elf relocations before + /// looking up the symbol in the .symtab section. + // + /// Optionally, support position relative relocations by considering the + /// ksymtab entry as 32 bit and applying the relocation relative to the + /// section header (i.e. the symbol position as we are reading the first + /// symbol). + /// + /// @return the symbol resulting from the lookup of the symbol address we + /// got from reading the first entry of the ksymtab or null if no such entry + /// could be found. + elf_symbol_sptr + try_reading_first_ksymtab_entry(Elf_Scn* section, + bool position_relative_relocations) const + { + // this function does not support relocatable ksymtab entries (as for + // example in kernel modules). Hence assert here on not having any + // relocation sections around. We can consider this a TODO that we have to + // work around in the rest of the code. + ABG_ASSERT(!find_any_ksymtab_reloc_section()); + + Elf_Data* elf_data = elf_rawdata(section, 0); + uint8_t* bytes = reinterpret_cast(elf_data->d_buf); + bool is_big_endian = elf_architecture_is_big_endian(); + elf_symbol_sptr symbol; + GElf_Addr symbol_address = 0; + + unsigned char symbol_value_size; + if (position_relative_relocations) + symbol_value_size = sizeof(int32_t); + else + symbol_value_size = architecture_word_size(); + + if (position_relative_relocations) + { + int32_t offset = 0; + ABG_ASSERT(read_int_from_array_of_bytes(bytes, symbol_value_size, + is_big_endian, offset)); + GElf_Shdr section_header; + gelf_getshdr(section, §ion_header); + symbol_address = offset + section_header.sh_addr; + } + else + ABG_ASSERT(read_int_from_array_of_bytes(bytes, symbol_value_size, + is_big_endian, symbol_address)); + + symbol_address = maybe_adjust_fn_sym_address(symbol_address); + symbol = lookup_elf_symbol_from_address(symbol_address); + return symbol; + } + /// Try reading the first __ksymtab section entry as if it is in the - /// pre-v4_19 format and lookup a symbol from the .symbol section to - /// see if that succeeds. If it does, then we can assume the - /// __ksymtab section is in the pre-v4_19 format. + /// pre-v4_19 format, that is without position relative relocations. /// /// @return the symbol resulting from the lookup of the symbol /// address we got from reading the first entry of the ksymtab - /// section assuming the pre-v4.19 format. If nil, it means the + /// section assuming the pre-v4.19 format. If null, it means the /// __ksymtab section is not in the pre-v4.19 format. elf_symbol_sptr try_reading_first_ksymtab_entry_using_pre_v4_19_format() const { Elf_Scn *section = find_any_ksymtab_section(); - Elf_Data *elf_data = elf_rawdata(section, 0); - uint8_t *bytes = reinterpret_cast(elf_data->d_buf); - bool is_big_endian = elf_architecture_is_big_endian(); - elf_symbol_sptr symbol; - unsigned char symbol_value_size = architecture_word_size(); - - GElf_Addr symbol_address = 0, adjusted_symbol_address = 0; - ABG_ASSERT(read_int_from_array_of_bytes(bytes, - symbol_value_size, - is_big_endian, - symbol_address)); - adjusted_symbol_address = maybe_adjust_fn_sym_address(symbol_address); - symbol = lookup_elf_symbol_from_address(adjusted_symbol_address); - return symbol; + return try_reading_first_ksymtab_entry(section, false); } /// Try reading the first __ksymtab section entry as if it is in the - /// v4_19 format and lookup a symbol from the .symbol section to see - /// if that succeeds. If it does, then we can assume the __ksymtab - /// section is in the v4_19 format. + /// v4_19 format, that is with position relative relocations. /// /// @return the symbol resulting from the lookup of the symbol /// address we got from reading the first entry of the ksymtab - /// section assuming the v4.19 format. If nil, it means the + /// section assuming the v4.19 format. If null, it means the /// __ksymtab section is not in the v4.19 format. elf_symbol_sptr try_reading_first_ksymtab_entry_using_v4_19_format() const { Elf_Scn *section = find_any_ksymtab_section(); - Elf_Data *elf_data = elf_rawdata(section, 0); - uint8_t *bytes = reinterpret_cast(elf_data->d_buf); - bool is_big_endian = elf_architecture_is_big_endian(); - elf_symbol_sptr symbol; - - int32_t offset = 0; - const unsigned char symbol_value_size = sizeof(offset); - GElf_Addr symbol_address = 0, adjusted_symbol_address = 0; - ABG_ASSERT(read_int_from_array_of_bytes(bytes, - symbol_value_size, - is_big_endian, - offset)); - GElf_Shdr mem; - GElf_Shdr *section_header = gelf_getshdr(section, &mem); - symbol_address = offset + section_header->sh_addr; - - adjusted_symbol_address = maybe_adjust_fn_sym_address(symbol_address); - symbol = lookup_elf_symbol_from_address(adjusted_symbol_address); - return symbol; + return try_reading_first_ksymtab_entry(section, true); } /// Try to determine the format of the __ksymtab and __ksymtab_gpl