Skip to content

Commit

Permalink
Add elf symtab dumping tool
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremy-rifkin committed Feb 3, 2025
1 parent b724d13 commit 2b7d47d
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 2 deletions.
37 changes: 37 additions & 0 deletions src/binary/elf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
14 changes: 14 additions & 0 deletions src/binary/elf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions src/utils/result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
1 change: 1 addition & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ function(binary TARGET)
endfunction()

add_subdirectory(dwarfdump)
add_subdirectory(symbol_tables)
1 change: 1 addition & 0 deletions tools/symbol_tables/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
binary(symbol_tables)
82 changes: 82 additions & 0 deletions tools/symbol_tables/main.cpp
Original file line number Diff line number Diff line change
@@ -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();
}

0 comments on commit 2b7d47d

Please sign in to comment.