diff --git a/include/dylib.hpp b/include/dylib.hpp index 2ee6b8e..99686bc 100644 --- a/include/dylib.hpp +++ b/include/dylib.hpp @@ -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; }; /** @@ -273,7 +280,7 @@ class library { * * @return the list of symbols in the dynamic library */ - std::vector symbols(symbol_params params = symbol_params()) const; + std::vector symbols() const; /** * @return the dynamic library handle diff --git a/src/dylib.cpp b/src/dylib.cpp index 75250dd..f10bfd8 100644 --- a/src/dylib.cpp +++ b/src/dylib.cpp @@ -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 get_symbols(native_handle_type handle, int fd, bool demangle, bool loadable); +std::vector 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 { @@ -147,7 +148,6 @@ native_symbol_type library::get_symbol(const char *symbol_name) const { std::vector matching_symbols; std::string initial_error; native_symbol_type symbol; - symbol_params sym_params; size_t symbol_name_len; if (!symbol_name) @@ -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()) { @@ -197,16 +199,14 @@ native_handle_type library::native_handle() noexcept { return m_handle; } -std::vector library::symbols(symbol_params params) const { +std::vector 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()); diff --git a/src/symbols.cpp b/src/symbols.cpp index cd2f9b6..c7bc3e5 100644 --- a/src/symbols.cpp +++ b/src/symbols.cpp @@ -14,20 +14,32 @@ std::string demangle_symbol(const char *symbol); -static void add_symbol(std::vector &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 &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 ************************/ @@ -36,8 +48,8 @@ static void add_symbol(std::vector &result, const char *symbol, boo #include #include -std::vector get_symbols(HMODULE handle, int fd, bool demangle, bool loadable) { - std::vector symbols_list; +std::vector get_symbols(HMODULE handle, int fd, bool demangle, bool loadable) { + std::vector symbols_list; PIMAGE_EXPORT_DIRECTORY pExportDir; PIMAGE_DOS_HEADER pDosHeader; PIMAGE_NT_HEADERS pNTHeaders; @@ -67,8 +79,7 @@ std::vector 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; @@ -98,8 +109,7 @@ std::vector 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 &symbols_list, void *handle, int fd, - bool demangle, bool loadable, off_t offset) { +static void get_symbols_at_off(std::vector &symbols_list, void *handle, int fd, off_t offset) { mach_header_arch mh; uint32_t ncmds; @@ -147,8 +157,7 @@ static void get_symbols_at_off(std::vector &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)); } } @@ -156,8 +165,8 @@ static void get_symbols_at_off(std::vector &symbols_list, void *han } } -std::vector get_symbols(void *handle, int fd, bool demangle, bool loadable) { - std::vector symbols_list; +std::vector get_symbols(void *handle, int fd) { + std::vector symbols_list; uint32_t magic; lseek(fd, 0, SEEK_SET); @@ -177,10 +186,10 @@ std::vector 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"); } @@ -205,8 +214,8 @@ std::vector get_symbols(void *handle, int fd, bool demangle, bool l #error "Environment not 32 or 64-bit." #endif -std::vector get_symbols(void *handle, int fd, bool demangle, bool loadable) { - std::vector result; +std::vector get_symbols(void *handle, int fd, bool demangle, bool loadable) { + std::vector result; struct link_map *map = nullptr; ElfSym *symtab = nullptr; char *strtab = nullptr; @@ -238,8 +247,7 @@ std::vector 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)); } } diff --git a/tests/tests.cpp b/tests/tests.cpp index f6ff492..91942b2 100755 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -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 symbols; + std::vector 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 symbols; + std::vector 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) {