Search both the elf symbol table and dynamic symbol table
This commit is contained in:
parent
06c9c14995
commit
9077430b6a
@ -90,12 +90,20 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
optional<std::string> elf::lookup_symbol(frame_ptr pc) {
|
optional<std::string> elf::lookup_symbol(frame_ptr pc) {
|
||||||
// TODO: Also search the SHT_DYNSYM at some point, maybe
|
if(auto symtab = get_symtab()) {
|
||||||
auto symtab_ = get_symtab();
|
if(auto symbol = lookup_symbol(pc, symtab.unwrap_value())) {
|
||||||
if(symtab_.is_error()) {
|
return symbol;
|
||||||
return nullopt;
|
}
|
||||||
}
|
}
|
||||||
auto& maybe_symtab = symtab_.unwrap_value();
|
if(auto dynamic_symtab = get_dynamic_symtab()) {
|
||||||
|
if(auto symbol = lookup_symbol(pc, dynamic_symtab.unwrap_value())) {
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<std::string> elf::lookup_symbol(frame_ptr pc, const optional<symtab_info>& maybe_symtab) {
|
||||||
if(!maybe_symtab) {
|
if(!maybe_symtab) {
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
@ -259,18 +267,61 @@ namespace detail {
|
|||||||
return symtab;
|
return symtab;
|
||||||
}
|
}
|
||||||
if(tried_to_load_symtab) {
|
if(tried_to_load_symtab) {
|
||||||
return internal_error("previous strtab load failed {}", object_path);
|
return internal_error("previous symtab load failed {}", object_path);
|
||||||
}
|
}
|
||||||
tried_to_load_symtab = true;
|
tried_to_load_symtab = true;
|
||||||
if(is_64) {
|
if(is_64) {
|
||||||
return get_symtab_impl<64>();
|
auto res = get_symtab_impl<64>(false);
|
||||||
|
if(res.has_value()) {
|
||||||
|
symtab = std::move(res).unwrap_value();
|
||||||
|
did_load_symtab = true;
|
||||||
|
return symtab;
|
||||||
|
} else {
|
||||||
|
return std::move(res).unwrap_error();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return get_symtab_impl<32>();
|
auto res = get_symtab_impl<32>(false);
|
||||||
|
if(res.has_value()) {
|
||||||
|
symtab = std::move(res).unwrap_value();
|
||||||
|
did_load_symtab = true;
|
||||||
|
return symtab;
|
||||||
|
} else {
|
||||||
|
return std::move(res).unwrap_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<const optional<elf::symtab_info>&, internal_error> elf::get_dynamic_symtab() {
|
||||||
|
if(did_load_dynamic_symtab) {
|
||||||
|
return dynamic_symtab;
|
||||||
|
}
|
||||||
|
if(tried_to_load_dynamic_symtab) {
|
||||||
|
return internal_error("previous dynamic symtab load failed {}", object_path);
|
||||||
|
}
|
||||||
|
tried_to_load_dynamic_symtab = true;
|
||||||
|
if(is_64) {
|
||||||
|
auto res = get_symtab_impl<64>(true);
|
||||||
|
if(res.has_value()) {
|
||||||
|
dynamic_symtab = std::move(res).unwrap_value();
|
||||||
|
did_load_dynamic_symtab = true;
|
||||||
|
return dynamic_symtab;
|
||||||
|
} else {
|
||||||
|
return std::move(res).unwrap_error();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto res = get_symtab_impl<32>(true);
|
||||||
|
if(res.has_value()) {
|
||||||
|
dynamic_symtab = std::move(res).unwrap_value();
|
||||||
|
did_load_dynamic_symtab = true;
|
||||||
|
return dynamic_symtab;
|
||||||
|
} else {
|
||||||
|
return std::move(res).unwrap_error();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::size_t Bits>
|
template<std::size_t Bits>
|
||||||
Result<const optional<elf::symtab_info>&, internal_error> elf::get_symtab_impl() {
|
Result<optional<elf::symtab_info>, internal_error> elf::get_symtab_impl(bool dynamic) {
|
||||||
// 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
|
||||||
@ -281,8 +332,9 @@ namespace detail {
|
|||||||
return std::move(sections_).unwrap_error();
|
return std::move(sections_).unwrap_error();
|
||||||
}
|
}
|
||||||
const auto& sections = sections_.unwrap_value();
|
const auto& sections = sections_.unwrap_value();
|
||||||
|
optional<symtab_info> symbol_table;
|
||||||
for(const auto& section : sections) {
|
for(const auto& section : sections) {
|
||||||
if(section.sh_type == SHT_SYMTAB) {
|
if(section.sh_type == (dynamic ? SHT_DYNSYM : SHT_SYMTAB)) {
|
||||||
if(section.sh_entsize != sizeof(SymEntry)) {
|
if(section.sh_entsize != sizeof(SymEntry)) {
|
||||||
return internal_error("elf seems corrupted, sym entry mismatch {}", object_path);
|
return internal_error("elf seems corrupted, sym entry mismatch {}", object_path);
|
||||||
}
|
}
|
||||||
@ -296,8 +348,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 = symtab_info{};
|
symbol_table = symtab_info{};
|
||||||
symtab.unwrap().entries.reserve(buffer.size());
|
symbol_table.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);
|
||||||
@ -306,23 +358,20 @@ 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.unwrap().entries.push_back(normalized);
|
symbol_table.unwrap().entries.push_back(normalized);
|
||||||
}
|
}
|
||||||
std::sort(
|
std::sort(
|
||||||
symtab.unwrap().entries.begin(),
|
symbol_table.unwrap().entries.begin(),
|
||||||
symtab.unwrap().entries.end(),
|
symbol_table.unwrap().entries.end(),
|
||||||
[] (const symtab_entry& a, const symtab_entry& b) {
|
[] (const symtab_entry& a, const symtab_entry& b) {
|
||||||
return a.st_value < b.st_value;
|
return a.st_value < b.st_value;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
symtab.unwrap().strtab_link = section.sh_link;
|
symbol_table.unwrap().strtab_link = section.sh_link;
|
||||||
did_load_symtab = true;
|
break;
|
||||||
return symtab;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// OK to not have a symbol table
|
return symbol_table;
|
||||||
did_load_symtab = true;
|
|
||||||
return symtab;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,6 +64,10 @@ namespace detail {
|
|||||||
bool did_load_symtab = false;
|
bool did_load_symtab = false;
|
||||||
optional<symtab_info> symtab;
|
optional<symtab_info> symtab;
|
||||||
|
|
||||||
|
bool tried_to_load_dynamic_symtab = false;
|
||||||
|
bool did_load_dynamic_symtab = false;
|
||||||
|
optional<symtab_info> dynamic_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);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -77,6 +81,8 @@ namespace detail {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
optional<std::string> lookup_symbol(frame_ptr pc);
|
optional<std::string> lookup_symbol(frame_ptr pc);
|
||||||
|
private:
|
||||||
|
optional<std::string> lookup_symbol(frame_ptr pc, const optional<symtab_info>& maybe_symtab);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
|
template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
|
||||||
@ -93,8 +99,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 optional<symtab_info>&, internal_error> get_symtab();
|
Result<const optional<symtab_info>&, internal_error> get_symtab();
|
||||||
|
Result<const optional<symtab_info>&, internal_error> get_dynamic_symtab();
|
||||||
template<std::size_t Bits>
|
template<std::size_t Bits>
|
||||||
Result<const optional<symtab_info>&, internal_error> get_symtab_impl();
|
Result<optional<symtab_info>, internal_error> get_symtab_impl(bool dynamic);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user