-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
edacd4d
commit 603c12d
Showing
5 changed files
with
89 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ | |
* @link https://github.com/martin-olivier/dylib | ||
* | ||
* @author Martin Olivier <[email protected]> | ||
* @copyright (c) 2023 Martin Olivier | ||
* @copyright (c) 2024 Martin Olivier | ||
* | ||
* This library is released under MIT license | ||
*/ | ||
|
@@ -37,11 +37,9 @@ | |
* The dylib class can hold a dynamic library instance and interact with it | ||
* by getting its symbols like functions or global variables | ||
*/ | ||
class dylib | ||
{ | ||
class dylib { | ||
public: | ||
struct filename_components | ||
{ | ||
struct filename_components { | ||
static constexpr const char *prefix = DYLIB_WIN_OTHER("", "lib"); | ||
static constexpr const char *suffix = DYLIB_WIN_MAC_OTHER(".dll", ".dylib", ".so"); | ||
}; | ||
|
@@ -59,8 +57,7 @@ class dylib | |
* | ||
* @param message the error message | ||
*/ | ||
class exception : public std::runtime_error | ||
{ | ||
class exception : public std::runtime_error { | ||
public: | ||
explicit exception(const std::string &message) : std::runtime_error(message) {} | ||
}; | ||
|
@@ -70,8 +67,7 @@ class dylib | |
* | ||
* @param message the error message | ||
*/ | ||
class load_error : public exception | ||
{ | ||
class load_error : public exception { | ||
public: | ||
explicit load_error(const std::string &message) : exception(message) {} | ||
}; | ||
|
@@ -81,8 +77,7 @@ class dylib | |
* | ||
* @param message the error message | ||
*/ | ||
class symbol_error : public exception | ||
{ | ||
class symbol_error : public exception { | ||
public: | ||
explicit symbol_error(const std::string &message) : exception(message) {} | ||
}; | ||
|
@@ -170,8 +165,7 @@ class dylib | |
* @return a pointer to the requested function | ||
*/ | ||
template <typename T> | ||
T *get_function(const char *symbol_name) const | ||
{ | ||
T *get_function(const char *symbol_name) const { | ||
#if (defined(__GNUC__) && __GNUC__ >= 8) | ||
#pragma GCC diagnostic push | ||
#pragma GCC diagnostic ignored "-Wcast-function-type" | ||
|
@@ -183,8 +177,7 @@ class dylib | |
} | ||
|
||
template <typename T> | ||
T *get_function(const std::string &symbol_name) const | ||
{ | ||
T *get_function(const std::string &symbol_name) const { | ||
return get_function<T>(symbol_name.c_str()); | ||
} | ||
|
||
|
@@ -199,14 +192,12 @@ class dylib | |
* @return a reference to the requested variable | ||
*/ | ||
template <typename T> | ||
T &get_variable(const char *symbol_name) const | ||
{ | ||
T &get_variable(const char *symbol_name) const { | ||
return *reinterpret_cast<T *>(get_symbol(symbol_name)); | ||
} | ||
|
||
template <typename T> | ||
T &get_variable(const std::string &symbol_name) const | ||
{ | ||
T &get_variable(const std::string &symbol_name) const { | ||
return get_variable<T>(symbol_name.c_str()); | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,12 @@ | ||
/** | ||
* @file dylib.cpp | ||
* | ||
* @author Martin Olivier <[email protected]> | ||
* @copyright (c) 2024 Martin Olivier | ||
* | ||
* This library is released under MIT license | ||
*/ | ||
|
||
#if (defined(_WIN32) || defined(_WIN64)) | ||
#ifndef WIN32_LEAN_AND_MEAN | ||
#define WIN32_LEAN_AND_MEAN | ||
|
@@ -32,27 +41,23 @@ | |
|
||
std::vector<std::string> get_symbols(int fd, bool demangle); | ||
|
||
static dylib::native_handle_type open_lib(const char *path) noexcept | ||
{ | ||
static dylib::native_handle_type open_lib(const char *path) noexcept { | ||
#if (defined(_WIN32) || defined(_WIN64)) | ||
return LoadLibraryA(path); | ||
#else | ||
return dlopen(path, RTLD_NOW | RTLD_LOCAL); | ||
#endif | ||
} | ||
|
||
static dylib::native_symbol_type locate_symbol(dylib::native_handle_type lib, const char *name) noexcept | ||
{ | ||
static dylib::native_symbol_type locate_symbol(dylib::native_handle_type lib, const char *name) noexcept { | ||
return DYLIB_WIN_OTHER(GetProcAddress, dlsym)(lib, name); | ||
} | ||
|
||
static void close_lib(dylib::native_handle_type lib) noexcept | ||
{ | ||
static void close_lib(dylib::native_handle_type lib) noexcept { | ||
DYLIB_WIN_OTHER(FreeLibrary, dlclose)(lib); | ||
} | ||
|
||
static std::string get_error_description() noexcept | ||
{ | ||
static std::string get_error_description() noexcept { | ||
#if (defined(_WIN32) || defined(_WIN64)) | ||
constexpr const size_t buf_size = 512; | ||
auto error_code = GetLastError(); | ||
|
@@ -70,20 +75,17 @@ static std::string get_error_description() noexcept | |
} | ||
|
||
dylib::dylib(dylib &&other) noexcept | ||
: m_handle(other.m_handle) | ||
{ | ||
: m_handle(other.m_handle) { | ||
other.m_handle = nullptr; | ||
} | ||
|
||
dylib &dylib::operator=(dylib &&other) noexcept | ||
{ | ||
dylib &dylib::operator=(dylib &&other) noexcept { | ||
if (this != &other) | ||
std::swap(m_handle, other.m_handle); | ||
return *this; | ||
} | ||
|
||
dylib::dylib(const char *dir_path, const char *lib_name, bool decorations) | ||
{ | ||
dylib::dylib(const char *dir_path, const char *lib_name, bool decorations) { | ||
if (!dir_path || !lib_name) | ||
throw std::invalid_argument("Null parameter"); | ||
|
||
|
@@ -104,43 +106,37 @@ dylib::dylib(const char *dir_path, const char *lib_name, bool decorations) | |
m_fd = open((final_path + final_name).c_str(), O_RDONLY); | ||
|
||
if (m_fd < 0) | ||
{ | ||
throw load_error("Could not load library"); | ||
} | ||
} | ||
|
||
dylib::~dylib() | ||
{ | ||
dylib::~dylib() { | ||
if (m_handle) | ||
close_lib(m_handle); | ||
if (m_fd > -1) | ||
close(m_fd); | ||
} | ||
|
||
std::string get_demangled_name(const char *symbol) | ||
{ | ||
std::string get_demangled_name(const char *symbol) { | ||
std::string result; | ||
size_t size = strlen(symbol); | ||
int status; | ||
char *buf; | ||
|
||
buf = (char *)malloc(size); | ||
buf = reinterpret_cast<char *>(malloc(size)); | ||
if (buf == NULL) | ||
throw std::bad_alloc(); | ||
|
||
buf = abi::__cxa_demangle(symbol, buf, &size, &status); | ||
|
||
if (buf) | ||
{ | ||
if (buf) { | ||
result = buf; | ||
free(buf); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
dylib::native_symbol_type dylib::get_symbol(const char *symbol_name) const | ||
{ | ||
dylib::native_symbol_type dylib::get_symbol(const char *symbol_name) const { | ||
std::vector<std::string> matching_symbols; | ||
std::vector<std::string> all_symbols; | ||
|
||
|
@@ -151,12 +147,10 @@ dylib::native_symbol_type dylib::get_symbol(const char *symbol_name) const | |
|
||
auto symbol = locate_symbol(m_handle, symbol_name); | ||
|
||
if (symbol == nullptr) | ||
{ | ||
if (symbol == nullptr) { | ||
all_symbols = symbols({.demangle = false}); | ||
|
||
for (auto &sym : all_symbols) | ||
{ | ||
for (auto &sym : all_symbols) { | ||
auto demangled = get_demangled_name(sym.c_str()); | ||
|
||
if (demangled.empty()) | ||
|
@@ -168,16 +162,13 @@ dylib::native_symbol_type dylib::get_symbol(const char *symbol_name) const | |
matching_symbols.push_back(sym); | ||
} | ||
|
||
if (matching_symbols.size() == 0) | ||
if (matching_symbols.size() == 0) { | ||
throw symbol_error("Could not get symbol '" + std::string(symbol_name) + "'\n" + get_error_description()); | ||
else if (matching_symbols.size() == 1) | ||
{ | ||
} else if (matching_symbols.size() == 1) { | ||
symbol = locate_symbol(m_handle, matching_symbols.front().c_str()); | ||
if (symbol == nullptr) | ||
throw symbol_error("Could not get symbol '" + std::string(symbol_name) + "'\n" + get_error_description()); | ||
} | ||
else | ||
{ | ||
} else { | ||
throw symbol_error( | ||
"Could not get symbol '" + std::string(symbol_name) + "': multiple matches"); | ||
} | ||
|
@@ -186,33 +177,28 @@ dylib::native_symbol_type dylib::get_symbol(const char *symbol_name) const | |
return symbol; | ||
} | ||
|
||
dylib::native_symbol_type dylib::get_symbol(const std::string &symbol_name) const | ||
{ | ||
dylib::native_symbol_type dylib::get_symbol(const std::string &symbol_name) const { | ||
return get_symbol(symbol_name.c_str()); | ||
} | ||
|
||
bool dylib::has_symbol(const char *symbol_name) const noexcept | ||
{ | ||
bool dylib::has_symbol(const char *symbol_name) const noexcept { | ||
if (!m_handle || !symbol_name) | ||
return false; | ||
return locate_symbol(m_handle, symbol_name) != nullptr; | ||
} | ||
|
||
bool dylib::has_symbol(const std::string &symbol) const noexcept | ||
{ | ||
bool dylib::has_symbol(const std::string &symbol) const noexcept { | ||
return has_symbol(symbol.c_str()); | ||
} | ||
|
||
dylib::native_handle_type dylib::native_handle() noexcept | ||
{ | ||
dylib::native_handle_type dylib::native_handle() noexcept { | ||
return m_handle; | ||
} | ||
|
||
std::vector<std::string> dylib::symbols(symbols_params params) const | ||
{ | ||
std::vector<std::string> dylib::symbols(symbols_params params) const { | ||
try { | ||
return get_symbols(m_fd, params.demangle); | ||
} catch (const std::string &e) { | ||
throw symbol_error(e); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,12 @@ | ||
/** | ||
* @file linux.cpp | ||
* | ||
* @author Martin Olivier <[email protected]> | ||
* @copyright (c) 2024 Martin Olivier | ||
* | ||
* This library is released under MIT license | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <libelf.h> | ||
|
@@ -12,8 +21,7 @@ | |
|
||
std::string get_demangled_name(const char *symbol); | ||
|
||
std::vector<std::string> get_symbols(int fd, bool demangle) | ||
{ | ||
std::vector<std::string> get_symbols(int fd, bool demangle) { | ||
std::vector<std::string> result; | ||
|
||
if (elf_version(EV_CURRENT) == EV_NONE) | ||
|
@@ -31,15 +39,13 @@ std::vector<std::string> get_symbols(int fd, bool demangle) | |
|
||
Elf_Scn *scn = NULL; | ||
GElf_Shdr shdr; | ||
while ((scn = elf_nextscn(elf, scn)) != NULL) | ||
{ | ||
while ((scn = elf_nextscn(elf, scn)) != NULL) { | ||
if (gelf_getshdr(scn, &shdr) != &shdr) { | ||
elf_end(elf); | ||
throw std::string("gelf_getshdr() failed"); | ||
} | ||
|
||
if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) | ||
{ | ||
if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { | ||
Elf_Data *data = NULL; | ||
data = elf_getdata(scn, data); | ||
if (!data) { | ||
|
@@ -48,8 +54,7 @@ std::vector<std::string> get_symbols(int fd, bool demangle) | |
} | ||
|
||
int count = shdr.sh_size / shdr.sh_entsize; | ||
for (int i = 0; i < count; i++) | ||
{ | ||
for (int i = 0; i < count; i++) { | ||
GElf_Sym sym; | ||
if (!gelf_getsym(data, i, &sym)) { | ||
elf_end(elf); | ||
|
@@ -59,21 +64,19 @@ std::vector<std::string> get_symbols(int fd, bool demangle) | |
const char *name = elf_strptr(elf, shdr.sh_link, sym.st_name); | ||
if (!name) | ||
continue; | ||
|
||
if (strcmp(name, "") == 0) | ||
continue; | ||
|
||
if (demangle) | ||
{ | ||
if (demangle) { | ||
std::string demangled = get_demangled_name(name); | ||
if (!demangled.empty()) | ||
{ | ||
if (!demangled.empty()) { | ||
if (std::find(result.begin(), result.end(), name) == result.end()) | ||
result.push_back(demangled); | ||
continue; | ||
} | ||
} | ||
|
||
if (std::find(result.begin(), result.end(), name) != result.end()) | ||
continue; | ||
result.push_back(name); | ||
|
Oops, something went wrong.