Skip to content

Commit

Permalink
feat: new loadable param for symbols function
Browse files Browse the repository at this point in the history
Now, the symbols function takes a struct as parameter that contains 'demangle' and 'loadable' booleans. If 'loadable' is set to true, the function will only return symbols that can be loaded using dlsym or GetProcAddress.

Signed-off-by: Martin Olivier <[email protected]>
  • Loading branch information
martin-olivier authored Aug 1, 2024
1 parent 1575bdf commit 814b4f7
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 20 deletions.
17 changes: 16 additions & 1 deletion include/dylib.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ class dylib {
static constexpr bool add_filename_decorations = true;
static constexpr bool no_filename_decorations = false;

struct symbol_params {
bool demangle = false;
bool loadable = false;
};

/**
* This exception is raised when the library failed to load a dynamic library or a symbol
*
Expand Down Expand Up @@ -211,7 +216,17 @@ class dylib {
return get_variable<T>(symbol_name.c_str());
}

std::vector<std::string> symbols(bool demangle = false) const;
/**
* Get the list of symbols from the dynamic library currently loaded in the object
*
* @throws dylib::symbol_error if an error occured during symbols collection
*
* @param demangle if true, returns unmangled symbols
* @param loadable if true, returns only loadable symbols
*
* @return the list of symbols
*/
std::vector<std::string> symbols(symbol_params params = {}) const;

/**
* @return the dynamic library handle
Expand Down
20 changes: 15 additions & 5 deletions src/dylib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@
#define DYLIB_WIN_OTHER(win_def, other_def) other_def
#endif

using lib_fd_t = DYLIB_WIN_OTHER(HMODULE, int);

std::string get_demangled_name(const char *symbol);
std::vector<std::string> get_symbols(lib_fd_t fd, bool demangle);

#if (defined(_WIN32) || defined(_WIN64))
std::vector<std::string> get_symbols(HMODULE handle, bool demangle, bool loadable);
#else
std::vector<std::string> get_symbols(void *handle, int fd, bool demangle, bool loadable);
#endif

static dylib::native_handle_type open_lib(const char *path) noexcept {
#if (defined(_WIN32) || defined(_WIN64))
Expand Down Expand Up @@ -179,9 +182,16 @@ dylib::native_handle_type dylib::native_handle() noexcept {
return m_handle;
}

std::vector<std::string> dylib::symbols(bool demangle) const {
std::vector<std::string> dylib::symbols(symbol_params params) const {
try {
return get_symbols(DYLIB_WIN_OTHER(m_handle, m_fd), demangle);
return get_symbols(
m_handle,
#if !(defined(_WIN32) || defined(_WIN64))
m_fd,
#endif
params.demangle,
params.loadable
);
} catch (const std::string &e) {
throw symbol_error(e);
}
Expand Down
32 changes: 18 additions & 14 deletions src/symbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ static void add_symbol(std::vector<std::string> &result, const char *name, bool
#include <windows.h>
#include <tchar.h>

std::vector<std::string> get_symbols(HMODULE hModule, bool demangle) {
std::vector<std::string> get_symbols(HMODULE handle, bool demangle, bool loadable) {
std::vector<std::string> result;

// Get the DOS header
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)handle;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
throw std::string("Invalid DOS header");

// Get the NT headers
PIMAGE_NT_HEADERS pNTHeaders = (PIMAGE_NT_HEADERS)((BYTE *)hModule + pDosHeader->e_lfanew);
PIMAGE_NT_HEADERS pNTHeaders = (PIMAGE_NT_HEADERS)((BYTE *)handle + pDosHeader->e_lfanew);
if (pNTHeaders->Signature != IMAGE_NT_SIGNATURE)
throw std::string("Invalid NT headers");

Expand All @@ -60,17 +60,18 @@ std::vector<std::string> get_symbols(HMODULE hModule, bool demangle) {
if (exportDirRVA == 0)
throw std::string("No export directory found");

PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)((BYTE *)hModule + exportDirRVA);
PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)((BYTE *)handle + exportDirRVA);

// Get the list of exported function names
DWORD *pNames = (DWORD *)((BYTE *)hModule + pExportDir->AddressOfNames);
DWORD *pFunctions = (DWORD *)((BYTE *)hModule + pExportDir->AddressOfFunctions);
WORD *pNameOrdinals = (WORD *)((BYTE *)hModule + pExportDir->AddressOfNameOrdinals);
DWORD *pNames = (DWORD *)((BYTE *)handle + pExportDir->AddressOfNames);
DWORD *pFunctions = (DWORD *)((BYTE *)handle + pExportDir->AddressOfFunctions);
WORD *pNameOrdinals = (WORD *)((BYTE *)handle + pExportDir->AddressOfNameOrdinals);

for (DWORD i = 0; i < pExportDir->NumberOfNames; ++i) {
const char *name = (const char *)((BYTE *)hModule + pNames[i]);
const char *name = (const char *)((BYTE *)handle + pNames[i]);

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

return result;
Expand All @@ -84,7 +85,7 @@ std::vector<std::string> get_symbols(HMODULE hModule, bool demangle) {
#include <fcntl.h>
#include <unistd.h>

static std::vector<std::string> get_symbols_at_off(int fd, bool demangle, off_t offset, bool is_64_bit) {
static std::vector<std::string> get_symbols_at_off(int fd, bool demangle, bool loadable, off_t offset, bool is_64_bit) {
std::vector<std::string> result;

lseek(fd, offset, SEEK_SET);
Expand Down Expand Up @@ -144,7 +145,8 @@ static std::vector<std::string> get_symbols_at_off(int fd, bool demangle, off_t
strx = symbols[j].n_un.n_strx;

const char *name = &strtab[strx];
add_symbol(result, name, demangle);
if (!loadable || dlsym(handle, name))
add_symbol(result, name, demangle);
}

free(symbols64);
Expand All @@ -158,7 +160,7 @@ static std::vector<std::string> get_symbols_at_off(int fd, bool demangle, off_t
return result;
}

std::vector<std::string> get_symbols(int fd, bool demangle) {
std::vector<std::string> get_symbols(void *handle, int fd, bool demangle, bool loadable) {
std::vector<std::string> result;
std::vector<std::string> tmp;
uint32_t magic;
Expand All @@ -180,6 +182,7 @@ std::vector<std::string> get_symbols(int fd, bool demangle) {
tmp = get_symbols_at_off(
fd,
demangle,
loadable,
ntohl(fat_arches[i].offset),
ntohl(fat_arches[i].cputype) == CPU_TYPE_X86_64);
std::move(tmp.begin(), tmp.end(), std::back_inserter(result));
Expand All @@ -204,7 +207,7 @@ std::vector<std::string> get_symbols(int fd, bool demangle) {
#include <fcntl.h>
#include <unistd.h>

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

if (elf_version(EV_CURRENT) == EV_NONE)
Expand Down Expand Up @@ -245,7 +248,8 @@ std::vector<std::string> get_symbols(int fd, bool demangle) {
}

const char *name = elf_strptr(elf, shdr.sh_link, sym.st_name);
add_symbol(result, name, demangle);
if (!loadable || dlsym(handle, name))
add_symbol(result, name, demangle);
}
}
}
Expand Down

0 comments on commit 814b4f7

Please sign in to comment.