diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d6006046b..cc1732b22c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ endif() project( hosttrace LANGUAGES C CXX - VERSION 0.0.1) + VERSION 0.0.2) message( STATUS @@ -108,8 +108,9 @@ if(DYNINST_API_RT) endif() set_target_properties( - hosttrace-library PROPERTIES OUTPUT_NAME hosttrace INSTALL_RPATH - "\$ORIGIN:${DYNINST_API_RT_DIR}") + hosttrace-library + PROPERTIES OUTPUT_NAME hosttrace + INSTALL_RPATH "\$ORIGIN:\$ORIGIN/dyninst-tpls/libs:${DYNINST_API_RT_DIR}") install( TARGETS hosttrace-library @@ -138,9 +139,12 @@ target_link_libraries( set_target_properties( hosttrace-exe - PROPERTIES OUTPUT_NAME hosttrace - INSTALL_RPATH_USE_LINK_PATH ON - INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:${DYNINST_API_RT_DIR}") + PROPERTIES + OUTPUT_NAME hosttrace + INSTALL_RPATH_USE_LINK_PATH ON + INSTALL_RPATH + "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}/dyninst-tpls/lib:${DYNINST_API_RT_DIR}" + ) install( TARGETS hosttrace-exe diff --git a/cmake/Packages.cmake b/cmake/Packages.cmake index ca817f0d7e..853fb107b4 100644 --- a/cmake/Packages.cmake +++ b/cmake/Packages.cmake @@ -78,13 +78,13 @@ if(HOSTTRACE_BUILD_DYNINST) OFF CACHE BOOL "Build dyninst parseThat executable") set(DYNINST_BUILD_SHARED_LIBS - OFF + ON CACHE BOOL "Build shared dyninst libraries") set(DYNINST_BUILD_STATIC_LIBS - ON + OFF CACHE BOOL "Build static dyninst libraries") set(DYNINST_ENABLE_LTO - ON + OFF CACHE BOOL "Enable LTO for dyninst libraries") hosttrace_save_variables(PIC VARIABLES CMAKE_POSITION_INDEPENDENT_CODE) diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000000..459741e98e --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,26 @@ + +FROM ubuntu:20.04 + +ENV HOME /root +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US +ENV LC_ALL C +ENV SHELL /bin/bash +ENV BASH_ENV /etc/bash.bashrc +ENV DEBIAN_FRONTEND noninteractive + +WORKDIR /tmp +SHELL [ "/bin/bash", "-c" ] + +RUN apt-get update && \ + apt-get dist-upgrade -y && \ + apt-get install -y build-essential cmake libnuma-dev wget gnupg2 m4 && \ + wget -q -O - https://repo.radeon.com/rocm/rocm.gpg.key | apt-key add - && \ + echo 'deb [arch=amd64] https://repo.radeon.com/rocm/apt/debian/ ubuntu main' | tee /etc/apt/sources.list.d/rocm.list && \ + apt-get update && \ + apt-get dist-upgrade -y && \ + apt-get install -y rocm-dev rocm-utils roctracer-dev rocprofiler-dev hip-base hsa-amd-aqlprofile hsa-rocr-dev hsakmt-roct-dev + +ENV LC_ALL C.UTF-8 +WORKDIR /home +SHELL [ "/bin/bash", "--login", "-c" ] diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 4de5b8a5db..1c704b7cb6 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -2,5 +2,8 @@ cmake_minimum_required(VERSION 3.15 FATAL_ERROR) project(hosttrace-dyninst-examples LANGUAGES CXX) +set(CMAKE_VISIBILITY_INLINES_HIDDEN OFF) +set(CMAKE_CXX_VISIBILITY_PRESET "default") + add_subdirectory(transpose) add_subdirectory(parallel-overhead) diff --git a/examples/parallel-overhead/parallel-overhead.cpp b/examples/parallel-overhead/parallel-overhead.cpp index 99d77d2fcd..8c7e005a1c 100644 --- a/examples/parallel-overhead/parallel-overhead.cpp +++ b/examples/parallel-overhead/parallel-overhead.cpp @@ -29,7 +29,7 @@ run(size_t nitr, long n) int main(int argc, char** argv) { - size_t nthread = 16; + size_t nthread = std::min(16, std::thread::hardware_concurrency()); size_t nitr = 50000; long nfib = 10; if(argc > 1) nfib = atol(argv[1]); diff --git a/external/dyninst b/external/dyninst index b96fa72a02..076d8bdef4 160000 --- a/external/dyninst +++ b/external/dyninst @@ -1 +1 @@ -Subproject commit b96fa72a026eb703a4fc742c08180a47b01d914c +Subproject commit 076d8bdef4f22639d16ca65cda9b909b6c726047 diff --git a/external/timemory b/external/timemory index 174607ac8c..9f27fafd2e 160000 --- a/external/timemory +++ b/external/timemory @@ -1 +1 @@ -Subproject commit 174607ac8cf4b93284dab3ad028806f26ebde216 +Subproject commit 9f27fafd2e28f8db2b1cc908b2c910a45136b31d diff --git a/include/hosttrace.hpp b/include/hosttrace.hpp index 7f2adfb74f..98d223417b 100644 --- a/include/hosttrace.hpp +++ b/include/hosttrace.hpp @@ -122,7 +122,6 @@ static bool binary_rewrite = 0; static bool loop_level_instr = false; static bool werror = false; static bool stl_func_instr = false; -static bool cstd_func_instr = false; static bool use_mpi = false; static bool is_static_exe = false; static bool use_return_info = false; @@ -200,11 +199,16 @@ function_signature get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t* cfGraph, basic_loop_t* loopToInstrument); +bool +query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc, + flow_graph_t* cfGraph = nullptr, basic_loop_t* loopToInstrument = nullptr, + bool allow_traps = true); + template -void +bool insert_instr(address_space_t* mutatee, procedure_t* funcToInstr, Tp traceFunc, procedure_loc_t traceLoc, flow_graph_t* cfGraph = nullptr, - basic_loop_t* loopToInstrument = nullptr); + basic_loop_t* loopToInstrument = nullptr, bool allow_traps = true); void errorFunc(error_level_t level, int num, const char** params); @@ -321,19 +325,17 @@ struct function_signature { if(m_info_end) { - ss << '/' << "[{" << m_row.first << "," << m_col.first << "}-{" - << m_row.second << "," << m_col.second << "}]"; + ss << " [{" << m_row.first << "," << m_col.first << "}-{" << m_row.second + << "," << m_col.second << "}]"; } else { ss << "[{" << m_row.first << "," << m_col.first << "}]"; } } - else - { - if(use_file_info && m_file.length() > 0) ss << '/' << m_file; - if(use_line_info && m_row.first > 0) ss << ":" << m_row.first; - } + if(use_file_info && m_file.length() > 0) ss << " [" << m_file; + if(use_line_info && m_row.first > 0) ss << ":" << m_row.first; + if(use_file_info && m_file.length() > 0) ss << "]"; m_signature = ss.str(); return m_signature; @@ -369,18 +371,25 @@ struct module_function } module_function(const string_t& _module, const string_t& _func, - const function_signature& _sign) + const function_signature& _sign, procedure_t* proc) : module(_module) , function(_func) , signature(_sign) - {} + { + if(proc) + { + std::pair _range{}; + if(proc->getAddressRange(_range.first, _range.second)) + address_range = _range.second - _range.first; + } + } module_function(module_t* mod, procedure_t* proc) { char modname[FUNCNAMELEN]; char fname[FUNCNAMELEN]; - mod->getName(modname, FUNCNAMELEN); + mod->getFullName(modname, FUNCNAMELEN); proc->getName(fname, FUNCNAMELEN); module = modname; @@ -431,7 +440,7 @@ struct module_function }; // clang-format off - ss << std::setw(14) << rhs.address_range << " " + ss << std::setw(14) << rhs.address_range << " " << std::setw(w0 + 8) << std::left << _get_str(rhs.module) << " " << std::setw(w1 + 8) << std::left << _get_str(rhs.function) << " " << std::setw(w2 + 8) << std::left << _get_str(rhs.signature.get()); diff --git a/include/library.hpp b/include/library.hpp index 8819b57220..0295b2e884 100644 --- a/include/library.hpp +++ b/include/library.hpp @@ -71,6 +71,7 @@ extern "C" if(get_debug()) \ { \ fprintf(stderr, __VA_ARGS__); \ + fflush(stderr); \ } //--------------------------------------------------------------------------------------// diff --git a/src/hosttrace-details.cpp b/src/hosttrace-details.cpp index a3e2f59261..d800182cf2 100644 --- a/src/hosttrace-details.cpp +++ b/src/hosttrace-details.cpp @@ -443,8 +443,8 @@ c_stdlib_function_constraint(const std::string& _func) inline void consume() { - consume_parameters(initialize_expr, bpatch, use_mpi, stl_func_instr, cstd_func_instr, - werror, loop_level_instr, error_print, binary_rewrite, debug_print, + consume_parameters(initialize_expr, bpatch, use_mpi, stl_func_instr, werror, + loop_level_instr, error_print, binary_rewrite, debug_print, expect_error, is_static_exe, available_module_functions, instrumented_module_functions); } diff --git a/src/hosttrace.cpp b/src/hosttrace.cpp index 16dca37309..f0b89b7ec9 100644 --- a/src/hosttrace.cpp +++ b/src/hosttrace.cpp @@ -31,6 +31,8 @@ static bool is_driver = false; static bool allow_overlapping = false; static bool instr_dynamic_callsites = false; +static bool instr_traps = false; +static bool instr_loop_traps = false; static size_t batch_size = 50; static strset_t extra_libs = {}; static size_t min_address_range = (1 << 9); // 512 @@ -54,7 +56,7 @@ static string_t instr_pop_hash = "hosttrace_pop_trace_hash"; static string_t print_instrumented = {}; static string_t print_available = {}; static string_t print_overlapping = {}; -static std::string modfunc_dump_dir = "hosttrace-module-functions"; +static std::string modfunc_dump_dir = {}; std::string get_absolute_exe_filepath(std::string exe_name); @@ -114,14 +116,14 @@ main(int argc, char** argv) bpatch->setTypeChecking(true); bpatch->setSaveFPR(true); bpatch->setDelayedParsing(true); - bpatch->setInstrStackFrames(true); + bpatch->setDebugParsing(false); + bpatch->setInstrStackFrames(false); bpatch->setLivenessAnalysis(false); bpatch->setBaseTrampDeletion(false); bpatch->setTrampRecursive(false); bpatch->setMergeTramp(false); - std::set dyninst_defs = { "TypeChecking", "SaveFPR", "DelayedParsing", - "InstrStackFrames" }; + std::set dyninst_defs = { "TypeChecking", "SaveFPR", "DelayedParsing" }; int _argc = argc; int _cmdc = 0; @@ -329,14 +331,35 @@ main(int argc, char** argv) parser .add_argument({ "--min-address-range-loop" }, "If the address range of a function containing a loop is less than " - "this value, " - "exclude it from instrumentation") + "this value, exclude it from instrumentation") .count(1) .dtype("size_t") .set_default(min_loop_address_range) .action([](parser_t& p) { min_loop_address_range = p.get("min-address-range-loop"); }); + parser + .add_argument( + { "--traps" }, + "Instrument points which require using a trap. On the x86 architecture, " + "because instructions are of variable size, the instruction at a point may " + "be too small for Dyninst to replace it with the normal code sequence used " + "to call instrumentation. Also, when instrumentation is placed at points " + "other than subroutine entry, exit, or call points, traps may be used to " + "ensure the instrumentation fits. In this case, Dyninst replaces the " + "instruction with a single-byte instruction that generates a trap.") + .max_count(1) + .dtype("bool") + .set_default(instr_traps) + .action([](parser_t& p) { instr_traps = p.get("traps"); }); + parser + .add_argument({ "--loop-traps" }, + "Instrument points within a loop which require using a trap (only " + "relevant when --instrument-loops is enabled).") + .max_count(1) + .dtype("bool") + .set_default(instr_loop_traps) + .action([](parser_t& p) { instr_loop_traps = p.get("loop-traps"); }); parser.add_argument() .names({ "--allow-overlapping" }) .description( @@ -352,7 +375,6 @@ main(int argc, char** argv) "function lists, e.g. {print-dir}/available.txt") .count(1) .dtype("string") - .set_default(modfunc_dump_dir) .action([](parser_t& p) { modfunc_dump_dir = p.get("print-dir"); }); parser .add_argument( @@ -397,8 +419,9 @@ main(int argc, char** argv) .add_argument({ "--dyninst-options" }, "Advanced dyninst options: BPatch::set