From 0da62c980eb6db80759dd3757d34ada4ba6cab64 Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Tue, 7 Feb 2023 03:39:10 -0600 Subject: [PATCH] Binary instrumentation: more robust exclusion of functions used internally (#238) ## Overview This PR attempts to increase the stability of binary rewrite and runtime instrumentation. ### Improved protection against self-instrumentation Using ~~the binary analysis capabilities added from #229~~ the Dyninst SymtabAPI, OmniTrace now does a much better job of avoiding instrumentation of functions which are internally called by OmniTrace: - The `omnitrace` executable searches for and parses the symbols of various libraries which are known to cause problems when instrumented - GNU libraries which are common to nearly every library, e.g., `"libc.so.6"`, `"libdl.so.2"`, etc., and thus are outside the scope of the users optimizations efforts - Libraries which OmniTrace depends on for functionality, e.g. `"libunwind.so"`, `"libgotcha.so"`, `"libroctracer64.so"`, etc. - OmniTrace skips instrumenting any `module_function` instance when it's member `module_name` or `function_name` variable matches the library name, source file, or function name found for that symbol (unless the user explicitly requests that it be eligible for instrumentation) - Note: the parsing of the "internal" libraries may result in longer instrumentation time and higher memory usage. Please file an issue if either of these is found to be excessive. ### Function filters based on linkage and visibility Added options to restrict instrumentation to certain linkage types (e.g. avoid instrumenting weak symbols) and visibility types (e.g. avoid instrumenting hidden symbols). ### Function filters based on instructions In the past, after instrumentation, some applications instrumented by Dyninst would fail with a trap signal (e.g. #147). In several cases, it was found that this occurred whenever certain instructions were present in the function so an option was added to exclude functions based on one or more regex patterns was added. ## Details - generates list of "internal" libraries and attempts to find the first match via: - the library is already open, e.g. `dlopen(, RTLD_LAZY | RTLD_NOLOAD)` - searching for the library in `LD_LIBRARY_PATH` - searching for the library in `OMNITRACE_ROCM_PATH`, `ROCM_PATH` - searching the folders from `/sbin/ldconfig -p` - searching for the library in common places such as `/usr/local/lib` - provides new `--linkage` command line option to restrict instrumentation to functions with particular type(s) of linkage - Linkage types: `unknown`, `global`, `local`, `weak`, `unique` - provides new `--visibility` command line option to restrict instrumentation to functions with particular type(s) of visibility - Visibility types: `unknown`, `default`, `hidden`, `protected`, `internal` - provides new `--internal-module-include` and `--internal-function-include` command line regex options to bypass automatic exclusion from instrumentation - provides new `--internal-library-append` command line option to specify a library should be considered internal - provides new `--internal-library-remove` command line option to specify a library should not be considered internal - provides new `--instruction-exclude` command line regex option to exclude functions which contain matching instructions - provides new `--internal-library-deps` command line option to treat libraries linked to internal libraries as internal libraries - generally, this will only be helpful during runtime instrumentation when OmniTrace is built with an external dyninst library which is dynamically linked to boost libraries and the application is using the same boost libraries - relaxed restrictions in `module_function::is_module_constrained()` - relaxed restrictions in `module_function::is_routine_constrained()` - added a few miscellaneous nullptr checks ## Miscellaneous - Fix `LD_PRELOAD` + `OMNITRACE_DL_VERBOSE=3` issue - Adds a sampling offload verbose message - Improves MPI send-recv.cpp example error message - Minor tweaks to binary library - `binary::get_linked_path` returns `std::optional` - renamed `binary::symbol::read_bfd` to `binary::symbol::read_bfd_line_info` - `binary::get_binary_info` has param options for reading line info and included undefined symbols - fixed another edge case instance of resource deadlock during first call to configure_settings - improved the error log printing in `omnitrace` (does not print repeated messages) * fix OMNITRACE_DL_VERBOSE=3 + preload issue - join needs to handle nullptr * sampling offload verbose message * mpi-send-recv error message * binary updates - get_linked_path returns std::optional - get_binary_info accepts include_undef flag - renamed symbol::read_bfd to symbol::read_bfd_line_info - get_binary_info has param options for reading line info and included undefined symbols * config updates (initialization) - fixed another instance of resource deadlock during first call to configure_settings * Testing fix for HIP w/o rocprofiler support - disable rocprofiler tests when HIP enabled but OMNITRACE_USE_ROCPROFILER=OFF * omnitrace exe: insert_instr nullptr check * omnitrace exe: new method for determining internal constraints - added internal-libs.cpp - using binary::get_binary_info on various known libs used by omnitrace - any matching func/file from symbols found in known internal libs are excluded - relaxed restrictions in is_module_constrained - relaxed restrictions in is_routine_constrained - added a few safety checks * internal libs append/remove - options to change which libs are considered internal libraries * omnitrace exe instruction exclude - regex option for excluding functions containing specific instructions * fix is_internal_constrained * binary link map verbose message * support constraints on linkage and visibility of symbols * misc fixes - fix compiler error for Ubuntu Jammy + GCC 12 - dlopen + libtbbmalloc_proxy appears to be causing issues on OpenSUSE * Performance details + MT - multithread processing internal info - report timing info * Defer parsing internal data - wait until after address space is created * Performance improvement finding for get_symtab_function * fix data race in get_binary_info * remove set_default for linkage and visibility argparse * Parse internal libs with Dyninst::Symtab instead of binary reader - conflicting versions of libraries for binary analysis causes problems - expanded whole function restrictions - expanded module_function::is_routine_constrained regex * internal lib updates - include memory usage info - option to read libraries linked against internal libs: --internal-library-deps - defer parsing internal libs data to when processing modules --- examples/mpi/send-recv.c | 2 +- source/bin/omnitrace/CMakeLists.txt | 16 +- source/bin/omnitrace/details.cpp | 247 ++++++++- source/bin/omnitrace/fwd.hpp | 88 +++- source/bin/omnitrace/internal_libs.cpp | 592 ++++++++++++++++++++++ source/bin/omnitrace/internal_libs.hpp | 167 ++++++ source/bin/omnitrace/log.cpp | 32 +- source/bin/omnitrace/module_function.cpp | 192 ++++++- source/bin/omnitrace/module_function.hpp | 46 +- source/bin/omnitrace/omnitrace.cpp | 202 ++++++-- source/bin/omnitrace/omnitrace.hpp | 7 +- source/lib/binary/analysis.cpp | 23 +- source/lib/binary/analysis.hpp | 3 +- source/lib/binary/link_map.cpp | 16 +- source/lib/binary/link_map.hpp | 3 +- source/lib/binary/symbol.cpp | 3 +- source/lib/binary/symbol.hpp | 2 +- source/lib/common/join.hpp | 10 +- source/lib/core/config.cpp | 27 +- source/lib/core/config.hpp | 10 +- source/lib/omnitrace/library/sampling.cpp | 3 +- tests/CMakeLists.txt | 58 ++- 22 files changed, 1568 insertions(+), 181 deletions(-) create mode 100644 source/bin/omnitrace/internal_libs.cpp create mode 100644 source/bin/omnitrace/internal_libs.hpp diff --git a/examples/mpi/send-recv.c b/examples/mpi/send-recv.c index 7ac673972c..ee43a07183 100644 --- a/examples/mpi/send-recv.c +++ b/examples/mpi/send-recv.c @@ -27,7 +27,7 @@ main(int argc, char** argv) // We are assuming 2 processes for this task if(world_size != 2) { - fprintf(stderr, "World size must be two for %s\n", argv[0]); + fprintf(stderr, "World size must be two for %s, not %i\n", argv[0], world_size); MPI_Abort(MPI_COMM_WORLD, 1); } diff --git a/source/bin/omnitrace/CMakeLists.txt b/source/bin/omnitrace/CMakeLists.txt index 38b7e63213..fb9be4ce0f 100644 --- a/source/bin/omnitrace/CMakeLists.txt +++ b/source/bin/omnitrace/CMakeLists.txt @@ -10,17 +10,19 @@ add_executable(omnitrace-exe) target_sources( omnitrace-exe - PRIVATE ${CMAKE_CURRENT_LIST_DIR}/omnitrace.cpp - ${CMAKE_CURRENT_LIST_DIR}/details.cpp + PRIVATE ${CMAKE_CURRENT_LIST_DIR}/details.cpp ${CMAKE_CURRENT_LIST_DIR}/function_signature.cpp - ${CMAKE_CURRENT_LIST_DIR}/log.cpp - ${CMAKE_CURRENT_LIST_DIR}/module_function.cpp - ${CMAKE_CURRENT_LIST_DIR}/omnitrace.hpp - ${CMAKE_CURRENT_LIST_DIR}/fwd.hpp ${CMAKE_CURRENT_LIST_DIR}/function_signature.hpp + ${CMAKE_CURRENT_LIST_DIR}/fwd.hpp ${CMAKE_CURRENT_LIST_DIR}/info.hpp + ${CMAKE_CURRENT_LIST_DIR}/internal_libs.cpp + ${CMAKE_CURRENT_LIST_DIR}/internal_libs.hpp + ${CMAKE_CURRENT_LIST_DIR}/log.cpp ${CMAKE_CURRENT_LIST_DIR}/log.hpp - ${CMAKE_CURRENT_LIST_DIR}/module_function.hpp) + ${CMAKE_CURRENT_LIST_DIR}/module_function.cpp + ${CMAKE_CURRENT_LIST_DIR}/module_function.hpp + ${CMAKE_CURRENT_LIST_DIR}/omnitrace.cpp + ${CMAKE_CURRENT_LIST_DIR}/omnitrace.hpp) target_link_libraries( omnitrace-exe diff --git a/source/bin/omnitrace/details.cpp b/source/bin/omnitrace/details.cpp index 3e6664c3f9..34c62390a6 100644 --- a/source/bin/omnitrace/details.cpp +++ b/source/bin/omnitrace/details.cpp @@ -25,6 +25,9 @@ #include "log.hpp" #include "omnitrace.hpp" +#include +#include + #include #include @@ -39,17 +42,24 @@ get_whole_function_names() "sem_init", "sem_destroy", "sem_open", "sem_close", "sem_post", "sem_wait", "sem_getvalue", "sem_clockwait", "sem_timedwait", "sem_trywait", "sem_unlink", "fork", "do_futex_wait", "dl_iterate_phdr", "dlinfo", "dlopen", "dlmopen", - "dlvsym", "dlsym", "getenv", "setenv", "unsetenv", "printf", "fprintf", "fflush", - "malloc", "malloc_stats", "malloc_trim", "mallopt", "calloc", "free", "pvalloc", - "valloc", "mmap", "munmap", "fopen", "fclose", "fmemopen", "fmemclose", - "backtrace", "backtrace_symbols", "backtrace_symbols_fd", "sigaddset", - "sigandset", "sigdelset", "sigemptyset", "sigfillset", "sighold", "sigisemptyset", - "sigismember", "sigorset", "sigrelse", "sigvec", "strtok", "strstr", "sbrk", - "strxfrm", "atexit", "ompt_start_tool", "nanosleep", "cfree", "tolower", - "toupper", "fileno", "fileno_unlocked", "exit", "quick_exit", "abort", "mbind", - "migrate_pages", "move_pages", "numa_migrate_pages", "numa_move_pages", - "numa_alloc", "numa_alloc_local", "numa_alloc_interleaved", "numa_alloc_onnode", - "numa_realloc", "numa_free", + "dlvsym", "dlsym", "dlerror", "dladdr", "_dl_sym", "_dl_vsym", "_dl_addr", + "getenv", "setenv", "unsetenv", "printf", "fprintf", "vprintf", + "buffered_vfprintf", "vfprintf", "printf_positional", "puts", "fputs", "vfputs", + "fflush", "fwrite", "malloc", "malloc_stats", "malloc_trim", "mallopt", "calloc", + "free", "pvalloc", "valloc", "sysmalloc", "posix_memalign", "freehook", + "mallochook", "memalignhook", "mprobe", "reallochook", "mmap", "munmap", "fopen", + "fclose", "fmemopen", "fmemclose", "backtrace", "backtrace_symbols", + "backtrace_symbols_fd", "sigaddset", "sigandset", "sigdelset", "sigemptyset", + "sigfillset", "sighold", "sigisemptyset", "sigismember", "sigorset", "sigrelse", + "sigvec", "strtok", "strstr", "sbrk", "strxfrm", "atexit", "ompt_start_tool", + "nanosleep", "cfree", "tolower", "toupper", "fileno", "fileno_unlocked", "exit", + "quick_exit", "abort", "mbind", "migrate_pages", "move_pages", + "numa_migrate_pages", "numa_move_pages", "numa_alloc", "numa_alloc_local", + "numa_alloc_interleaved", "numa_alloc_onnode", "numa_realloc", "numa_free", + "round_and_return", "_init", "_fini", "_start", "__do_global_dtors_aux", + "__libc_csu_init", "__libc_csu_fini", "__hip_module_ctor", "__hip_module_dtor", + "__hipRegisterManagedVar", "__hipRegisterFunction", "__hipPushCallConfiguration", + "__hipPopCallConfiguration", "hipApiName", "enlarge_userbuf", // below are functions which never terminate "rocr::core::Signal::WaitAny", "rocr::core::Runtime::AsyncEventsLoop", "rocr::core::BusyWaitSignal::WaitAcquire", @@ -108,6 +118,59 @@ get_name(module_t* _module) return _v.at(_module); } +symtab_func_t* +get_symtab_function(procedure_t* _func) +{ + static auto _v = std::unordered_map{}; + + auto itr = _v.find(_func); + if(itr == _v.end()) + { + auto _name = _func->getName(); + { + auto nitr = symtab_data.mangled_symbol_names.find(_name); + if(nitr != symtab_data.mangled_symbol_names.end()) + { + _v.emplace(_func, nitr->second->getFunction()); + return _v.at(_func); + } + } + + for(auto& fitr : symtab_data.symbols) + { + if(_name == fitr.first->getName()) + { + _v.emplace(_func, fitr.first); + return _v.at(_func); + } + } + + auto _dname = _func->getDemangledName(); + + { + auto nitr = symtab_data.typed_func_names.find(_dname); + if(nitr != symtab_data.typed_func_names.end()) + { + _v.emplace(_func, nitr->second); + return _v.at(_func); + } + } + + { + auto nitr = symtab_data.typed_symbol_names.find(_dname); + if(nitr != symtab_data.typed_symbol_names.end()) + { + _v.emplace(_func, nitr->second->getFunction()); + return _v.at(_func); + } + } + + if(_v.find(_func) == _v.end()) _v.emplace(_func, nullptr); + } + + return _v.at(_func); +} + namespace { std::string @@ -390,7 +453,7 @@ find_function(image_t* app_image, const std::string& _name, const strset_t& _ext auto _find = [app_image](const std::string& _f) -> procedure_t* { // Extract the vector of functions - bpvector_t _found; + std::vector _found; auto* ret = app_image->findFunction(_f.c_str(), _found, false, true, true); if(ret == nullptr || _found.empty()) return nullptr; return _found.at(0); @@ -488,6 +551,83 @@ error_func_fake(error_level_t level, int num, const char* const* params) .force(level < BPatchInfo); } +#include "internal_libs.hpp" + +#include +#include + +using ::timemory::join::join; + +//======================================================================================// +// +// Read the symtab data from Dyninst +// +void +process_modules(const std::vector& _app_modules) +{ + parse_internal_libs_data(); + + auto _wc = tim::component::wall_clock{}; + auto _pr = tim::component::peak_rss{}; + _wc.start(); + _pr.start(); + + for(auto* itr : _app_modules) + { + auto* _module = SymTab::convert(itr); + if(_module) symtab_data.modules.emplace_back(_module); + } + + verbprintf(0, "Processing %zu modules...\n", symtab_data.modules.size()); + + const auto& _data = get_internal_libs_data(); + auto _names = std::set{}; + for(const auto& itr : _data) + { + _names.emplace(itr.first); + for(const auto& ditr : itr.second) + _names.emplace(ditr.first); + } + + for(auto* itr : symtab_data.modules) + { + const auto* _base_name = tim::filepath::basename(itr->fullName()); + auto _real_name = tim::filepath::realpath(itr->fullName(), nullptr, false); + + if(_names.count(_base_name) == 0 && _names.count(_real_name) == 0) + { + verbprintf(2, "Processing symbol table for module '%s'...\n", + itr->fullName().c_str()); + } + + symtab_data.functions.emplace(itr, std::vector{}); + itr->getAllFunctions(symtab_data.functions.at(itr)); + for(auto* fitr : symtab_data.functions.at(itr)) + { + symtab_data.typed_func_names[tim::demangle(fitr->getName())] = fitr; + + symtab_data.symbols.emplace(fitr, std::vector{}); + fitr->getSymbols(symtab_data.symbols.at(fitr)); + for(auto* sitr : symtab_data.symbols.at(fitr)) + { + symtab_data.mangled_symbol_names[sitr->getMangledName()] = sitr; + symtab_data.typed_symbol_names[sitr->getTypedName()] = sitr; + } + } + } + + _pr.stop(); + _wc.stop(); + verbprintf(0, "Processing %zu modules... Done (%.3f %s, %.3f %s)\n", + _app_modules.size(), _wc.get(), _wc.display_unit().c_str(), _pr.get(), + _pr.display_unit().c_str()); +} + +//======================================================================================// +// +// I/O assistance +// + namespace std { std::string @@ -538,4 +678,87 @@ to_string(error_level_t _level) return JOIN("", tim::log::color::warning(), "UnknownErrorLevel", static_cast(_level)); } + +namespace +{ +std::string&& +to_lower(std::string&& _v) +{ + for(auto& itr : std::move(_v)) + itr = tolower(itr); + return std::move(_v); +} +} // namespace + +std::string +to_string(symbol_visibility_t _v) +{ + return to_lower(SymTab::Symbol::symbolVisibility2Str(_v) + 3); +} + +std::string +to_string(symbol_linkage_t _v) +{ + return to_lower(SymTab::Symbol::symbolLinkage2Str(_v) + 3); +} } // namespace std + +template +Tp +from_string(std::string_view _v) +{ + if constexpr(std::is_same::value) + { + for(const auto& itr : + { SV_UNKNOWN, SV_DEFAULT, SV_INTERNAL, SV_HIDDEN, SV_PROTECTED }) + if(_v == std::to_string(itr)) return itr; + return SV_UNKNOWN; + } + else if constexpr(std::is_same::value) + { + for(const auto& itr : { SL_UNKNOWN, SL_GLOBAL, SL_LOCAL, SL_WEAK, SL_UNIQUE }) + if(_v == std::to_string(itr)) return itr; + return SL_UNKNOWN; + } + else + { + static_assert(std::is_empty::value, "Error! not defined"); + return Tp{}; + } +} + +template symbol_visibility_t +from_string(std::string_view _v); + +template symbol_linkage_t +from_string(std::string_view _v); + +std::ostream& +operator<<(std::ostream& _os, symbol_linkage_t _v) +{ + return (_os << std::to_string(_v)); +} + +std::ostream& +operator<<(std::ostream& _os, symbol_visibility_t _v) +{ + return (_os << std::to_string(_v)); +} + +std::istream& +operator>>(std::istream& _is, symbol_linkage_t& _v) +{ + auto _v_s = std::string{}; + _is >> _v_s; + _v = from_string(_v_s); + return _is; +} + +std::istream& +operator>>(std::istream& _is, symbol_visibility_t& _v) +{ + auto _v_s = std::string{}; + _is >> _v_s; + _v = from_string(_v_s); + return _is; +} diff --git a/source/bin/omnitrace/fwd.hpp b/source/bin/omnitrace/fwd.hpp index 85f110efe0..acff922b07 100644 --- a/source/bin/omnitrace/fwd.hpp +++ b/source/bin/omnitrace/fwd.hpp @@ -49,8 +49,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -61,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -88,9 +91,6 @@ struct function_signature; struct basic_block_signature; struct module_function; -template -using bpvector_t = BPatch_Vector; - using string_t = std::string; using string_view_t = std::string_view; using stringstream_t = std::stringstream; @@ -127,14 +127,40 @@ using snippet_handle_t = BPatchSnippetHandle; using patch_pointer_t = std::shared_ptr; using snippet_pointer_t = std::shared_ptr; using call_expr_pointer_t = std::shared_ptr; -using snippet_vec_t = bpvector_t; -using procedure_vec_t = bpvector_t; +using snippet_vec_t = std::vector; +using procedure_vec_t = std::vector; using basic_block_set_t = std::set; -using basic_loop_vec_t = bpvector_t; +using basic_loop_vec_t = std::vector; using snippet_pointer_vec_t = std::vector; using instruction_t = Dyninst::InstructionAPI::Instruction; using instruction_category_t = Dyninst::InstructionAPI::InsnCategory; +namespace SymTab = ::Dyninst::SymtabAPI; +using symtab_t = SymTab::Symtab; +using symtab_module_t = SymTab::Module; +using symtab_symbol_t = SymTab::Symbol; +using symtab_func_t = SymTab::Function; +using symbol_linkage_t = SymTab::Symbol::SymbolLinkage; +using symbol_visibility_t = SymTab::Symbol::SymbolVisibility; + +constexpr auto SL_UNKNOWN = symtab_symbol_t::SL_UNKNOWN; +constexpr auto SL_GLOBAL = symtab_symbol_t::SL_GLOBAL; +constexpr auto SL_LOCAL = symtab_symbol_t::SL_LOCAL; +constexpr auto SL_WEAK = symtab_symbol_t::SL_WEAK; +constexpr auto SL_UNIQUE = symtab_symbol_t::SL_UNIQUE; + +constexpr auto SV_UNKNOWN = symtab_symbol_t::SV_UNKNOWN; +constexpr auto SV_DEFAULT = symtab_symbol_t::SV_DEFAULT; +constexpr auto SV_INTERNAL = symtab_symbol_t::SV_INTERNAL; +constexpr auto SV_HIDDEN = symtab_symbol_t::SV_HIDDEN; +constexpr auto SV_PROTECTED = symtab_symbol_t::SV_PROTECTED; + +constexpr auto SL_END_V = + std::max({ SL_UNKNOWN, SL_GLOBAL, SL_LOCAL, SL_WEAK, SL_UNIQUE }) + 1; + +constexpr auto SV_END_V = + std::max({ SV_UNKNOWN, SV_DEFAULT, SV_INTERNAL, SV_HIDDEN, SV_PROTECTED }) + 1; + void omnitrace_prefork_callback(thread_t* parent, thread_t* child); @@ -165,6 +191,7 @@ extern bool loop_level_instr; extern bool instr_dynamic_callsites; extern bool instr_traps; extern bool instr_loop_traps; +extern bool parse_all_modules; extern size_t min_address_range; extern size_t min_loop_address_range; extern size_t min_instructions; @@ -182,6 +209,7 @@ extern int num_log_entries; // extern bool simulate; extern bool include_uninstr; +extern bool include_internal_linked_libs; // // string settings // @@ -209,7 +237,26 @@ extern regexvec_t file_exclude; extern regexvec_t file_restrict; extern regexvec_t func_restrict; extern regexvec_t caller_include; +extern regexvec_t func_internal_include; +extern regexvec_t file_internal_include; +extern regexvec_t instruction_exclude; extern CodeCoverageMode coverage_mode; +// +// symtab variables +// +struct symtab_data_s +{ + std::vector modules = {}; + std::map> functions = {}; + std::map> symbols = {}; + std::unordered_map mangled_symbol_names = {}; + std::unordered_map typed_func_names = {}; + std::unordered_map typed_symbol_names = {}; +}; + +extern symtab_data_s symtab_data; +extern std::set enabled_linkage; +extern std::set enabled_visibility; // logging extern std::unique_ptr log_ofs; @@ -267,6 +314,9 @@ consume_parameters(T&&...) //======================================================================================// +void +process_modules(const std::vector&); + strset_t get_whole_function_names(); @@ -293,7 +343,7 @@ query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc, flow_graph_t* cf template bool -insert_instr(address_space_t* mutatee, const bpvector_t& _points, Tp traceFunc, +insert_instr(address_space_t* mutatee, const std::vector& _points, Tp traceFunc, procedure_loc_t traceLoc, bool allow_traps = instr_traps); template @@ -317,13 +367,33 @@ void error_func_fake(error_level_t level, int num, const char* const* params); std::string_view -get_name(procedure_t* _module); +get_name(procedure_t*); std::string_view -get_name(module_t* _module); +get_name(module_t*); + +symtab_func_t* +get_symtab_function(procedure_t*); namespace std { std::string to_string(instruction_category_t); std::string to_string(error_level_t); +std::string to_string(symbol_visibility_t); +std::string to_string(symbol_linkage_t); } // namespace std + +template +Tp from_string(std::string_view); + +std::ostream& +operator<<(std::ostream&, symbol_linkage_t); + +std::ostream& +operator<<(std::ostream&, symbol_visibility_t); + +std::istream& +operator>>(std::istream&, symbol_linkage_t&); + +std::istream& +operator>>(std::istream&, symbol_visibility_t&); diff --git a/source/bin/omnitrace/internal_libs.cpp b/source/bin/omnitrace/internal_libs.cpp new file mode 100644 index 0000000000..35504f23db --- /dev/null +++ b/source/bin/omnitrace/internal_libs.cpp @@ -0,0 +1,592 @@ +// MIT License +// +// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include "internal_libs.hpp" +#include "binary/analysis.hpp" +#include "binary/binary_info.hpp" +#include "binary/link_map.hpp" +#include "binary/scope_filter.hpp" +#include "binary/symbol.hpp" +#include "common/defines.h" +#include "core/utility.hpp" +#include "fwd.hpp" +#include "log.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace +{ +namespace filepath = ::tim::filepath; +using ::tim::delimit; +using ::tim::get_env; +using ::timemory::join::join; +using strview_init_t = std::initializer_list; +using strview_set_t = std::set; +using open_modes_vec_t = std::vector; + +auto +get_exe_realpath() +{ + return filepath::realpath("/proc/self/exe", nullptr, false); +} + +auto& +get_symtab_file_cache() +{ + static auto _cache = std::unordered_map>{}; + return _cache; +} + +symtab_t* +get_symtab_file(const std::string& _name) +{ + auto& _cache = get_symtab_file_cache(); + auto itr = _cache.find(_name); + if(itr == _cache.end()) + { + symtab_t* _v = SymTab::Symtab::findOpenSymtab(_name); + bool _closable = (_v == nullptr); + if(!_v) SymTab::Symtab::openFile(_v, _name); + + TIMEMORY_PREFER(_v != nullptr) + << "Warning! Dyninst could not open a Symtab instance for file '" << _name + << "'\n"; + _cache.emplace(_name, std::make_pair(_v, _closable)); + } + + return _cache.at(_name).first; +} + +bool +close_symtab_file(const std::string& _name) +{ + auto& _cache = get_symtab_file_cache(); + auto itr = _cache.find(_name); + if(itr != _cache.end()) + { + symtab_t* _symtab = itr->second.first; + bool _closable = itr->second.second; + if(_symtab && _closable) SymTab::Symtab::closeSymtab(_symtab); + _cache.erase(itr); + return true; + } + return false; +} + +template