Add elf symtab dumping tool
This commit is contained in:
parent
b724d1328c
commit
2b7d47d627
@ -133,6 +133,43 @@ namespace detail {
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
Result<optional<std::vector<elf::symbol_entry>>, internal_error> elf::get_symtab_entries() {
|
||||
return resolve_symtab_entries(get_symtab());
|
||||
}
|
||||
Result<optional<std::vector<elf::symbol_entry>>, internal_error> elf::get_dynamic_symtab_entries() {
|
||||
return resolve_symtab_entries(get_dynamic_symtab());
|
||||
}
|
||||
|
||||
Result<optional<std::vector<elf::symbol_entry>>, internal_error> elf::resolve_symtab_entries(
|
||||
const Result<const optional<elf::symtab_info> &, internal_error>& symtab
|
||||
) {
|
||||
if(!symtab) {
|
||||
return symtab.unwrap_error();
|
||||
}
|
||||
if(!symtab.unwrap_value()) {
|
||||
return nullopt;
|
||||
}
|
||||
const auto& info = symtab.unwrap_value().unwrap();
|
||||
optional<const std::vector<char>&> strtab;
|
||||
if(info.strtab_link != SHN_UNDEF) {
|
||||
auto strtab_ = get_strtab(info.strtab_link);
|
||||
if(strtab_.is_error()) {
|
||||
return strtab_.unwrap_error();
|
||||
}
|
||||
strtab = strtab_.unwrap_value();
|
||||
}
|
||||
std::vector<symbol_entry> res;
|
||||
for(const auto& entry : info.entries) {
|
||||
res.push_back({
|
||||
strtab.unwrap().data() + entry.st_name,
|
||||
entry.st_shndx,
|
||||
entry.st_value,
|
||||
entry.st_size
|
||||
});
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type>
|
||||
T elf::byteswap_if_needed(T value) {
|
||||
if(cpptrace::detail::is_little_endian() == is_little_endian) {
|
||||
|
||||
@ -84,6 +84,20 @@ namespace detail {
|
||||
private:
|
||||
optional<std::string> lookup_symbol(frame_ptr pc, const optional<symtab_info>& maybe_symtab);
|
||||
|
||||
public:
|
||||
struct symbol_entry {
|
||||
std::string st_name;
|
||||
uint16_t st_shndx;
|
||||
uint64_t st_value;
|
||||
uint64_t st_size;
|
||||
};
|
||||
Result<optional<std::vector<symbol_entry>>, internal_error> get_symtab_entries();
|
||||
Result<optional<std::vector<symbol_entry>>, internal_error> get_dynamic_symtab_entries();
|
||||
private:
|
||||
Result<optional<std::vector<symbol_entry>>, internal_error> resolve_symtab_entries(
|
||||
const Result<const optional<symtab_info> &, internal_error>&
|
||||
);
|
||||
|
||||
private:
|
||||
template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
|
||||
T byteswap_if_needed(T value);
|
||||
|
||||
@ -28,8 +28,8 @@ namespace detail {
|
||||
std::fprintf(stderr, "%s\n", unwrap_error().what());
|
||||
}
|
||||
}
|
||||
Result(value_type& value) : value_(value_type(value)), active(member::value) {}
|
||||
Result(E& error) : error_(E(error)), active(member::error) {
|
||||
Result(const value_type& value) : value_(value_type(value)), active(member::value) {}
|
||||
Result(const E& error) : error_(E(error)), active(member::error) {
|
||||
if(!should_absorb_trace_exceptions()) {
|
||||
std::fprintf(stderr, "%s\n", unwrap_error().what());
|
||||
}
|
||||
|
||||
@ -44,3 +44,4 @@ function(binary TARGET)
|
||||
endfunction()
|
||||
|
||||
add_subdirectory(dwarfdump)
|
||||
add_subdirectory(symbol_tables)
|
||||
|
||||
1
tools/symbol_tables/CMakeLists.txt
Normal file
1
tools/symbol_tables/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
||||
binary(symbol_tables)
|
||||
82
tools/symbol_tables/main.cpp
Normal file
82
tools/symbol_tables/main.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
#include <lyra/lyra.hpp>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/std.h>
|
||||
#include <fmt/ostream.h>
|
||||
#include <cpptrace/cpptrace.hpp>
|
||||
#include <cpptrace/from_current.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include "binary/elf.hpp"
|
||||
#include "binary/mach-o.hpp"
|
||||
|
||||
using namespace std::literals;
|
||||
using namespace cpptrace::detail;
|
||||
|
||||
template<> struct fmt::formatter<lyra::cli> : ostream_formatter {};
|
||||
|
||||
#if IS_LINUX
|
||||
void dump_symtab_result(const Result<optional<std::vector<elf::symbol_entry>>, internal_error>& res) {
|
||||
if(!res) {
|
||||
fmt::println(stderr, "Error loading: {}", res.unwrap_error().what());
|
||||
}
|
||||
const auto& entries_ = res.unwrap_value();
|
||||
if(!entries_) {
|
||||
fmt::println("Empty symbol table");
|
||||
}
|
||||
const auto& entries = entries_.unwrap();
|
||||
fmt::println("{:16} {:16} {:4} {}", "value", "size", "shdx", "symbol");
|
||||
for(const auto& entry : entries) {
|
||||
fmt::println("{:016x} {:016x} {:04x} {}", entry.st_value, entry.st_size, entry.st_shndx, entry.st_name);
|
||||
}
|
||||
}
|
||||
|
||||
void dump_symbols(const std::filesystem::path& path) {
|
||||
auto elf_ = elf::open_elf(path);
|
||||
if(!elf_) {
|
||||
fmt::println(stderr, "Error reading file: {}", elf_.unwrap_error().what());
|
||||
}
|
||||
auto& elf = elf_.unwrap_value();
|
||||
fmt::println("Symtab:");
|
||||
dump_symtab_result(elf.get_symtab_entries());
|
||||
fmt::println("Dynamic symtab:");
|
||||
dump_symtab_result(elf.get_dynamic_symtab_entries());
|
||||
}
|
||||
#elif IS_APPLE
|
||||
void dump_symbols(const std::filesystem::path& path) {
|
||||
fmt::println("Not implemented yet (TODO)");
|
||||
}
|
||||
#else
|
||||
void dump_symbols(const std::filesystem::path& path) {
|
||||
fmt::println("Unable to dump symbol table on this platform");
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv) CPPTRACE_TRY {
|
||||
bool show_help = false;
|
||||
std::filesystem::path path;
|
||||
auto cli = lyra::cli()
|
||||
| lyra::help(show_help)
|
||||
| lyra::arg(path, "binary path")("binary to dump symbol tables for").required();
|
||||
if(auto result = cli.parse({ argc, argv }); !result) {
|
||||
fmt::println(stderr, "Error in command line: {}", result.message());
|
||||
fmt::println("{}", cli);
|
||||
return 1;
|
||||
}
|
||||
if(show_help) {
|
||||
fmt::println("{}", cli);
|
||||
return 0;
|
||||
}
|
||||
if(!std::filesystem::exists(path)) {
|
||||
fmt::println(stderr, "Error: Path doesn't exist {}", path);
|
||||
return 1;
|
||||
}
|
||||
if(!std::filesystem::is_regular_file(path)) {
|
||||
fmt::println(stderr, "Error: Path isn't a regular file {}", path);
|
||||
return 1;
|
||||
}
|
||||
dump_symbols(path);
|
||||
} CPPTRACE_CATCH(const std::exception& e) {
|
||||
fmt::println(stderr, "Caught exception {}: {}", cpptrace::demangle(typeid(e).name()), e.what());
|
||||
cpptrace::from_current_exception().print();
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user