diff --git a/.clang-tidy b/.clang-tidy index ec883837c..1d384b848 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -23,6 +23,7 @@ performance-*,\ readability-*,\ -readability-function-size,\ -readability-identifier-naming,\ +-readability-identifier-length,\ -readability-implicit-bool-cast,\ -readability-inconsistent-declaration-parameter-name,\ -readability-named-parameter,\ diff --git a/.github/workflows/cpack.yml b/.github/workflows/cpack.yml index 878bdf348..16eab94be 100644 --- a/.github/workflows/cpack.yml +++ b/.github/workflows/cpack.yml @@ -54,6 +54,9 @@ jobs: - os-distro: "ubuntu" os-version: "20.04" rocm-version: "6.0" + - os-distro: "ubuntu" + os-version: "20.04" + rocm-version: "6.1" # ubuntu 22.04 - os-distro: "ubuntu" os-version: "22.04" @@ -73,6 +76,9 @@ jobs: - os-distro: "ubuntu" os-version: "22.04" rocm-version: "6.0" + - os-distro: "ubuntu" + os-version: "22.04" + rocm-version: "6.1" # opensuse 15.3 - os-distro: "opensuse" os-version: "15.3" @@ -114,6 +120,9 @@ jobs: - os-distro: "opensuse" os-version: "15.4" rocm-version: "6.0" + - os-distro: "opensuse" + os-version: "15.4" + rocm-version: "6.1" # opensuse 15.5 - os-distro: "opensuse" os-version: "15.5" @@ -121,6 +130,9 @@ jobs: - os-distro: "opensuse" os-version: "15.5" rocm-version: "6.0" + - os-distro: "opensuse" + os-version: "15.5" + rocm-version: "6.1" # RHEL 8.7 - os-distro: "rhel" os-version: "8.7" @@ -153,6 +165,9 @@ jobs: - os-distro: "rhel" os-version: "8.8" rocm-version: "6.0" + - os-distro: "rhel" + os-version: "8.8" + rocm-version: "6.1" # RHEL 8.9 - os-distro: "rhel" os-version: "8.9" @@ -160,6 +175,9 @@ jobs: - os-distro: "rhel" os-version: "8.9" rocm-version: "6.0" + - os-distro: "rhel" + os-version: "8.9" + rocm-version: "6.1" # RHEL 9.1 - os-distro: "rhel" os-version: "9.1" @@ -183,6 +201,9 @@ jobs: - os-distro: "rhel" os-version: "9.2" rocm-version: "6.0" + - os-distro: "rhel" + os-version: "9.2" + rocm-version: "6.1" # RHEL 9.3 - os-distro: "rhel" os-version: "9.3" @@ -190,6 +211,9 @@ jobs: - os-distro: "rhel" os-version: "9.3" rocm-version: "6.0" + - os-distro: "rhel" + os-version: "9.3" + rocm-version: "6.1" steps: - name: Free Disk Space diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 3731ea82d..c5af45159 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -49,7 +49,7 @@ jobs: conda activate omnitrace-docs ./update-docs.sh - name: Upload artifact - uses: actions/upload-pages-artifact@v1 + uses: actions/upload-pages-artifact@v3 with: path: ./docs @@ -67,4 +67,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1 + uses: actions/deploy-pages@v4 diff --git a/VERSION b/VERSION index ca7176690..0a5af26df 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.11.2 +1.11.3 diff --git a/cmake/Packages.cmake b/cmake/Packages.cmake index 34d0a7a2c..13b831314 100644 --- a/cmake/Packages.cmake +++ b/cmake/Packages.cmake @@ -291,6 +291,7 @@ if(OMNITRACE_BUILD_DYNINST) set(DYNINST_OPTION_PREFIX ON) set(DYNINST_BUILD_DOCS OFF) + set(DYNINST_BUILD_RTLIB OFF) set(DYNINST_QUIET_CONFIG ON CACHE BOOL "Suppress dyninst cmake messages") @@ -344,7 +345,6 @@ if(OMNITRACE_BUILD_DYNINST) dynDwarf dynElf dyninstAPI - dyninstAPI_RT instructionAPI parseAPI patchAPI @@ -360,9 +360,6 @@ if(OMNITRACE_BUILD_DYNINST) endif() endforeach() - omnitrace_install_tpl(dyninstAPI_RT omnitrace-rt - "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}" core) - # for packaging install( DIRECTORY ${DYNINST_TPL_STAGING_PREFIX}/lib/ @@ -373,35 +370,11 @@ if(OMNITRACE_BUILD_DYNINST) target_link_libraries(omnitrace-dyninst INTERFACE Dyninst::Dyninst) - set(OMNITRACE_DYNINST_API_RT - ${PROJECT_BINARY_DIR}/external/dyninst/dyninstAPI_RT/libdyninstAPI_RT${CMAKE_SHARED_LIBRARY_SUFFIX} - ) - - if(OMNITRACE_DYNINST_API_RT) - omnitrace_target_compile_definitions( - omnitrace-dyninst - INTERFACE - DYNINST_API_RT="${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}:$:${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$:$" - ) - endif() - else() find_package(Dyninst ${omnitrace_FIND_QUIETLY} REQUIRED COMPONENTS dyninstAPI parseAPI instructionAPI symtabAPI) if(TARGET Dyninst::Dyninst) # updated Dyninst CMake system was found - # useful for defining the location of the runtime API - find_library( - OMNITRACE_DYNINST_API_RT dyninstAPI_RT - HINTS ${Dyninst_ROOT_DIR} ${Dyninst_DIR} - PATHS ${Dyninst_ROOT_DIR} ${Dyninst_DIR} - PATH_SUFFIXES lib NO_CACHE) - - if(OMNITRACE_DYNINST_API_RT) - omnitrace_target_compile_definitions( - omnitrace-dyninst INTERFACE DYNINST_API_RT="${OMNITRACE_DYNINST_API_RT}") - endif() - target_link_libraries(omnitrace-dyninst INTERFACE Dyninst::Dyninst) else() # updated Dyninst CMake system was not found set(_BOOST_COMPONENTS atomic system thread date_time) @@ -424,13 +397,6 @@ else() PATH_SUFFIXES include) endif() - # useful for defining the location of the runtime API - find_library( - OMNITRACE_DYNINST_API_RT dyninstAPI_RT - HINTS ${Dyninst_ROOT_DIR} ${Dyninst_DIR} - PATHS ${Dyninst_ROOT_DIR} ${Dyninst_DIR} - PATH_SUFFIXES lib) - # try to find TBB find_package(TBB QUIET) @@ -447,11 +413,6 @@ else() PATH_SUFFIXES include) endif() - if(OMNITRACE_DYNINST_API_RT) - omnitrace_target_compile_definitions( - omnitrace-dyninst INTERFACE DYNINST_API_RT="${OMNITRACE_DYNINST_API_RT}") - endif() - target_link_libraries(omnitrace-dyninst INTERFACE ${DYNINST_LIBRARIES} ${Boost_LIBRARIES}) foreach( diff --git a/docker/build-docker.sh b/docker/build-docker.sh index beafa2da3..c716c187f 100755 --- a/docker/build-docker.sh +++ b/docker/build-docker.sh @@ -177,7 +177,7 @@ do 4.1* | 4.0*) ROCM_REPO_DIST="xenial" ;; - 5.3 | 5.3.* | 5.4 | 5.4.* | 5.5 | 5.5.* | 5.6 | 5.6.* | 5.7 | 5.7.* | 6.0 | 6.0.*) + 5.3 | 5.3.* | 5.4 | 5.4.* | 5.5 | 5.5.* | 5.6 | 5.6.* | 5.7 | 5.7.* | 6.*) case "${VERSION}" in 22.04) ROCM_REPO_DIST="ubuntu" @@ -208,7 +208,7 @@ do # set the sub-URL in https://repo.radeon.com/amdgpu-install/ case "${ROCM_VERSION}" in - 5.3 | 5.3.* | 5.4 | 5.4.* | 5.5 | 5.5.* | 5.6 | 5.6.* | 5.7 | 5.7.* | 6.0 | 6.0.*) + 5.3 | 5.3.* | 5.4 | 5.4.* | 5.5 | 5.5.* | 5.6 | 5.6.* | 5.7 | 5.7.* | 6.*) ROCM_RPM=${ROCM_VERSION}/rhel/${RPM_PATH}/amdgpu-install-${ROCM_MAJOR}.${ROCM_MINOR}.${ROCM_VERSN}-1${RPM_TAG}.noarch.rpm ;; 5.2 | 5.2.* | 5.1 | 5.1.* | 5.0 | 5.0.* | 4.*) @@ -236,7 +236,7 @@ do ;; esac case "${ROCM_VERSION}" in - 5.3 | 5.3.* | 5.4 | 5.4.* | 5.5 | 5.5.* | 5.6 | 5.6.* | 5.7 | 5.7.* | 6.0 | 6.0.*) + 5.3 | 5.3.* | 5.4 | 5.4.* | 5.5 | 5.5.* | 5.6 | 5.6.* | 5.7 | 5.7.* | 6.*) ROCM_RPM=${ROCM_VERSION}/sle/${VERSION}/amdgpu-install-${ROCM_MAJOR}.${ROCM_MINOR}.${ROCM_VERSN}-1.noarch.rpm ;; 5.2 | 5.2.*) diff --git a/examples/lulesh/external/kokkos b/examples/lulesh/external/kokkos index 698a67731..1a0c2ff6d 160000 --- a/examples/lulesh/external/kokkos +++ b/examples/lulesh/external/kokkos @@ -1 +1 @@ -Subproject commit 698a67731a4c3b20ef4fcb728298176e49474033 +Subproject commit 1a0c2ff6daf1068c65529ec04c2c046177847869 diff --git a/external/dyninst b/external/dyninst index d3ab0a71e..dedad14f5 160000 --- a/external/dyninst +++ b/external/dyninst @@ -1 +1 @@ -Subproject commit d3ab0a71e925bd01b20c6362f14006d34ece7112 +Subproject commit dedad14f5555ba179ab07a5c2d14091a99351045 diff --git a/external/timemory b/external/timemory index 2a1bcba0c..86d2d12a8 160000 --- a/external/timemory +++ b/external/timemory @@ -1 +1 @@ -Subproject commit 2a1bcba0cad46efd4421c0c7a145e83b161fb934 +Subproject commit 86d2d12a8b188053b7cacdb1ece1eba5aa9f32c9 diff --git a/source/bin/omnitrace-instrument/CMakeLists.txt b/source/bin/omnitrace-instrument/CMakeLists.txt index db5b094d6..ffed45638 100644 --- a/source/bin/omnitrace-instrument/CMakeLists.txt +++ b/source/bin/omnitrace-instrument/CMakeLists.txt @@ -45,6 +45,8 @@ if(OMNITRACE_BUILD_DYNINST) target_compile_definitions(omnitrace-instrument PRIVATE OMNITRACE_BUILD_DYNINST=1) endif() +add_target_flag_if_avail(omnitrace-instrument "-Wno-deprecated-declarations") + omnitrace_strip_target(omnitrace-instrument) if(CMAKE_BUILD_TYPE MATCHES "^(DEBUG|Debug)") diff --git a/source/bin/omnitrace-instrument/omnitrace-instrument.cpp b/source/bin/omnitrace-instrument/omnitrace-instrument.cpp index b55091adb..91844e90a 100644 --- a/source/bin/omnitrace-instrument/omnitrace-instrument.cpp +++ b/source/bin/omnitrace-instrument/omnitrace-instrument.cpp @@ -22,6 +22,7 @@ #include "omnitrace-instrument.hpp" #include "common/defines.h" +#include "common/join.hpp" #include "dl/dl.hpp" #include "fwd.hpp" #include "internal_libs.hpp" @@ -187,18 +188,26 @@ strset_t print_formats = { "txt", "json std::string modfunc_dump_dir = {}; auto regex_opts = std::regex_constants::egrep | std::regex_constants::optimize; -strvec_t lib_search_paths = - tim::delimit(JOIN(':', tim::get_env("DYNINSTAPI_RT_LIB"), - tim::get_env("DYNINST_REWRITER_PATHS"), - tim::get_env("LD_LIBRARY_PATH")), - ":"); +std::string +get_internal_libpath() +{ + auto _exe = std::string_view{ ::realpath("/proc/self/exe", nullptr) }; + auto _pos = _exe.find_last_of('/'); + auto _dir = std::string{ "./" }; + if(_pos != std::string_view::npos) _dir = _exe.substr(0, _pos); + return omnitrace::common::join("/", _dir, "..", "lib"); +} + +strvec_t lib_search_paths = tim::delimit( + JOIN(':', get_internal_libpath(), tim::get_env("DYNINSTAPI_RT_LIB"), + tim::get_env("DYNINST_REWRITER_PATHS"), + tim::get_env("LD_LIBRARY_PATH")), + ":"); strvec_t bin_search_paths = tim::delimit(tim::get_env("PATH"), ":"); -#if defined(DYNINST_API_RT) -auto _dyn_api_rt_paths = tim::delimit(DYNINST_API_RT, ":"); -#else -auto _dyn_api_rt_paths = std::vector{}; -#endif +auto _dyn_api_rt_paths = tim::delimit( + JOIN(":", get_internal_libpath(), JOIN("/", get_internal_libpath(), "omnitrace")), + ":"); std::string get_absolute_filepath(std::string _name, const strvec_t& _paths); diff --git a/source/bin/omnitrace-run/impl.cpp b/source/bin/omnitrace-run/impl.cpp index 58e0e8f94..ae3f486c2 100644 --- a/source/bin/omnitrace-run/impl.cpp +++ b/source/bin/omnitrace-run/impl.cpp @@ -191,6 +191,7 @@ prepare_environment_for_run(parser_data_t& _data) if(_data.launcher.empty()) { omnitrace::argparse::add_ld_preload(_data); + omnitrace::argparse::add_ld_library_path(_data); } } diff --git a/source/bin/omnitrace-sample/impl.cpp b/source/bin/omnitrace-sample/impl.cpp index 47d38443c..4833f9b56 100644 --- a/source/bin/omnitrace-sample/impl.cpp +++ b/source/bin/omnitrace-sample/impl.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -129,13 +130,11 @@ get_initial_environment() } } - update_env(_env, "LD_PRELOAD", - get_realpath(get_internal_libpath("libomnitrace-dl.so")), true); + auto _dl_libpath = get_realpath(get_internal_libpath("libomnitrace-dl.so")); + auto _omni_libpath = get_realpath(get_internal_libpath("libomnitrace.so")); - auto* _dl_libpath = - realpath(get_internal_libpath("libomnitrace-dl.so").c_str(), nullptr); - auto* _omni_libpath = - realpath(get_internal_libpath("libomnitrace.so").c_str(), nullptr); + update_env(_env, "LD_PRELOAD", _dl_libpath, UPD_APPEND); + update_env(_env, "LD_LIBRARY_PATH", tim::filepath::dirname(_dl_libpath), UPD_APPEND); auto _mode = get_env("OMNITRACE_MODE", "sampling", false); @@ -154,12 +153,9 @@ get_initial_environment() #if defined(OMNITRACE_USE_OMPT) if(!getenv("OMP_TOOL_LIBRARIES")) - update_env(_env, "OMP_TOOL_LIBRARIES", _dl_libpath, true); + update_env(_env, "OMP_TOOL_LIBRARIES", _dl_libpath, UPD_APPEND); #endif - free(_dl_libpath); - free(_omni_libpath); - return _env; } @@ -223,29 +219,42 @@ print_updated_environment(std::vector _env) template void update_env(std::vector& _environ, std::string_view _env_var, Tp&& _env_val, - bool _append) + update_mode&& _mode, std::string_view _join_delim) { updated_envs.emplace(_env_var); + auto _prepend = (_mode & UPD_PREPEND) == UPD_PREPEND; + auto _append = (_mode & UPD_APPEND) == UPD_APPEND; + auto _weak_upd = (_mode & UPD_WEAK) == UPD_WEAK; + auto _key = join("", _env_var, "="); for(auto& itr : _environ) { if(!itr) continue; if(std::string_view{ itr }.find(_key) == 0) { - if(_append) + if(_weak_upd) + { + // if the value has changed, do not update but allow overridding the value + // inherited from the initial env + if(original_envs.find(std::string{ itr }) == original_envs.end()) return; + } + + if(_prepend || _append) { if(std::string_view{ itr }.find(join("", _env_val)) == std::string_view::npos) { auto _val = std::string{ itr }.substr(_key.length()); free(itr); - if(_env_var == "LD_PRELOAD") - itr = strdup( - join('=', _env_var, join(":", _val, _env_val)).c_str()); + if(_prepend) + itr = + strdup(join('=', _env_var, join(_join_delim, _val, _env_val)) + .c_str()); else - itr = strdup( - join('=', _env_var, join(":", _env_val, _val)).c_str()); + itr = + strdup(join('=', _env_var, join(_join_delim, _env_val, _val)) + .c_str()); } } else @@ -562,7 +571,7 @@ parse_args(int argc, char** argv, std::vector& _env) parser.add_argument({ "--profile-format" }, "Data formats for profiling results") .min_count(1) .max_count(3) - .requires({ "profile|flat-profile" }) + .required({ "profile|flat-profile" }) .choices({ "text", "json", "console" }) .action([&](parser_t& p) { auto _v = p.get>("profile"); @@ -624,7 +633,7 @@ parse_args(int argc, char** argv, std::vector& _env) .add_argument({ "--cpus" }, "CPU IDs for frequency sampling. Supports integers and/or ranges") .dtype("int or range") - .requires({ "host" }) + .required({ "host" }) .action([&](parser_t& p) { update_env( _env, "OMNITRACE_SAMPLING_CPUS", @@ -634,7 +643,7 @@ parse_args(int argc, char** argv, std::vector& _env) .add_argument({ "--gpus" }, "GPU IDs for SMI queries. Supports integers and/or ranges") .dtype("int or range") - .requires({ "device" }) + .required({ "device" }) .action([&](parser_t& p) { update_env( _env, "OMNITRACE_SAMPLING_GPUS", @@ -709,7 +718,7 @@ parse_args(int argc, char** argv, std::vector& _env) parser.add_argument({ "--realtime" }, _realtime_desc) .min_count(0) - .requires(std::move(_realtime_reqs)) + .required(std::move(_realtime_reqs)) .action([&](parser_t& p) { auto _v = p.get>("realtime"); update_env(_env, "OMNITRACE_SAMPLING_REALTIME", true); @@ -783,10 +792,10 @@ parse_args(int argc, char** argv, std::vector& _env) _update("OMNITRACE_TRACE_THREAD_SPIN_LOCKS", _v.count("spin-locks") > 0); if(_v.count("all") > 0 || _v.count("ompt") > 0) - update_env(_env, "OMP_TOOL_LIBRARIES", _dl_libpath, true); + update_env(_env, "OMP_TOOL_LIBRARIES", _dl_libpath, UPD_APPEND); if(_v.count("all") > 0 || _v.count("kokkosp") > 0) - update_env(_env, "KOKKOS_PROFILE_LIBRARY", _omni_libpath, true); + update_env(_env, "KOKKOS_PROFILE_LIBRARY", _omni_libpath, UPD_APPEND); }); parser.add_argument({ "-E", "--exclude" }, "Exclude data from these backends") diff --git a/source/bin/omnitrace-sample/omnitrace-sample.hpp b/source/bin/omnitrace-sample/omnitrace-sample.hpp index e09588b1a..5c446a40a 100644 --- a/source/bin/omnitrace-sample/omnitrace-sample.hpp +++ b/source/bin/omnitrace-sample/omnitrace-sample.hpp @@ -26,13 +26,22 @@ #include #include +enum update_mode : int +{ + UPD_REPLACE = 0x1, + UPD_PREPEND = 0x2, + UPD_APPEND = 0x3, + UPD_WEAK = 0x4, +}; + std::string -get_realpath(const std::string&); +get_realpath(const std::string& _fpath); void print_command(const std::vector& _argv); -void print_updated_environment(std::vector); +void +print_updated_environment(std::vector _env); std::vector get_initial_environment(); @@ -42,10 +51,11 @@ get_internal_libpath(const std::string& _lib); template void -update_env(std::vector&, std::string_view, Tp&&, bool _append = false); +update_env(std::vector& _environ, std::string_view _env_var, Tp&& _env_val, + update_mode&& _mode = UPD_REPLACE, std::string_view _join_delim = ":"); void -remove_env(std::vector&, std::string_view); +remove_env(std::vector& _environ, std::string_view _env_var); std::vector -parse_args(int argc, char** argv, std::vector&); +parse_args(int argc, char** argv, std::vector& envp); diff --git a/source/bin/tests/CMakeLists.txt b/source/bin/tests/CMakeLists.txt index 24345625c..bb1123ac8 100644 --- a/source/bin/tests/CMakeLists.txt +++ b/source/bin/tests/CMakeLists.txt @@ -16,16 +16,6 @@ function(OMNITRACE_ADD_BIN_TEST) if(NOT TEST_WORKING_DIRECTORY) set(TEST_WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) endif() - if(NOT OMNITRACE_DYNINST_API_RT_DIR AND OMNITRACE_DYNINST_API_RT) - get_filename_component(OMNITRACE_DYNINST_API_RT_DIR "${OMNITRACE_DYNINST_API_RT}" - DIRECTORY) - endif() - - if(OMNITRACE_BUILD_DYNINST) - set(OMNITRACE_DYNINST_API_RT_DIR - "${PROJECT_BINARY_DIR}/external/dyninst/dyninstAPI_RT:${PROJECT_BINARY_DIR}/external/dyninst/dyninstAPI" - ) - endif() if(NOT TEST_ENVIRONMENT) set(TEST_ENVIRONMENT @@ -33,7 +23,7 @@ function(OMNITRACE_ADD_BIN_TEST) "OMNITRACE_PROFILE=ON" "OMNITRACE_USE_SAMPLING=ON" "OMNITRACE_TIME_OUTPUT=OFF" - "LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}" + "LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}:$ENV{LD_LIBRARY_PATH}" ) endif() diff --git a/source/lib/CMakeLists.txt b/source/lib/CMakeLists.txt index 5bc9fb781..e1a5d06fb 100644 --- a/source/lib/CMakeLists.txt +++ b/source/lib/CMakeLists.txt @@ -77,4 +77,5 @@ add_subdirectory(binary) add_subdirectory(omnitrace) add_subdirectory(omnitrace-dl) +add_subdirectory(omnitrace-rt) add_subdirectory(omnitrace-user) diff --git a/source/lib/core/argparse.cpp b/source/lib/core/argparse.cpp index b69a4c5de..c91ad674b 100644 --- a/source/lib/core/argparse.cpp +++ b/source/lib/core/argparse.cpp @@ -248,6 +248,15 @@ add_ld_preload(parser_data& _data) return _data; } +parser_data& +add_ld_library_path(parser_data& _data) +{ + auto _libdir = filepath::dirname(_data.dl_libpath); + if(filepath::exists(_libdir)) + update_env(_data, "LD_LIBRARY_PATH", _libdir, UPD_APPEND); + return _data; +} + parser_data& add_core_arguments(parser_t& _parser, parser_data& _data) { @@ -870,7 +879,7 @@ add_core_arguments(parser_t& _parser, parser_data& _data) .min_count(1) .max_count(3) .dtype("string") - .requires({ "profile|flat-profile" }) + .required({ "profile|flat-profile" }) .choices({ "text", "json", "console" }) .action([&](parser_t& p) { auto _v = p.get("profile-format"); @@ -976,7 +985,7 @@ add_core_arguments(parser_t& _parser, parser_data& _data) { "--cpus" }, "CPU IDs for frequency sampling. Supports integers and/or ranges") .dtype("int and/or range") - .requires({ "host" }) + .required({ "host" }) .action([&](parser_t& p) { update_env(_data, "OMNITRACE_SAMPLING_CPUS", join(array_config_t{ "," }, p.get("cpus"))); @@ -992,7 +1001,7 @@ add_core_arguments(parser_t& _parser, parser_data& _data) .add_argument({ "--gpus" }, "GPU IDs for SMI queries. Supports integers and/or ranges") .dtype("int and/or range") - .requires({ "device" }) + .required({ "device" }) .action([&](parser_t& p) { update_env(_data, "OMNITRACE_SAMPLING_GPUS", join(array_config_t{ "," }, p.get("gpus"))); @@ -1117,7 +1126,7 @@ add_core_arguments(parser_t& _parser, parser_data& _data) _parser.add_argument({ "--sample-realtime" }, _realtime_desc) .min_count(0) .dtype("[freq] [delay] [tids...]") - .requires(std::move(_realtime_reqs)) + .required(std::move(_realtime_reqs)) .action([&](parser_t& p) { auto _v = p.get>("sample-realtime"); update_env(_data, "OMNITRACE_SAMPLING_REALTIME", true); diff --git a/source/lib/core/argparse.hpp b/source/lib/core/argparse.hpp index 7a7d55ce3..0e30463d3 100644 --- a/source/lib/core/argparse.hpp +++ b/source/lib/core/argparse.hpp @@ -81,6 +81,9 @@ init_parser(parser_data&); parser_data& add_ld_preload(parser_data&); +parser_data& +add_ld_library_path(parser_data&); + parser_data& add_core_arguments(parser_t&, parser_data&); diff --git a/source/lib/omnitrace-rt/CMakeLists.txt b/source/lib/omnitrace-rt/CMakeLists.txt new file mode 100644 index 000000000..c189d4d29 --- /dev/null +++ b/source/lib/omnitrace-rt/CMakeLists.txt @@ -0,0 +1,138 @@ +# +# C extensions are required +# +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_EXTENSIONS ON) +set(CMAKE_C_STANDARD_REQUIRED ON) + +# ------------------------------------------------------------------------------# +# target sources +# ------------------------------------------------------------------------------# + +include(cmake/platform.cmake) + +set(SRC_LIST src/RTcommon.c src/RTmemEmulator.c) + +if(PLATFORM MATCHES freebsd) + list( + APPEND + SRC_LIST + src/RTposix.c + src/RTfreebsd.c + src/RTheap.c + src/RTheap-freebsd.c + src/RTthread.c + src/RTspace.S + src/RTsignal.c) +elseif(PLATFORM MATCHES linux) + list( + APPEND + SRC_LIST + src/RTposix.c + src/RTlinux.c + src/RTheap.c + src/RTheap-linux.c + src/RTthread.c + src/RTspace.S + src/RTsignal.c) + list(APPEND RT_STATIC_ONLY_SRC_LIST src/RTstatic_ctors_dtors_begin.c + src/RTstatic_ctors_dtors_end.c) +elseif(PLATFORM MATCHES nt OR PLATFORM MATCHES windows) + list(APPEND SRC_LIST src/RTheap.c src/RTheap-win.c src/RTwinnt.c src/RTthread.c + src/RTthread-x86.c) +endif() + +set(SRC_LIST_i386 src/RTthread-x86.c src/RTtlsgetaddr-x86.S) +set(RT_STATIC_ONLY_SRC_LIST_i386 src/RTstatic_ctors_dtors-x86.c) +set(SRC_LIST_x86_64 src/RTthread-x86-64.c src/RTtlsgetaddr-x86.S) +set(RT_STATIC_ONLY_SRC_LIST_x86_64 src/RTstatic_ctors_dtors-x86.c) +set(SRC_LIST_ppc32 src/RTthread-powerpc.c src/RTthread-powerpc-asm.S) +set(RT_STATIC_ONLY_SRC_LIST_ppc32 src/RTstatic_ctors_dtors-ppc32.c) +set(SRC_LIST_ppc64 src/RTthread-powerpc.c src/RTthread-powerpc-asm.S) +set(RT_STATIC_ONLY_SRC_LIST_ppc64 src/RTstatic_ctors_dtors-ppc64.c) +set(SRC_LIST_aarch64 src/RTthread-aarch64.c + # src/RTthread-aarch64-asm.S + ) +set(RT_STATIC_ONLY_SRC_LIST_aarch64 src/RTstatic_ctors_dtors-aarch64.c) + +# We use gcc to compile the various assembly files, but cmake doesn't default to knowing +# that gcc can handle .S. +enable_language(ASM) +file(GLOB SRC_ASSEMBLY "src/*.S") +if(NEED_NATIVE_ASSEMBER) + set_source_files_properties(${SRC_ASSEMBLY} PROPERTIES LANGUAGE ASM) +else() + set_source_files_properties(${SRC_ASSEMBLY} PROPERTIES LANGUAGE C) +endif() + +# The arch-specific files other than RTthread-x86 are Unix-only. +if(UNIX) + if(PLATFORM MATCHES amd64 OR PLATFORM MATCHES x86_64) + set(SRC_LIST_mabi ${SRC_LIST} ${SRC_LIST_i386}) + set(RT_STATIC_ONLY_SRC_LIST_mabi ${RT_STATIC_ONLY_SRC_LIST} + ${RT_STATIC_ONLY_SRC_LIST_i386}) + list(APPEND SRC_LIST ${SRC_LIST_x86_64}) + list(APPEND RT_STATIC_ONLY_SRC_LIST ${RT_STATIC_ONLY_SRC_LIST_x86_64}) + elseif(PLATFORM MATCHES ppc64) + set(SRC_LIST_mabi ${SRC_LIST} ${SRC_LIST_ppc32}) + set(RT_STATIC_ONLY_SRC_LIST_mabi ${RT_STATIC_ONLY_SRC_LIST} + ${RT_STATIC_ONLY_SRC_LIST_ppc32}) + list(APPEND SRC_LIST ${SRC_LIST_ppc64}) + list(APPEND RT_STATIC_ONLY_SRC_LIST ${RT_STATIC_ONLY_SRC_LIST_ppc64}) + elseif(PLATFORM MATCHES i386) + list(APPEND SRC_LIST ${SRC_LIST_i386}) + list(APPEND RT_STATIC_ONLY_SRC_LIST ${RT_STATIC_ONLY_SRC_LIST_i386}) + elseif(PLATFORM MATCHES ppc32) + list(APPEND SRC_LIST ${SRC_LIST_ppc32}) + list(APPEND RT_STATIC_ONLY_SRC_LIST ${RT_STATIC_ONLY_SRC_LIST_ppc32}) + elseif(PLATFORM MATCHES aarch64) + list(APPEND SRC_LIST ${SRC_LIST_aarch64}) + list(APPEND RT_STATIC_ONLY_SRC_LIST ${RT_STATIC_ONLY_SRC_LIST_aarch64}) + endif() +endif() + +add_library(omnitrace-rt-library SHARED) +add_library(omnitrace::omnitrace-rt-library ALIAS omnitrace-rt-library) + +target_sources(omnitrace-rt-library PRIVATE ${SRC_LIST}) +target_include_directories( + omnitrace-rt-library PRIVATE $ + $) +target_compile_definitions(omnitrace-rt-library PRIVATE ${UNIFIED_DEFINES}) +target_link_libraries( + omnitrace-rt-library + PUBLIC $ + PRIVATE omnitrace::omnitrace-threading) + +add_target_cxx_flag_if_avail(omnitrace-rt-library "-g3") + +set_target_properties( + omnitrace-rt-library + PROPERTIES OUTPUT_NAME omnitrace-rt + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + BUILD_RPATH "\$ORIGIN" + INSTALL_RPATH "\$ORIGIN") + +omnitrace_strip_target(omnitrace-rt-library) + +install(TARGETS omnitrace-rt-library DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +if(NOT EXISTS ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}) + file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}) +endif() + +add_custom_target( + omnitrace-rt-library-dyninstAPI_RT-symlink ALL + ${CMAKE_COMMAND} -E create_symlink ../$ + ${CMAKE_SHARED_LIBRARY_PREFIX}dyninstAPI_RT${CMAKE_SHARED_LIBRARY_SUFFIX} + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} + DEPENDS omnitrace-rt-library + COMMENT + "Creating ${CMAKE_SHARED_LIBRARY_PREFIX}dyninstAPI_RT${CMAKE_SHARED_LIBRARY_SUFFIX} to omnitrace-rt..." + ) + +install( + FILES + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/${CMAKE_SHARED_LIBRARY_PREFIX}dyninstAPI_RT${CMAKE_SHARED_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}) diff --git a/source/lib/omnitrace-rt/cmake/dynsysname b/source/lib/omnitrace-rt/cmake/dynsysname new file mode 100755 index 000000000..dc4678c47 --- /dev/null +++ b/source/lib/omnitrace-rt/cmake/dynsysname @@ -0,0 +1,74 @@ +#!/bin/bash + +P=$1 + +# i386/Linux, x86-64/Linux, ppc/Linux, ppc64/Linux +if [ ${P/linux/} != ${P} ]; then + if [ ${P/i686/} != ${P} ]; then + PLATFORM=i386-unknown-linux2.4 + fi + if [ ${P/i586/} != ${P} ]; then + PLATFORM=i386-unknown-linux2.4 + fi + if [ ${P/i486/} != ${P} ]; then + PLATFORM=i386-unknown-linux2.4 + fi + if [ ${P/i386/} != ${P} ]; then + PLATFORM=i386-unknown-linux2.4 + fi + if [ ${P/x86_64/} != ${P} ]; then + PLATFORM=x86_64-unknown-linux2.4 + fi + if [ ${P/ppc64/} != ${P} ]; then + PLATFORM=ppc64_linux + fi + if [ ${P/powerpc64/} != ${P} ]; then + PLATFORM=ppc64_linux + fi + if [ ${P/powerpc-/} != ${P} ]; then + PLATFORM=ppc32_linux + fi + if [ ${P/ppc-/} != ${P} ]; then + PLATFORM=ppc32_linux + fi + if [ ${P/aarch64-/} != ${P} ]; then + PLATFORM=aarch64-unknown-linux + fi +# Freebsd +elif [ ${P/freebsd/} != ${P} ]; then + if [ ${P/i686/} != ${P} ]; then + PLATFORM=i386-unknown-freebsd7.2 + fi + if [ ${P/i586/} != ${P} ]; then + PLATFORM=i386-unknown-freebsd7.2 + fi + if [ ${P/i486/} != ${P} ]; then + PLATFORM=i386-unknown-freebsd7.2 + fi + if [ ${P/i386/} != ${P} ]; then + PLATFORM=i386-unknown-freebsd7.2 + fi + if [ ${P/x86_64/} != ${P} ]; then + PLATFORM=amd64-unknown-freebsd7.2 + fi + +# VxWorks +elif [ ${P/vxworks/} != ${P} ]; then + if [ ${P/i686/} != ${P} ]; then + PLATFORM=i386-unknown-vxworks6.x + fi + if [ ${P/i586/} != ${P} ]; then + PLATFORM=i386-unknown-vxworks6.x + fi + if [ ${P/i486/} != ${P} ]; then + PLATFORM=i386-unknown-vxworks6.x + fi + if [ ${P/i386/} != ${P} ]; then + PLATFORM=i386-unknown-vxworks6.x + fi + if [ ${P/powerpc-/} != ${P} ]; then + PLATFORM=ppc32-unknown-vxworks6.x + fi +fi + +echo $PLATFORM diff --git a/source/lib/omnitrace-rt/cmake/platform.cmake b/source/lib/omnitrace-rt/cmake/platform.cmake new file mode 100644 index 000000000..ae7370092 --- /dev/null +++ b/source/lib/omnitrace-rt/cmake/platform.cmake @@ -0,0 +1,132 @@ +# +# +# +set(PLATFORM $ENV{PLATFORM}) + +set(VALID_PLATFORMS + amd64-unknown-freebsd7.2 i386-unknown-freebsd7.2 i386-unknown-linux2.4 ppc32_linux + ppc64_linux x86_64-unknown-linux2.4 aarch64-unknown-linux) + +if(NOT PLATFORM) + set(INVALID_PLATFORM true) +else() + list(FIND VALID_PLATFORMS ${PLATFORM} PLATFORM_FOUND) + if(PLATFORM_FOUND EQUAL -1) + set(INVALID_PLATFORM true) + endif() +endif() + +execute_process( + COMMAND ${CMAKE_CURRENT_LIST_DIR}/sysname + OUTPUT_VARIABLE SYSNAME_OUT + OUTPUT_STRIP_TRAILING_WHITESPACE) +string(REPLACE "\n" "" SYSPLATFORM ${SYSNAME_OUT}) + +if(INVALID_PLATFORM) + # Try to set it automatically + execute_process( + COMMAND ${CMAKE_CURRENT_LIST_DIR}/dynsysname ${SYSNAME_OUT} + OUTPUT_VARIABLE DYNSYSNAME_OUT + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE "\n" "" PLATFORM ${DYNSYSNAME_OUT}) + omnitrace_message(STATUS + "-- Attempting to automatically identify platform: ${PLATFORM}") +endif() + +list(FIND VALID_PLATFORMS ${PLATFORM} PLATFORM_FOUND) + +if(PLATFORM_FOUND EQUAL -1) + omnitrace_message( + FATAL_ERROR + "Error: unknown platform ${PLATFORM}; please set the PLATFORM environment variable to one of the following options: ${VALID_PLATFORMS}" + ) +endif() + +if(PLATFORM MATCHES i386) + set(ARCH_DEFINES arch_x86) + list(APPEND CAP_DEFINES cap_fixpoint_gen cap_noaddr_gen cap_stripped_binaries + cap_tramp_liveness cap_virtual_registers cap_stack_mods) +elseif(PLATFORM MATCHES x86_64 OR PLATFORM MATCHES amd64) + set(ARCH_DEFINES arch_x86_64 arch_64bit) + list( + APPEND + CAP_DEFINES + cap_32_64 + cap_fixpoint_gen + cap_noaddr_gen + cap_registers + cap_stripped_binaries + cap_tramp_liveness + cap_stack_mods) +elseif(PLATFORM MATCHES ppc32) + set(ARCH_DEFINES arch_power) + list(APPEND CAP_DEFINES cap_registers) +elseif(PLATFORM MATCHES ppc64) + set(ARCH_DEFINES arch_power arch_64bit) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64") + list(APPEND CAP_DEFINES cap_32_64 cap_registers cap_toc_64) + + if(SYSPLATFORM MATCHES ppc64le) + list(APPEND CAP_DEFINES arch_ppc_little_endian) + endif() +elseif(PLATFORM MATCHES aarch64) + # set(ARCH_DEFINES aarch_64 arch_64bit) + set(ARCH_DEFINES arch_aarch64 arch_64bit) + list(APPEND CAP_DEFINES cap_32_64 cap_registers) +endif() + +if(PLATFORM MATCHES linux) + set(OS_DEFINES os_linux) + list(APPEND CAP_DEFINES cap_async_events cap_binary_rewriter cap_dwarf + cap_mutatee_traps cap_ptrace) + set(BUG_DEFINES bug_syscall_changepc_rewind bug_force_terminate_failure) +elseif(PLATFORM MATCHES cnl) + set(OS_DEFINES os_linux os_cnl) + list(APPEND CAP_DEFINES cap_async_events cap_binary_rewriter cap_dwarf + cap_mutatee_traps cap_ptrace) + set(BUG_DEFINES bug_syscall_changepc_rewind) +elseif(PLATFORM MATCHES freebsd) + set(OS_DEFINES os_freebsd) + list(APPEND CAP_DEFINES cap_binary_rewriter cap_dwarf cap_mutatee_traps) + set(BUG_DEFINES + bug_freebsd_missing_sigstop bug_freebsd_mt_suspend bug_freebsd_change_pc + bug_phdrs_first_page bug_syscall_changepc_rewind) +elseif(PLATFORM STREQUAL i386-unknown-nt4.0) + set(OS_DEFINES os_windows) + list(APPEND CAP_DEFINES cap_mem_emulation cap_mutatee_traps) +endif() + +if(PLATFORM STREQUAL i386-unknown-linux2.4) + set(OLD_DEFINES i386_unknown_linux2_0) +elseif(PLATFORM STREQUAL x86_64-unknown-linux2.4) + set(OLD_DEFINES x86_64_unknown_linux2_4) +elseif(PLATFORM STREQUAL ppc32_linux) + set(OLD_DEFINES ppc32_linux) + set(BUG_DEFINES ${BUG_DEFINES} bug_registers_after_exit) +elseif(PLATFORM STREQUAL ppc64_linux) + set(OLD_DEFINES ppc64_linux) + set(BUG_DEFINES ${BUG_DEFINES} bug_registers_after_exit) +elseif(PLATFORM STREQUAL x86_64_cnl) + set(OLD_DEFINES x86_64_cnl x86_64_unknown_linux2_4) +elseif(PLATFORM STREQUAL i386-unknown-freebsd7.2) + set(OLD_DEFINES i386_unknown_freebsd7_0) +elseif(PLATFORM STREQUAL amd64-unknown-freebsd7.2) + set(OLD_DEFINES amd64_unknown_freebsd7_0) +elseif(PLATFORM STREQUAL i386-unknown-nt4.0) + set(OLD_DEFINES i386_unknown_nt4_0) +elseif(PLATFORM STREQUAL aarch64-unknown-linux) + set(OLD_DEFINES aarch64_unknown_linux) +else(PLATFORM STREQUAL i386-unknown-linux2.4) + dyninst_message(FATAL_ERROR "Unknown platform: ${PLATFORM}") +endif() + +if(Thread_DB_FOUND) + dyninst_message(STATUS "-- Enabling ThreadDB support") + list(APPEND CAP_DEFINES cap_thread_db) +endif() + +set(UNIFIED_DEFINES ${CAP_DEFINES} ${BUG_DEFINES} ${ARCH_DEFINES} ${OS_DEFINES} + ${OLD_DEFINES}) + +list(REMOVE_DUPLICATES UNIFIED_DEFINES) diff --git a/source/lib/omnitrace-rt/cmake/sysname b/source/lib/omnitrace-rt/cmake/sysname new file mode 100755 index 000000000..e615eaaa7 --- /dev/null +++ b/source/lib/omnitrace-rt/cmake/sysname @@ -0,0 +1,681 @@ +#!/bin/bash +# $Id: sysname,v 1.6 2005/08/09 16:13:16 gquinn Exp $ +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Written by Per Bothner . +# The master version of this file is at the FSF in /home/gd/gnu/lib. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +if (test -f /.attbin/uname) >/dev/null 2>&1; then + PATH=$PATH:/.attbin + export PATH +fi + +UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown +UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown +UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown +UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown + +trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15 + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +alpha:OSF1:V*:*) + # After 1.2, OSF1 uses "V1.3" for uname -r. + echo alpha-dec-osf$(echo ${UNAME_RELEASE} | sed -e 's/^V//') + exit 0 + ;; +alpha:OSF1:*:*) + # 1.2 uses "1.2" for uname -r. + echo alpha-dec-osf${UNAME_RELEASE} + exit 0 + ;; +21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 + ;; +amiga:NetBSD:*:*) + echo m68k-cbm-netbsd${UNAME_RELEASE} + exit 0 + ;; +arm:RISC*:1.[012]*:* | arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0 + ;; +Pyramid*:OSx*:*:*) + if test "$( (/bin/universe) 2>/dev/null)" = att; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 + ;; +sun4*:SunOS:5.*:*) + echo sparc-sun-solaris2$(echo ${UNAME_RELEASE} | sed -e 's/[^.]*//') + exit 0 + ;; +i86pc:SunOS:5.*:*) + echo i386-unknown-solaris2$(echo ${UNAME_RELEASE} | sed -e 's/[^.]*//') + exit 0 + ;; +sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3$(echo ${UNAME_RELEASE} | sed -e 's/[^.]*//') + exit 0 + ;; +sun4*:SunOS:*:*) + case "$(/usr/bin/arch -k)" in + Series* | S4*) + UNAME_RELEASE=$(uname -v) + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos$(echo ${UNAME_RELEASE} | sed -e 's/-/_/') + exit 0 + ;; +sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 + ;; +atari*:NetBSD:*:*) + echo m68k-atari-netbsd${UNAME_RELEASE} + exit 0 + ;; +sun3*:NetBSD:*:*) + echo m68k-sun-netbsd${UNAME_RELEASE} + exit 0 + ;; +mac68k:NetBSD:*:*) + echo m68k-apple-netbsd${UNAME_RELEASE} + exit 0 + ;; +RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 + ;; +VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 + ;; +mips:*:4*:UMIPS) + echo mips-mips-riscos4sysv + exit 0 + ;; +mips:*:5*:RISCos) + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 + ;; +m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 + ;; +m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 + ;; +m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 + ;; +AViiON:dgux:*:*) + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ + -o ${TARGET_BINARY_INTERFACE}x = x ]; then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + exit 0 + ;; +M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 + ;; +M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 + ;; +XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 + ;; +Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 + ;; +*:IRIX*:*:*) + echo mips-sgi-irix$(echo ${UNAME_RELEASE} | sed -e 's/-/_/g') + exit 0 + ;; +????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 + ;; # Note that: echo "'`uname -s`'" gives 'AIX ' +i[34]86:AIX:*:*) + echo i386-ibm-aix + exit 0 + ;; +*:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' <dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 + ;; +*:AIX:*:4) + if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ]; then + IBM_REV=$(/usr/bin/oslevel) + else + IBM_REV=4.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 + ;; +*:AIX:*:5) + if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ]; then + IBM_REV=$(/usr/bin/oslevel) + else + IBM_REV=5.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 + ;; +*:AIX:*:*) + echo rs6000-ibm-aix + exit 0 + ;; +ibmrt:4.4BSD:* | romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 + ;; +ibmrt:*BSD:* | romp-ibm:BSD:*) # covers RT/PC NetBSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 + ;; # report: romp-ibm BSD 4.3 +*:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 + ;; +DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 + ;; +9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 + ;; +hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 + ;; +9000/[3478]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/7?? | 9000/8?[79]) HP_ARCH=hppa1.1 ;; + 9000/8??) HP_ARCH=hppa1.0 ;; + esac + HPUX_REV=$(echo ${UNAME_RELEASE} | sed -e 's/[^.]*.[0B]*//') + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 + ;; +3050*:HI-UX:*:*) + sed 's/^ //' <dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo unknown-hitachi-hiuxwe2 + exit 0 + ;; +9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + echo hppa1.1-hp-bsd + exit 0 + ;; +9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 + ;; +hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + echo hppa1.1-hp-osf + exit 0 + ;; +hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 + ;; +parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 + ;; +C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 + ;; +C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc; then + echo c32-convex-bsd + else + echo c2-convex-bsd + fi + exit 0 + ;; +C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 + ;; +C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 + ;; +C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 + ;; +CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 + ;; +CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 + ;; +CRAY*C90:*:*:*) + echo c90-cray-unicos${UNAME_RELEASE} + exit 0 + ;; +CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 + ;; +hp3[0-9][05]:NetBSD:*:*) + echo m68k-hp-netbsd${UNAME_RELEASE} + exit 0 + ;; +i[34]86:BSD/386:*:* | *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 + ;; +i[3456]86:CYGWIN_NT*:*:*) + echo i386-unknown-nt4.0 + exit 0 + ;; +*:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd$(echo ${UNAME_RELEASE} | sed -e 's/[-(].*//') + exit 0 + ;; +*:NetBSD:*:*) + echo ${UNAME_MACHINE}-unknown-netbsd$(echo ${UNAME_RELEASE} | sed -e 's/[-_].*/\./') + exit 0 + ;; +*:GNU:*:*) + echo $(echo ${UNAME_MACHINE} | sed -e 's,/.*$,,')-unknown-gnu$(echo ${UNAME_RELEASE} | sed -e 's,/.*$,,') + exit 0 + ;; +*:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. + ld_help_string=$(ld --help 2>&1) + if echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: elf_i[345]86"; then + echo "${UNAME_MACHINE}-unknown-linux" + exit 0 + elif echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: i[345]86linux"; then + echo "${UNAME_MACHINE}-unknown-linuxaout" + exit 0 + elif echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: i[345]86coff"; then + echo "${UNAME_MACHINE}-unknown-linuxcoff" + exit 0 + elif echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: elf64_ia64"; then + echo "${UNAME_MACHINE}-unknown-linux" + exit 0 + elif echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: elf_x86_64"; then + echo "${UNAME_MACHINE}-unknown-linux" + exit 0 + elif test "${UNAME_MACHINE}" = "alpha"; then + echo alpha-unknown-linux + exit 0 + else + # Either a pre-BFD a.out linker (linuxoldld) or one that does not give us + # useful --help. Gcc wants to distinguish between linuxoldld and linuxaout. + test ! -d /usr/lib/ldscripts/. && + echo "${UNAME_MACHINE}-unknown-linuxoldld" && exit 0 + # Determine whether the default compiler is a.out or elf + cat >dummy.c </dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + fi + ;; + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions + # are messed up and put the nodename in both sysname and nodename. +i[34]86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 + ;; +i[34]86:*:4.*:* | i[34]86:SYSTEM_V:4.*:*) + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} + else + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE} + fi + exit 0 + ;; +i[34]86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=$(sed -n 's/.*Version //p' /dev/null >/dev/null; then + UNAME_REL=$( (/bin/uname -X | egrep Release | sed -e 's/.*= //')) + (/bin/uname -X | egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-unknown-sysv32 + fi + exit 0 + ;; +Intel:Mach:3*:*) + echo i386-unknown-mach3 + exit 0 + ;; +paragon:*:*:*) + echo i860-intel-osf1 + exit 0 + ;; +i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 + ;; +mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 + ;; +M680[234]0:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 + ;; +3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0) + uname -p 2>/dev/null | grep 86 >/dev/null && + echo i486-ncr-sysv4.3 && exit 0 + ;; +3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + uname -p 2>/dev/null | grep 86 >/dev/null && + echo i486-ncr-sysv4 && exit 0 + ;; +m680[234]0:LynxOS:2.[23]*:*) + echo m68k-lynx-lynxos${UNAME_RELEASE} + exit 0 + ;; +mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 + ;; +i[34]86:LynxOS:2.[23]*:*) + echo i386-lynx-lynxos${UNAME_RELEASE} + exit 0 + ;; +TSUNAMI:LynxOS:2.[23]*:*) + echo sparc-lynx-lynxos${UNAME_RELEASE} + exit 0 + ;; +rs6000:LynxOS:2.[23]*:*) + echo rs6000-lynx-lynxos${UNAME_RELEASE} + exit 0 + ;; +RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 + ;; +*:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null; then + UNAME_MACHINE=$( (uname -p) 2>/dev/null) + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 + ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +cat >dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=$( (hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null); + printf ("%s-next-nextstep%s\n", __ARCHITECTURE__, version==2 ? "2" : "3"); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-unknown-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +#if !defined (ultrix) + printf ("vax-dec-bsd\n"); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0 +rm -f dummy.c dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { + echo ${ISP}-apollo-${SYSTYPE} + exit 0 +} + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ]; then + case $(getsysinfo -f cpu_type) in + c1*) + echo c1-convex-bsd + exit 0 + ;; + c2*) + if getsysinfo -f scalar_acc; then + echo c32-convex-bsd + else + echo c2-convex-bsd + fi + exit 0 + ;; + c34*) + echo c34-convex-bsd + exit 0 + ;; + c38*) + echo c38-convex-bsd + exit 0 + ;; + c4*) + echo c4-convex-bsd + exit 0 + ;; + esac +fi + +#echo '(Unable to guess system type)' 1>&2 + +exit 1 diff --git a/source/lib/omnitrace-rt/h/Types.h b/source/lib/omnitrace-rt/h/Types.h new file mode 100644 index 000000000..0c676d9ab --- /dev/null +++ b/source/lib/omnitrace-rt/h/Types.h @@ -0,0 +1,197 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/************************************************************************ + * $Id: Types.h,v 1.38 2008/08/29 21:45:10 legendre Exp $ + * Types.h: commonly used types (used by runtime libs and other modules) + ************************************************************************/ + +#if !defined(_Types_h_) +# define _Types_h_ + +/* Sets up 64 and 32 bit + types: + int64_t uint64_t int32_t uint32_t + constant macros: + I64_C(x) UI64_C(x) + limits: + I64_MAX I64_MIN UI64_MAX + I32_MAX I32_MIN UI32_MAX + + note: needs to be included before anything that includes inttypes.h + (eg. stdio on some systems) +*/ + +/* Set up the 32 AND 64 BIT TYPES ===================================== */ +/* + --- inttypes.h --- + int32_t uint32_t int64_t uint64_t 32B lmts 64Blmts 64BlitMacros# +Linux yes yes yes yes yes yes yes +FreeBSD yes yes yes yes yes yes yes +WindowsNT nonexistant + + # we rename all of the 64 bit literal macros to our shortened name +*/ + +# if defined(os_windows) +typedef signed __int64 int64_t; +typedef signed __int32 int32_t; +typedef signed __int16 int16_t; +typedef signed __int8 int8_t; +typedef unsigned __int64 uint64_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int8 uint8_t; + +# elif defined(os_linux) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS +# endif +# include +# if defined(arch_x86_64) || defined(arch_64bit) +# define TYPE64BIT +# endif +typedef long double double128_t; + +# elif defined(os_freebsd) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS +# endif +# include +typedef long double double128_t; + +/* FreeBSD doesn't define this */ +typedef int64_t off64_t; + +# else +# error Unknown architecture +# endif + +/* Set up the 64 BIT LITERAL MACROS =================================== */ +# if defined(os_windows) +/* nt ----------------------------- */ +# define I64_C(x) (x##i64) +# define UI64_C(x) (x##ui64) +# else /* linux, freebsd ----------------- */ +# define I64_C(x) INT64_C(x) +# define UI64_C(x) UINT64_C(x) +# endif + +/* Set up the 32 and 64 BIT LIMITS for those not already set up ======= */ +# if defined(os_windows) +/* nt ----------------------------- */ +# include +# define I64_MAX _I64_MAX +# define UI64_MAX _UI64_MAX +# define I64_MIN _I64_MIN +# define I32_MAX _I32_MAX +# define I32_MIN _I32_MIN +# define UI32_MAX _UI32_MAX +# else /* linux, freebsd ----------------- */ +# define I64_MAX INT64_MAX +# define UI64_MAX UINT64_MAX +# define I64_MIN INT64_MIN +# define I32_MAX INT32_MAX +# define I32_MIN INT32_MIN +# define UI32_MAX UINT32_MAX +# endif + +/* +typedef int64_t time64; +*/ + +# if defined(__cplusplus) +# include "h/dyntypes.h" +using namespace Dyninst; +static const Address ADDR_NULL = (Address)(0); +# else +# define ADDR_NULL (0) +typedef unsigned long Address; +# endif +/* Note the inherent assumption that the size of a "long" integer matches + that of an address (void*) on every supported Paradyn/Dyninst system! + (This can be checked with Address_chk().) +*/ + +typedef unsigned int Word; + +typedef long long int RegValue; /* register content 64-bit */ +/* This needs to be an int since it is sometimes used to pass offsets + to the code generator (i.e. if-statement) - jkh 5/24/99 */ +typedef unsigned int Register; /* a register number, e.g., [0..31] */ +static const Register Null_Register = (Register)(-1); /* '255' */ +/* Easily noticeable name... */ +static const Register REG_NULL = (Register)(-1); + +// Virtual Memory Map -- shared between platforms +# define PREMS_PRIVATE (1 << 4) +# define PREMS_SHARED (1 << 3) +# define PREMS_READ (1 << 2) +# define PREMS_WRITE (1 << 1) +# define PREMS_EXEC (1 << 0) + +# define MAPENTRIES_PATH_SIZE 512 +# define MAPENTRIES_PATH_SIZE_STR "512" +typedef struct maps_entries +{ + Address start; + Address end; + unsigned prems; + Address offset; + int dev_major; + int dev_minor; + unsigned long inode; + char path[MAPENTRIES_PATH_SIZE]; +} map_entries; + +# ifdef __cplusplus + +# include "h/util.h" + +COMMON_EXPORT void +Address_chk(); +COMMON_EXPORT char* +Address_str(Address addr); + +// NB: this is probably inappropriate for 64-bit addresses! +inline unsigned +hash_address(const Address& addr) +{ + return (unsigned) ((addr >> 2) & 0xffffffff); +} +# endif /* __cplusplus */ + +#endif /* !defined(_Types_h_) */ diff --git a/source/lib/omnitrace-rt/h/compiler_annotations.h b/source/lib/omnitrace-rt/h/compiler_annotations.h new file mode 100644 index 000000000..b2a854c1f --- /dev/null +++ b/source/lib/omnitrace-rt/h/compiler_annotations.h @@ -0,0 +1,171 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef COMPILER_ANNOTATIONS_H +#define COMPILER_ANNOTATIONS_H + +/*********************************************************************** + * + * DYNINST_FALLTHROUGH + * + * Eliminates "this statement may fall through" warnings when used as the last + * statment of a switch case that falls through to the next case. The macro + * is used as shown in indicate that case 2 should fall through to case 1. + * + * switch (x) { + * case 2: + * foo(); + * DYNINST_FALLTHROUGH; + * case 1: + * foo(); + * break; + * default: + * error(); + * break; + * } + */ + +#if defined(__cpluscplus) && defined(__has_cpp_attribute) +# if __has_cpp_attribute(fallthrough) +# define DYNINST_FALLTHROUGH [[fallthrough]] +# elif __has_cpp_attribute(gcc::fallthrough) +# define DYNINST_FALLTHROUGH [[gcc::fallthrough]] +# elif __has_cpp_attribute(clang::fallthrough) +# define DYNINST_FALLTHROUGH [[clang::fallthrough]] +# endif +#elif !defined(__cpluscplus) && defined(__has_c_attribute) +# if __has_c_attribute(fallthrough) +# define DYNINST_FALLTHROUGH [[fallthrough]] +# elif __STDC_VERSION__ > 201710 +// scoped attribute names are only valid in C starting with 2x +# if __has_c_attribute(gcc::fallthrough) +# define DYNINST_FALLTHROUGH [[gcc::fallthrough]] +# elif __has_c_attribute(clang::fallthrough) +# define DYNINST_FALLTHROUGH [[clang::fallthrough]] +# endif +# endif +#elif defined(__has_attribute) +# if __has_attribute(fallthrough) +# define DYNINST_FALLTHROUGH __attribute__((fallthrough)) +# elif __cplusplus || __STDC_VERSION__ > 201710 +// scoped attribute names are only valid in C++ or C starting with 2x +# if __has_attribute(gcc::fallthrough) +# define DYNINST_FALLTHROUGH __attribute__((gcc::fallthrough)) +# elif __has_attribute(clang::fallthrough) +# define DYNINST_FALLTHROUGH __attribute__((clang::fallthrough)) +# endif +# endif +#endif + +#if !defined(DYNINST_FALLTHROUGH) +# define DYNINST_FALLTHROUGH \ + do \ + { \ + } while(0) +#endif + +/*********************************************************************** + * + * DYNINST_PRINTF_ANNOTATION(fmtIndex, argIndex) + * DYNINST_SCANF_ANNOTATION(fmtIndex, argIndex) + * DYNINST_FORMAT_ANNOTATION(fmtType, fmtIndex, argIndex) + * + * Annotates a function as taking a printf for scanf format string and vararg + * list of values allowing the compiler to validate the format string and the + * supplied arguments. fmtIndex is the 1-based index of the format string, and + * argIndex is the 1-based index that begins the variable argument list used by + * printf or scanf. + * + * The annotation should be placed after the declaration of the function. For + * example: + * + * myprintf(int level, char *fmt, ...) DYNINST_PRINTF_ANNOTATION(2, 3); + */ + +#if defined(__has_attribute) +# if __has_attribute(format) +# define DYNINST_FORMAT_ANNOTATION(fmtType, fmtIndex, argIndex) \ + __attribute__((format(fmtType, fmtIndex, argIndex))) +# endif +#endif + +#if !defined(DYNINST_FORMAT_ANNOTATION) +# define DYNINST_FORMAT_ANNOTATION(fmtType, fmtIndex, argIndex) +#endif + +#define DYNINST_PRINTF_ANNOTATION(fmtIndex, argIndex) \ + DYNINST_FORMAT_ANNOTATION(printf, fmtIndex, argIndex) +#define DYNINST_SCANF_ANNOTATION(fmtIndex, argIndex) \ + DYNINST_FORMAT_ANNOTATION(scanf, fmtIndex, argIndex) + +/*********************************************************************** + * + * DYNINST_MALLOC_ANNOTATION + * DYNINST_MALLOC_DEALLOC_ANNOTATION(freeFunction) + * DYNINST_MALLOC_DEALLOC_POS_ANNOTATION(freeFunction, pos) + * + * Annotates a function as returning a unique pointer to suitable memory + * to hold an object. The second form names the matching deallocator, and + * the third form indicates the position of the pointer in the argument list. + * + * The annotation should be placed after the declaration of the function. For + * example: + * + * Obj* myalloc(int x) DYNINST_MALLOC_ANNOTATION; + * void mydealloc2(Obj* o); + * Obj* myalloc2(int x) DYNINST_MALLOC_DEALLOC_ANNOTATION(mydealloc2); + * void mydealloc3(int y, Obj* o); + * Obj* myalloc3(int x) DYNINST_MALLOC_DEALLOC_POS_ANNOTATION(mydealloc3, 2); + */ + +#if defined(__has_attribute) +# if __has_attribute(malloc) +# define DYNINST_MALLOC_ANNOTATION __attribute__((malloc)) +# if __GNUC__ >= 11 +// malloc attribute with 1 and 2 params is gcc 11 and later only +# define DYNINST_MALLOC_DEALLOC_ANNOTATION(f) \ + __attribute__((malloc, malloc(f))) +# define DYNINST_MALLOC_DEALLOC_POS_ANNOTATION(f, p) \ + __attribute__((malloc, malloc(f, p))) +# endif +# endif +#endif + +#if !defined(DYNINST_MALLOC_ANNOTATION) +# define DYNINST_MALLOC_ANNOTATION +#endif +#if !defined(DYNINST_MALLOC_DEALLOC_ANNOTATION) +# define DYNINST_MALLOC_DEALLOC_ANNOTATION(f) DYNINST_MALLOC_ANNOTATION +#endif +#if !defined(DYNINST_MALLOC_DEALLOC_POS_ANNOTATION) +# define DYNINST_MALLOC_DEALLOC_POS_ANNOTATION(f, p) DYNINST_MALLOC_ANNOTATION +#endif + +#endif /* COMPILER_ANNOTATIONS_H */ diff --git a/source/lib/omnitrace-rt/h/dyninstAPI_RT.h b/source/lib/omnitrace-rt/h/dyninstAPI_RT.h new file mode 100644 index 000000000..45f49cc85 --- /dev/null +++ b/source/lib/omnitrace-rt/h/dyninstAPI_RT.h @@ -0,0 +1,284 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * $Id: dyninstAPI_RT.h,v 1.45 2008/04/15 16:43:43 roundy Exp $ + * This file contains the standard instrumentation functions that are provided + * by the run-time instrumentation layer. + */ + +#ifndef _DYNINSTAPI_RT_H +#define _DYNINSTAPI_RT_H + +/* + * Define the size of the per process data area. + * + * This should be a power of two to reduce paging and caching shifts. + * Note that larger sizes may result in requiring longjumps within + * mini-trampolines to reach within this area. + */ + +#if !defined(target_smallmem) +# define SYN_INST_BUF_SIZE (1024 * 1024 * 4) +#else +# define SYN_INST_BUF_SIZE (1024 * 1024 * 1) +#endif + +#define DYNINST_BREAKPOINT_SIGNUM (SIGRTMIN + 4) + +#include +#include + +#include "h/Types.h" + +#include "dyninstRTExport.h" + +/* If we must make up a boolean type, we should make it unique */ +typedef unsigned char RT_Boolean; +static const RT_Boolean RT_TRUE = 1; +static const RT_Boolean RT_FALSE = 0; + +DLLEXPORT extern char gLoadLibraryErrorString[]; +extern void* gBRKptr; + +struct DYNINST_bootstrapStruct +{ + int event; /* "event" values: + 0 --> nothing + 1 --> end of DYNINSTinit (normal) + 2 --> end of DYNINSTinit (forked process) + 3 --> start of DYNINSTexec (before exec) + */ + int pid; + int ppid; /* parent of forked process */ +}; + +typedef enum +{ + DSE_undefined, + DSE_forkEntry, + DSE_forkExit, + DSE_execEntry, + DSE_execExit, + DSE_exitEntry, + DSE_loadLibrary, + DSE_lwpExit, + DSE_snippetBreakpoint, + DSE_stopThread, + DSE_userMessage, + DSE_dynFuncCall +} DYNINST_synch_event_t; + +extern int DYNINSTdebugPrintRT; /* control run-time lib debug/trace prints */ +#if !defined(RTprintf) +# define RTprintf \ + if(DYNINSTdebugPrintRT) printf +#endif + +#define TARGET_CACHE_WIDTH 128 +#define TARGET_CACHE_WAYS 2 + +#define THREAD_AWAITING_DELETION -2 + +#define ERROR_STRING_LENGTH 256 +typedef enum +{ + rtBPatch_nullEvent, + rtBPatch_newConnectionEvent, + rtBPatch_internalShutDownEvent, + rtBPatch_threadCreateEvent, + rtBPatch_threadDestroyEvent, + rtBPatch_dynamicCallEvent, + rtBPatch_userEvent +} rtBPatch_asyncEventType; +const char* asyncEventType2str(rtBPatch_asyncEventType); + +typedef struct +{ + unsigned int pid; + rtBPatch_asyncEventType type; + unsigned int event_fd; + unsigned int size; +} rtBPatch_asyncEventRecord; + +typedef struct +{ + void* call_site_addr; + void* call_target; +} BPatch_dynamicCallRecord; + +typedef struct +{ + int ppid; /*Parent process's pid*/ + dyntid_t tid; /*Thread library ID for thread*/ + int lwp; /*OS id for thread*/ + int index; /*The dyninst index for this thread*/ + void* stack_addr; /*The top of this thread's stack*/ + void* start_pc; /*The pc of this threads initial function*/ +} BPatch_newThreadEventRecord; + +#if defined(arch_x86_64) /* cannot use MUTATEE_32 here b/c libdyninstAPI.so compiles \ + this */ +/*these are the 32 bit structures for use with 32 bit mutatees on AMD64*/ +typedef struct +{ + unsigned int call_site_addr; + unsigned int call_target; +} BPatch_dynamicCallRecord32; + +typedef struct +{ + int ppid; /*Parent process's pid*/ + unsigned int tid; /*Thread library ID for thread*/ + int lwp; /*OS id for thread*/ + int index; /*The dyninst index for this thread*/ + unsigned int stack_addr; /*The top of this thread's stack*/ + unsigned int start_pc; /*The pc of this threads initial function*/ +} BPatch_newThreadEventRecord32; +#endif + +typedef struct +{ + int index; /*Index of the dead thread*/ +} BPatch_deleteThreadEventRecord; + +/* Let's define some constants for, well, everything.... */ +/* These should be different to avoid unexpected collisions */ + +#if !defined(DYNINST_SINGLETHREADED) +# define DYNINST_SINGLETHREADED -128 +#endif +#define DYNINST_TRACEPIPE_ERRVAL -1 +#define DYNINST_PRINTF_ERRVAL -2 + +#define DYNINST_NOT_IN_HASHTABLE ((unsigned) -1) + +DLLEXPORT extern int DYNINST_break_point_event; + +typedef struct +{ + void* source; + void* target; +} trapMapping_t; + +#define TRAP_HEADER_SIG 0x759191D6 +#define DT_DYNINST 0x6D191957 + +#if defined(_MSC_VER) +# pragma warning(disable : 4200) +#endif +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +// Disable warning about flexible array members in C++ +// FIXME: Flexible array member, traps[], in structure below +#endif +struct trap_mapping_header +{ + uint32_t signature; + uint32_t num_entries; + int32_t pos; + uint32_t padding; + uint64_t low_entry; + uint64_t high_entry; + trapMapping_t + traps[]; // Don't change this to a pointer, despite any compiler warnings +}; +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#endif + +#define MAX_MEMORY_MAPPER_ELEMENTS 1024 + +typedef struct +{ + long start; + long size; +} MemoryMapperCopyElement; + +typedef struct +{ + unsigned long lo; + unsigned long hi; + long shift; + MemoryMapperCopyElement* copyList; +} MemoryMapperElement; + +struct MemoryMapper +{ + int guard1; + int guard2; + int size; + int padding; + MemoryMapperElement elements[MAX_MEMORY_MAPPER_ELEMENTS]; +}; + +/* 32/64 bit versions for the mutator */ + +typedef struct +{ + uint32_t lo; + uint32_t hi; + uint32_t shift; + void* copyList; +} MemoryMapperElement32; + +typedef struct +{ + uint64_t lo; + uint64_t hi; + uint64_t shift; + void* copyList; +} MemoryMapperElement64; + +struct MemoryMapper32 +{ + int guard1; + int guard2; + int size; + int padding; + MemoryMapperElement32 elements[MAX_MEMORY_MAPPER_ELEMENTS]; +}; + +struct MemoryMapper64 +{ + int guard1; + int guard2; + int size; + int padding; + MemoryMapperElement64 elements[MAX_MEMORY_MAPPER_ELEMENTS]; +}; + +DLLEXPORT extern struct MemoryMapper RTmemoryMapper; + +extern int RTuntranslatedEntryCounter; + +#include "dyninstRTExport.h" +#endif /* _DYNINSTAPI_RT_H */ diff --git a/source/lib/omnitrace-rt/h/dyninstRTExport.h b/source/lib/omnitrace-rt/h/dyninstRTExport.h new file mode 100644 index 000000000..b01f83b1b --- /dev/null +++ b/source/lib/omnitrace-rt/h/dyninstRTExport.h @@ -0,0 +1,142 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _DYNINST_RT_EXPORT_H_ +#define _DYNINST_RT_EXPORT_H_ +#ifndef ASSEMBLER +/* This file contains function prototypes that may be useful for + dyninst users to directly have access to from their own runtime + libraries. +*/ + +# if !defined(DLLEXPORT) +# if defined(_MSC_VER) +/* If we're on Windows, we need to explicetely export these functions: */ +# define DLLEXPORT __declspec(dllexport) +# else +# define DLLEXPORT __attribute__((visibility("default"))) +# endif +# endif +/* + DYNINSTuserMessage(void *msg, unsigned int msg_size) may be used + in conjunction with the dyninstAPI method + BPatch_process::registerUserMessageCallback(), to implement a generic + user-defined, asynchronous communications protocol from the mutatee + (via this runtime library) to the mutator. + + Calls to DYNINSTuserMessage() will result in (of bytes) + being sent to the mutator, and then passed to the callback function + provided by the API user via registerUserMessageCallback(). + + Returns zero on success, nonzero on failure. +*/ +DLLEXPORT int +DYNINSTuserMessage(void* msg, unsigned int msg_size); + +/* Returns the number of threads DYNINST currently knows about. (Which + may differ at certain times from the number of threads actually present.) */ +DLLEXPORT int +DYNINSTthreadCount(); + +/** + * These function implement a locking mechanism that can be used by + * a user's runtime library. + * + * Be sure to always check for DYNINST_LIVE_LOCK and DYNINST_DEAD_LOCK. + * When instrumenting multithread or signal-based application as these error + * conditions can trigger even on simple synchronization mechanisms. + **/ + +/* The contents of this structure are subject to change between + dyninst versions. Don't rely on it. */ +typedef void* dyntid_t; +# define DYNINST_INITIAL_LOCK_PID ((void*) -129) + +typedef struct +{ + volatile int mutex; + dyntid_t tid; +} dyninst_lock_t; + +/* Return values for 'dyninst_lock' */ +# define DYNINST_LIVE_LOCK -1 +# define DYNINST_DEAD_LOCK -2 + +/* Declare a lock already initialized */ +# define DECLARE_DYNINST_LOCK(lck) dyninst_lock_t lck = { 0, DYNINST_INITIAL_LOCK_PID } + +DLLEXPORT void +dyninst_init_lock(dyninst_lock_t* lock); +DLLEXPORT void +dyninst_free_lock(dyninst_lock_t* lock); +DLLEXPORT int +dyninst_lock(dyninst_lock_t* lock); +DLLEXPORT void +dyninst_unlock(dyninst_lock_t* lock); + +/** + * Internal functions that we export to ensure they show up. + **/ + +DLLEXPORT void +DYNINSTsafeBreakPoint(); +DLLEXPORT void +DYNINSTinit(); +DLLEXPORT void +DYNINST_snippetBreakpoint(); +DLLEXPORT void +DYNINST_stopThread(void*, void*, void*, void*); +DLLEXPORT void +DYNINST_stopInterProc(void*, void*, void*, void*, void*, void*); +DLLEXPORT void +RThandleShadow(void*, void*, void*, void*, void*); +DLLEXPORT unsigned long +RTtranslateMemory(unsigned long, unsigned long, unsigned long); +DLLEXPORT unsigned long +RTtranslateMemoryShift(unsigned long, unsigned long, unsigned long); +DLLEXPORT void* +DYNINSTos_malloc(size_t, void*, void*); +DLLEXPORT int +DYNINSTloadLibrary(char*); + +/** + * And variables + **/ + +DLLEXPORT extern dyntid_t (*DYNINST_pthread_self)(void); +DLLEXPORT extern unsigned int DYNINSTobsCostLow; +DLLEXPORT extern int libdyninstAPI_RT_init_localCause; +DLLEXPORT extern int libdyninstAPI_RT_init_localPid; +DLLEXPORT extern int libdyninstAPI_RT_init_maxthreads; +DLLEXPORT extern int libdyninstAPI_RT_init_debug_flag; +DLLEXPORT extern struct DYNINST_bootstrapStruct DYNINST_bootstrap_info; + +#endif +#endif diff --git a/source/lib/omnitrace-rt/h/dyntypes.h b/source/lib/omnitrace-rt/h/dyntypes.h new file mode 100644 index 000000000..09e7468ad --- /dev/null +++ b/source/lib/omnitrace-rt/h/dyntypes.h @@ -0,0 +1,122 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined(DYNTYPES_H) +# define DYNTYPES_H + +# if defined(_MSC_VER) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# include +# endif + +# ifndef FILE__ +# if defined(_MSC_VER) +# define FILE__ \ + (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) +# else +# define FILE__ \ + (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) +# endif +# endif + +# if defined(_POWER) && !defined(__GNUC__) +# define XLC +# endif + +# include +# include + +// NB: std::hash has overloads for [un]scoped enums +template , + typename Comp = std::equal_to, + typename Alloc = std::allocator>> +using dyn_hash_map = std::unordered_map; + +template , + typename Comp = std::equal_to, typename Alloc = std::allocator> +using dyn_hash_set = std::unordered_set; + +// We require C++11 thread_local support +# define dyn_tls thread_local + +namespace Dyninst +{ +# if defined(_WIN64) +typedef uintptr_t Address; +typedef uintptr_t Offset; +# else +typedef unsigned long Address; +typedef unsigned long Offset; +# endif + +# if defined(_MSC_VER) +typedef int PID; +typedef HANDLE PROC_HANDLE; +typedef HANDLE LWP; +typedef HANDLE THR_ID; +typedef DWORD psaddr_t; // for breakpoints; match the debug struct + +# define NULL_PID -1 +# define NULL_LWP INVALID_HANDLE_VALUE +# define NULL_THR_ID INVALID_HANDLE_VALUE +# define DYNINST_SINGLETHREADED INVALID_HANDLE_VALUE +# else +typedef int PID; +typedef int PROC_HANDLE; +typedef int LWP; +typedef long THR_ID; + +# define NULL_PID -1 +# define NULL_LWP -1 +# define NULL_THR_ID -1 +# ifndef INVALID_HANDLE_VALUE +# define INVALID_HANDLE_VALUE -1 +# endif +# endif + +int +ThrIDToTid(Dyninst::THR_ID id); +} // namespace Dyninst + +namespace Dyninst +{ +typedef enum +{ + OSNone, + Linux, + FreeBSD, + Windows +} OSType; +} + +#endif diff --git a/source/lib/omnitrace-rt/h/util.h b/source/lib/omnitrace-rt/h/util.h new file mode 100644 index 000000000..7bf31cbb7 --- /dev/null +++ b/source/lib/omnitrace-rt/h/util.h @@ -0,0 +1,243 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined(SYMTAB_EXPORT) +# if defined(_MSC_VER) +# if defined SYMTAB_LIB +# define SYMTAB_EXPORT __declspec(dllexport) +# else +# define SYMTAB_EXPORT __declspec(dllimport) +# endif +# else +# define SYMTAB_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(SYMLITE_EXPORT) +# if defined(_MSC_VER) +# if defined SYMLITE_LIB +# define SYMLITE_EXPORT __declspec(dllexport) +# else +# define SYMLITE_EXPORT __declspec(dllimport) +# endif +# else +# define SYMLITE_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(DYNELF_EXPORT) +# if defined(_MSC_VER) +# if defined DYNELF_LIB +# define DYNELF_EXPORT __declspec(dllexport) +# else +# define DYNELF_EXPORT __declspec(dllimport) +# endif +# else +# define DYNELF_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(DYNDWARF_EXPORT) +# if defined(_MSC_VER) +# if defined DYNDWARF_LIB +# define DYNDWARF_EXPORT __declspec(dllexport) +# else +# define DYNDWARF_EXPORT __declspec(dllimport) +# endif +# else +# define DYNDWARF_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(COMMON_EXPORT) +# if defined(_MSC_VER) +# if defined(COMMON_LIB) +# define COMMON_EXPORT __declspec(dllexport) +# else +# define COMMON_EXPORT __declspec(dllimport) +# endif +# else +# define COMMON_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(COMMON_TEMPLATE_EXPORT) +# if defined(_MSC_VER) +# if defined(COMMON_LIB) || defined(INSTRUCTION_LIB) || defined(SYMTAB_LIB) || \ + defined(BPATCH_LIBRARY) +# define COMMON_TEMPLATE_EXPORT __declspec(dllexport) +# else +# define COMMON_TEMPLATE_EXPORT __declspec(dllimport) +# endif +# else +# define COMMON_TEMPLATE_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(INSTRUCTION_EXPORT) +# if defined(_MSC_VER) +# if defined(INSTRUCTION_LIB) +# define INSTRUCTION_EXPORT __declspec(dllexport) +# else +# define INSTRUCTION_EXPORT __declspec(dllimport) +# endif +# else +# define INSTRUCTION_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(PARSER_EXPORT) +# if defined(_MSC_VER) +# if defined(PARSER_LIB) +# define PARSER_EXPORT __declspec(dllexport) +# else +# define PARSER_EXPORT __declspec(dllimport) +# endif +# else +# define PARSER_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(PATCHAPI_EXPORT) +# if defined(_MSC_VER) +# if defined(PATCHAPI_LIB) +# define PATCHAPI_EXPORT __declspec(dllexport) +# else +# define PATCHAPI_EXPORT __declspec(dllimport) +# endif +# else +# define PATCHAPI_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(DATAFLOW_EXPORT) +# if defined(_MSC_VER) +# if defined(DATAFLOW_LIB) +# define DATAFLOW_EXPORT __declspec(dllexport) +# else +# define DATAFLOW_EXPORT __declspec(dllimport) +# endif +# else +# define DATAFLOW_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(PC_EXPORT) +# if defined(_MSC_VER) +# if defined(PROCCONTROL_EXPORTS) +# define PC_EXPORT __declspec(dllexport) +# else +# define PC_EXPORT __declspec(dllimport) +# endif +# else +# define PC_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(SW_EXPORT) +# if defined(_MSC_VER) +# if defined(STACKWALKER_EXPORTS) +# define SW_EXPORT __declspec(dllexport) +# else +# define SW_EXPORT __declspec(dllimport) +# endif +# else +# define SW_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(INJECTOR_EXPORT) +# if defined(_MSC_VER) +# if defined(INJECTOR_EXPORTS) +# define INJECTOR_EXPORT __declspec(dllexport) +# else +# define INJECTOR_EXPORT __declspec(dllimport) +# endif +# else +# define INJECTOR_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#if !defined(SYMEVAL_EXPORT) +# if defined(_MSC_VER) +# if defined(SYMEVAL_LIB) +# define SYMEVAL_EXPORT __declspec(dllexport) +# else +# define SYMEVAL_EXPORT __declspec(dllimport) +# endif +# else +# define SYMEVAL_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +#ifndef __UTIL_H__ +# define __UTIL_H__ + +# include "dyntypes.h" +# include + +# if defined(_MSC_VER) +# pragma warning(disable : 4251 4275 4396 4996) +# endif + +namespace Dyninst +{ +COMMON_EXPORT unsigned +addrHashCommon(const Address& addr); +COMMON_EXPORT unsigned +ptrHash(const void* addr); +COMMON_EXPORT unsigned +ptrHash(void* addr); + +COMMON_EXPORT unsigned +addrHash(const Address& addr); +COMMON_EXPORT unsigned +addrHash4(const Address& addr); +COMMON_EXPORT unsigned +addrHash16(const Address& addr); + +COMMON_EXPORT unsigned + stringhash(const std::string& s); +COMMON_EXPORT std::string + itos(int); +COMMON_EXPORT std::string + utos(unsigned); + +# define WILDCARD_CHAR '?' +# define MULTIPLE_WILDCARD_CHAR '*' + +COMMON_EXPORT bool +wildcardEquiv(const std::string& us, const std::string& them, bool checkCase = false); + +const char* +platform_string(); +} // namespace Dyninst + +#endif diff --git a/source/lib/omnitrace-rt/src/DYNINSTAPI_RT_EXPORTS b/source/lib/omnitrace-rt/src/DYNINSTAPI_RT_EXPORTS new file mode 100644 index 000000000..2c37dcf4b --- /dev/null +++ b/source/lib/omnitrace-rt/src/DYNINSTAPI_RT_EXPORTS @@ -0,0 +1,16 @@ +curRPC +DYNINSTversion +DYNINSTobsCostLow +DYNINSTglobalData +DYNINSTinit +DYNINSTos_init +pcAtLastIRPC +DYNINSTos_malloc +DYNINSTos_free +DYNINSTheap_useMalloc +DYNINSTheap_mmapFdOpen +DYNINSTheap_mmapFdClose +DYNINSTgetMemoryMap +DYNINSTstaticHeap_16M_textHeap_1 +DYNINSTstaticHeap_16M_anyHeap_1 +DYNINSTstaticHeap_32K_lowmemHeap_1 diff --git a/source/lib/omnitrace-rt/src/RTcommon.c b/source/lib/omnitrace-rt/src/RTcommon.c new file mode 100644 index 000000000..00e7fe7d9 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTcommon.c @@ -0,0 +1,814 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* $Id: RTcommon.c,v 1.78 2008/04/15 16:43:44 roundy Exp $ */ + +#include "RTcommon.h" +#include "RTthread.h" +#include "h/dyninstAPI_RT.h" +#include +#include +#include +#include +#include + +unsigned int DYNINSTobsCostLow; +DLLEXPORT unsigned int DYNINSThasInitialized = 0; +struct DYNINST_bootstrapStruct DYNINST_bootstrap_info; +char gLoadLibraryErrorString[ERROR_STRING_LENGTH]; +int DYNINSTdebugRTlib = 0; + +DLLEXPORT int DYNINSTstaticMode = 1; + +/** + * Allocate the Dyninst heaps + * + * The IA-64 requires that instruction be 16-byte aligned, so we have to + * align the heaps if we want to use them for inferior RPCs. + **/ +#define HEAP_TYPE double +#define ALIGN_ATTRIB + +#if defined(os_linux) || defined(os_freebsd) +# define HEAP_LOCAL extern +#else +# define HEAP_LOCAL DLLEXPORT +#endif + +HEAP_LOCAL HEAP_TYPE + DYNINSTglobalData[SYN_INST_BUF_SIZE / sizeof(HEAP_TYPE)] ALIGN_ATTRIB; + +#if !defined(target_smallmem) +HEAP_LOCAL HEAP_TYPE + DYNINSTstaticHeap_512K_lowmemHeap_1[512 * 1024 / sizeof(HEAP_TYPE)] ALIGN_ATTRIB; +HEAP_LOCAL HEAP_TYPE + DYNINSTstaticHeap_16M_anyHeap_1[16 * 1024 * 1024 / sizeof(HEAP_TYPE)] ALIGN_ATTRIB; +/* These are necessary due to silly C-style 'extern'/linking conventions. */ +const unsigned long sizeOfLowMemHeap1 = sizeof(DYNINSTstaticHeap_512K_lowmemHeap_1); +const unsigned long sizeOfAnyHeap1 = sizeof(DYNINSTstaticHeap_16M_anyHeap_1); +#else +HEAP_LOCAL HEAP_TYPE + DYNINSTstaticHeap_8K_lowmemHeap_1[8 * 1024 / sizeof(HEAP_TYPE)] ALIGN_ATTRIB; +HEAP_LOCAL HEAP_TYPE + DYNINSTstaticHeap_32K_anyHeap_1[32 * 1024 / sizeof(HEAP_TYPE)] ALIGN_ATTRIB; +/* These are necessary due to silly C-style 'extern'/linking conventions. */ +const unsigned long sizeOfLowMemHeap1 = sizeof(DYNINSTstaticHeap_8K_lowmemHeap_1); +const unsigned long sizeOfAnyHeap1 = sizeof(DYNINSTstaticHeap_32K_anyHeap_1); +#endif + +/** + * One some platforms we can tell when a fork or exec is occurring through + * system-provided events. On others we do it ourselves. Enumerated type + * defined in header file + **/ +DLLEXPORT DYNINST_synch_event_t DYNINST_synch_event_id = DSE_undefined; +DLLEXPORT void* DYNINST_synch_event_arg1; +/* Code to read args 2,3 would have to be moved from dyninstAPI's*/ +/* process::handleStopThread to signalgenerator::decodeRTSignal in*/ +/* order for other signals to make use of them, as currently only the*/ +/* stopThread event needs makes use of them. */ +DLLEXPORT void* DYNINST_synch_event_arg2 = NULL; /* not read in dyninst's decodeRTSignal*/ +DLLEXPORT void* DYNINST_synch_event_arg3 = NULL; /* not read in dyninst's decodeRTSignal*/ +DLLEXPORT int DYNINST_break_point_event = 0; + +/** + * These variables are used to pass arguments into DYNINSTinit + * when it is called as an _init function + **/ +int libdyninstAPI_RT_init_localCause = -1; +int libdyninstAPI_RT_init_localPid = -1; +int libdyninstAPI_RT_init_maxthreads = -1; +int libdyninstAPI_RT_init_debug_flag = 0; + +int DYNINST_mutatorPid; +int DYNINSTdebugPrintRT = 0; +int isMutatedExec = 0; + +// stopThread cache variables +char cacheLRUflags[TARGET_CACHE_WIDTH]; +DLLEXPORT void* DYNINST_target_cache[TARGET_CACHE_WIDTH][TARGET_CACHE_WAYS]; +FILE* stOut; +int fakeTickCount; + +#ifdef _MSC_VER +# define TLS_VAR __declspec(thread) +#else +// Note, the initial-exec model gives us static TLS which can be accessed +// directly, unlike dynamic TLS that calls __tls_get_addr(). Such calls risk +// recursing back to us if they're also instrumented, ad infinitum. Static TLS +// must be used very sparingly though, because it is a limited resource. +// *** This case is very special -- do not use IE in general libraries! *** + +# if defined(DYNINST_RT_STATIC_LIB) +# define TLS_VAR __thread __attribute__((tls_model("local-exec"))) +# else +# define TLS_VAR __thread __attribute__((tls_model("initial-exec"))) +# endif +#endif + +// It's tempting to make this a char, but glibc < 2.17 hits a bug: +// https://sourceware.org/bugzilla/show_bug.cgi?id=14898 +static TLS_VAR short DYNINST_tls_tramp_guard = 1; + +DLLEXPORT int +DYNINST_lock_tramp_guard() +{ + if(!DYNINST_tls_tramp_guard) return 0; + DYNINST_tls_tramp_guard = 0; + return 1; +} +DLLEXPORT void +DYNINST_unlock_tramp_guard() +{ + DYNINST_tls_tramp_guard = 1; +} + +DECLARE_DYNINST_LOCK(DYNINST_trace_lock); + +/** + * Init the FPU. We've seen bugs with Linux (e.g., Redhat 6.2 stock kernel on + * PIIIs) where processes started by Paradyn started with FPU uninitialized. + * DYNINSTdummydouble is global so the compiler won't optimize away FP code + * in initFPU + **/ +double DYNINSTdummydouble = 4321.71; +static void +initFPU() +{ + double x = 17.1234; + DYNINSTdummydouble *= x; +} + +/** + * This function is called in both static and dynamic rewriting, on + * all platforms that support binary rewriting, but before DYNINSTinit + **/ +void +DYNINSTBaseInit() +{ +#if defined(cap_mutatee_traps) + DYNINSTinitializeTrapHandler(); +#endif + DYNINST_unlock_tramp_guard(); + DYNINSThasInitialized = 1; + + RTuntranslatedEntryCounter = 0; +} + +/** + * The Dyninst API arranges for this function to be called at the entry to + * main() via libdyninstAPI_RT_init (defined in RTposix.c and RTwinnt.c). + * libdyninstAPI_RT_init is called by one of the following methods: + * GCC: link with gcc -shared, and use __attribute__((constructor)); + * Linux: ld with -init libdyninstAPI_RT_init + * gcc with -Wl,-init -Wl,... + * Windows: called from DllMain, which exists in lieu of libdyninstAPI_RT_init + * + * This is only called in the Dynamic instrumentation case. Static + * libraries don't call this. + **/ +void +DYNINSTinit() +{ + rtdebug_printf("%s[%d]: DYNINSTinit: welcome to DYNINSTinit()\n", __FILE__, + __LINE__); + initFPU(); + mark_heaps_exec(); + + tc_lock_init(&DYNINST_trace_lock); + DYNINSThasInitialized = 1; + rtdebug_printf("%s[%d]: welcome to DYNINSTinit\n", __FILE__, __LINE__); + + /* sanity check */ + assert(sizeof(int64_t) == 8); + assert(sizeof(int32_t) == 4); + + /* defensive stuff */ + memset(DYNINST_target_cache, 0, + sizeof(void*) * TARGET_CACHE_WIDTH * TARGET_CACHE_WAYS); + memset(cacheLRUflags, 1, sizeof(char) * TARGET_CACHE_WIDTH); + // stOut = fopen("rtdump.txt","w"); + + rtdebug_printf("%s[%d]: leaving DYNINSTinit\n", __FILE__, __LINE__); + fakeTickCount = 0; + /* Memory emulation */ +} + +/** + * Does what it's called. Used by the paradyn daemon as a default in certain + * cases (MT in particular) + **/ +int +DYNINSTreturnZero() +{ + return 0; +} + +/* Used to by dyninst breakpoint snippet */ +void +DYNINST_snippetBreakpoint() +{ + tc_lock_lock(&DYNINST_trace_lock); + + /* Set the state so the mutator knows what's up */ + DYNINST_synch_event_id = DSE_snippetBreakpoint; + DYNINST_synch_event_arg1 = NULL; + /* Stop ourselves */ + DYNINSTbreakPoint(); + /* Once the stop completes, clean up */ + DYNINST_synch_event_id = DSE_undefined; + + tc_lock_unlock(&DYNINST_trace_lock); +} + +/* Used to instrument (and report) the entry of fork */ +DLLEXPORT void +DYNINST_instForkEntry() +{ + tc_lock_lock(&DYNINST_trace_lock); + + /* Set the state so the mutator knows what's up */ + DYNINST_synch_event_id = DSE_forkEntry; + DYNINST_synch_event_arg1 = NULL; + /* Stop ourselves */ + DYNINSTbreakPoint(); + /* Once the stop completes, clean up */ + DYNINST_synch_event_id = DSE_undefined; + DYNINST_synch_event_arg1 = NULL; + + tc_lock_unlock(&DYNINST_trace_lock); +} + +/* Used to instrument (and report) the exit of fork */ +/* We use the safe breakpoint on the child side of fork + as we may not be attached at that point. The parent + side uses the normal version. */ +DLLEXPORT void +DYNINST_instForkExit(void* arg1) +{ +//#warning "This function is not implemented for AARCH64 yet!" +#if !defined(arch_aarch64) + tc_lock_lock(&DYNINST_trace_lock); + + /* Set the state so the mutator knows what's up */ + DYNINST_synch_event_id = DSE_forkExit; + DYNINST_synch_event_arg1 = arg1; + /* Stop ourselves */ + if((long int) arg1 == 0) + { + /* Child... */ + DYNINSTsafeBreakPoint(); + } + else + { + DYNINSTbreakPoint(); + } + /* Once the stop completes, clean up */ + DYNINST_synch_event_id = DSE_undefined; + DYNINST_synch_event_arg1 = NULL; + + tc_lock_unlock(&DYNINST_trace_lock); +#else + // Silence compiler warnings + (void) arg1; + assert(0); +#endif +} + +/* Used to instrument (and report) the entry of exec */ +DLLEXPORT void +DYNINST_instExecEntry(void* arg1) +{ +//#warning "This function is not implemented for AARCH64 yet!" +#if !defined(arch_aarch64) + tc_lock_lock(&DYNINST_trace_lock); + + /* Set the state so the mutator knows what's up */ + DYNINST_synch_event_id = DSE_execEntry; + DYNINST_synch_event_arg1 = arg1; + /* Stop ourselves */ + DYNINSTbreakPoint(); + /* Once the stop completes, clean up */ + DYNINST_synch_event_id = DSE_undefined; + DYNINST_synch_event_arg1 = NULL; + + tc_lock_unlock(&DYNINST_trace_lock); +#endif + // Silence compiler warnings + (void) arg1; +} + +/* Used to instrument (and report) the exit of exec */ +DLLEXPORT void +DYNINST_instExecExit(void* arg1) +{ + tc_lock_lock(&DYNINST_trace_lock); + + /* Set the state so the mutator knows what's up */ + DYNINST_synch_event_id = DSE_execExit; + DYNINST_synch_event_arg1 = arg1; + /* Stop ourselves */ + DYNINSTbreakPoint(); + /* Once the stop completes, clean up */ + DYNINST_synch_event_id = DSE_undefined; + DYNINST_synch_event_arg1 = NULL; + + tc_lock_unlock(&DYNINST_trace_lock); +} + +/* Used to instrument (and report) the entry of exit */ +DLLEXPORT void +DYNINST_instExitEntry(void* arg1) +{ + tc_lock_lock(&DYNINST_trace_lock); + + /* Set the state so the mutator knows what's up */ + DYNINST_synch_event_id = DSE_exitEntry; + DYNINST_synch_event_arg1 = arg1; + /* Stop ourselves */ + DYNINSTbreakPoint(); + /* Once the stop completes, clean up */ + DYNINST_synch_event_id = DSE_undefined; + DYNINST_synch_event_arg1 = NULL; + + tc_lock_unlock(&DYNINST_trace_lock); +} + +/* Used to instrument (and report) the entry of exit */ +DLLEXPORT void +DYNINST_instLoadLibrary(void* arg1) +{ + tc_lock_lock(&DYNINST_trace_lock); + + /* Set the state so the mutator knows what's up */ + DYNINST_synch_event_id = DSE_loadLibrary; + DYNINST_synch_event_arg1 = arg1; + /* Stop ourselves */ + DYNINSTbreakPoint(); + /* Once the stop completes, clean up */ + DYNINST_synch_event_id = DSE_undefined; + DYNINST_synch_event_arg1 = NULL; + + tc_lock_unlock(&DYNINST_trace_lock); +} + +/* Used to instrument (and report) the entry of exit */ +DLLEXPORT void +DYNINST_instLwpExit(void) +{ + tc_lock_lock(&DYNINST_trace_lock); + + /* Set the state so the mutator knows what's up */ + DYNINST_synch_event_id = DSE_lwpExit; + DYNINST_synch_event_arg1 = NULL; + /* Stop ourselves */ + DYNINSTbreakPoint(); + /* Once the stop completes, clean up */ + DYNINST_synch_event_id = DSE_undefined; + DYNINST_synch_event_arg1 = NULL; + + tc_lock_unlock(&DYNINST_trace_lock); +} + +// implementation of an N=2 way associative cache to keep access time low +// width = 32 +// the cache contains valid addresses +// add to the cache when an instrumented instruction misses in the cache +// update flags for the cache when an instrumented instruction hits in the cache +// instrumentation will take the form of a call to cache check +RT_Boolean +cacheLookup(void* calculation) +{ + int index = ((unsigned long) calculation) % TARGET_CACHE_WIDTH; + if(DYNINST_target_cache[index][0] == calculation) + { + cacheLRUflags[index] = 0; + return RT_TRUE; + } + else if(DYNINST_target_cache[index][1] == calculation) + { + cacheLRUflags[index] = 1; + return RT_TRUE; + } + else + { // miss + if(cacheLRUflags[index] == 0) + { + DYNINST_target_cache[index][1] = calculation; + cacheLRUflags[index] = 1; + } + else + { + DYNINST_target_cache[index][0] = calculation; + cacheLRUflags[index] = 0; + } + return RT_FALSE; + } +} + +/** + * Receives two snippets as arguments and stops the mutatee + * while the mutator reads the arguments, saved to + * DYNINST_synch_event... global variables. + * + * if flag useCache==1, does a cache lookup and stops only + * if there is a cache miss + * + * The flags are: + * bit 0: useCache + * bit 1: true if interpAsTarget + * bit 2: true if interpAsReturnAddr + **/ +//#define STACKDUMP +void +DYNINST_stopThread(void* pointAddr, void* callBackID, void* flags, void* calculation) +{ + static int reentrant = 0; + + RT_Boolean isInCache = RT_FALSE; + + if(reentrant == 1) + { + return; + } + reentrant = 1; + tc_lock_lock(&DYNINST_trace_lock); + rtdebug_printf("RT_st: pt[%lx] flags[%lx] calc[%lx] ", (unsigned long) pointAddr, + (unsigned long) flags, (unsigned long) calculation); + +#if 0 && defined STACKDUMP + //if (0 && ((unsigned long)calculation == 0x9746a3 || + // (unsigned long)calculation == 0x77dd761b)) + //{ + fprintf(stOut,"RT_st: %lx(%lx)\n", (long)pointAddr,&calculation); + fprintf(stOut,"at instr w/ targ=%lx\n",(long)calculation); + for (bidx=0; bidx < 0x100; bidx+=4) { + fprintf(stOut,"0x%x: ", (int)stackBase+bidx); + fprintf(stOut,"%02hhx", stackBase[bidx]); + fprintf(stOut,"%02hhx", stackBase[bidx+1]); + fprintf(stOut,"%02hhx", stackBase[bidx+2]); + fprintf(stOut,"%02hhx", stackBase[bidx+3]); + fprintf(stOut,"\n"); + } + //} + // fsg: read from 40a4aa, how did it become 40a380? +#endif + + if((((long) flags) & 0x04)) + { + rtdebug_printf("ret-addr stopThread yields %lx", (unsigned long) calculation); + // fprintf(stderr,"[$0x%lx]\n", (long)calculation); + } + + if(0 != (((long) flags) & 0x03)) + { + // do the lookup if the useCache bit is set, or if it represents + // the address of real code, so that we add the address to the cache + // even if we will stop the thread if there's a cache hit + isInCache = cacheLookup(calculation); + } + + // if the cache flag bit is not set, or if we get a cache miss, + // stop the thread so that we can call back to the mutatee + if(0 == (((long) flags) & 0x01) || !isInCache) + { + /* Set vars for Dyninst to read */ + DYNINST_synch_event_id = DSE_stopThread; + DYNINST_synch_event_arg1 = pointAddr; + DYNINST_synch_event_arg2 = callBackID; + DYNINST_synch_event_arg3 = calculation; + + // encode interp as target or as return addr by making + // callback ID negative + if(0 != (((long) flags) & 0x06)) + { + DYNINST_synch_event_arg2 = (void*) (-1 * (long) DYNINST_synch_event_arg2); + } + + rtdebug_printf("stopping! isInCache=%d\n", isInCache); + + /* Stop ourselves */ + DYNINSTbreakPoint(); + + /* Once the stop completes, clean up */ + DYNINST_synch_event_id = DSE_undefined; + DYNINST_synch_event_arg1 = NULL; + DYNINST_synch_event_arg2 = NULL; + DYNINST_synch_event_arg3 = NULL; + } + fflush(stOut); + tc_lock_unlock(&DYNINST_trace_lock); + reentrant = 0; + return; +} + +// zeroes out the useCache flag if the call is interprocedural +void +DYNINST_stopInterProc(void* pointAddr, void* callBackID, void* flags, void* calculation, + void* objStart, void* objEnd) +{ +#if defined STACKDUMP + fprintf(stOut, "RT_sip: calc=%lx objStart=%lx objEnd=%lx\n", calculation, objStart, + objEnd); + fflush(stOut); +#endif + if(calculation < objStart || calculation >= objEnd) + { + flags = (void*) ((long) (((int) ((long) flags)) & 0xfffffffe)); + } + DYNINST_stopThread(pointAddr, callBackID, flags, calculation); +} + +// boundsArray is a sequence of (blockStart,blockEnd) pairs +DLLEXPORT RT_Boolean +DYNINST_boundsCheck(void** boundsArray_, void* arrayLen_, void* writeTarget_) +{ + RT_Boolean callStopThread = RT_FALSE; + const unsigned long writeTarget = (unsigned long) writeTarget_; + const long arrayLen = (long) arrayLen_; + unsigned long* boundsArray = (unsigned long*) boundsArray_; + // set idx to halfway into the array, ensuring we use a blockStart address + int idx = (int) arrayLen / 4 * 2; + int lowIdx = 0; + int highIdx = (int) arrayLen; + // fprintf(stderr,"D_bc@%p: boundsArray=%p target=%lx idx=%d arrayLen=%d [%d]\n", + // (void*)DYNINST_boundsCheck, boundsArray_, writeTarget_, idx, arrayLen, __LINE__); + // rtdebug_printf("D_bc@%p: boundsArray=%p target=%lx idx=%d arrayLen=%d [%d]\n", + // (void*)DYNINST_boundsCheck, boundsArray_, writeTarget_, idx, arrayLen, __LINE__); + if((unsigned long) boundsArray < 0x10000000) + { + printf("D_bc: boundsArray_ = %lx, returning false\n", + (unsigned long) boundsArray); + return RT_FALSE; + } + while(lowIdx < highIdx) + { + if(idx > arrayLen || idx < 0) + rtdebug_printf("ERROR: out of bounds idx=%d, arrayLen = %ld [%d]\n", idx, + arrayLen, __LINE__); + rtdebug_printf("D_bc: low=%d high=%d arr[%d]=%lx [%d]\n", lowIdx, highIdx, idx, + boundsArray[idx], __LINE__); + if(writeTarget < boundsArray[idx]) + { + rtdebug_printf("D_bc: [%d]\n", __LINE__); + highIdx = idx; + idx = (highIdx - lowIdx) / 4 * 2 + lowIdx; + } + else if(boundsArray[idx + 1] <= writeTarget) + { + rtdebug_printf("D_bc: [%d]\n", __LINE__); + lowIdx = idx + 2; + idx = (highIdx - lowIdx) / 4 * 2 + lowIdx; + } + else + { + rtdebug_printf("D_bc: callST=true [%d]\n", __LINE__); + callStopThread = RT_TRUE; + break; + } + } + rtdebug_printf("D_bc: boundsArray=%p ret=%d [%d]\n", (void*) boundsArray, + callStopThread, __LINE__); + return callStopThread; +} + +/** + * Used to report addresses of functions called at dynamic call sites + **/ +DLLEXPORT int +DYNINSTasyncDynFuncCall(void* call_target, void* call_addr) +{ + if(DYNINSTstaticMode) return 0; + + tc_lock_lock(&DYNINST_trace_lock); + + /* Set the state so the mutator knows what's up */ + DYNINST_synch_event_id = DSE_dynFuncCall; + DYNINST_synch_event_arg1 = call_target; + DYNINST_synch_event_arg2 = call_addr; + /* Stop ourselves */ + DYNINSTbreakPoint(); + /* Once the stop completes, clean up */ + DYNINST_synch_event_id = DSE_undefined; + DYNINST_synch_event_arg1 = NULL; + DYNINST_synch_event_arg2 = NULL; + + tc_lock_unlock(&DYNINST_trace_lock); + + return 0; +} + +int +DYNINSTuserMessage(void* msg, unsigned int msg_size) +{ + unsigned long msg_size_long = (unsigned long) msg_size; + if(DYNINSTstaticMode) + { + return 0; + } + + tc_lock_lock(&DYNINST_trace_lock); + + /* Set the state so the mutator knows what's up */ + DYNINST_synch_event_id = DSE_userMessage; + DYNINST_synch_event_arg1 = msg; + DYNINST_synch_event_arg2 = (void*) msg_size_long; + /* Stop ourselves */ + DYNINSTbreakPoint(); + /* Once the stop completes, clean up */ + DYNINST_synch_event_id = DSE_undefined; + DYNINST_synch_event_arg1 = NULL; + DYNINST_synch_event_arg2 = NULL; + + tc_lock_unlock(&DYNINST_trace_lock); + + return 0; +} + +int +tc_lock_init(tc_lock_t* t) +{ + t->mutex = 0; + t->tid = (dyntid_t) DYNINST_INITIAL_LOCK_PID; + return 0; +} + +int +tc_lock_unlock(tc_lock_t* t) +{ + t->tid = (dyntid_t) DYNINST_INITIAL_LOCK_PID; + t->mutex = 0; + return 0; +} + +int +tc_lock_destroy(tc_lock_t* t) +{ + t->tid = (dyntid_t) DYNINST_INITIAL_LOCK_PID; + t->mutex = 0; + return 0; +} + +void +dyninst_init_lock(dyninst_lock_t* lock) +{ + lock->tid = (dyntid_t) DYNINST_INITIAL_LOCK_PID; + lock->mutex = 0; +} + +void +dyninst_free_lock(dyninst_lock_t* lock) +{ + (void) lock; /* unused parameter */ +} + +int +dyninst_lock(dyninst_lock_t* lock) +{ + return tc_lock_lock(lock); +} + +void +dyninst_unlock(dyninst_lock_t* lock) +{ + tc_lock_unlock(lock); +} + +int +rtdebug_printf(const char* format, ...) +{ + int ret; + va_list va; + if(!DYNINSTdebugRTlib) return 0; + if(NULL == format) return DYNINST_PRINTF_ERRVAL; + + fprintf(stderr, "[RTLIB]"); + va_start(va, format); + ret = vfprintf(stderr, format, va); + va_end(va); + + return ret; +} + +// clang-format off +#ifndef CASE_RETURN_STR +# define CASE_RETURN_STR(x) \ + case x: return #x +#endif +// clang-format on + +const char* +asyncEventType2str(rtBPatch_asyncEventType t) +{ + switch(t) + { + CASE_RETURN_STR(rtBPatch_nullEvent); + CASE_RETURN_STR(rtBPatch_newConnectionEvent); + CASE_RETURN_STR(rtBPatch_internalShutDownEvent); + CASE_RETURN_STR(rtBPatch_threadCreateEvent); + CASE_RETURN_STR(rtBPatch_threadDestroyEvent); + CASE_RETURN_STR(rtBPatch_dynamicCallEvent); + CASE_RETURN_STR(rtBPatch_userEvent); + default: return "bad_async_event_type"; + } +} + +DLLEXPORT volatile unsigned long dyninstTrapTableUsed; +DLLEXPORT volatile unsigned long dyninstTrapTableVersion; +DLLEXPORT volatile trapMapping_t* dyninstTrapTable; +DLLEXPORT volatile unsigned long dyninstTrapTableIsSorted; + +void* +dyninstTrapTranslate(void* source, volatile unsigned long* table_used, + volatile unsigned long* table_version, + volatile trapMapping_t** trap_table, + volatile unsigned long* is_sorted) +{ + volatile unsigned local_version; + unsigned i; + void* target; + + do + { + local_version = *table_version; + target = NULL; + + if(*is_sorted) + { + unsigned min = 0; + unsigned mid = 0; + unsigned max = *table_used; + unsigned prev = max + 1; + + for(;;) + { + mid = (min + max) / 2; + if(mid == prev) + { + fprintf(stderr, + "ERROR: dyninstTrapTranslate couldn't find " + "entry for %p: min=%x mid=%x max=%x prev=%x\n", + source, min, mid, max, prev); + break; + } + prev = mid; + + if((*trap_table)[mid].source < source) + min = mid; + else if((*trap_table)[mid].source > source) + max = mid; + else + { + target = (*trap_table)[mid].target; + break; + } + } + } + else + { /*!dyninstTrapTableIsSorted*/ + for(i = 0; i < *table_used; i++) + { + if((*trap_table)[i].source == source) + { + target = (*trap_table)[i].target; + break; + } + } + } + } while(local_version != *table_version); + + return target; +} + +DLLEXPORT void +DYNINSTtrapFunction() +{ + __asm__ __volatile__("nop\n" :::); +} diff --git a/source/lib/omnitrace-rt/src/RTcommon.h b/source/lib/omnitrace-rt/src/RTcommon.h new file mode 100644 index 000000000..e2963e41c --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTcommon.h @@ -0,0 +1,84 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _RTCOMMON_H_ +#define _RTCOMMON_H_ + +#include "RTthread.h" +#include "h/compiler_annotations.h" +#include "h/dyninstAPI_RT.h" +#include + +void +DYNINSTtrapFunction(); +void +DYNINSTbreakPoint(); +/* Use a signal that is safe if we're not attached. */ +void +DYNINSTsafeBreakPoint(); +void +DYNINSTinit(); +int +DYNINSTreturnZero(); +int +DYNINSTwriteEvent(void* ev, size_t sz); +int +DYNINSTasyncConnect(int pid); + +int +DYNINSTinitializeTrapHandler(); +void* +dyninstTrapTranslate(void* source, volatile unsigned long* table_used, + volatile unsigned long* table_version, + volatile trapMapping_t** trap_table, + volatile unsigned long* is_sorted); + +extern int DYNINST_mutatorPid; +extern int libdyninstAPI_RT_init_localCause; +extern int libdyninstAPI_RT_init_localPid; +extern int libdyninstAPI_RT_init_maxthreads; +extern int libdyninstAPI_RT_init_debug_flag; +extern int DYNINSTdebugPrintRT; +extern tc_lock_t DYNINST_trace_lock; + +extern void* +map_region(void* addr, int len, int fd); +extern int +unmap_region(void* addr, int len); +extern void +mark_heaps_exec(void); + +extern int DYNINSTdebugRTlib; + +DLLEXPORT extern int DYNINSTstaticMode; + +int +rtdebug_printf(const char* format, ...) DYNINST_PRINTF_ANNOTATION(1, 2); +#endif diff --git a/source/lib/omnitrace-rt/src/RTfreebsd.c b/source/lib/omnitrace-rt/src/RTfreebsd.c new file mode 100644 index 000000000..bce22784b --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTfreebsd.c @@ -0,0 +1,729 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/************************************************************************ + * $Id: RTlinux.c,v 1.54 2008/04/11 23:30:44 legendre Exp $ + * RTlinux.c: mutatee-side library function specific to Linux + ************************************************************************/ + +#include "h/dyninstAPI_RT.h" +#include "src/RTcommon.h" +#include "src/RTthread.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* FreeBSD libc has stubs so a static version shouldn't need libpthreads */ +#include + +extern double DYNINSTstaticHeap_512K_lowmemHeap_1[]; +extern double DYNINSTstaticHeap_16M_anyHeap_1[]; +extern unsigned long sizeOfLowMemHeap1; +extern unsigned long sizeOfAnyHeap1; + +static struct trap_mapping_header* +getStaticTrapMap(unsigned long addr); + +/** RT lib initialization **/ + +void +mark_heaps_exec() +{ + RTprintf("*** Initializing dyninstAPI runtime.\n"); + + /* Grab the page size, to align the heap pointer. */ + long int pageSize = sysconf(_SC_PAGESIZE); + if(pageSize == 0 || pageSize == -1) + { + fprintf(stderr, "*** Failed to obtain page size, guessing 16K.\n"); + perror("mark_heaps_exec"); + pageSize = 1024 * 16; + } /* end pageSize initialization */ + + /* Align the heap pointer. */ + unsigned long int alignedHeapPointer = + (unsigned long int) DYNINSTstaticHeap_16M_anyHeap_1; + alignedHeapPointer = (alignedHeapPointer) & ~(pageSize - 1); + unsigned long int adjustedSize = (unsigned long int) DYNINSTstaticHeap_16M_anyHeap_1 - + alignedHeapPointer + sizeOfAnyHeap1; + + /* Make the heap's page executable. */ + int result = mprotect((void*) alignedHeapPointer, (size_t) adjustedSize, + PROT_READ | PROT_WRITE | PROT_EXEC); + if(result != 0) + { + fprintf(stderr, + "%s[%d]: Couldn't make DYNINSTstaticHeap_16M_anyHeap_1 executable!\n", + __FILE__, __LINE__); + perror("mark_heaps_exec"); + } + RTprintf("*** Marked memory from 0x%lx to 0x%lx executable.\n", alignedHeapPointer, + alignedHeapPointer + adjustedSize); + + /* Mark _both_ heaps executable. */ + alignedHeapPointer = (unsigned long int) DYNINSTstaticHeap_512K_lowmemHeap_1; + alignedHeapPointer = (alignedHeapPointer) & ~(pageSize - 1); + adjustedSize = (unsigned long int) DYNINSTstaticHeap_512K_lowmemHeap_1 - + alignedHeapPointer + sizeOfLowMemHeap1; + + /* Make the heap's page executable. */ + result = mprotect((void*) alignedHeapPointer, (size_t) adjustedSize, + PROT_READ | PROT_WRITE | PROT_EXEC); + if(result != 0) + { + fprintf(stderr, + "%s[%d]: Couldn't make DYNINSTstaticHeap_512K_lowmemHeap_1 executable!\n", + __FILE__, __LINE__); + perror("mark_heaps_exec"); + } + RTprintf("*** Marked memory from 0x%lx to 0x%lx executable.\n", alignedHeapPointer, + alignedHeapPointer + adjustedSize); +} /* end mark_heaps_exec() */ + +#if defined(cap_binary_rewriter) && !defined(DYNINST_RT_STATIC_LIB) +/* For a static binary, all global constructors are combined in an undefined + * order. Also, DYNINSTBaseInit must be run after all global constructors have + * been run. Since the order of global constructors is undefined, DYNINSTBaseInit + * cannot be run as a constructor in static binaries. Instead, it is run from a + * special constructor handler that processes all the global constructors in + * the binary. Leaving this code in would create a global constructor for the + * function runDYNINSTBaseInit(). See DYNINSTglobal_ctors_handler. + */ +extern void +DYNINSTBaseInit(); +void +runDYNINSTBaseInit() __attribute__((constructor)); +void +runDYNINSTBaseInit() +{ + DYNINSTBaseInit(); +} +#endif + +/** Dynamic instrumentation support **/ + +static int +tkill(pid_t pid, long lwp, int sig) +{ + static int has_tkill = 1; + int result = 0; + + if(has_tkill) + { + result = syscall(SYS_thr_kill2, pid, lwp, sig); + if(0 != result && ENOSYS == errno) + { + has_tkill = 0; + } + } + + if(!has_tkill) + { + result = kill(pid, sig); + } + + return (result == 0); +} + +void +DYNINSTbreakPoint() +{ + if(DYNINSTstaticMode) return; + + DYNINST_break_point_event = 1; + while(DYNINST_break_point_event) + { + tkill(getpid(), dyn_lwp_self(), DYNINST_BREAKPOINT_SIGNUM); + } + /* Mutator resets to 0 */ +} + +static int failed_breakpoint = 0; +void +uncaught_breakpoint(int sig) +{ + failed_breakpoint = 1; +} + +void +DYNINSTsafeBreakPoint() +{ + if(DYNINSTstaticMode) return; + + DYNINST_break_point_event = 1; + while(DYNINST_break_point_event) + { + tkill(getpid(), dyn_lwp_self(), SIGSTOP); + } + /* Mutator resets to 0 */ + +#if 0 + if( DYNINSTstaticMode ) return; + DYNINST_break_point_event = 2; + sigset_t emptyset; + sigemptyset(&emptyset); + + // There is a bug with attaching to a stopped process on FreeBSD This + // achieves the same result as long as Dyninst attaches to the process when + // it is in sigsuspend + while( DYNINST_break_point_event ) { + sigsuspend(&emptyset); + } +#endif +} + +#if !defined(DYNINST_RT_STATIC_LIB) +static int +get_dlopen_error() +{ + const char* err_str; + err_str = dlerror(); + if(err_str) + { + strncpy(gLoadLibraryErrorString, err_str, (size_t) ERROR_STRING_LENGTH); + return 1; + } + + sprintf(gLoadLibraryErrorString, "unknown error withe dlopen"); + return 0; +} + +int +DYNINSTloadLibrary(char* libname) +{ + void* res; + gLoadLibraryErrorString[0] = '\0'; + res = dlopen(libname, RTLD_NOW | RTLD_GLOBAL); + if(res) return 1; + + get_dlopen_error(); + return 0; +} +#endif + +/** threading support **/ + +int +dyn_lwp_self() +{ + static int gettid_not_valid = 0; + int result; + + if(gettid_not_valid) return getpid(); + + long lwp_id; + result = syscall(SYS_thr_self, &lwp_id); + if(result && errno == ENOSYS) + { + gettid_not_valid = 1; + return getpid(); + } + + return lwp_id; +} + +int +dyn_pid_self() +{ + return getpid(); +} + +dyntid_t (*DYNINST_pthread_self)(void); + +dyntid_t +dyn_pthread_self() +{ + dyntid_t me; + if(DYNINSTstaticMode) + { + return (dyntid_t) pthread_self(); + } + if(!DYNINST_pthread_self) + { + return (dyntid_t) DYNINST_SINGLETHREADED; + } + me = (*DYNINST_pthread_self)(); + return (dyntid_t) me; +} + +int +DYNINST_am_initial_thread(dyntid_t tid) +{ + /* + * LWPs and PIDs are in different namespaces on FreeBSD. + * + * I don't really know a good way to determine this without + * doing an expensive sysctl. + * + * Luckily, this function isn't used anymore + */ + assert(!"This function is unimplemented on FreeBSD"); + return 0; +} + +/** trap based instrumentation **/ + +#if defined(cap_mutatee_traps) + +# include + +# if defined(arch_x86) || defined(MUTATEE_32) +# define UC_PC(x) x->uc_mcontext.mc_eip +# elif defined(arch_x86_64) +# define UC_PC(x) x->uc_mcontext.mc_rip +# endif // UC_PC + +extern unsigned long dyninstTrapTableUsed; +extern unsigned long dyninstTrapTableVersion; +extern trapMapping_t* dyninstTrapTable; +extern unsigned long dyninstTrapTableIsSorted; + +/** + * This comment is now obsolete, left for historic purposes + * + * Called by the SIGTRAP handler, dyninstTrapHandler. This function is + * closly intwined with dyninstTrapHandler, don't modify one without + * understanding the other. + * + * This function sets up the calling context that was passed to the + * SIGTRAP handler so that control will be redirected to our instrumentation + * when we do the setcontext call. + * + * There are a couple things that make this more difficult than it should be: + * 1. The OS provided calling context is similar to the GLIBC calling context, + * but not compatible. We'll create a new GLIBC compatible context and + * copy the possibly stomped registers from the OS context into it. The + * incompatiblities seem to deal with FP and other special purpose registers. + * 2. setcontext doesn't restore the flags register. Thus dyninstTrapHandler + * will save the flags register first thing and pass us its value in the + * flags parameter. We'll then push the instrumentation entry and flags + * onto the context's stack. Instead of transfering control straight to the + * instrumentation, we'll actually go back to dyninstTrapHandler, which will + * do a popf/ret to restore flags and go to instrumentation. The 'retPoint' + * parameter is the address in dyninstTrapHandler the popf/ret can be found. + **/ +void +dyninstTrapHandler(int sig, siginfo_t* sg, ucontext_t* context) +{ + void* orig_ip; + void* trap_to; + + orig_ip = UC_PC(context); + assert(orig_ip); + + // Find the new IP we're going to and substitute. Leave everything else untouched + if(DYNINSTstaticMode) + { + unsigned long zero = 0; + unsigned long one = 1; + struct trap_mapping_header* hdr = getStaticTrapMap((unsigned long) orig_ip); + if(!hdr) return; + + assert(hdr); + trapMapping_t* mapping = &(hdr->traps[0]); + trap_to = dyninstTrapTranslate(orig_ip, (unsigned long*) &hdr->num_entries, &zero, + (volatile trapMapping_t**) &mapping, &one); + } + else + { + trap_to = dyninstTrapTranslate( + orig_ip, &dyninstTrapTableUsed, &dyninstTrapTableVersion, + (volatile trapMapping_t**) &dyninstTrapTable, &dyninstTrapTableIsSorted); + } + UC_PC(context) = (long) trap_to; +} + +# if defined(cap_binary_rewriter) + +# define NUM_LIBRARIES 512 // Important, max number of rewritten libraries + +# define WORD_SIZE (8 * sizeof(unsigned)) +# define NUM_LIBRARIES_BITMASK_SIZE (1 + NUM_LIBRARIES / WORD_SIZE) +struct trap_mapping_header* all_headers[NUM_LIBRARIES]; + +static unsigned all_headers_current[NUM_LIBRARIES_BITMASK_SIZE]; +static unsigned all_headers_last[NUM_LIBRARIES_BITMASK_SIZE]; + +# if !defined(arch_x86_64) || defined(MUTATEE_32) +typedef Elf32_Dyn ElfX_Dyn; +typedef Elf32_Ehdr ElfX_Ehdr; +# else +typedef Elf64_Dyn ElfX_Dyn; +typedef Elf64_Ehdr ElfX_Ehdr; +# endif + +static int +parse_libs(); +static int +parse_link_map(struct link_map* l); +static void +clear_unloaded_libs(); + +static void +set_bit(unsigned* bit_mask, int bit, char value); +static void +clear_bitmask(unsigned* bit_mask); +static unsigned +get_next_free_bitmask(unsigned* bit_mask, int last_pos); +static unsigned +get_next_set_bitmask(unsigned* bit_mask, int last_pos); + +static tc_lock_t trap_mapping_lock; + +static struct trap_mapping_header* +getStaticTrapMap(unsigned long addr) +{ + struct trap_mapping_header* header; + int i; + + tc_lock_lock(&trap_mapping_lock); + parse_libs(); + + i = -1; + for(;;) + { + i = get_next_set_bitmask(all_headers_current, i); + assert(i >= 0 && i <= NUM_LIBRARIES); + if(i == NUM_LIBRARIES) + { + header = NULL; + goto done; + } + header = all_headers[i]; + if(addr >= header->low_entry && addr <= header->high_entry) + { + goto done; + } + } +done: + tc_lock_unlock(&trap_mapping_lock); + return header; +} + +static struct link_map* +getLinkMap() +{ + struct link_map* map = NULL; +# if !defined(DYNINST_RT_STATIC_LIB) + if(dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map)) + { + return NULL; + } + + // Rewind the current link map pointer to find the + // start of the list + struct link_map* last_map; + while(map != NULL) + { + last_map = map; + map = map->l_prev; + } + + map = last_map; +# endif + return map; +} + +static int +parse_libs() +{ + struct link_map* l_current; + + l_current = getLinkMap(); + if(!l_current) return -1; + + clear_bitmask(all_headers_current); + while(l_current) + { + parse_link_map(l_current); + l_current = l_current->l_next; + } + clear_unloaded_libs(); + + return 0; +} + +// parse_link_map return values +# define PARSED 0 +# define NOT_REWRITTEN 1 +# define ALREADY_PARSED 2 +# define ERROR_INTERNAL -1 +# define ERROR_FULL -2 +static int +parse_link_map(struct link_map* l) +{ + ElfX_Dyn* dynamic_ptr; + struct trap_mapping_header* header; + unsigned int i, new_pos; + + dynamic_ptr = (ElfX_Dyn*) l->l_ld; + if(!dynamic_ptr) return -1; + + assert(sizeof(dynamic_ptr->d_un.d_ptr) == sizeof(void*)); + for(; dynamic_ptr->d_tag != DT_NULL && dynamic_ptr->d_tag != DT_DYNINST; + dynamic_ptr++) + ; + if(dynamic_ptr->d_tag == DT_NULL) + { + return NOT_REWRITTEN; + } + + header = (struct trap_mapping_header*) (dynamic_ptr->d_un.d_val + l->l_addr); + + caddr_t libAddr = l->l_addr; + + // Executables have an implicit zero load address but the library load address + // may be non-zero + if(((ElfX_Ehdr*) libAddr)->e_type == ET_EXEC) + { + libAddr = 0; + } + else if(((ElfX_Ehdr*) libAddr)->e_type == ET_DYN) + { + // Account for library_adjust mechanism which is used for shared libraries + // on FreeBSD + libAddr += getpagesize(); + } + + header = (struct trap_mapping_header*) (dynamic_ptr->d_un.d_val + libAddr); + + if(header->signature != TRAP_HEADER_SIG) return ERROR_INTERNAL; + if(header->pos != -1) + { + set_bit(all_headers_current, header->pos, 1); + assert(all_headers[header->pos] == header); + return ALREADY_PARSED; + } + + for(i = 0; i < header->num_entries; i++) + { + header->traps[i].source = + (void*) (((unsigned long) header->traps[i].source) + libAddr); + header->traps[i].target = + (void*) (((unsigned long) header->traps[i].target) + libAddr); + if(!header->low_entry || + header->low_entry > (unsigned long) header->traps[i].source) + header->low_entry = (unsigned long) header->traps[i].source; + if(!header->high_entry || + header->high_entry < (unsigned long) header->traps[i].source) + header->high_entry = (unsigned long) header->traps[i].source; + } + + new_pos = get_next_free_bitmask(all_headers_last, -1); + assert(new_pos >= 0 && new_pos < NUM_LIBRARIES); + if(new_pos == NUM_LIBRARIES) return ERROR_FULL; + + header->pos = new_pos; + all_headers[new_pos] = header; + set_bit(all_headers_current, new_pos, 1); + set_bit(all_headers_last, new_pos, 1); + + return PARSED; +} + +static void +clear_unloaded_libs() +{ + unsigned i; + for(i = 0; i < NUM_LIBRARIES_BITMASK_SIZE; i++) + { + all_headers_last[i] = all_headers_current[i]; + } +} + +static void +set_bit(unsigned* bit_mask, int bit, char value) +{ + assert(bit < NUM_LIBRARIES); + unsigned* word = bit_mask + bit / WORD_SIZE; + unsigned shift = bit % WORD_SIZE; + if(value) + { + *word |= (1 << shift); + } + else + { + *word &= ~(1 << shift); + } +} + +static void +clear_bitmask(unsigned* bit_mask) +{ + unsigned i; + for(i = 0; i < NUM_LIBRARIES_BITMASK_SIZE; i++) + { + bit_mask[i] = 0; + } +} + +static unsigned +get_next_free_bitmask(unsigned* bit_mask, int last_pos) +{ + unsigned i, j; + j = last_pos + 1; + i = j / WORD_SIZE; + for(; j < NUM_LIBRARIES; i++) + { + if(bit_mask[i] == (unsigned) -1) + { + j += WORD_SIZE; + continue; + } + for(;;) + { + if(!((1 << (j % WORD_SIZE) & bit_mask[i]))) + { + return j; + } + j++; + if(j % WORD_SIZE == 0) + { + break; + } + } + } + return NUM_LIBRARIES; +} + +static unsigned +get_next_set_bitmask(unsigned* bit_mask, int last_pos) +{ + unsigned i, j; + j = last_pos + 1; + i = j / WORD_SIZE; + for(; j < NUM_LIBRARIES; i++) + { + if(bit_mask[i] == (unsigned) 0) + { + j += WORD_SIZE; + continue; + } + for(;;) + { + if((1 << (j % WORD_SIZE) & bit_mask[i])) + { + return j; + } + j++; + if(j % WORD_SIZE == 0) + { + break; + } + } + } + return NUM_LIBRARIES; +} + +# endif + +#endif /* cap_mutatee_traps */ + +/* + * Note: this program is for historical purposes only, we use libthread_db + * now to get thread information. + * + * A program to determine the offsets of certain thread structures on FreeBSD + * + * This program should be compiled with the headers from the libthr library from + * /usr/src. This can be installed using sysinstall. The following arguments + * should be added to the compile once these headers are installed. + * + * -I/usr/src/lib/libthr/arch/amd64/include -I/usr/src/lib/libthr/thread + * + * Change amd64 to what ever is appropriate. + +#include +#include +#include +#include +#include + +#include "thr_private.h" + +pthread_attr_t attr; + +void *foo(void *f) { + unsigned long stack_addr; + void *(*start_func)(void *); + unsigned long tid; + + // Get all the values + syscall(SYS_thr_self, &tid); + + start_func = foo; + + asm("mov %%rbp,%0" : "=r" (stack_addr)); + + pthread_t threadSelf = pthread_self(); + + printf("TID: %u == %u\n", tid, threadSelf->tid); + printf("STACK: 0x%lx == 0x%lx\n", stack_addr, threadSelf->attr.stackaddr_attr + +threadSelf->attr.stacksize_attr); printf("START: 0x%lx == 0x%lx\n", (unsigned +long)start_func, (unsigned long)threadSelf->start_routine); + + unsigned char *ptr = (unsigned char *)threadSelf; + unsigned long tidVal = *((unsigned long *)(ptr + offsetof(struct pthread, tid))); + unsigned long stackAddrVal = *((unsigned long *)(ptr + offsetof(struct pthread, attr) ++ offsetof(struct pthread_attr, stackaddr_attr))); unsigned long stackSizeVal = +*((unsigned long *)(ptr + offsetof(struct pthread, attr) + offsetof(struct pthread_attr, +stacksize_attr))); unsigned long startFuncVal = *((unsigned long *)(ptr + offsetof(struct +pthread, start_routine))); + + printf("TID = %u, offset = %u\n", tidVal, offsetof(struct pthread, tid)); + printf("STACK = 0x%lx, offset = %u\n", stackAddrVal, offsetof(struct pthread, attr) + +offsetof(struct pthread_attr, stackaddr_attr)); printf("SIZE = 0x%lx, offset = %u\n", +stackSizeVal, offsetof(struct pthread, attr) + offsetof(struct pthread_attr, +stacksize_attr)); printf("START = 0x%lx, offset = %u\n", startFuncVal, offsetof(struct +pthread, start_routine)); + + return NULL; +} + +int main(int argc, char *argv[]) { + pthread_t t; + void *result; + pthread_attr_init(&attr); + pthread_create(&t, &attr, foo, NULL); + pthread_join(t, &result); + + return 0; +} +*/ diff --git a/source/lib/omnitrace-rt/src/RTheap-freebsd.c b/source/lib/omnitrace-rt/src/RTheap-freebsd.c new file mode 100644 index 000000000..f05cfcf74 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTheap-freebsd.c @@ -0,0 +1,85 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* RTheap-freebsd.c: FreeBSD-specific heap components */ + +#include "RTheap.h" +#include +#include /* open() */ +#include +#include +#include /* str* */ +#include /* mmap() */ +#include /* open() */ +#include +#include /* read() */ +#include /* sbrk(), read(), mmap */ + +#if defined(MUTATEE64) +int DYNINSTheap_align = 4; /* heaps are word-aligned */ + +Address DYNINSTheap_loAddr = 0x4096; +Address DYNINSTheap_hiAddr = ~0x0; +#else +int DYNINSTheap_align = 4; /* heaps are word-aligned */ + +Address DYNINSTheap_loAddr = 0x50000000; +Address DYNINSTheap_hiAddr = 0xb0000000; +#endif + +int DYNINSTheap_mmapFlags = MAP_FIXED | MAP_PRIVATE; + +RT_Boolean +DYNINSTheap_useMalloc(void* lo, void* hi) +{ + /* We do not save footprint space by allocating in + the user's heap on this platform, so we stay out of it. */ + return RT_FALSE; +} + +int +DYNINSTheap_mmapFdOpen(void) +{ + int fd = open("/dev/zero", O_RDWR); + return fd; +} + +void +DYNINSTheap_mmapFdClose(int fd) +{ + close(fd); +} + +int +DYNINSTgetMemoryMap(unsigned* nump, dyninstmm_t** mapp) +{ + assert(!"Unimplemented on FreeBSD for the time being"); + return -1; +} diff --git a/source/lib/omnitrace-rt/src/RTheap-linux.c b/source/lib/omnitrace-rt/src/RTheap-linux.c new file mode 100644 index 000000000..80f835310 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTheap-linux.c @@ -0,0 +1,132 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* $Id: RTheap-linux.c,v 1.9 2008/01/31 18:01:54 legendre Exp $ */ +/* RTheap-linux.c: Linux-specific heap components */ + +#include "RTheap.h" +#include +#include /* open() */ +#include +#include +#include /* str* */ +#include /* mmap() */ +#include /* open() */ +#include +#include /* read() */ +#include /* sbrk(), read(), mmap */ + +#if 1 // defined(MUTATEE64) + +int DYNINSTheap_align = 4; /* heaps are word-aligned */ + +Address DYNINSTheap_loAddr = 0x10000; /* Bump to 64k to make SELinux happier */ +Address DYNINSTheap_hiAddr = ~(Address) 0x0; +#elif defined(arch_power) +int DYNINSTheap_align = 4; /* heaps are word-aligned */ +Address DYNINSTheap_loAddr = + ~(Address) 0; // should be defined by getpagesize() when used. +Address DYNINSTheap_hiAddr = ~(Address) 0; +#else +int DYNINSTheap_align = 4; /* heaps are word-aligned */ + +Address DYNINSTheap_loAddr = 0x50000000; +Address DYNINSTheap_hiAddr = 0xb0000000; +#endif + +int DYNINSTheap_mmapFlags = MAP_ANONYMOUS | MAP_PRIVATE; + +RT_Boolean +DYNINSTheap_useMalloc(void* lo, void* hi) +{ + /* We do not save footprint space by allocating in + the user's heap on this platform, so we stay out of it. */ + (void) lo; /* unused parameter */ + (void) hi; /* unused parameter */ + return RT_FALSE; +} + +int +DYNINSTheap_mmapFdOpen(void) +{ + int fd = open("/dev/zero", O_RDWR); + return fd; +} + +void +DYNINSTheap_mmapFdClose(int fd) +{ + close(fd); +} + +int +DYNINSTgetMemoryMap(unsigned* nump, dyninstmm_t** mapp) +{ + FILE* procmaps; + Address saddr = 0, eaddr = 0; + int num_matches; + procmaps = fopen("/proc/self/maps", "r"); + dyninstmm_t* maps = *mapp; + if(procmaps == NULL) return -1; + *nump = 0; + while(((num_matches = fscanf(procmaps, "%lx-%lx", &saddr, &eaddr)) != EOF) && + (*nump < 1024)) + { + if(num_matches == 2) + { + maps[*nump].pr_vaddr = saddr; + maps[*nump].pr_size = eaddr - saddr; + (*nump)++; + // skip to next line + int ch; + while((ch = fgetc(procmaps)) != '\n' && ch != EOF) + { + if(ch == EOF) break; + } + } + else + { + break; + } + } + fclose(procmaps); + return *nump < 1024; + + /* + Here are two lines from 'cat /proc/self/maps' on Linux 2.2. Each + describes a segment of the address space. We parse out the first + two addresses for the start address and length of the segment. We + throw away the rest. + + |SADDR-| |EADDR-| + 0804a000-0804c000 rw-p 00001000 08:09 12089 /bin/cat + 0804c000-0804f000 rwxp 00000000 00:00 0 + */ +} diff --git a/source/lib/omnitrace-rt/src/RTheap-win.c b/source/lib/omnitrace-rt/src/RTheap-win.c new file mode 100644 index 000000000..5916c74bb --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTheap-win.c @@ -0,0 +1,153 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "src/RTcommon.h" +#include "src/RTheap.h" +#include +#include + +int DYNINSTheap_align = 16; +Address DYNINSTheap_loAddr = 0x400000; // 4MB mark +Address DYNINSTheap_hiAddr = 0x7FFFFFFF; // 2GB mark + +int +getpagesize() +{ + SYSTEM_INFO info; + static int page_size = 0; + if(page_size) return page_size; + GetSystemInfo(&info); + page_size = info.dwPageSize; + return page_size; +} + +void* +map_region(void* addr, int len, int fd) +{ + void* result; + DWORD lastError; + char* lpMessage = NULL; + result = VirtualAlloc(addr, len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if(!result) + { + lastError = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)(lpMessage), 0, NULL); + fprintf(stderr, "VirtualAlloc failed in RTlib: %s\n", lpMessage); + LocalFree((LPVOID) lpMessage); + } + else + { + fprintf(stderr, "VirtualAlloc succeeded, %p to %p mapped for RTlib heap\n", addr, + (char*) (addr) + len); + } + return result; +} + +int +unmap_region(void* addr, int len) +{ + BOOL result; + result = VirtualFree(addr, 0, MEM_RELEASE); + return (int) result; +} + +int +DYNINSTheap_mmapFdOpen(void) +{ + return 0; +} + +void +DYNINSTheap_mmapFdClose(int fd) +{} + +RT_Boolean +DYNINSTheap_useMalloc(void* lo, void* hi) +{ + return RT_FALSE; +} + +int +DYNINSTgetMemoryMap(unsigned* nump, dyninstmm_t** mapp) +{ + dyninstmm_t* map = NULL; + void* temp; + Address cur, base; + MEMORY_BASIC_INFORMATION mem; + unsigned count = 0, size = 0; + static unsigned alloc_size = 256; + + map = (dyninstmm_t*) malloc(alloc_size * sizeof(dyninstmm_t)); + memset(map, 0, alloc_size * sizeof(dyninstmm_t)); + + cur = DYNINSTheap_loAddr; + for(; cur < DYNINSTheap_hiAddr; cur += size) + { + VirtualQuery((void*) cur, &mem, sizeof(MEMORY_BASIC_INFORMATION)); + base = (Address) mem.BaseAddress; + size = mem.RegionSize; + + if(!size) goto done_err; + if(mem.State & MEM_FREE) continue; + + if(count && (base <= map[count - 1].pr_vaddr + map[count - 1].pr_size)) + { + // We have two continuous regions, just merge them into one + map[count - 1].pr_size = base + size - map[count - 1].pr_vaddr; + continue; + } + + if(count >= alloc_size) + { + // Grow the allocation buffer, if we need to + alloc_size *= 2; + temp = realloc(map, alloc_size * sizeof(dyninstmm_t)); + if(!temp) goto done_err; + map = (dyninstmm_t*) temp; + } + + map[count].pr_vaddr = base; + map[count].pr_size = size; + count++; + } + + *nump = count; + *mapp = map; + return 0; + +done_err: + free(map); + *nump = 0; + *mapp = NULL; + return -1; +} diff --git a/source/lib/omnitrace-rt/src/RTheap.c b/source/lib/omnitrace-rt/src/RTheap.c new file mode 100644 index 000000000..e28875b09 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTheap.c @@ -0,0 +1,223 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* $Id: RTheap.c,v 1.25 2006/05/03 00:31:25 jodom Exp $ */ +/* RTheap.c: platform-generic heap management */ + +#include +#include +#if !defined(os_windows) /* ccw 15 may 2000 : 29 mar 2001 */ + /* win does not have these header files. it appears the only + one that is used assert.h anyway. + */ +# include +# include /* open() */ +# include /* open() */ +# include +# include +#else +extern int +getpagesize(); +#endif +#include + +#include "src/RTcommon.h" +#include "src/RTheap.h" + +typedef enum +{ + HEAP_TYPE_UNKNOWN = 0x0, + HEAP_TYPE_MMAP = 0x1, + HEAP_TYPE_MALLOC = 0x2 +} heapType_t; + +typedef struct heap_t +{ + void* ret_addr; /* address returned to mutator */ + void* addr; /* actual heap address */ + size_t len; /* actual heap length */ + heapType_t type; /* heap allocation type */ +} heap_t; + +typedef struct heapList_t +{ + heap_t heap; + struct heapList_t* prev; + struct heapList_t* next; +} heapList_t; + +/* local variables */ +static heapList_t* Heaps = NULL; +static int psize = -1; + +static Address +heap_alignUp(Address addr, int align) +{ + if(addr % align == 0) return addr; + return ((addr / align) + 1) * align; +} + +static Address +trymmap(size_t len, Address beg, Address end, size_t inc, int fd) +{ + Address addr; + void* result; + /*We have a possibly large region (beg to end) and a hopefully smaller */ + /* allocation size (len). We try to map at every page in the region*/ + /* until we get one that succeeds.*/ + for(addr = beg; addr + len <= end; addr += inc) + { + result = map_region((void*) addr, len, fd); + if(result) + { + /* Success doesn't necessarily mean it actually mapped at the hinted + * address. Return if it's in range, else unmap and try again. */ + if((Address) result >= beg && (Address) result + len <= end) + return (Address) result; + unmap_region(result, len); + } + } + return (Address) NULL; +} + +void* +DYNINSTos_malloc(size_t nbytes, void* lo_addr, void* hi_addr) +{ + char* heap; + size_t size = nbytes; + heapList_t* node = NULL; + /* initialize page size */ + if(psize == -1) psize = getpagesize(); + + /* buffer size must be aligned */ + if(size % DYNINSTheap_align != 0) + { + return ((void*) -1); + } + + /* use malloc() if appropriate */ + if(DYNINSTheap_useMalloc(lo_addr, hi_addr)) + { + char* ret_heap; + int size_heap = size + DYNINSTheap_align + sizeof(heapList_t); + heap = malloc(size_heap); + if(heap == NULL) + { +#ifdef DEBUG + fprintf(stderr, "Failed to MALLOC\n"); +#endif + return NULL; + } + ret_heap = (char*) heap_alignUp((Address) heap, DYNINSTheap_align); + + /* malloc buffer must meet range constraints */ + if(ret_heap < (char*) lo_addr || ret_heap + size - 1 > (char*) hi_addr) + { + free(heap); +#ifdef DEBUG + fprintf(stderr, "MALLOC'd area fails range constraints\n"); +#endif + return NULL; + } + + /* define new heap */ + node = (heapList_t*) (ret_heap + size); + node->heap.ret_addr = (void*) ret_heap; + node->heap.addr = heap; + node->heap.len = size_heap; + node->heap.type = HEAP_TYPE_MALLOC; + } + else + { /* use mmap() for allocation */ + Address lo = heap_alignUp((Address) lo_addr, psize); + Address hi = (Address) hi_addr; + heap = (char*) trymmap(size + sizeof(struct heapList_t), lo, hi, psize, -1); + if(!heap) return NULL; + node = (heapList_t*) (heap + size); + + /* define new heap */ + node->heap.addr = heap; + node->heap.ret_addr = heap; + node->heap.len = size + sizeof(struct heapList_t); + node->heap.type = HEAP_TYPE_MMAP; + } + + /* insert new heap into heap list */ + node->prev = NULL; + node->next = Heaps; + if(Heaps) Heaps->prev = node; + Heaps = node; +#ifdef DEBUG + fprintf(stderr, "new heap at %lx, size %lx\n", node->heap.ret_addr, node->heap.len); +#endif + return node->heap.ret_addr; +} + +int +DYNINSTos_free(void* buf) +{ + int ret = 0; + heapList_t* t; + /* + fprintf(stderr, "*** DYNINSTos_free(0x%08x)\n", buf); + */ + for(t = Heaps; t != NULL; t = t->next) + { + /* lookup heap by (returned) address */ + heap_t* heap = &t->heap; + if(heap->ret_addr != buf) continue; + + /* remove heap from list */ + if(t->next) t->next->prev = t->prev; + if(t->prev) t->prev->next = t->next; + if(Heaps == t) Heaps = t->next; + + /* deallocate heap */ + switch(heap->type) + { + case HEAP_TYPE_MMAP: + if(!unmap_region(heap->addr, heap->len)) + { + perror("DYNINSTos_free(munmap)"); + ret = -1; + } + break; + case HEAP_TYPE_MALLOC: free(heap->addr); break; + default: + fprintf(stderr, "DYNINSTos_free(): unknown inferior heap type\n"); + ret = -1; + break; + } + + break; + } + + return ret; +} diff --git a/source/lib/omnitrace-rt/src/RTheap.h b/source/lib/omnitrace-rt/src/RTheap.h new file mode 100644 index 000000000..d8ea26434 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTheap.h @@ -0,0 +1,83 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* $Id: RTheap.h,v 1.10 2007/01/18 07:53:56 jaw Exp $ */ + +#ifndef _RT_HEAP_H +#define _RT_HEAP_H + +#include "h/dyninstAPI_RT.h" /* RT_Boolean, Address */ + +#if defined(os_linux) || defined(os_freebsd) + +/* LINUX */ +typedef struct +{ + Address pr_vaddr; + unsigned long pr_size; +} dyninstmm_t; + +#elif defined(os_windows) +typedef struct +{ + Address pr_vaddr; + unsigned long pr_size; +} dyninstmm_t; + +#else +# error Dynamic heaps are not implemented on this platform +#endif + +/* + * platform-specific variables + */ + +extern int DYNINSTheap_align; +extern Address DYNINSTheap_loAddr; +extern Address DYNINSTheap_hiAddr; +extern int DYNINSTheap_mmapFlags; + +/* + * platform-specific functions + */ + +RT_Boolean +DYNINSTheap_useMalloc(void* lo, void* hi); +int +DYNINSTheap_mmapFdOpen(); +void +DYNINSTheap_mmapFdClose(int fd); +int +DYNINSTheap_getMemoryMap(unsigned*, dyninstmm_t** mmap); + +int +DYNINSTgetMemoryMap(unsigned* nump, dyninstmm_t** mapp); + +#endif /* _RT_HEAP_H */ diff --git a/source/lib/omnitrace-rt/src/RTlinux.c b/source/lib/omnitrace-rt/src/RTlinux.c new file mode 100644 index 000000000..0d4be4576 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTlinux.c @@ -0,0 +1,829 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/************************************************************************ + * $Id: RTlinux.c,v 1.54 2008/04/11 23:30:44 legendre Exp $ + * RTlinux.c: mutatee-side library function specific to Linux + ************************************************************************/ + +#include "h/dyninstAPI_RT.h" +#include "src/RTcommon.h" +#include "src/RTthread.h" +#include +#include +#include +#include + +#if !defined(DYNINST_RT_STATIC_LIB) +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(DYNINST_RT_STATIC_LIB) +/* + * The weak symbol here removes the dependence of the static version of this + * library on pthread_self. If pthread_self is available, then it will be + * linked. Otherwise, the linker will ignore it. + */ +# pragma weak pthread_self +extern pthread_t +pthread_self(void); +#else +# include +#endif + +extern double DYNINSTstaticHeap_512K_lowmemHeap_1[]; +extern double DYNINSTstaticHeap_16M_anyHeap_1[]; +extern unsigned long sizeOfLowMemHeap1; +extern unsigned long sizeOfAnyHeap1; + +static struct trap_mapping_header* +getStaticTrapMap(unsigned long addr); + +#if defined(arch_power) && defined(arch_64bit) && defined(os_linux) +unsigned long DYNINSTlinkSave; +unsigned long DYNINSTtocSave; +#endif + +/************************************************************************ + * void DYNINSTbreakPoint(void) + * + * stop oneself. + ************************************************************************/ + +#ifndef SYS_tkill +# define SYS_tkill 238 +#endif + +int +t_kill(int pid, int sig) +{ + static int has_tkill = 1; + long int result = 0; + if(has_tkill) + { + result = syscall(SYS_tkill, pid, sig); + if(result == -1 && errno == ENOSYS) + { + has_tkill = 0; + } + } + if(!has_tkill) + { + result = kill(pid, sig); + } + + return (result == 0); +} + +void +DYNINSTbreakPoint() +{ + if(DYNINSTstaticMode) return; + // Call into a funtion that contains a + // trap instruction. + DYNINSTtrapFunction(); +} + +static int failed_breakpoint = 0; +void +uncaught_breakpoint(int sig) +{ + (void) sig; /* unused parameter */ + failed_breakpoint = 1; +} + +void +DYNINSTsafeBreakPoint() +{ + if(DYNINSTstaticMode) return; + + DYNINST_break_point_event = 2; /* Not the same as above */ + // while (DYNINST_break_point_event) + kill(dyn_lwp_self(), SIGSTOP); +} + +void +mark_heaps_exec() +{ + /* Grab the page size, to align the heap pointer. */ + long int pageSize = sysconf(_SC_PAGESIZE); + if(pageSize == 0 || pageSize == -1) + { + fprintf(stderr, "*** Failed to obtain page size, guessing 16K.\n"); + perror("mark_heaps_exec"); + pageSize = 1024 * 16; + } /* end pageSize initialization */ + + /* Align the heap pointer. */ + unsigned long int alignedHeapPointer = + (unsigned long int) DYNINSTstaticHeap_16M_anyHeap_1; + alignedHeapPointer = (alignedHeapPointer) & ~(pageSize - 1); + unsigned long int adjustedSize = (unsigned long int) DYNINSTstaticHeap_16M_anyHeap_1 - + alignedHeapPointer + sizeOfAnyHeap1; + + /* Make the heap's page executable. */ + int result = mprotect((void*) alignedHeapPointer, (size_t) adjustedSize, + PROT_READ | PROT_WRITE | PROT_EXEC); + if(result != 0) + { + fprintf(stderr, + "%s[%d]: Couldn't make DYNINSTstaticHeap_16M_anyHeap_1 executable!\n", + __FILE__, __LINE__); + perror("mark_heaps_exec"); + } + RTprintf("*** Marked memory from 0x%lx to 0x%lx executable.\n", alignedHeapPointer, + alignedHeapPointer + adjustedSize); + + /* Mark _both_ heaps executable. */ + alignedHeapPointer = (unsigned long int) DYNINSTstaticHeap_512K_lowmemHeap_1; + alignedHeapPointer = (alignedHeapPointer) & ~(pageSize - 1); + adjustedSize = (unsigned long int) DYNINSTstaticHeap_512K_lowmemHeap_1 - + alignedHeapPointer + sizeOfLowMemHeap1; + + /* Make the heap's page executable. */ + result = mprotect((void*) alignedHeapPointer, (size_t) adjustedSize, + PROT_READ | PROT_WRITE | PROT_EXEC); + if(result != 0) + { + fprintf(stderr, + "%s[%d]: Couldn't make DYNINSTstaticHeap_512K_lowmemHeap_1 executable!\n", + __FILE__, __LINE__); + perror("mark_heaps_exec"); + } + RTprintf("*** Marked memory from 0x%lx to 0x%lx executable.\n", alignedHeapPointer, + alignedHeapPointer + adjustedSize); +} /* end mark_heaps_exec() */ + +/************************************************************************ + * void DYNINSTos_init(void) + * + * OS initialization function + ************************************************************************/ +int DYNINST_sysEntry; + +#if !defined(DYNINST_RT_STATIC_LIB) +/* + * For now, removing dependence of static version of this library + * on libdl. + */ +typedef struct dlopen_args +{ + const char* libname; + int mode; + void* result; + void* caller; +} dlopen_args_t; + +void* (*DYNINST_do_dlopen)(dlopen_args_t*) = NULL; + +static int +get_dlopen_error() +{ + char* err_str; + err_str = dlerror(); + if(err_str) + { + strncpy(gLoadLibraryErrorString, err_str, (size_t) ERROR_STRING_LENGTH); + return 1; + } + else + { + sprintf(gLoadLibraryErrorString, "unknown error with dlopen"); + return 0; + } + return 0; +} + +int +DYNINSTloadLibrary(char* libname) +{ + void* res; + gLoadLibraryErrorString[0] = '\0'; + res = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL); + if(res) + { + return 1; + } + + get_dlopen_error(); +# if defined(arch_x86) + /* dlopen on recent glibcs has a "security check" so that + only registered modules can call it. Unfortunately, progs + that don't include libdl break this check, so that we + can only call _dl_open (the dlopen worker function) from + within glibc. We do this by calling do_dlopen + We fool this check by calling an addr written by the + mutator */ + if(strstr(gLoadLibraryErrorString, "invalid caller") != NULL && + DYNINST_do_dlopen != NULL) + { + dlopen_args_t args; + args.libname = libname; + args.mode = RTLD_NOW | RTLD_GLOBAL; + args.result = 0; + args.caller = (void*) DYNINST_do_dlopen; + // There's a do_dlopen function in glibc. However, it's _not_ + // exported; thus, getting the address is a bit of a pain. + + (*DYNINST_do_dlopen)(&args); + // Duplicate the above + if(args.result != NULL) + { + return 1; + } + else + get_dlopen_error(); + } +# endif + return 0; +} +#endif + +// Define this value so that we can compile on a system that doesn't have +// gettid and still run on one that does. +#if !defined(SYS_gettid) + +# if defined(arch_x86) +# define SYS_gettid 224 +# elif defined(arch_x86_64) +# define SYS_gettid 186 +# endif + +#endif + +int +dyn_lwp_self() +{ + static int gettid_not_valid = 0; + int result; + + if(gettid_not_valid) return getpid(); + + result = syscall((long int) SYS_gettid); + if(result == -1 && errno == ENOSYS) + { + gettid_not_valid = 1; + return getpid(); + } + return result; +} + +int +dyn_pid_self() +{ + return getpid(); +} + +dyntid_t (*DYNINST_pthread_self)(void); + +dyntid_t +dyn_pthread_self() +{ + dyntid_t me; + if(DYNINSTstaticMode) + { +#if defined(DYNINST_RT_STATIC_LIB) + /* This special case is necessary because the static + * version of libc doesn't define a version of pthread_self + * unlike the shared version of the library. + */ + if(!pthread_self) + { + return (dyntid_t) DYNINST_SINGLETHREADED; + } +#endif + return (dyntid_t) pthread_self(); + } + if(!DYNINST_pthread_self) + { + return (dyntid_t) DYNINST_SINGLETHREADED; + } + me = (*DYNINST_pthread_self)(); + return (dyntid_t) me; +} + +/* + We reserve index 0 for the initial thread. This value varies by + platform but is always constant for that platform. Wrap that + platform-ness here. +*/ +int +DYNINST_am_initial_thread(dyntid_t tid) +{ + (void) tid; /* unused parameter */ + if(dyn_lwp_self() == getpid()) + { + return 1; + } + return 0; +} /* end DYNINST_am_initial_thread() */ + +#if defined(cap_mutatee_traps) + +# include + +// Register numbers experimentally verified + +# if defined(arch_x86) +# define UC_PC(x) x->uc_mcontext.gregs[14] +# elif defined(arch_x86_64) +# if defined(MUTATEE_32) +# define UC_PC(x) x->uc_mcontext.gregs[14] +# else // 64-bit +# define UC_PC(x) x->uc_mcontext.gregs[16] +# endif // amd-64 +# elif defined(arch_power) +# if defined(arch_64bit) +# define UC_PC(x) x->uc_mcontext.regs->nip +# else // 32-bit +# define UC_PC(x) x->uc_mcontext.uc_regs->gregs[32] +# endif // power +# elif defined(arch_aarch64) +//#warning "UC_PC: in aarch64, pc is not directly accessable." +// aarch64 pc is not one of 31 GPRs, but an independent reg +# define UC_PC(x) x->uc_mcontext.pc +# endif // UC_PC + +extern volatile unsigned long dyninstTrapTableUsed; +extern volatile unsigned long dyninstTrapTableVersion; +extern volatile trapMapping_t* dyninstTrapTable; +extern volatile unsigned long dyninstTrapTableIsSorted; + +/** + * This comment is now obsolete, left for historic purposes + * + * Called by the SIGTRAP handler, dyninstTrapHandler. This function is + * closly intwined with dyninstTrapHandler, don't modify one without + * understanding the other. + * + * This function sets up the calling context that was passed to the + * SIGTRAP handler so that control will be redirected to our instrumentation + * when we do the setcontext call. + * + * There are a couple things that make this more difficult than it should be: + * 1. The OS provided calling context is similar to the GLIBC calling context, + * but not compatible. We'll create a new GLIBC compatible context and + * copy the possibly stomped registers from the OS context into it. The + * incompatiblities seem to deal with FP and other special purpose registers. + * 2. setcontext doesn't restore the flags register. Thus dyninstTrapHandler + * will save the flags register first thing and pass us its value in the + * flags parameter. We'll then push the instrumentation entry and flags + * onto the context's stack. Instead of transfering control straight to the + * instrumentation, we'll actually go back to dyninstTrapHandler, which will + * do a popf/ret to restore flags and go to instrumentation. The 'retPoint' + * parameter is the address in dyninstTrapHandler the popf/ret can be found. + **/ + +void +dyninstTrapHandler(int sig, siginfo_t* sg, ucontext_t* context) +{ + void* orig_ip; + void* trap_to; + (void) sig; /* unused parameter */ + (void) sg; /* unused parameter */ + + orig_ip = (void*) UC_PC(context); + assert(orig_ip); + // Find the new IP we're going to and substitute. Leave everything else untouched. + if(DYNINSTstaticMode) + { + unsigned long zero = 0; + unsigned long one = 1; + struct trap_mapping_header* hdr = getStaticTrapMap((unsigned long) orig_ip); + assert(hdr); + volatile trapMapping_t* mapping = &(hdr->traps[0]); + trap_to = dyninstTrapTranslate(orig_ip, (unsigned long*) &hdr->num_entries, &zero, + &mapping, &one); + } + else + { + trap_to = + dyninstTrapTranslate(orig_ip, &dyninstTrapTableUsed, &dyninstTrapTableVersion, + &dyninstTrapTable, &dyninstTrapTableIsSorted); + } + UC_PC(context) = (long) trap_to; +} + +# if defined(cap_binary_rewriter) + +extern struct r_debug _r_debug; +// Remove because of an issue with glibc-2.35+ switching to namespaces. +// Previously there was a dynamic relocation against _r_debug in the loader which +// picked up the interposed definition, but glibc now uses a direct internal hidden +// symbol reference and thus no longer updates the interposed object. +// +// DLLEXPORT struct r_debug _r_debug __attribute__((weak)); + +/* Verify that the r_debug variable is visible */ +void +r_debugCheck() +{ +# define LIBC_VERSION_BUFFER_LENGTH 1024 + char _version_s[LIBC_VERSION_BUFFER_LENGTH]; + snprintf(_version_s, LIBC_VERSION_BUFFER_LENGTH, "%s", gnu_get_libc_version()); + unsigned long _version[2]; + unsigned long idx = 0; + char* token = strtok(_version_s, "."); + while(token != NULL && idx < 2) + { + _version[idx++] = atol(token); + token = strtok(NULL, "."); + } + if(_version[0] < 2 || (_version[0] == 2 && _version[1] < 35)) + { + assert(_r_debug.r_map); + } +# undef LIBC_VERSION_BUFFER_LENGTH +} + +# define NUM_LIBRARIES 512 // Important, max number of rewritten libraries + +# define WORD_SIZE (8 * sizeof(unsigned)) +# define NUM_LIBRARIES_BITMASK_SIZE (1 + NUM_LIBRARIES / WORD_SIZE) +struct trap_mapping_header* all_headers[NUM_LIBRARIES]; + +# if !defined(arch_x86_64) || defined(MUTATEE_32) +typedef Elf32_Dyn ElfX_Dyn; +# else +typedef Elf64_Dyn ElfX_Dyn; +# endif + +struct trap_mapping_header* +getStaticTrapMap(unsigned long addr); + +# if !defined(arch_aarch64) +static unsigned all_headers_current[NUM_LIBRARIES_BITMASK_SIZE]; +static unsigned all_headers_last[NUM_LIBRARIES_BITMASK_SIZE]; + +static int +parse_libs(); +static int +parse_link_map(struct link_map* l); +static void +clear_unloaded_libs(); + +static void +set_bit(unsigned* bit_mask, int bit, char value); +// static char get_bit(unsigned *bit_mask, int bit); +static void +clear_bitmask(unsigned* bit_mask); +static unsigned +get_next_free_bitmask(unsigned* bit_mask, int last_pos); +static unsigned +get_next_set_bitmask(unsigned* bit_mask, int last_pos); + +static tc_lock_t trap_mapping_lock; +# endif + +static struct trap_mapping_header* +getStaticTrapMap(unsigned long addr) +{ +# if !defined(arch_aarch64) + struct trap_mapping_header* header; + int i; + + tc_lock_lock(&trap_mapping_lock); + parse_libs(); + + i = -1; + for(;;) + { + i = get_next_set_bitmask(all_headers_current, i); + assert(i >= 0 && i <= NUM_LIBRARIES); + if(i == NUM_LIBRARIES) + { + header = NULL; + rtdebug_printf("%s[%d]: getStaticTrapMap: returning NULL\n", __FILE__, + __LINE__); + goto done; + } + header = all_headers[i]; + if(addr >= header->low_entry && addr <= header->high_entry) + { + goto done; + } + } +done: + tc_lock_unlock(&trap_mapping_lock); + return header; +# else + // Silence compiler warnings + (void) addr; + assert(0); + return NULL; +# endif +} + +# if !defined(arch_aarch64) +static int +parse_libs() +{ + struct link_map* l_current; + + l_current = _r_debug.r_map; + if(!l_current) + { + rtdebug_printf("%s[%d]: parse_libs: _r_debug.r_map was not set\n", __FILE__, + __LINE__); + return -1; + } + + clear_bitmask(all_headers_current); + while(l_current) + { + parse_link_map(l_current); + l_current = l_current->l_next; + } + clear_unloaded_libs(); + + return 0; +} + +// parse_link_map return values +# define PARSED 0 +# define NOT_REWRITTEN 1 +# define ALREADY_PARSED 2 +# define ERROR_INTERNAL -1 +# define ERROR_FULL -2 +static int +parse_link_map(struct link_map* l) +{ + ElfX_Dyn* dynamic_ptr; + struct trap_mapping_header* header; + unsigned int i, new_pos; + + dynamic_ptr = (ElfX_Dyn*) l->l_ld; + if(!dynamic_ptr) return -1; + + assert(sizeof(dynamic_ptr->d_un.d_ptr) == sizeof(void*)); + for(; dynamic_ptr->d_tag != DT_NULL && dynamic_ptr->d_tag != DT_DYNINST; + dynamic_ptr++) + ; + if(dynamic_ptr->d_tag == DT_NULL) + { + return NOT_REWRITTEN; + } + + header = (struct trap_mapping_header*) (dynamic_ptr->d_un.d_val + l->l_addr); + + if(header->signature != TRAP_HEADER_SIG) return ERROR_INTERNAL; + if(header->pos != -1) + { + set_bit(all_headers_current, header->pos, 1); + assert(all_headers[header->pos] == header); + return ALREADY_PARSED; + } + + for(i = 0; i < header->num_entries; i++) + { + header->traps[i].source = + (void*) (((unsigned long) header->traps[i].source) + l->l_addr); + header->traps[i].target = + (void*) (((unsigned long) header->traps[i].target) + l->l_addr); + if(!header->low_entry || + header->low_entry > (unsigned long) header->traps[i].source) + header->low_entry = (unsigned long) header->traps[i].source; + if(!header->high_entry || + header->high_entry < (unsigned long) header->traps[i].source) + header->high_entry = (unsigned long) header->traps[i].source; + } + + new_pos = get_next_free_bitmask(all_headers_last, -1); + assert(new_pos < NUM_LIBRARIES); + if(new_pos == NUM_LIBRARIES) return ERROR_FULL; + + header->pos = new_pos; + all_headers[new_pos] = header; + set_bit(all_headers_current, new_pos, 1); + set_bit(all_headers_last, new_pos, 1); + + return PARSED; +} + +static void +clear_unloaded_libs() +{ + unsigned i; + for(i = 0; i < NUM_LIBRARIES_BITMASK_SIZE; i++) + { + all_headers_last[i] = all_headers_current[i]; + } +} + +static void +set_bit(unsigned* bit_mask, int bit, char value) +{ + assert(bit < NUM_LIBRARIES); + unsigned* word = bit_mask + bit / WORD_SIZE; + unsigned shift = bit % WORD_SIZE; + if(value) + { + *word |= (1 << shift); + } + else + { + *word &= ~(1 << shift); + } +} + +// Wasn't actually needed +/* +static char get_bit(unsigned *bit_mask, int bit) { + assert(bit < NUM_LIBRARIES); + unsigned *word = bit_mask + bit / WORD_SIZE; + unsigned shift = bit % WORD_SIZE; + return (*word & (1 << shift)) ? 1 : 0; +} +*/ + +static void +clear_bitmask(unsigned* bit_mask) +{ + unsigned i; + for(i = 0; i < NUM_LIBRARIES_BITMASK_SIZE; i++) + { + bit_mask[i] = 0; + } +} + +static unsigned +get_next_free_bitmask(unsigned* bit_mask, int last_pos) +{ + unsigned i, j; + j = last_pos + 1; + i = j / WORD_SIZE; + for(; j < NUM_LIBRARIES; i++) + { + if(bit_mask[i] == (unsigned) -1) + { + j += WORD_SIZE; + continue; + } + for(;;) + { + if(!((1 << (j % WORD_SIZE) & bit_mask[i]))) + { + return j; + } + j++; + if(j % WORD_SIZE == 0) + { + break; + } + } + } + return NUM_LIBRARIES; +} + +static unsigned +get_next_set_bitmask(unsigned* bit_mask, int last_pos) +{ + unsigned i, j; + j = last_pos + 1; + i = j / WORD_SIZE; + for(; j < NUM_LIBRARIES; i++) + { + if(bit_mask[i] == (unsigned) 0) + { + j += WORD_SIZE; + continue; + } + for(;;) + { + if((1 << (j % WORD_SIZE) & bit_mask[i])) + { + return j; + } + j++; + if(j % WORD_SIZE == 0) + { + break; + } + } + } + return NUM_LIBRARIES; +} +# endif + +# endif + +#endif /* cap_mutatee_traps */ + +#if defined(cap_binary_rewriter) && !defined(DYNINST_RT_STATIC_LIB) +/* For a static binary, all global constructors are combined in an undefined + * order. Also, DYNINSTBaseInit must be run after all global constructors have + * been run. Since the order of global constructors is undefined, DYNINSTBaseInit + * cannot be run as a constructor in static binaries. Instead, it is run from a + * special constructor handler that processes all the global constructors in + * the binary. Leaving this code in would create a global constructor for the + * function runDYNINSTBaseInit(). See DYNINSTglobal_ctors_handler. + */ +extern void +r_debugCheck(); +extern void +DYNINSTBaseInit(); +void +runDYNINSTBaseInit() __attribute__((constructor)); +void +runDYNINSTBaseInit() +{ + r_debugCheck(); + DYNINSTBaseInit(); +} +#endif + +/* +//Small program for finding the correct values to fill in pos_in_pthreadt +// above +#include +#include +#include +#include +#include + +#define gettid() syscall(SYS_gettid) + +pthread_attr_t attr; + +void *foo(void *f) { + pid_t pid, tid; + unsigned stack_addr; + unsigned best_stack = 0xffffffff; + int best_stack_pos = 0; + void *start_func; + int *p; + int i = 0; + pid = getpid(); + tid = gettid(); + start_func = foo; + //x86 only. + asm("movl %%ebp,%0" : "=r" (stack_addr)); + p = (int *) pthread_self(); + while (i < 1000) + { + if (*p == (unsigned) pid) + printf("pid @ %d\n", i); + if (*p == (unsigned) tid) + printf("lwp @ %d\n", i); + if (*p > stack_addr && *p < best_stack) + { + best_stack = *p; + best_stack_pos = i; + } + if (*p == (unsigned) start_func) + printf("func @ %d\n", i); + i += sizeof(int); + p++; + } + printf("stack @ %d\n", best_stack_pos); + return NULL; +} + +int main(int argc, char *argv[]) +{ + pthread_t t; + void *result; + pthread_attr_init(&attr); + pthread_create(&t, &attr, foo, NULL); + pthread_join(t, &result); + return 0; +} +*/ diff --git a/source/lib/omnitrace-rt/src/RTmemEmulator.c b/source/lib/omnitrace-rt/src/RTmemEmulator.c new file mode 100644 index 000000000..78c97be97 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTmemEmulator.c @@ -0,0 +1,205 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "h/dyninstAPI_RT.h" +#include "src/RTcommon.h" +#include +#include +#include +#include + +#if defined(__GNUC__) +# include +# define FAST_CALL __attribute__((fastcall)) +#elif defined(os_windows) +# define FAST_CALL __fastcall +#endif + +/* Code to assist in remapping memory operations that were affected + * by our instrumentation */ + +extern void +DYNINST_stopThread(void*, void*, void*, void*); + +#if _MSC_VER +struct MemoryMapper RTmemoryMapper = { 0, 0, 0, 0 }; +#else +struct MemoryMapper RTmemoryMapper = { 0, 0, 0, 0, { { 0 } } }; +#endif +extern FILE* stOut; + +//#define DEBUG_MEM_EM + +unsigned long +RTtranslateMemory(unsigned long input, unsigned long origAddr, unsigned long currAddr) +{ + /* Standard nonblocking synchronization construct */ + int index; + int min; + int max; + volatile int guard2; + (void) origAddr; /* unused parameter */ + (void) currAddr; /* unused parameter */ + + do + { + guard2 = RTmemoryMapper.guard2; + min = 0; + max = (RTmemoryMapper.size - 1); + do + { + index = min + ((max - min) / 2); + if(input >= RTmemoryMapper.elements[index].lo) + { + /* Either correct or too low */ + if(input < RTmemoryMapper.elements[index].hi) + { + break; + } + else + { + min = index + 1; + } + } + else + { + /* Too high */ + max = index - 1; + } + } while(min <= max); + } while(guard2 != RTmemoryMapper.guard1); + + if(min <= max) + { + if(RTmemoryMapper.elements[index].shift == -1) + { + return 0; + } + else + { + return input + RTmemoryMapper.elements[index].shift; + } + } + else + { + return input; + } + return 0; +} + +unsigned long +RTtranslateMemoryShift(unsigned long input, unsigned long origAddr, + unsigned long currAddr) +{ + /* Standard nonblocking synchronization construct */ + int index; + int min; + int max; + volatile int guard2; + (void) origAddr; /* unused parameter */ + (void) currAddr; /* unused parameter */ + + do + { + guard2 = RTmemoryMapper.guard2; + min = 0; + max = (RTmemoryMapper.size - 1); + do + { + index = min + ((max - min) / 2); + if(input >= RTmemoryMapper.elements[index].lo) + { + /* Either correct or too low */ + if(input < RTmemoryMapper.elements[index].hi) + { + break; + } + else + { + min = index + 1; + } + } + else + { + /* Too high */ + max = index - 1; + } + } while(min <= max); + } while(guard2 != RTmemoryMapper.guard1); + + if(min <= max) + { + if(RTmemoryMapper.elements[index].shift == -1) + { + fflush(stOut); + return -1 * input; + } + else + { + return RTmemoryMapper.elements[index].shift; + } + } + else + { + return 0; + } + return 0; +} + +int RTuntranslatedEntryCounter; +extern void +DYNINST_stopThread(void* pointAddr, void* callBackID, void* flags, void* calculation); + +void +RThandleShadow(void* direction, void* pointAddr, void* callbackID, void* flags, + void* calculation) +{ + (void) calculation; /* unused parameter */ + if((int) ((long) direction) == 1) + { + if(RTuntranslatedEntryCounter == 0) + { + // Entering a system call... + DYNINST_stopThread(pointAddr, callbackID, flags, (void*) 1); + } + RTuntranslatedEntryCounter++; + } + else + { + if(RTuntranslatedEntryCounter > 0) + { + RTuntranslatedEntryCounter--; + } + if(RTuntranslatedEntryCounter == 0) + { + DYNINST_stopThread(pointAddr, callbackID, flags, (void*) 0); + } + } +} diff --git a/source/lib/omnitrace-rt/src/RTposix.c b/source/lib/omnitrace-rt/src/RTposix.c new file mode 100644 index 000000000..f39b38047 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTposix.c @@ -0,0 +1,308 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/************************************************************************ + * $Id: RTposix.c,v 1.37 2008/04/11 23:30:45 legendre Exp $ + * RTposix.c: runtime instrumentation functions for generic posix. + ************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "h/dyninstAPI_RT.h" +#include "src/RTcommon.h" +#include "src/RTheap.h" + +#define SOCKLEN_T socklen_t + +#if !(defined(arch_power) && defined(os_linux)) +void +RTmutatedBinary_init() +{ + return; +} +#endif + +#if defined(__GNUC) || defined(__GNUC__) +# if defined(DYNINST_RT_STATIC_LIB) +/* + * In the static version of the library, constructors cannot be + * used to run code at initialization. See DYNINSTglobal_ctors_handler. + */ +void +libdyninstAPI_RT_init(void); +# else +void +libdyninstAPI_RT_init(void) __attribute__((constructor)); +# endif +#endif + +#if defined(cap_async_events) +struct passwd* passwd_info = NULL; +#endif + +void +libdyninstAPI_RT_init() +{ + static int initCalledOnce = 0; + + rtdebug_printf("%s[%d]: DYNINSTinit: welcome to libdyninstAPI_RT_init()\n", + __FILE__, __LINE__); + + if(initCalledOnce) return; + initCalledOnce++; + + DYNINSTinit(); + rtdebug_printf("%s[%d]: did DYNINSTinit\n", __FILE__, __LINE__); +} + +/************************************************************************ + * void DYNINSTasyncConnect(int pid) + * + * Connect to mutator's async handler thread. is pid of mutator + ************************************************************************/ + +static int async_socket = -1; +static int needToDisconnect = 0; +static char socket_path[255]; + +int +DYNINSTasyncConnect(int pid) +{ + if(DYNINSTstaticMode) return 0; +#if defined(cap_async_events) + int sock_fd; + struct sockaddr_un sadr; + int res; + int mutatee_pid; + uid_t euid; + + rtdebug_printf("%s[%d]: DYNINSTasyncConnnect: entry\n", __FILE__, __LINE__); + rtdebug_printf("%s[%d]: DYNINSTinit: before geteuid\n", __FILE__, __LINE__); + + euid = geteuid(); + passwd_info = getpwuid(euid); + assert(passwd_info); + + if(async_socket != -1) + { + fprintf(stderr, "%s[%d]: - DYNINSTasyncConnect already initialized\n", __FILE__, + __LINE__); + + rtdebug_printf("%s[%d]: DYNINSTasyncConnnect: already connected\n", __FILE__, + __LINE__); + return 0; + } + + rtdebug_printf("%s[%d]: DYNINSTasyncConnnect: before socket 2\n", __FILE__, + __LINE__); + mutatee_pid = getpid(); + + snprintf(socket_path, (size_t) 255, "%s/dyninstAsync.%s.%d.%d", P_tmpdir, + passwd_info->pw_name, pid, mutatee_pid); + + rtdebug_printf("%s[%d]: DYNINSTasyncConnnect: before socket: %s\n", __FILE__, + __LINE__, socket_path); + + errno = 0; + + sock_fd = socket(PF_UNIX, SOCK_STREAM, 0); + + if(sock_fd < 0) + { + fprintf(stderr, "%s[%d]: DYNINSTasyncConnect() socket(%s): %s\n", __FILE__, + __LINE__, socket_path, strerror(errno)); + abort(); + } + + rtdebug_printf("%s[%d]: DYNINSTasyncConnnect: after socket\n", __FILE__, __LINE__); + + sadr.sun_family = PF_UNIX; + strcpy(sadr.sun_path, socket_path); + + rtdebug_printf("%s[%d]: DYNINSTasyncConnnect: before connect\n", __FILE__, + __LINE__); + res = 0; + errno = 0; + + res = connect(sock_fd, (struct sockaddr*) &sadr, sizeof(sadr)); + + if(res < 0) + { + perror("DYNINSTasyncConnect() connect()"); + } + + rtdebug_printf( + "%s[%d]: DYNINSTasyncConnnect: after connect to %s, res = %d, -- %s\n", + __FILE__, __LINE__, socket_path, res, strerror(errno)); + + /* maybe need to do fcntl to set nonblocking writes on this fd */ + + if(async_socket == -1) + { + rtdebug_printf("%s[%d]: WARN: async socket has not been reset!!\n", __FILE__, + __LINE__); + } + + async_socket = sock_fd; + + needToDisconnect = 1; + + /* atexit(exit_func); */ + rtdebug_printf("%s[%d]: leaving DYNINSTasyncConnect\n", __FILE__, __LINE__); + return 1; +#else + fprintf(stderr, "%s[%d]: called DYNINSTasyncConect when async_events disabled\n", + __FILE__, __LINE__); + return 0; +#endif +} + +int +DYNINSTasyncDisconnect() +{ + if(DYNINSTstaticMode) return 0; + rtdebug_printf("%s[%d]: welcome to DYNINSTasyncDisconnect\n", __FILE__, __LINE__); + if(needToDisconnect) + { + close(async_socket); + needToDisconnect = 0; + } + async_socket = -1; + return 0; +} + +int +DYNINSTwriteEvent(void* ev, size_t sz) +{ + ssize_t res; + + if(DYNINSTstaticMode) return 0; + + rtdebug_printf("%s[%d]: welcome to DYNINSTwriteEvent: %zu bytes\n", __FILE__, + __LINE__, sz); + if(-1 == async_socket) + { + rtdebug_printf("%s[%d]: failed to DYNINSTwriteEvent, no socket\n", __FILE__, + __LINE__); + return -1; + } + +try_again: + res = write(async_socket, ev, sz); + if(-1 == res) + { + if(errno == EINTR || errno == EAGAIN) + goto try_again; + else + { + perror("write"); + return -1; + } + } + if((size_t) res != sz) + { + /* maybe we need logic to handle partial writes? */ + fprintf(stderr, "%s[%d]: partial ? write error, %zd bytes, should be %zu\n", + __FILE__, __LINE__, res, sz); + return -1; + } + return 0; +} + +// Important note: addr will be zero in two cases here +// One is the case where we're doing a constrained low mmap, in which case MAP_32BIT +// is precisely correct. The other is the case where our +// constrained map attempts have failed, and we're doing a scan for first available +// mappable page. In that case, MAP_32BIT does no harm. +void* +map_region(void* addr, int len, int fd) +{ + void* result; + int flags = DYNINSTheap_mmapFlags; +#if defined(arch_x86_64) + if(addr == 0) flags |= MAP_32BIT; +#endif + result = mmap(addr, len, PROT_READ | PROT_WRITE | PROT_EXEC, flags, fd, 0); + if(result == MAP_FAILED) return NULL; + return result; +} + +int +unmap_region(void* addr, int len) +{ + int result; + result = munmap(addr, len); + if(result == -1) return 0; + return 1; +} + +#if defined(cap_mutatee_traps) +extern void +dyninstTrapHandler(int sig, siginfo_t* info, void* context); + +int +DYNINSTinitializeTrapHandler() +{ + int result; + struct sigaction new_handler; + int signo = SIGTRAP; + + // If environment variable DYNINST_SIGNAL_TRAMPOLINE_SIGILL is set, + // we use SIGILL as the signal for signal trampoline. + // The mutatee has to be generated with DYNINST_SIGNAL_TRAMPOLINE_SIGILL set + // so that the mutator will generates illegal instructions as trampolines. + if(getenv("DYNINST_SIGNAL_TRAMPOLINE_SIGILL")) + { + signo = SIGILL; + } + + new_handler.sa_sigaction = dyninstTrapHandler; + // new_handler.sa_restorer = NULL; obsolete + sigemptyset(&new_handler.sa_mask); + new_handler.sa_flags = SA_SIGINFO | SA_NODEFER; + + result = sigaction(signo, &new_handler, NULL); + return (result == 0) ? 1 /*Success*/ : 0 /*Fail*/; +} + +#endif diff --git a/source/lib/omnitrace-rt/src/RTsigill-x86.S b/source/lib/omnitrace-rt/src/RTsigill-x86.S new file mode 100644 index 000000000..a57b18ac0 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTsigill-x86.S @@ -0,0 +1,64 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + DYNINSTsigill: + + DYNINSTsigill executes an illegal instruction, causing SIGILL to be + sent to the calling process. It is only needed for + detach-on-the-fly, where detached mutatees stop to wait for the + mutator or paradynd to reattach by sending themselves SIGILL. + + A detached mutatee that stops itself with SIGSTOP will not be + noticed by the mutator or paradynd. It must send SIGILL to be + noticed. + + There are two ways to send SIGILL to yourself: call kill() or + execute an illegal instruction. + + We chose to use illegal instructions. The SIGILL handler has a + simpler implementation if SIGILL is caused by an illegal + instruction. We do not use kill() to send SIGILL. + + The test suite calls this function through the dynamic loader to + avoid duplication of code in the test suite and additional makefile + complexity. + + 3000 bytes of source code for 3 bytes of object code. +*/ + + .text + .globl DYNINSTsigill + +DYNINSTsigill: + ud2 + ret + +.section .note.GNU-stack,"",@progbits diff --git a/source/lib/omnitrace-rt/src/RTsignal-x86.S b/source/lib/omnitrace-rt/src/RTsignal-x86.S new file mode 100644 index 000000000..d67783286 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTsignal-x86.S @@ -0,0 +1,30 @@ +.globl dyninstTrapHandler2 +.type dyninstTrapHandler2, @function +dyninstTrapHandler2: + pushf + pushl %ebp + movl %esp, %ebp + call __i686.get_pc_thunk.bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx + call .Lnext_insn +.Lnext_insn: + addl $.Lret_point-.Lnext_insn,(%esp) + pushl 0x4(%ebp) + pushl 0x14(%ebp) + call dyninstSetupContext@PLT + movl $0x0, 0x0 +.Lret_point: + popf + ret + +#if defined(DYNINST_RT_STATIC_LIB) +__i686.get_pc_thunk.bx: + mov (%esp), %ebx + ret + +__i686.get_pc_thunk.cx: + mov (%esp), %ecx + ret +#endif + +.section .note.GNU-stack,"",@progbits diff --git a/source/lib/omnitrace-rt/src/RTsignal-x86_64.S b/source/lib/omnitrace-rt/src/RTsignal-x86_64.S new file mode 100644 index 000000000..bf08369c5 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTsignal-x86_64.S @@ -0,0 +1,21 @@ +.globl dyninstTrapHandler2 +.type dyninstTrapHandler2, @function +dyninstTrapHandler2: + pushfq + pushq %rbp + mov %rsp, %rbp + mov %rdx, %rdi + leaq 0(%rip), %rdx +.Lnext_insn: + addq $.Lret_point - .Lnext_insn, %rdx + mov 0x8(%rbp), %rsi + call dyninstSetupContext@PLT + movl $0x0, 0x0 +.Lret_point: + pop %rax + pop %r10 + pop %r11 + popfq + retq + +.section .note.GNU-stack,"",@progbits diff --git a/source/lib/omnitrace-rt/src/RTsignal.c b/source/lib/omnitrace-rt/src/RTsignal.c new file mode 100644 index 000000000..2ce0fc1da --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTsignal.c @@ -0,0 +1,66 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/************************************************************************ + * RTsignal.c: C-language signal handling code + ************************************************************************/ + +#include +#include + +#include "h/dyninstAPI_RT.h" + +typedef void (*dynsighandler_t)(int); + +DLLEXPORT int +dyn_sigaction(int signum, const struct sigaction* act, struct sigaction* oldact) +{ + if(signum != SIGTRAP) + { + return sigaction(signum, act, oldact); + } + else + { + return 0; + } +} + +DLLEXPORT dynsighandler_t +dyn_signal(int signum, dynsighandler_t handler) +{ + if(signum != SIGTRAP) + { + return signal(signum, handler); + } + else + { + return SIG_DFL; + } +} diff --git a/source/lib/omnitrace-rt/src/RTspace-smallmem.s b/source/lib/omnitrace-rt/src/RTspace-smallmem.s new file mode 100644 index 000000000..684eef2d5 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTspace-smallmem.s @@ -0,0 +1,18 @@ +.file "RTspace.s" + +.globl DYNINSTstaticHeap_8K_lowmemHeap_1 +.type DYNINSTstaticHeap_8K_lowmemHeap_1, @object +.size DYNINSTstaticHeap_8K_lowmemHeap_1, 8192 + +.globl DYNINSTstaticHeap_32K_anyHeap_1 +.type DYNINSTstaticHeap_32K_anyHeap_1, @object +.size DYNINSTstaticHeap_32K_anyHeap_1, 32768 + +.section .dyninst_heap,"awx",@nobits +.align 16 +DYNINSTstaticHeap_8K_lowmemHeap_1: + .skip 8192 +DYNINSTstaticHeap_32K_anyHeap_1: + .skip 32768 + +.section .note.GNU-stack,"",@progbits diff --git a/source/lib/omnitrace-rt/src/RTspace.S b/source/lib/omnitrace-rt/src/RTspace.S new file mode 100644 index 000000000..39ca52220 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTspace.S @@ -0,0 +1,18 @@ +.file "RTspace.s" + +.globl DYNINSTstaticHeap_512K_lowmemHeap_1 +.type DYNINSTstaticHeap_512K_lowmemHeap_1, @object +.size DYNINSTstaticHeap_512K_lowmemHeap_1, 524288 + +.globl DYNINSTstaticHeap_16M_anyHeap_1 +.type DYNINSTstaticHeap_16M_anyHeap_1, @object +.size DYNINSTstaticHeap_16M_anyHeap_1, 16777216 + +.section .dyninst_heap,"aw",@nobits +.align 16 +DYNINSTstaticHeap_512K_lowmemHeap_1: + .skip 524288 +DYNINSTstaticHeap_16M_anyHeap_1: + .skip 16777216 + +.section .note.GNU-stack,"",@progbits diff --git a/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors-aarch64.c b/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors-aarch64.c new file mode 100644 index 000000000..b915ae376 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors-aarch64.c @@ -0,0 +1,82 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +//#warning "This file is not implemented yet!" + +#if defined(DYNINST_RT_STATIC_LIB) + +# include + +void (*DYNINSTctors_addr)(void); +void (*DYNINSTdtors_addr)(void); + +//#if defined(MUTATEE64) +// static const unsigned long long CTOR_LIST_TERM = 0x0000000000000000ULL; +// static const unsigned long long CTOR_LIST_START = 0xffffffffffffffffULL; +// static const unsigned long long DTOR_LIST_TERM = 0x0000000000000000ULL; +// static const unsigned long long DTOR_LIST_START = 0xffffffffffffffffULL; +//#else +/* +static const unsigned CTOR_LIST_TERM = 0x00000000; +static const unsigned CTOR_LIST_START = 0xffffffff; +static const unsigned DTOR_LIST_TERM = 0x00000000; +static const unsigned DTOR_LIST_START = 0xffffffff; +*/ +//#endif + +extern void +DYNINSTBaseInit(); + +/* + * When rewritting a static binary, .ctors and .dtors sections of + * instrumentation code needs to be combined with the existing .ctors + * and .dtors sections of the static binary. + * + * The following functions process the .ctors and .dtors sections + * that have been rewritten. The rewriter will relocate the + * address of DYNINSTctors_addr and DYNINSTdtors_addr to point to + * new .ctors and .dtors sections. + */ + +void +DYNINSTglobal_ctors_handler() +{ + //#warning "This function is not implemented yet!" + assert(0); +} + +void +DYNINSTglobal_dtors_handler() +{ + //#warning "This function is not implemented yet!" + assert(0); +} + +#endif diff --git a/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors-ppc32.c b/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors-ppc32.c new file mode 100644 index 000000000..8bf192069 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors-ppc32.c @@ -0,0 +1,102 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if defined(DYNINST_RT_STATIC_LIB) +void (*DYNINSTctors_addr)(void); +void (*DYNINSTdtors_addr)(void); + +# if defined(MUTATEE64) +static const unsigned long long CTOR_LIST_TERM = 0x0000000000000000ULL; +static const unsigned long long CTOR_LIST_START = 0xffffffffffffffffULL; +static const unsigned long long DTOR_LIST_TERM = 0x0000000000000000ULL; +static const unsigned long long DTOR_LIST_START = 0xffffffffffffffffULL; +# else +static const unsigned CTOR_LIST_TERM = 0x00000000; +static const unsigned CTOR_LIST_START = 0xffffffff; +static const unsigned DTOR_LIST_TERM = 0x00000000; +static const unsigned DTOR_LIST_START = 0xffffffff; +# endif + +extern void +DYNINSTBaseInit(); + +/* + * When rewritting a static binary, .ctors and .dtors sections of + * instrumentation code needs to be combined with the existing .ctors + * and .dtors sections of the static binary. + * + * The following functions process the .ctors and .dtors sections + * that have been rewritten. The rewriter will relocate the + * address of DYNINSTctors_addr and DYNINSTdtors_addr to point to + * new .ctors and .dtors sections. + */ + +void +DYNINSTglobal_ctors_handler() +{ + void (**ctors_array)(void) = &DYNINSTctors_addr; + + // Find end of function pointer list + void (**tmp_ptr)(void) = ctors_array; + unsigned size = 0; + while(*tmp_ptr != ((void (*)(void)) CTOR_LIST_TERM)) + { + size++; + tmp_ptr++; + } + + // Constructors are called in the reverse order that they are listed + tmp_ptr = &ctors_array[size - 1]; // skip list end + while(*tmp_ptr != ((void (*)(void)) CTOR_LIST_START)) + { + (*tmp_ptr)(); + tmp_ptr--; + } + + // This ensures that instrumentation cannot execute until all global + // constructors have run + DYNINSTBaseInit(); +} + +void +DYNINSTglobal_dtors_handler() +{ + void (**dtors_array)(void) = &DYNINSTdtors_addr; + + // Destructors are called in the forward order that they are listed + void (**tmp_ptr)(void) = &dtors_array[1]; // skip list start + while(*tmp_ptr != ((void (*)(void)) DTOR_LIST_TERM)) + { + (*tmp_ptr)(); + tmp_ptr++; + } +} + +#endif diff --git a/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors-ppc64.c b/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors-ppc64.c new file mode 100644 index 000000000..596fab3b5 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors-ppc64.c @@ -0,0 +1,72 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if defined(DYNINST_RT_STATIC_LIB) + +# include + +extern void (*DYNINSTctors_begin)(void); +extern void (*DYNINSTdtors_begin)(void); +extern void (*DYNINSTctors_end)(void); +extern void (*DYNINSTdtors_end)(void); + +extern void +DYNINSTBaseInit(); + +void +DYNINSTglobal_ctors_handler() +{ + void (**ctor)(void) = &DYNINSTctors_begin; + + while(ctor != (&DYNINSTctors_end)) + { + if(*ctor && ((intptr_t) *ctor != -1)) (*ctor)(); + ctor++; + } + + // This ensures that instrumentation cannot execute until all global + // constructors have run + DYNINSTBaseInit(); +} + +void +DYNINSTglobal_dtors_handler() +{ + void (**dtor)(void) = &DYNINSTdtors_begin; + + // Destructors are called in the forward order that they are listed + while(dtor != (&DYNINSTdtors_end)) + { + if(*dtor && ((intptr_t) *dtor != -1)) (*dtor)(); + dtor++; + } +} + +#endif diff --git a/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors-x86.c b/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors-x86.c new file mode 100644 index 000000000..76e8fabec --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors-x86.c @@ -0,0 +1,129 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if defined(DYNINST_RT_STATIC_LIB) +# include +void* DYNINSTirel_start; +void* DYNINSTirel_end; + +extern void (*DYNINSTctors_begin)(void); +extern void (*DYNINSTdtors_begin)(void); +extern void (*DYNINSTctors_end)(void); +extern void (*DYNINSTdtors_end)(void); + +extern void +DYNINSTBaseInit(); + +typedef struct +{ + long* offset; + long info; + long (*ptr)(void); +} rela_t; + +typedef struct +{ + long* offset; + long info; +} rel_t; + +/* + * When rewritting a static binary, .ctors and .dtors sections of + * instrumentation code needs to be combined with the existing .ctors + * and .dtors sections of the static binary. + * + * The following functions process the .ctors and .dtors sections + * that have been rewritten. The rewriter will relocate the + * address of DYNINSTctors_addr and DYNINSTdtors_addr to point to + * new .ctors and .dtors sections. + */ + +void +DYNINSTglobal_ctors_handler() +{ + void (**ctor)(void) = &DYNINSTctors_begin; + + while(ctor != (&DYNINSTctors_end)) + { + if(*ctor && ((intptr_t) *ctor != -1)) (*ctor)(); + ctor++; + } + + // This ensures that instrumentation cannot execute until all global + // constructors have run + DYNINSTBaseInit(); +} + +void +DYNINSTglobal_dtors_handler() +{ + void (**dtor)(void) = &DYNINSTdtors_begin; + + // Destructors are called in the forward order that they are listed + while(dtor != (&DYNINSTdtors_end)) + { + if(*dtor && ((intptr_t) *dtor != -1)) (*dtor)(); + dtor++; + } +} + +void +DYNINSTglobal_irel_handler() +{ + if(sizeof(long) == 8) + { + rela_t* rel = 0; + for(rel = (rela_t*) (&DYNINSTirel_start); rel != (rela_t*) (&DYNINSTirel_end); + ++rel) + { + long result = 0; + if(rel->info != 0x25) continue; + result = (rel->ptr()); + *(rel->offset) = result; + } + } + else + { + rel_t* rel = 0; + for(rel = (rel_t*) (&DYNINSTirel_start); rel != (rel_t*) (&DYNINSTirel_end); + ++rel) + { + typedef long (*funcptr)(void); + long (*ptr)(void) = 0; + long result = 0; + if(rel->info != 0x2a) continue; + ptr = (funcptr)(*rel->offset); + result = ptr(); + *(rel->offset) = result; + } + } +} + +#endif diff --git a/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors_begin.c b/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors_begin.c new file mode 100644 index 000000000..5b0c19c8c --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors_begin.c @@ -0,0 +1,4 @@ +#if defined(DYNINST_RT_STATIC_LIB) +void (*DYNINSTctors_begin)(void) __attribute__((section(".init_array"))); +void (*DYNINSTdtors_begin)(void) __attribute__((section(".fini_array"))); +#endif diff --git a/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors_end.c b/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors_end.c new file mode 100644 index 000000000..f8fee4d5a --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTstatic_ctors_dtors_end.c @@ -0,0 +1,4 @@ +#if defined(DYNINST_RT_STATIC_LIB) +void (*DYNINSTctors_end)(void) __attribute__((section(".init_array"))); +void (*DYNINSTdtors_end)(void) __attribute__((section(".fini_array"))); +#endif diff --git a/source/lib/omnitrace-rt/src/RTthread-aarch64.c b/source/lib/omnitrace-rt/src/RTthread-aarch64.c new file mode 100644 index 000000000..96d3f9cf7 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTthread-aarch64.c @@ -0,0 +1,41 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "src/RTthread.h" +#include +int +tc_lock_lock(tc_lock_t* t) +{ + dyntid_t me = dyn_pthread_self(); + volatile bool* l = (volatile bool*) (&(t->mutex)); + while(__atomic_test_and_set(l, __ATOMIC_ACQUIRE)) + if(t->tid == me) return DYNINST_DEAD_LOCK; + return 0; +} diff --git a/source/lib/omnitrace-rt/src/RTthread-power-asm.s b/source/lib/omnitrace-rt/src/RTthread-power-asm.s new file mode 100644 index 000000000..80fa0a03c --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTthread-power-asm.s @@ -0,0 +1,9 @@ +#include "RTconst.h" +#include "../../dyninstAPI/src/inst-power.h" + .machine "push" +#ifndef __clang__ + .machine "ppc" +#endif + .machine "pop" + +.section .note.GNU-stack,"",@progbits diff --git a/source/lib/omnitrace-rt/src/RTthread-powerpc-asm.S b/source/lib/omnitrace-rt/src/RTthread-powerpc-asm.S new file mode 100644 index 000000000..fd59bdcd2 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTthread-powerpc-asm.S @@ -0,0 +1,77 @@ + .file "RTthread-powerpc-asm.S" + .machine "push" +#if defined(arch_ppc_little_endian) + .abiversion 2 +#endif + +#ifndef __clang__ +# if defined(arch_64bit) + .machine "ppc64" +# else + .machine "ppc" +# endif +#endif + + .section ".text" + .align 2 +# /* ------------------------------------------- */ +# /* int atomic_set(volatile int *int_ptr); */ +# /* */ +# /* The only possible values at the given */ +# /* memory location are 0 and 1. Attempt to */ +# /* atomically update the value from 0 to 1. */ +# /* Return 1 if such an atomic update occurred; */ +# /* return 0 otherwise. */ +# /* ------------------------------------------- */ +#if defined(arch_ppc_little_endian) + .section ".toc", "aw" + .section ".text" + .align 2 + .p2align 4,,15 + .globl atomic_set + .type atomic_set, @function +atomic_set: +#elif defined(arch_64bit) + .globl atomic_set + .section ".opd", "aw" + .align 3 +atomic_set: + .quad .atomic_set, .TOC.@tocbase, 0 + .size atomic_set, 24 + + .previous + .globl .atomic_set + .type .atomic_set, @function +.atomic_set: +#else + .globl atomic_set + .type atomic_set, @function +atomic_set: +#endif + addi 4,0,1 # r4 = 1 + # Attempt atomic memory swap + lwarx 5,0,3 # r5 = *int_ptr (load reserve indexed) + stwcx. 4,0,3 # *int_ptr = 1 (store conditional indexed) + bne- atomic_set_return_0 # if atomic swap failed, return 0 + + cmpw 5,4 # if original value was already 1, + beq- atomic_set_return_0 # return 0 because no value update occurred + + addi 3,0,1 # function return value = r3 = 1 + blr # branch via link register (function return) + +atomic_set_return_0: + addi 3,0,0 # function return value = r3 = 0 + blr # branch via link register (function return) + +#if defined(arch_ppc_little_endian) + .size atomic_set, . - atomic_set +#elif defined(arch_64bit) + .size .atomic_set, . - .atomic_set +#else + .size atomic_set, . - atomic_set +#endif + + .machine "pop" + +.section .note.GNU-stack,"",@progbits diff --git a/source/lib/omnitrace-rt/src/RTthread-powerpc.c b/source/lib/omnitrace-rt/src/RTthread-powerpc.c new file mode 100644 index 000000000..14e291a15 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTthread-powerpc.c @@ -0,0 +1,63 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "src/RTthread.h" + +/** + * atomic_set will do the following atomically: + * if (*val == 0) { + * *val = 1; + * return 1; + * } + * return 0; + * + **/ + +extern int +atomic_set(volatile int* int_ptr); + +int +tc_lock_lock(tc_lock_t* tc) +{ + dyntid_t me; + + me = dyn_pthread_self(); + if(me == tc->tid) return DYNINST_DEAD_LOCK; + + while(1) + { + if(tc->mutex == 0 && atomic_set(&tc->mutex)) + { + tc->tid = me; + break; + } + } + return 0; +} diff --git a/source/lib/omnitrace-rt/src/RTthread-x86-64.c b/source/lib/omnitrace-rt/src/RTthread-x86-64.c new file mode 100644 index 000000000..b13473f39 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTthread-x86-64.c @@ -0,0 +1,54 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "src/RTthread.h" + +static int +atomic_set(volatile int* val) +{ + int result = 1; + __asm__ __volatile__("xchgl %0, %1\n" : "+r"(result), "+m"(*val)::"memory"); + return !result; +} + +int +tc_lock_lock(tc_lock_t* tc) +{ + dyntid_t me; + + me = dyn_pthread_self(); + if(me == tc->tid) return DYNINST_DEAD_LOCK; + + while(!atomic_set(&tc->mutex)) + ; + + tc->tid = me; + return 0; +} diff --git a/source/lib/omnitrace-rt/src/RTthread-x86.c b/source/lib/omnitrace-rt/src/RTthread-x86.c new file mode 100644 index 000000000..4e2aee717 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTthread-x86.c @@ -0,0 +1,89 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "src/RTthread.h" +#include + +/** + * atomic_set will do the following atomically: + * if (*val == 0) { + * *val = 1; + * return 1; + * } + * return 0; + * + * We need two versions since windows uses a different assembly syntax + * (AT&T syntax on Linux and Intel on Windows) + **/ +#if defined(os_windows) +int +atomic_set(volatile int* val) +{ + int result; +# ifdef _WIN64 + result = _InterlockedCompareExchange(val, 1, 0); + return !result; +# else + __asm + { + mov eax, 0 ; + mov ebx, 1 ; + mov ecx, val ; + lock cmpxchg [ecx],ebx ; + setz al ; + mov result, eax ; + } +# endif + return result; +} +#else +static int +atomic_set(volatile int* val) +{ + int result = 1; + __asm__ __volatile__("xchgl %0, %1\n" : "+r"(result), "+m"(*val)::"memory"); + return !result; +} +#endif + +int +tc_lock_lock(tc_lock_t* tc) +{ + dyntid_t me; + + me = dyn_pthread_self(); + if(me == tc->tid) return DYNINST_DEAD_LOCK; + + while(!atomic_set(&tc->mutex)) + ; + + tc->tid = me; + return 0; +} diff --git a/source/lib/omnitrace-rt/src/RTthread.c b/source/lib/omnitrace-rt/src/RTthread.c new file mode 100644 index 000000000..ffd164686 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTthread.c @@ -0,0 +1,51 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "RTcommon.h" +#include "RTthread.h" +#include "h/dyninstAPI_RT.h" +#include "h/dyninstRTExport.h" + +int DYNINST_multithread_capable; +extern unsigned int DYNINSThasInitialized; + +static void (*rt_newthr_cb)(int) = NULL; +void +setNewthrCB(void (*cb)(int)) +{ + rt_newthr_cb = cb; +} + +#define IDX_NONE -1 diff --git a/source/lib/omnitrace-rt/src/RTthread.h b/source/lib/omnitrace-rt/src/RTthread.h new file mode 100644 index 000000000..ecd3d1353 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTthread.h @@ -0,0 +1,62 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _RTTHREAD_H_ +#define _RTTHREAD_H_ + +#include "h/dyninstAPI_RT.h" +#include "h/dyninstRTExport.h" + +DLLEXPORT dyntid_t +dyn_pthread_self(); /*Thread library identifier*/ +int +dyn_lwp_self(); /*LWP used by the kernel identifier*/ +int +dyn_pid_self(); /*PID identifier representing the containing process*/ + +extern int DYNINST_multithread_capable; + +typedef dyninst_lock_t tc_lock_t; + +#define DECLARE_TC_LOCK(l) tc_lock_t l = { 0, (dyntid_t) -1 } + +int +tc_lock_init(tc_lock_t*); +int +tc_lock_lock(tc_lock_t*); +int +tc_lock_unlock(tc_lock_t*); +int +tc_lock_destroy(tc_lock_t*); + +int +DYNINST_am_initial_thread(dyntid_t tid); + +#endif diff --git a/source/lib/omnitrace-rt/src/RTtlsgetaddr-x86.S b/source/lib/omnitrace-rt/src/RTtlsgetaddr-x86.S new file mode 100644 index 000000000..836d0de4b --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTtlsgetaddr-x86.S @@ -0,0 +1,54 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This function is used to help support TLS when rewriting static binaries. + * It is originally provided by the dynamic linker (which is unavailable to + * static binaries). One TLS model is to call the function with a module + * index in order to retrieve a TLS variable (see general dynamic). This model + * is unnecessarily general for static binaries but does exist in some non-PIC + * relocatable files. The GNU ld approach is to perform code transformations to + * relax the TLS model. In order to keep the rewriter for static binaries + * simple, the approach of emulating a call to ___tls_get_addr was used instead + * of implementing these link-time code transformations. + */ + +#if defined(DYNINST_RT_STATIC_LIB) +.text +.globl ___tls_get_addr + +___tls_get_addr: + mov (%eax), %eax /* Gets the TLS offset of the variable */ + add %gs:0, %eax /* Gets the absolute address of the variable */ + ret + +#endif + +.section .note.GNU-stack,"",@progbits diff --git a/source/lib/omnitrace-rt/src/RTtlsgetaddr-x86_64.S b/source/lib/omnitrace-rt/src/RTtlsgetaddr-x86_64.S new file mode 100644 index 000000000..fb15168ee --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTtlsgetaddr-x86_64.S @@ -0,0 +1,58 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This function is used to help support TLS when rewriting static binaries. + * It is originally provided by the dynamic linker (which is unavailable to + * static binaries). One TLS model is to call the function with a module + * index in order to retrieve a TLS variable (see general dynamic). This model + * is unnecessarily general for static binaries but does exist in some non-PIC + * relocatable files. The GNU ld approach is to perform code transformations to + * relax the TLS model. In order to keep the rewriter for static binaries + * simple, the approach of emulating a call to ___tls_get_addr was used instead + * of implementing these link-time code transformations. + */ + + +#if defined(DYNINST_RT_STATIC_LIB) +.text +.globl ___tls_get_addr +.globl __tls_get_addr + +__tls_get_addr: +___tls_get_addr: + mov (%rdi), %rax /* Get the TLS offset of the variable */ + add %fs:0, %rax /* Get the absolute address of the variable */ + ret + +#endif + +.section .note.GNU-stack,"",@progbits + diff --git a/source/lib/omnitrace-rt/src/RTwinnt.c b/source/lib/omnitrace-rt/src/RTwinnt.c new file mode 100644 index 000000000..2ebfa0f75 --- /dev/null +++ b/source/lib/omnitrace-rt/src/RTwinnt.c @@ -0,0 +1,565 @@ +/* + * See the dyninst/COPYRIGHT file for copyright information. + * + * We provide the Paradyn Tools (below described as "Paradyn") + * on an AS IS basis, and do not warrant its validity or performance. + * We reserve the right to update, modify, or discontinue this + * software at any time. We shall have no obligation to supply such + * updates or modifications or any other form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/************************************************************************ + * $Id: RTwinnt.c,v 1.22 2006/06/09 03:50:49 jodom Exp $ + * RTwinnt.c: runtime instrumentation functions for Windows NT + ************************************************************************/ +#include "RTcommon.h" +#include "h/dyninstAPI_RT.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern unsigned long dyninstTrapTableUsed; +extern unsigned long dyninstTrapTableVersion; +extern trapMapping_t* dyninstTrapTable; +extern unsigned long dyninstTrapTableIsSorted; +extern void + DYNINSTBaseInit(); +extern double DYNINSTstaticHeap_512K_lowmemHeap_1[]; +extern double DYNINSTstaticHeap_16M_anyHeap_1[]; +extern unsigned long sizeOfLowMemHeap1; +extern unsigned long sizeOfAnyHeap1; + +/************************************************************************ + * void DYNINSTbreakPoint(void) + * + * stop oneself. + ************************************************************************/ + +void +DYNINSTbreakPoint(void) +{ + /* TODO: how do we stop all threads? */ + DYNINST_break_point_event = 1; + DebugBreak(); + DYNINST_break_point_event = 0; +} + +void +DYNINSTsafeBreakPoint() +{ + DYNINSTbreakPoint(); +} + +static dyntid_t initial_thread_tid; + +/* this function is automatically called when windows loads this dll + if we are launching a mutatee to instrument, dyninst will place + the correct values in libdyninstAPI_RT_DLL_localPid and + libdyninstAPI_RT_DLL_localCause and they will be passed to + DYNINSTinit to correctly initialize the dll. this keeps us + from having to instrument two steps from the mutator (load and then + the execution of DYNINSTinit() +*/ + +BOOL WINAPI +DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + static int DllMainCalledOnce = 0; + // fprintf(stderr,"RTLIB: In DllMain staticmode=%d %s[%d]\n", DYNINSTstaticMode, + // __FILE__,__LINE__); + + if(DllMainCalledOnce) return 1; + DllMainCalledOnce++; + + DYNINSTinit(); + +#if defined(cap_mutatee_traps) + if(DYNINSTstaticMode) + { + DYNINSTinitializeTrapHandler(); + } +#endif + + return 1; +} + +char gLoadLibraryErrorString[ERROR_STRING_LENGTH]; +int +DYNINSTloadLibrary(char* libname) +{ + HMODULE res; + gLoadLibraryErrorString[0] = '\0'; + res = LoadLibrary(libname); + if(res == NULL) + { + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), gLoadLibraryErrorString, + ERROR_STRING_LENGTH, NULL); + return 0; + } + return 1; +} + +/************************************************************************ + * void DYNINSTasyncConnect() + * + * Connect to mutator's async handler thread. is pid of mutator + ************************************************************************/ +// CRITICAL_SECTION comms_mutex; + +int async_socket = -1; +int connect_port = 0; + +int +DYNINSTasyncConnect(int mutatorpid) +{ + int sock_fd; + struct sockaddr_in sadr; + struct in_addr* inadr; + struct addrinfo* result = NULL; + + WORD wsversion = MAKEWORD(2, 0); + WSADATA wsadata; + rtBPatch_asyncEventRecord ev; + + if(async_socket != -1) + { + /*fprintf(stderr, "%s[%d]: already connected\n", __FILE__, __LINE__);*/ + return 0; + } + + RTprintf("%s[%d]: inside DYNINSTasyncConnect\n", __FILE__, __LINE__); + + if(0 == connect_port) + { + fprintf(stderr, "%s[%d]: DYNINSTasyncConnect, no port\n", __FILE__, __LINE__); + } + + WSAStartup(wsversion, &wsadata); + + RTprintf("%s[%d]: DYNINSTasyncConnect before gethostbyname\n", __FILE__, __LINE__); + + getaddrinfo("localhost", NULL, NULL, &result); + inadr = (struct in_addr*) result->ai_addr; + + RTprintf("%s[%d]: inside DYNINSTasyncConnect before memset\n", __FILE__, __LINE__); + + memset((void*) &sadr, 0, sizeof(sadr)); + sadr.sin_family = PF_INET; + sadr.sin_port = htons((u_short) connect_port); + sadr.sin_addr = *inadr; + + RTprintf("%s[%d]: DYNINSTasyncConnect before socket\n", __FILE__, __LINE__); + + sock_fd = socket(PF_INET, SOCK_STREAM, 0); + + if(sock_fd == INVALID_SOCKET) + { + fprintf(stderr, "DYNINST: socket failed: %d\n", WSAGetLastError()); + } + + RTprintf("%s[%d]: DYNINSTasyncConnect before connect\n", __FILE__, __LINE__); + + if(connect(sock_fd, (struct sockaddr*) &sadr, sizeof(sadr)) == SOCKET_ERROR) + { + fprintf(stderr, "DYNINSTasyncConnect: connect failed: %d\n", WSAGetLastError()); + } + + /* maybe need to do fcntl to set nonblocking writes on this fd */ + + async_socket = sock_fd; + + RTprintf("%s[%d]: DYNINSTasyncConnect before write\n", __FILE__, __LINE__); + + /* after connecting, we need to send along our pid */ + ev.type = rtBPatch_newConnectionEvent; + ev.pid = _getpid(); + + if(!DYNINSTwriteEvent((void*) &ev, sizeof(rtBPatch_asyncEventRecord))) + { + fprintf(stderr, "%s[%d]: DYNINSTwriteEventFailed\n", __FILE__, __LINE__); + } + + /* initialize comms mutex */ + + // InitializeCriticalSection(&comms_mutex); + // fprintf(stderr, "%s[%d]: DYNINSTasyncConnect appears to have succeeded\n", + // __FILE__, __LINE__); + + RTprintf("%s[%d]: leaving DYNINSTasyncConnect\n", __FILE__, __LINE__); + + freeaddrinfo(result); + + return 1; /*true*/ +} + +int +DYNINSTasyncDisconnect() +{ + WSACleanup(); + return _close(async_socket); +} + +void +printSysError(unsigned errNo) +{ + char buf[1000]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errNo, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 1000, NULL); + + fprintf(stderr, "*** System error [%d]: %s\n", errNo, buf); + fflush(stderr); +} + +int +DYNINSTwriteEvent(void* ev, size_t sz) +{ + DYNINSTasyncConnect(DYNINST_mutatorPid); + + if(send((SOCKET) async_socket, ev, sz, 0) != sz) + { + printSysError(WSAGetLastError()); + printf("DYNINSTwriteTrace: send error %d, %d %d\n", WSAGetLastError(), sz, + async_socket); + + if(async_socket == -1) return 1; + return 0; + } + return 1; +} + +int +dyn_pid_self() +{ + return _getpid(); +} + +int +dyn_lwp_self() +{ +#ifdef _WIN64 + return GetCurrentThreadId(); +#else + /* return GetCurrentThreadId(); */ + /* getCurrentThreadId() is conflicting with SD-Dyninst instrumentation. + * So I'm doing the massively unportable thing here and hard-coding the assembly + * FOR GREAT JUSTICE! + */ + /* This will do stack frame setup, but that seems harmless in this context... */ + __asm { + mov EAX,FS:[0x18] + mov EAX,DS:[EAX+0x24] + } +#endif +} + +dyntid_t +dyn_pthread_self() +{ + return (dyntid_t) dyn_lwp_self(); +} + +int +DYNINSTthreadInfo(BPatch_newThreadEventRecord* ev) +{ + return 1; +} + +/* + We reserve index 0 for the initial thread. This value varies by + platform but is always constant for that platform. Wrap that + platform-ness here. +*/ +int +DYNINST_am_initial_thread(dyntid_t tid) +{ + return (tid == initial_thread_tid); +} + +// Check that the address is backed by a file, +// get the binary's load address, +// get the PE header, assuming there is one, +// see if the last section has been tagged with "DYNINST_REWRITE" +// get trap-table header from last binary section's end - label - size +// sets allocBase to the binary's load address +static struct trap_mapping_header* +getStaticTrapMap(unsigned long addr, unsigned long* allocBase) +{ + struct trap_mapping_header* header = NULL; + char fileName[ERROR_STRING_LENGTH]; + DWORD actualNameLen = 0; + MEMORY_BASIC_INFORMATION memInfo; + int numSections = 0; + PIMAGE_NT_HEADERS peHdr = NULL; + IMAGE_SECTION_HEADER curSecn; + int sidx = 0; + char* str = NULL; + + // check that the address is backed by a file + actualNameLen = GetMappedFileName(GetCurrentProcess(), (LPVOID) addr, fileName, + ERROR_STRING_LENGTH); + if(!actualNameLen) + { + fileName[0] = '\0'; + goto done; // no file mapped at trap address + } + fileName[ERROR_STRING_LENGTH - 1] = '\0'; + + // get the binary's load address, size + if(!VirtualQuery((LPCVOID) addr, &memInfo, sizeof(memInfo)) || + MEM_COMMIT != memInfo.State) + { + fprintf(stderr, "ERROR IN RTLIB: getStaticTrapMap %s[%d]\n", __FILE__, __LINE__); + goto done; // shouldn't be possible given previous query, but hey + } + *allocBase = (unsigned long) memInfo.AllocationBase; + + rtdebug_printf("RTLIB: getStaticTrapMap addr=%lx meminfo.BaseAddress=%lx " + "meminfo.AllocationBase = %lx, memInfo.RegionSize = %lx, " + "%s[%d]\n", + addr, memInfo.BaseAddress, memInfo.AllocationBase, memInfo.RegionSize, + __FILE__, __LINE__); + + // get the PE header, assuming there is one + peHdr = ImageNtHeader(memInfo.AllocationBase); + if(!peHdr) + { + fprintf(stderr, "ERROR IN RTLIB: getStaticTrapMap %s[%d]\n", __FILE__, __LINE__); + goto done; // no pe header + } + + // see if the last section has been tagged with "DYNINST_REWRITE" + numSections = peHdr->FileHeader.NumberOfSections; + curSecn = *(PIMAGE_SECTION_HEADER)(((unsigned char*) peHdr) + sizeof(DWORD) + + sizeof(IMAGE_FILE_HEADER) + + peHdr->FileHeader.SizeOfOptionalHeader + + sizeof(IMAGE_SECTION_HEADER) * (numSections - 1)); + + // fprintf(stderr, "RTLIB: PE section header address = %lx\n", curSecn); + // fprintf(stderr, "curSecn.chars = %lx %s[%d]\n",curSecn.Characteristics, + // __FILE__,__LINE__); + if((sizeof(void*) + 16) > curSecn.SizeOfRawData) + { + fprintf(stderr, "ERROR IN RTLIB: getStaticTrapMap %s[%d]\n", __FILE__, __LINE__); + goto done; // last section is uninitialized, doesn't have trap table + } + + // fprintf(stderr, "RTLIB %s[%d]\n", __FILE__,__LINE__); + // fprintf(stderr, "RTLIB mi.ab =%lx cs.va =%lx cs.srd=%lx %s[%d]\n", + // memInfo.AllocationBase, curSecn.VirtualAddress, curSecn.SizeOfRawData, + // __FILE__,__LINE__); + str = (char*) ((long) memInfo.AllocationBase + curSecn.VirtualAddress + + curSecn.SizeOfRawData - 16); + if(0 != strncmp("DYNINST_REWRITE", str, 15)) + { + fprintf(stderr, + "ERROR IN RTLIB: getStaticTrapMap found bad string [%s] at %p (%s[%d])\n", + str, str, __FILE__, __LINE__); + goto done; // doesn't have DYNINST_REWRITE label + } + + // get trap-table header + header = (struct trap_mapping_header*) ((unsigned long) memInfo.AllocationBase + + *((unsigned long*) (str - sizeof(void*)))); + +done: + if(header) + { + rtdebug_printf("RTLIB: found trap map header at %lx: [%lx %lx]\n", + (unsigned long) header, header->low_entry, header->high_entry); + } + else + { + rtdebug_printf("ERROR: didn't find trap table\n"); + } + return header; +} + +// Find the target IP and substitute. Leave everything else untouched. +LONG +dyn_trapHandler(PEXCEPTION_POINTERS e) +{ + void* trap_to = 0; + void* trap_addr = (void*) ((unsigned char*) e->ExceptionRecord->ExceptionAddress); + unsigned long zero = 0; + unsigned long one = 1; + unsigned long loadAddr = 0; + struct trap_mapping_header* hdr = NULL; + trapMapping_t* mapping = NULL; + rtdebug_printf("RTLIB: In dyn_trapHandler for exception type 0x%lx at 0x%lx\n", + e->ExceptionRecord->ExceptionCode, trap_addr); + + assert(DYNINSTstaticMode && "detach on the fly not implemented on Windows"); + + if(EXCEPTION_BREAKPOINT != e->ExceptionRecord->ExceptionCode) + { + fprintf(stderr, + "RTLIB: dyn_trapHandler exiting early, exception " + "type = 0x%lx triggered at %p is not breakpoint %s[%d]\n", + e->ExceptionRecord->ExceptionCode, trap_addr, __FILE__, __LINE__); + return EXCEPTION_CONTINUE_SEARCH; + } + + hdr = getStaticTrapMap((unsigned long) trap_addr, &loadAddr); + assert(hdr); + mapping = &(hdr->traps[0]); + + rtdebug_printf("RTLIB: calling dyninstTrapTranslate(\n\t0x%lx, \n\t" + "0x%lx, \n\t0x%lx, \n\t0x%lx, \n\t0x%lx)\n", + (unsigned long) trap_addr - loadAddr + 1, hdr->num_entries, zero, + mapping, one); + + trap_to = dyninstTrapTranslate((void*) ((unsigned long) trap_addr - loadAddr + 1), + (unsigned long*) &hdr->num_entries, &zero, + (volatile trapMapping_t**) &mapping, &one); + +#ifdef _WIN64 + rtdebug_printf("RTLIB: changing Rip from trap at 0x%lx to 0x%lx\n", + e->ContextRecord->Rip, (long) trap_to + loadAddr); + e->ContextRecord->Rip = (long) trap_to + loadAddr; +#else + rtdebug_printf("RTLIB: changing Eip from trap at 0x%lx to 0x%lx\n", + e->ContextRecord->Eip, (long) trap_to + loadAddr); + e->ContextRecord->Eip = (long) trap_to + loadAddr; +#endif + return EXCEPTION_CONTINUE_EXECUTION; +} + +PVOID fake_AVEH_handle; +/* registers the trap handler by calling AddVectoredExceptionHandler + */ +int +DYNINSTinitializeTrapHandler() +{ + fake_AVEH_handle = AddVectoredExceptionHandler( + RT_TRUE, (PVECTORED_EXCEPTION_HANDLER) dyn_trapHandler); + rtdebug_printf("RTLIB: added vectored trap handler\n"); + return fake_AVEH_handle != 0; +} + +PVOID +dyn_AddVectoredExceptionHandler(ULONG isFirst, PVECTORED_EXCEPTION_HANDLER handler) +{ + PVOID handlerHandle; + if(isFirst) + { + RemoveVectoredExceptionHandler(fake_AVEH_handle); + handlerHandle = AddVectoredExceptionHandler(isFirst, handler); + fake_AVEH_handle = AddVectoredExceptionHandler( + isFirst, (PVECTORED_EXCEPTION_HANDLER) dyn_trapHandler); + } + else + { + handlerHandle = AddVectoredExceptionHandler(isFirst, handler); + } + return handlerHandle; +} + +extern int fakeTickCount; +extern FILE* stOut; +DWORD __stdcall DYNINST_FakeTickCount() +{ + DWORD tmp = 0x12345678; + if(0 == fakeTickCount) + { + fakeTickCount = tmp; + } + else + { + fakeTickCount = fakeTickCount + 2; + // fakeTickCount = fakeTickCount + (tmp - fakeTickCount)/1000 + 1; + } + fprintf(stOut, "0x%lx = DYNINST_FakeTickCount()\n", fakeTickCount); + return (DWORD) fakeTickCount; +} + +BOOL __stdcall DYNINST_FakeBlockInput(BOOL blockit) +{ + BOOL ret = RT_TRUE; + fprintf(stOut, "0x%lx = DYNINST_FakeBlockInput(%d)\n", ret, blockit); + return ret; +} + +DWORD __stdcall DYNINST_FakeSuspendThread(HANDLE hThread) +{ + DWORD suspendCnt = 0; + fprintf(stOut, "%d = DYNINST_FakeSuspendThread(%p)\n", suspendCnt, hThread); + return suspendCnt; +} + +BOOL __stdcall DYNINST_FakeCheckRemoteDebuggerPresent(HANDLE hProcess, + PBOOL bpDebuggerPresent) +{ + BOOL ret = RT_FALSE; + fprintf(stOut, "%d = DYNINST_FakeCheckRemoteDebuggerPresent(%p,%p)\n", ret, hProcess, + bpDebuggerPresent); + (*bpDebuggerPresent) = ret; + return ret; +} + +VOID __stdcall DYNINST_FakeGetSystemTime(LPSYSTEMTIME lpSystemTime) +{ + lpSystemTime->wYear = 2009; + lpSystemTime->wMonth = 5; + lpSystemTime->wDayOfWeek = 0; + lpSystemTime->wDay = 3; + lpSystemTime->wHour = 10; + lpSystemTime->wMinute = 1; + lpSystemTime->wSecond = 33; + lpSystemTime->wMilliseconds = 855; + fprintf(stOut, "called DYNINST_FakeGetSystemTime()\n"); + fflush(stOut); +} + +void +mark_heaps_exec() +{ + int OK; + DWORD old_permissions; + OK = VirtualProtect(DYNINSTstaticHeap_16M_anyHeap_1, sizeOfAnyHeap1, + PAGE_EXECUTE_READWRITE, &old_permissions); + if(!OK) + { + fprintf(stderr, "ERROR: 16M/any heap not usable in RTlib: %d\n", GetLastError()); + } + OK = VirtualProtect(DYNINSTstaticHeap_512K_lowmemHeap_1, sizeOfLowMemHeap1, + PAGE_EXECUTE_READWRITE, &old_permissions); + if(!OK) + { + fprintf(stderr, "ERROR: 512k/lowmem heap not usable in RTlib: %d\n", + GetLastError()); + } +} diff --git a/source/lib/omnitrace-rt/src/libSpace.s b/source/lib/omnitrace-rt/src/libSpace.s new file mode 100644 index 000000000..c506299a7 --- /dev/null +++ b/source/lib/omnitrace-rt/src/libSpace.s @@ -0,0 +1,23 @@ +.toc +.csect .text[PR] + .globl DYNINSTstaticHeap_1048576_textHeap_libSpace + .globl .DYNINSTstaticHeap_1048576_textHeap_libSpace +.csect DYNINSTstaticHeap_1048576_textHeap_libSpace[DS] +DYNINSTstaticHeap_1048576_textHeap_libSpace: + .long .DYNINSTstaticHeap_1048576_textHeap_libSpace, TOC[tc0], 0 +.csect .text[PR] +.DYNINSTstaticHeap_1048576_textHeap_libSpace: + blr + .space 1048576 +LT..DYNINSTstaticHeap_1048576_textHeap_libSpace: + .long 0 + .byte 0,0,32,96,128,1,0,1 + .long LT..DYNINSTstaticHeap_1048576_textHeap_libSpace-.DYNINSTstaticHeap_1048576_textHeap_libSpace + .short 43 + .byte "DYNINSTstaticHeap_1048576_textHeap_libSpace" + .byte 31 +_section_.text: +.csect .data[RW],3 + .long _section_.text + +.section .note.GNU-stack,"",@progbits diff --git a/source/lib/omnitrace-rt/src/libSpace64.s b/source/lib/omnitrace-rt/src/libSpace64.s new file mode 100644 index 000000000..946caa938 --- /dev/null +++ b/source/lib/omnitrace-rt/src/libSpace64.s @@ -0,0 +1,23 @@ +.toc +.csect .text[PR] + .globl DYNINSTstaticHeap_1048576_textHeap_libSpace + .globl .DYNINSTstaticHeap_1048576_textHeap_libSpace +.csect DYNINSTstaticHeap_1048576_textHeap_libSpace[DS] +DYNINSTstaticHeap_1048576_textHeap_libSpace: + .llong .DYNINSTstaticHeap_1048576_textHeap_libSpace, TOC[tc0], 0 +.csect .text[PR] +.DYNINSTstaticHeap_1048576_textHeap_libSpace: + blr + .space 1048576 +LT..DYNINSTstaticHeap_1048576_textHeap_libSpace: + .llong 0 + .byte 0,0,32,96,128,1,0,1 + .llong LT..DYNINSTstaticHeap_1048576_textHeap_libSpace-.DYNINSTstaticHeap_1048576_textHeap_libSpace + .short 43 + .byte "DYNINSTstaticHeap_1048576_textHeap_libSpace" + .byte 31 +_section_.text: +.csect .data[RW],3 + .llong _section_.text + +.section .note.GNU-stack,"",@progbits diff --git a/source/lib/omnitrace/CMakeLists.txt b/source/lib/omnitrace/CMakeLists.txt index 2107e0a0b..4928a85e7 100644 --- a/source/lib/omnitrace/CMakeLists.txt +++ b/source/lib/omnitrace/CMakeLists.txt @@ -18,11 +18,6 @@ add_subdirectory(library) target_link_libraries(omnitrace-object-library PRIVATE omnitrace::omnitrace-interface-library) -if(OMNITRACE_DYNINST_API_RT) - get_filename_component(OMNITRACE_DYNINST_API_RT_DIR "${OMNITRACE_DYNINST_API_RT}" - DIRECTORY) -endif() - # ------------------------------------------------------------------------------# # # omnitrace static library diff --git a/source/lib/omnitrace/library/thread_info.cpp b/source/lib/omnitrace/library/thread_info.cpp index bca571653..01ebf95f1 100644 --- a/source/lib/omnitrace/library/thread_info.cpp +++ b/source/lib/omnitrace/library/thread_info.cpp @@ -35,6 +35,8 @@ #include #include +#include + namespace omnitrace { namespace @@ -105,8 +107,9 @@ init_index_data(int64_t _tid, bool _offset = false) return itr; } -const auto unknown_thread = std::optional{}; -int64_t peak_num_threads = max_supported_threads; +thread_local int64_t offset_causal_count = 0; +const auto unknown_thread = std::optional{}; +int64_t peak_num_threads = max_supported_threads; } // namespace std::string @@ -187,8 +190,13 @@ thread_info::init(bool _offset) _info = thread_info{}; _info->is_offset = threading::offset_this_id(); _info->index_data = init_index_data(_tid, _info->is_offset); - _info->causal_count = &causal::delay::get_local(); _info->lifetime.first = tim::get_clock_real_now(); + + const auto _sequent_tid = _info->index_data->sequent_value; + _info->causal_count = (!_info->is_offset && _sequent_tid < peak_num_threads) + ? &causal::delay::get_local(_sequent_tid) + : &offset_causal_count; + if(_info->is_offset) set_thread_state(ThreadState::Disabled); } diff --git a/tests/omnitrace-testing.cmake b/tests/omnitrace-testing.cmake index 22763ae7d..9e4c88619 100644 --- a/tests/omnitrace-testing.cmake +++ b/tests/omnitrace-testing.cmake @@ -17,11 +17,6 @@ endif() omnitrace_message(STATUS "OS release: ${_OS_RELEASE}") -if(NOT OMNITRACE_DYNINST_API_RT_DIR AND OMNITRACE_DYNINST_API_RT) - get_filename_component(OMNITRACE_DYNINST_API_RT_DIR "${OMNITRACE_DYNINST_API_RT}" - DIRECTORY) -endif() - include(ProcessorCount) if(NOT DEFINED NUM_PROCS_REAL) processorcount(NUM_PROCS_REAL) @@ -46,15 +41,8 @@ if(MAX_CAUSAL_ITERATIONS GREATER 100) set(MAX_CAUSAL_ITERATIONS 100) endif() -if(OMNITRACE_BUILD_DYNINST) - set(OMNITRACE_DYNINST_API_RT_DIR - "${PROJECT_BINARY_DIR}/external/dyninst/dyninstAPI_RT:${PROJECT_BINARY_DIR}/external/dyninst/dyninstAPI" - ) -endif() - set(_test_library_path - "LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}" - ) + "LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}:$ENV{LD_LIBRARY_PATH}") set(_test_openmp_env "OMP_PROC_BIND=spread" "OMP_PLACES=threads" "OMP_NUM_THREADS=2") set(_base_environment diff --git a/tests/source/CMakeLists.txt b/tests/source/CMakeLists.txt index e28008475..ea9bae3c4 100644 --- a/tests/source/CMakeLists.txt +++ b/tests/source/CMakeLists.txt @@ -9,7 +9,7 @@ target_compile_definitions(thread-limit PRIVATE MAX_THREADS=${OMNITRACE_MAX_THRE target_link_libraries(thread-limit PRIVATE Threads::Threads tests-compile-options) set(_thread_limit_environment - "${_base_environment}" "OMNITRACE_USE_PERFETTO=ON" "OMNITRACE_USE_TIMEMORY=ON" + "${_base_environment}" "OMNITRACE_TRACE=ON" "OMNITRACE_PROFILE=ON" "OMNITRACE_COUT_OUTPUT=ON" "OMNITRACE_USE_SAMPLING=ON" "OMNITRACE_SAMPLING_FREQ=250" "OMNITRACE_VERBOSE=2" "OMNITRACE_TIMEMORY_COMPONENTS=wall_clock,peak_rss,page_rss")