Add elf symtab dumping tool
This commit is contained in:
parent
b724d1328c
commit
2b7d47d627
@ -133,6 +133,43 @@ namespace detail {
|
|||||||
return nullopt;
|
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>
|
template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type>
|
||||||
T elf::byteswap_if_needed(T value) {
|
T elf::byteswap_if_needed(T value) {
|
||||||
if(cpptrace::detail::is_little_endian() == is_little_endian) {
|
if(cpptrace::detail::is_little_endian() == is_little_endian) {
|
||||||
|
|||||||
@ -84,6 +84,20 @@ namespace detail {
|
|||||||
private:
|
private:
|
||||||
optional<std::string> lookup_symbol(frame_ptr pc, const optional<symtab_info>& maybe_symtab);
|
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:
|
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>
|
||||||
T byteswap_if_needed(T value);
|
T byteswap_if_needed(T value);
|
||||||
|
|||||||
@ -28,8 +28,8 @@ namespace detail {
|
|||||||
std::fprintf(stderr, "%s\n", unwrap_error().what());
|
std::fprintf(stderr, "%s\n", unwrap_error().what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Result(value_type& value) : value_(value_type(value)), active(member::value) {}
|
Result(const value_type& value) : value_(value_type(value)), active(member::value) {}
|
||||||
Result(E& error) : error_(E(error)), active(member::error) {
|
Result(const E& error) : error_(E(error)), active(member::error) {
|
||||||
if(!should_absorb_trace_exceptions()) {
|
if(!should_absorb_trace_exceptions()) {
|
||||||
std::fprintf(stderr, "%s\n", unwrap_error().what());
|
std::fprintf(stderr, "%s\n", unwrap_error().what());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,3 +44,4 @@ function(binary TARGET)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
add_subdirectory(dwarfdump)
|
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