Better handle symtab loading / optionality

This commit is contained in:
Jeremy Rifkin 2025-01-28 23:14:37 -06:00
parent 73ee7aa3a1
commit 7f6945c7d9
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4
2 changed files with 25 additions and 17 deletions

View File

@ -91,14 +91,17 @@ namespace detail {
std::string elf::lookup_symbol(frame_ptr pc) { std::string elf::lookup_symbol(frame_ptr pc) {
// TODO: Also search the SHT_DYNSYM at some point, maybe // TODO: Also search the SHT_DYNSYM at some point, maybe
auto symtab_ = get_symtab(); auto symtab_ = get_symtab();
if( if(symtab_.is_error()) {
symtab_.is_error() return "";
|| symtab_.unwrap_value().strtab_link == SHN_UNDEF }
|| symtab_.unwrap_value().entries.empty() auto& maybe_symtab = symtab_.unwrap_value();
) { if(!maybe_symtab) {
return "";
}
auto& symtab = maybe_symtab.unwrap();
if(symtab.strtab_link == SHN_UNDEF) {
return ""; return "";
} }
auto& symtab = symtab_.unwrap_value();
auto strtab_ = get_strtab(symtab.strtab_link); auto strtab_ = get_strtab(symtab.strtab_link);
if(strtab_.is_error()) { if(strtab_.is_error()) {
return ""; return "";
@ -250,7 +253,7 @@ namespace detail {
return entry.data; return entry.data;
} }
Result<const elf::symtab_info&, internal_error> elf::get_symtab() { Result<const optional<elf::symtab_info>&, internal_error> elf::get_symtab() {
if(did_load_symtab) { if(did_load_symtab) {
return symtab; return symtab;
} }
@ -266,7 +269,7 @@ namespace detail {
} }
template<std::size_t Bits> template<std::size_t Bits>
Result<const elf::symtab_info&, internal_error> elf::get_symtab_impl() { Result<const optional<elf::symtab_info>&, internal_error> elf::get_symtab_impl() {
// https://refspecs.linuxfoundation.org/elf/elf.pdf // https://refspecs.linuxfoundation.org/elf/elf.pdf
// page 66: only one sht_symtab and sht_dynsym section per file // page 66: only one sht_symtab and sht_dynsym section per file
// page 32: symtab spec // page 32: symtab spec
@ -292,7 +295,8 @@ namespace detail {
if(std::fread(buffer.data(), section.sh_entsize, buffer.size(), file) != buffer.size()) { if(std::fread(buffer.data(), section.sh_entsize, buffer.size(), file) != buffer.size()) {
return internal_error("fread error while loading elf symbol table"); return internal_error("fread error while loading elf symbol table");
} }
symtab.entries.reserve(buffer.size()); symtab = symtab_info{};
symtab.unwrap().entries.reserve(buffer.size());
for(const auto& entry : buffer) { for(const auto& entry : buffer) {
symtab_entry normalized; symtab_entry normalized;
normalized.st_name = byteswap_if_needed(entry.st_name); normalized.st_name = byteswap_if_needed(entry.st_name);
@ -301,12 +305,16 @@ namespace detail {
normalized.st_shndx = byteswap_if_needed(entry.st_shndx); normalized.st_shndx = byteswap_if_needed(entry.st_shndx);
normalized.st_value = byteswap_if_needed(entry.st_value); normalized.st_value = byteswap_if_needed(entry.st_value);
normalized.st_size = byteswap_if_needed(entry.st_size); normalized.st_size = byteswap_if_needed(entry.st_size);
symtab.entries.push_back(normalized); symtab.unwrap().entries.push_back(normalized);
} }
std::sort(symtab.entries.begin(), symtab.entries.end(), [] (const symtab_entry& a, const symtab_entry& b) { std::sort(
symtab.unwrap().entries.begin(),
symtab.unwrap().entries.end(),
[] (const symtab_entry& a, const symtab_entry& b) {
return a.st_value < b.st_value; return a.st_value < b.st_value;
}); }
symtab.strtab_link = section.sh_link; );
symtab.unwrap().strtab_link = section.sh_link;
did_load_symtab = true; did_load_symtab = true;
return symtab; return symtab;
} }

View File

@ -62,7 +62,7 @@ namespace detail {
}; };
bool tried_to_load_symtab = false; bool tried_to_load_symtab = false;
bool did_load_symtab = false; bool did_load_symtab = false;
symtab_info symtab; optional<symtab_info> symtab;
elf(file_wrapper file, const std::string& object_path, bool is_little_endian, bool is_64); elf(file_wrapper file, const std::string& object_path, bool is_little_endian, bool is_64);
@ -92,9 +92,9 @@ namespace detail {
Result<const std::vector<char>&, internal_error> get_strtab(std::size_t index); Result<const std::vector<char>&, internal_error> get_strtab(std::size_t index);
Result<const symtab_info&, internal_error> get_symtab(); Result<const optional<symtab_info>&, internal_error> get_symtab();
template<std::size_t Bits> template<std::size_t Bits>
Result<const symtab_info&, internal_error> get_symtab_impl(); Result<const optional<symtab_info>&, internal_error> get_symtab_impl();
}; };
} }
} }