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 <maennich@google.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Matthias Maennich 2019-10-21 17:09:49 +01:00 committed by Dodji Seketeli
parent 847800d497
commit 43679a6103

View File

@ -7588,67 +7588,86 @@ public:
return true; 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<uint8_t*>(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, &section_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 /// 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 /// pre-v4_19 format, that is without position relative relocations.
/// see if that succeeds. If it does, then we can assume the
/// __ksymtab section is in the pre-v4_19 format.
/// ///
/// @return the symbol resulting from the lookup of the symbol /// @return the symbol resulting from the lookup of the symbol
/// address we got from reading the first entry of the ksymtab /// 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. /// __ksymtab section is not in the pre-v4.19 format.
elf_symbol_sptr elf_symbol_sptr
try_reading_first_ksymtab_entry_using_pre_v4_19_format() const try_reading_first_ksymtab_entry_using_pre_v4_19_format() const
{ {
Elf_Scn *section = find_any_ksymtab_section(); Elf_Scn *section = find_any_ksymtab_section();
Elf_Data *elf_data = elf_rawdata(section, 0); return try_reading_first_ksymtab_entry(section, false);
uint8_t *bytes = reinterpret_cast<uint8_t*>(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;
} }
/// Try reading the first __ksymtab section entry as if it is in the /// 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 /// v4_19 format, that is with position relative relocations.
/// if that succeeds. If it does, then we can assume the __ksymtab
/// section is in the v4_19 format.
/// ///
/// @return the symbol resulting from the lookup of the symbol /// @return the symbol resulting from the lookup of the symbol
/// address we got from reading the first entry of the ksymtab /// 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. /// __ksymtab section is not in the v4.19 format.
elf_symbol_sptr elf_symbol_sptr
try_reading_first_ksymtab_entry_using_v4_19_format() const try_reading_first_ksymtab_entry_using_v4_19_format() const
{ {
Elf_Scn *section = find_any_ksymtab_section(); Elf_Scn *section = find_any_ksymtab_section();
Elf_Data *elf_data = elf_rawdata(section, 0); return try_reading_first_ksymtab_entry(section, true);
uint8_t *bytes = reinterpret_cast<uint8_t*>(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;
} }
/// Try to determine the format of the __ksymtab and __ksymtab_gpl /// Try to determine the format of the __ksymtab and __ksymtab_gpl