Skip to content

Commit

Permalink
symbols: add symbol_info and symbol_type
Browse files Browse the repository at this point in the history
Signed-off-by: Martin Olivier <martin.olivier@live.fr>
  • Loading branch information
martin-olivier committed Mar 2, 2025
1 parent e9f69a2 commit 5df9159
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 56 deletions.
15 changes: 11 additions & 4 deletions include/dylib.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,16 @@ struct decorations {
}
};

struct symbol_params {
bool demangle{false};
bool loadable{false};
enum symbol_type {
C,
CPP,
};

struct symbol_info {
std::string name;
std::string demangled_name;
symbol_type type;
bool loadable;
};

/**
Expand Down Expand Up @@ -273,7 +280,7 @@ class library {
*
* @return the list of symbols in the dynamic library
*/
std::vector<std::string> symbols(symbol_params params = symbol_params()) const;
std::vector<symbol_info> symbols() const;

/**
* @return the dynamic library handle
Expand Down
20 changes: 10 additions & 10 deletions src/dylib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
#include "dylib.hpp"

using dylib::library;
using dylib::symbol_info;
using dylib::native_handle_type;
using dylib::native_symbol_type;

std::vector<std::string> get_symbols(native_handle_type handle, int fd, bool demangle, bool loadable);
std::vector<symbol_info> get_symbols(native_handle_type handle, int fd);
std::string demangle_symbol(const char *symbol);

static native_handle_type open_lib(const char *path) noexcept {
Expand Down Expand Up @@ -147,7 +148,6 @@ native_symbol_type library::get_symbol(const char *symbol_name) const {
std::vector<std::string> matching_symbols;
std::string initial_error;
native_symbol_type symbol;
symbol_params sym_params;
size_t symbol_name_len;

if (!symbol_name)
Expand All @@ -164,14 +164,16 @@ native_symbol_type library::get_symbol(const char *symbol_name) const {
return symbol;

initial_error = get_error_description();
sym_params.loadable = true;

for (auto &sym : symbols(sym_params)) {
std::string demangled = demangle_symbol(sym.c_str());
for (const auto &sym : symbols()) {
if (!sym.loadable)
continue;

std::string demangled = demangle_symbol(sym.name.c_str());

if (demangled.find(symbol_name) == 0 &&
(demangled.size() == symbol_name_len || demangled[symbol_name_len] == '('))
matching_symbols.push_back(sym);
matching_symbols.push_back(sym.name);
}

switch (matching_symbols.size()) {
Expand All @@ -197,16 +199,14 @@ native_handle_type library::native_handle() noexcept {
return m_handle;
}

std::vector<std::string> library::symbols(symbol_params params) const {
std::vector<symbol_info> library::symbols() const {
if (!m_handle)
throw std::logic_error("Attempted to use a moved library object.");

try {
return get_symbols(
m_handle,
DYLIB_WIN_MAC_OTHER(-1, m_fd, -1),
params.demangle,
params.loadable
DYLIB_WIN_MAC_OTHER(-1, m_fd, -1)
);
} catch (const std::runtime_error &e) {
throw symbol_collection_error(e.what());
Expand Down
58 changes: 33 additions & 25 deletions src/symbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,32 @@

std::string demangle_symbol(const char *symbol);

static void add_symbol(std::vector<std::string> &result, const char *symbol, bool demangle) {
std::string final_symbol = symbol;
enum symbol_type {
C,
CPP,
};

struct symbol_info {
std::string name;
std::string demangled_name;
symbol_type type;
bool loadable;
};

static void add_symbol(std::vector<symbol_info> &result, const char *symbol, bool loadable) {
symbol_type type = symbol_type::C;
std::string demangled;

if (!symbol || strcmp(symbol, "") == 0)
return;

if (demangle) {
std::string demangled = demangle_symbol(symbol);
if (!demangled.empty())
final_symbol = demangled;
}
demangled = demangle_symbol(symbol);
if (demangled.empty())
demangled = symbol;
else
type = symbol_type::CPP;

if (std::find(result.begin(), result.end(), final_symbol) == result.end())
result.push_back(final_symbol);
result.push_back({symbol, demangled, type, loadable});
}

/************************ Windows ************************/
Expand All @@ -36,8 +48,8 @@ static void add_symbol(std::vector<std::string> &result, const char *symbol, boo
#include <windows.h>
#include <tchar.h>

std::vector<std::string> get_symbols(HMODULE handle, int fd, bool demangle, bool loadable) {
std::vector<std::string> symbols_list;
std::vector<symbol_info> get_symbols(HMODULE handle, int fd, bool demangle, bool loadable) {
std::vector<symbol_info> symbols_list;
PIMAGE_EXPORT_DIRECTORY pExportDir;
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNTHeaders;
Expand Down Expand Up @@ -67,8 +79,7 @@ std::vector<std::string> get_symbols(HMODULE handle, int fd, bool demangle, bool
for (DWORD i = 0; i < pExportDir->NumberOfNames; ++i) {
const char *name = (const char *)((BYTE *)handle + pNames[i]);

if (!loadable || GetProcAddress(handle, name))
add_symbol(symbols_list, name, demangle);
add_symbol(symbols_list, name, !!GetProcAddress(handle, name));
}

return symbols_list;
Expand Down Expand Up @@ -98,8 +109,7 @@ std::vector<std::string> get_symbols(HMODULE handle, int fd, bool demangle, bool
#error "Environment not 32 or 64-bit."
#endif

static void get_symbols_at_off(std::vector<std::string> &symbols_list, void *handle, int fd,
bool demangle, bool loadable, off_t offset) {
static void get_symbols_at_off(std::vector<symbol_info> &symbols_list, void *handle, int fd, off_t offset) {
mach_header_arch mh;
uint32_t ncmds;

Expand Down Expand Up @@ -147,17 +157,16 @@ static void get_symbols_at_off(std::vector<std::string> &symbols_list, void *han
if (name[0] == '_')
name++;

if (!loadable || dlsym(handle, name))
add_symbol(symbols_list, name, demangle);
add_symbol(symbols_list, name, !!dlsym(handle, name));
}
}

lseek(fd, cmd_offset + lc.cmdsize - sizeof(lc), SEEK_SET);
}
}

std::vector<std::string> get_symbols(void *handle, int fd, bool demangle, bool loadable) {
std::vector<std::string> symbols_list;
std::vector<symbol_info> get_symbols(void *handle, int fd) {
std::vector<symbol_info> symbols_list;
uint32_t magic;

lseek(fd, 0, SEEK_SET);
Expand All @@ -177,10 +186,10 @@ std::vector<std::string> get_symbols(void *handle, int fd, bool demangle, bool l
for (uint32_t i = 0; i < ntohl(fat_header.nfat_arch); i++) {
off_t off = ntohl(fat_arches[i].offset);

get_symbols_at_off(symbols_list, handle, fd, demangle, loadable, off);
get_symbols_at_off(symbols_list, handle, fd, off);
}
} else if (magic == DYLIB_MH_MAGIC || magic == DYLIB_MH_CIGAM) {
get_symbols_at_off(symbols_list, handle, fd, demangle, loadable, 0);
get_symbols_at_off(symbols_list, handle, fd, 0);
} else {
throw std::runtime_error("Unsupported file format");
}
Expand All @@ -205,8 +214,8 @@ std::vector<std::string> get_symbols(void *handle, int fd, bool demangle, bool l
#error "Environment not 32 or 64-bit."
#endif

std::vector<std::string> get_symbols(void *handle, int fd, bool demangle, bool loadable) {
std::vector<std::string> result;
std::vector<symbol_info> get_symbols(void *handle, int fd, bool demangle, bool loadable) {
std::vector<symbol_info> result;
struct link_map *map = nullptr;
ElfSym *symtab = nullptr;
char *strtab = nullptr;
Expand Down Expand Up @@ -238,8 +247,7 @@ std::vector<std::string> get_symbols(void *handle, int fd, bool demangle, bool l
if (DYLIB_ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC) {
const char *name = &strtab[sym->st_name];

if (!loadable || dlsym(handle, name))
add_symbol(result, name, demangle);
add_symbol(result, name, !!dlsym(handle, name));
}
}

Expand Down
27 changes: 10 additions & 17 deletions tests/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,35 +250,28 @@ TEST(cpp_symbols, callback) {

TEST(cpp_symbols, loadable) {
dylib::library lib("./dynamic_lib", dylib::decorations::os_default());
dylib::symbol_params params;
std::vector<std::string> symbols;
std::vector<dylib::symbol_info> symbols;

params.loadable = true;
symbols = lib.symbols();

symbols = lib.symbols(params);

for (auto &symbol : symbols)
EXPECT_TRUE(!!GET_SYM(lib.native_handle(), symbol.c_str()));
for (auto &symbol : symbols) {
if (symbol.loadable)
EXPECT_TRUE(!!GET_SYM(lib.native_handle(), symbol.name.c_str()));
}
}

TEST(cpp_symbols, demangle) {
dylib::library lib("./dynamic_lib", dylib::decorations::os_default());
dylib::symbol_params params;
std::vector<std::string> symbols;
std::vector<dylib::symbol_info> symbols;

params.loadable = true;
params.demangle = true;

symbols = lib.symbols(params);
symbols = lib.symbols();

for (auto &symbol : symbols) {
try {
EXPECT_TRUE(!!lib.get_symbol(symbol));
if (symbol.loadable)
EXPECT_TRUE(!!lib.get_symbol(symbol.name));
} catch (dylib::symbol_multiple_matches &) {}
}

EXPECT_TRUE(std::find(symbols.begin(), symbols.end(), "adder") != symbols.end());
EXPECT_TRUE(std::find(symbols.begin(), symbols.end(), "tools::adder(double, double)") != symbols.end());
}

int main(int ac, char **av) {
Expand Down

0 comments on commit 5df9159

Please sign in to comment.