fix omnitrace print-* with libraries (#94)
* fix omnitrace print-* with libraries * timemory submodule update * Update workflows to use ./bin/omnitrace instead of ./omnitrace * cmake format * update timemory submodule - fix ODR violations in utility/procfs * cmake updates - uniform find_package for all ROCm-based libraries * tweak transpose example - throw exception instead of std::exit * Inspect cmdv name before assuming not exe - some ELF execs "think" they are libraries so only assume rewrite + simulate + all-functions if filename looks like library - adds some test for --print-available -- <library> * Fix _has_lib_prefix when command is < 3 * Updates and reverts to omnitrace exe - update module_function operator< and operator== - add function_signature operator< - refactor module_function ctor - revert some previous changes w.r.t. simulate and include_unninstr * Fix source/bin/tests to use same output dir as tests * cmake format * Segfault mitigation + refactor + modify function iteration - refactor module_function ctor to avoid segfaults - string_t -> std::string - replace std::string with std::string_view in some places - get_name(module_t*) - get_name(procedure_t*) - disable using both app_modules and app_functions - new option: --parse-all-modules to iterate over app_modules - removed some unused code w.r.t. debug info * Disable module_function address range for uninstrumentable functions * Disable module_function address range for uninstrumentable functions * Refactored getting file/line info and init/fini - use dyninst insertInitCallback and insertFiniCallback if main not found - fixed all issues with segmentation faults in --simulate --all-functions * revert changes to Findrocprofiler.cmake
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
6bc86d1111
Коммит
d04cbe862e
@@ -51,6 +51,7 @@ parse:
|
||||
omnitrace_add_bin_test:
|
||||
flags:
|
||||
- WILL_FAIL
|
||||
- ADD_INVERSE
|
||||
kwargs:
|
||||
NAME: '*'
|
||||
ARGS: '*'
|
||||
|
||||
@@ -73,8 +73,8 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
run:
|
||||
cd build &&
|
||||
ldd ./omnitrace &&
|
||||
./omnitrace --help &&
|
||||
ldd ./bin/omnitrace &&
|
||||
./bin/omnitrace --help &&
|
||||
ctest -V -N -O omnitrace-ctest-${{ github.job }}-commands.log &&
|
||||
ctest -V --output-log omnitrace-ctest-${{ github.job }}.log --stop-on-failure
|
||||
|
||||
|
||||
@@ -102,8 +102,8 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
run:
|
||||
cd build &&
|
||||
ldd ./omnitrace &&
|
||||
./omnitrace --help &&
|
||||
ldd ./bin/omnitrace &&
|
||||
./bin/omnitrace --help &&
|
||||
ctest -V -N -O omnitrace-ctest-${{ github.job }}-commands.log &&
|
||||
ctest -V --output-log omnitrace-ctest-${{ github.job }}.log --stop-on-failure
|
||||
|
||||
|
||||
@@ -118,8 +118,8 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
run:
|
||||
cd build &&
|
||||
ldd ./omnitrace &&
|
||||
./omnitrace --help &&
|
||||
ldd ./bin/omnitrace &&
|
||||
./bin/omnitrace --help &&
|
||||
ctest -V -N -O omnitrace-ctest-${{ github.job }}-commands.log &&
|
||||
ctest -V --output-log omnitrace-ctest-${{ github.job }}.log --stop-on-failure
|
||||
|
||||
@@ -241,8 +241,8 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
run:
|
||||
cd build &&
|
||||
ldd ./omnitrace &&
|
||||
./omnitrace --help &&
|
||||
ldd ./bin/omnitrace &&
|
||||
./bin/omnitrace --help &&
|
||||
ctest -V -N -O omnitrace-ctest-${{ github.job }}-commands.log &&
|
||||
ctest -V --output-log omnitrace-ctest-${{ github.job }}.log --stop-on-failure
|
||||
|
||||
|
||||
@@ -781,6 +781,39 @@ function(OMNITRACE_FIND_SHARED_LIBRARY)
|
||||
find_library(${ARGN})
|
||||
endfunction()
|
||||
|
||||
function(OMNITRACE_BUILDTREE_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR)
|
||||
get_target_property(_TPL_VERSION ${_TPL_TARGET} VERSION)
|
||||
get_target_property(_TPL_SOVERSION ${_TPL_TARGET} SOVERSION)
|
||||
get_target_property(_TPL_NAME ${_TPL_TARGET} OUTPUT_NAME)
|
||||
set(_TPL_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX})
|
||||
set(_TPL_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
|
||||
foreach(_TAIL ${_TPL_SUFFIX} ${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
${_TPL_SUFFIX}.${_TPL_VERSION})
|
||||
set(_INP ${_TPL_PREFIX}${_TPL_NAME}${_TAIL})
|
||||
set(_OUT ${_TPL_PREFIX}${_NEW_NAME}${_TAIL})
|
||||
endforeach()
|
||||
|
||||
string(REPLACE " " "-" _TAIL "${ARGN}")
|
||||
|
||||
# build tree symbolic links
|
||||
add_custom_target(
|
||||
${_NEW_NAME}-build-tree-library${_TAIL} ALL
|
||||
${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${_TPL_TARGET}>
|
||||
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E create_symlink
|
||||
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION}
|
||||
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E create_symlink
|
||||
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}
|
||||
WORKING_DIRECTORY ${_BUILD_TREE_DIR}
|
||||
DEPENDS ${_TPL_TARGET}
|
||||
COMMENT "Creating ${_NEW_NAME} from ${_TPL_TARGET}...")
|
||||
endfunction()
|
||||
|
||||
function(OMNITRACE_INSTALL_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR)
|
||||
get_target_property(_TPL_VERSION ${_TPL_TARGET} VERSION)
|
||||
get_target_property(_TPL_SOVERSION ${_TPL_TARGET} SOVERSION)
|
||||
@@ -795,41 +828,17 @@ function(OMNITRACE_INSTALL_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR)
|
||||
endforeach()
|
||||
|
||||
# build tree symbolic links
|
||||
add_custom_target(
|
||||
${_NEW_NAME}-library ALL
|
||||
${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${_TPL_TARGET}>
|
||||
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E create_symlink
|
||||
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION}
|
||||
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E create_symlink
|
||||
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}
|
||||
WORKING_DIRECTORY ${_BUILD_TREE_DIR}
|
||||
DEPENDS ${_TPL_TARGET}
|
||||
COMMENT "Creating ${_NEW_NAME} from ${_TPL_TARGET}...")
|
||||
omnitrace_buildtree_tpl("${_TPL_TARGET}" "${_NEW_NAME}" "${_BUILD_TREE_DIR}" ${ARGN})
|
||||
|
||||
install(
|
||||
FILES $<TARGET_FILE:${_TPL_TARGET}>
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RENAME ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION})
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/install-tree
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E create_symlink
|
||||
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION}
|
||||
${PROJECT_BINARY_DIR}/install-tree/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E create_symlink
|
||||
${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
${PROJECT_BINARY_DIR}/install-tree/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX})
|
||||
install(
|
||||
FILES
|
||||
${PROJECT_BINARY_DIR}/install-tree/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
${PROJECT_BINARY_DIR}/install-tree/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}
|
||||
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION}
|
||||
${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
endfunction()
|
||||
|
||||
@@ -217,10 +217,13 @@ function(ROCM_VERSION_PARSE_VERSION_FILES)
|
||||
endif()
|
||||
|
||||
# convert env to cache if not defined
|
||||
foreach(_PATH ROCmVersion_DIR ROCmVersion_ROOT ROCmVersion_ROOT_DIR ROCM_PATH)
|
||||
foreach(_PATH ROCmVersion_DIR ROCmVersion_ROOT ROCmVersion_ROOT_DIR
|
||||
OMNITRACE_DEFAULT_ROCM_PATH ROCM_PATH)
|
||||
if(NOT DEFINED ${_PATH} AND DEFINED ENV{${_PATH}})
|
||||
set(_VAL "$ENV{${_PATH}}")
|
||||
get_filename_component(_VAL "${_VAL}" REALPATH)
|
||||
set(${_PATH}
|
||||
"$ENV{${_PATH}}"
|
||||
"${_VAL}"
|
||||
CACHE PATH "Search path for ROCm version for ROCmVersion")
|
||||
endif()
|
||||
endforeach()
|
||||
@@ -229,8 +232,11 @@ function(ROCM_VERSION_PARSE_VERSION_FILES)
|
||||
set(_PATHS ${ROCmVersion_DIR})
|
||||
else()
|
||||
set(_PATHS)
|
||||
foreach(_DIR ${ROCmVersion_DIR} ${ROCmVersion_ROOT} ${ROCmVersion_ROOT_DIR}
|
||||
$ENV{CMAKE_PREFIX_PATH} ${CMAKE_PREFIX_PATH} ${ROCM_PATH} /opt/rocm)
|
||||
foreach(
|
||||
_DIR
|
||||
${ROCmVersion_DIR} ${ROCmVersion_ROOT} ${ROCmVersion_ROOT_DIR}
|
||||
$ENV{CMAKE_PREFIX_PATH} ${CMAKE_PREFIX_PATH} ${OMNITRACE_DEFAULT_ROCM_PATH}
|
||||
${ROCM_PATH} /opt/rocm)
|
||||
if(EXISTS ${_DIR})
|
||||
get_filename_component(_ABS_DIR "${_DIR}" REALPATH)
|
||||
list(APPEND _PATHS ${_ABS_DIR})
|
||||
|
||||
@@ -9,7 +9,7 @@ if(NOT ROCM_PATH AND NOT "$ENV{ROCM_PATH}" STREQUAL "")
|
||||
set(ROCM_PATH "$ENV{ROCM_PATH}")
|
||||
endif()
|
||||
|
||||
foreach(_DIR ${ROCM_PATH} /opt/rocm /opt/rocm/rocm_smi)
|
||||
foreach(_DIR ${ROCmVersion_DIR} ${ROCM_PATH} /opt/rocm /opt/rocm/rocm_smi)
|
||||
if(EXISTS ${_DIR})
|
||||
get_filename_component(_ABS_DIR "${_DIR}" REALPATH)
|
||||
list(APPEND _ROCM_SMI_PATHS ${_ABS_DIR})
|
||||
|
||||
@@ -9,7 +9,7 @@ if(NOT ROCM_PATH AND NOT "$ENV{ROCM_PATH}" STREQUAL "")
|
||||
set(ROCM_PATH "$ENV{ROCM_PATH}")
|
||||
endif()
|
||||
|
||||
foreach(_DIR ${ROCM_PATH} /opt/rocm /opt/rocm/rocprofiler)
|
||||
foreach(_DIR ${ROCmVersion_DIR} ${ROCM_PATH} /opt/rocm /opt/rocm/rocprofiler)
|
||||
if(EXISTS ${_DIR})
|
||||
get_filename_component(_ABS_DIR "${_DIR}" REALPATH)
|
||||
list(APPEND _ROCM_ROCPROFILER_PATHS ${_ABS_DIR})
|
||||
@@ -48,7 +48,6 @@ find_path(
|
||||
mark_as_advanced(rocprofiler_hsa_INCLUDE_DIR)
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
find_library(
|
||||
rocprofiler_LIBRARY
|
||||
NAMES rocprofiler64 rocprofiler
|
||||
|
||||
@@ -9,7 +9,7 @@ if(NOT ROCM_PATH AND NOT "$ENV{ROCM_PATH}" STREQUAL "")
|
||||
set(ROCM_PATH "$ENV{ROCM_PATH}")
|
||||
endif()
|
||||
|
||||
foreach(_DIR ${ROCM_PATH} /opt/rocm /opt/rocm/roctracer)
|
||||
foreach(_DIR ${ROCmVersion_DIR} ${ROCM_PATH} /opt/rocm /opt/rocm/roctracer)
|
||||
if(EXISTS ${_DIR})
|
||||
get_filename_component(_ABS_DIR "${_DIR}" REALPATH)
|
||||
list(APPEND _ROCM_ROCTRACER_PATHS ${_ABS_DIR})
|
||||
@@ -70,7 +70,8 @@ find_library(
|
||||
PATHS ${roctracer_ROOT_DIR} ${_ROCM_ROCTRACER_PATHS}
|
||||
PATH_SUFFIXES lib lib64)
|
||||
|
||||
find_package(hsakmt)
|
||||
find_package(hsakmt HINTS ${_ROCM_ROCTRACER_PATHS} PATHS ${_ROCM_ROCTRACER_PATHS})
|
||||
|
||||
if(hsakmt_FOUND)
|
||||
set(roctracer_hsakmt_LIBRARY
|
||||
hsakmt::hsakmt
|
||||
|
||||
+52
-36
@@ -57,8 +57,14 @@ set(OMNITRACE_DEFAULT_ROCM_PATH
|
||||
/opt/rocm
|
||||
CACHE PATH "Default search path for ROCM")
|
||||
if(EXISTS ${OMNITRACE_DEFAULT_ROCM_PATH})
|
||||
get_filename_component(OMNITRACE_DEFAULT_ROCM_PATH "${OMNITRACE_DEFAULT_ROCM_PATH}"
|
||||
get_filename_component(_OMNITRACE_DEFAULT_ROCM_PATH "${OMNITRACE_DEFAULT_ROCM_PATH}"
|
||||
REALPATH)
|
||||
|
||||
if(NOT "${_OMNITRACE_DEFAULT_ROCM_PATH}" STREQUAL "${OMNITRACE_DEFAULT_ROCM_PATH}")
|
||||
set(OMNITRACE_DEFAULT_ROCM_PATH
|
||||
"${_OMNITRACE_DEFAULT_ROCM_PATH}"
|
||||
CACHE PATH "Default search path for ROCM" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
@@ -93,6 +99,49 @@ foreach(_LIB dl rt)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# hip version
|
||||
#
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
if(OMNITRACE_USE_HIP
|
||||
OR OMNITRACE_USE_ROCTRACER
|
||||
OR OMNITRACE_USE_ROCPROFILER
|
||||
OR OMNITRACE_USE_ROCM_SMI)
|
||||
find_package(ROCmVersion)
|
||||
|
||||
if(NOT ROCmVersion_FOUND)
|
||||
find_package(hip ${omnitrace_FIND_QUIETLY} REQUIRED HINTS
|
||||
${OMNITRACE_DEFAULT_ROCM_PATH} PATHS ${OMNITRACE_DEFAULT_ROCM_PATH})
|
||||
find_package(ROCmVersion REQUIRED HINTS ${ROCM_PATH} PATHS ${ROCM_PATH})
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_PREFIX_PATH ${ROCmVersion_DIR})
|
||||
|
||||
set(OMNITRACE_ROCM_VERSION ${ROCmVersion_FULL_VERSION})
|
||||
set(OMNITRACE_HIP_VERSION_MAJOR ${ROCmVersion_MAJOR_VERSION})
|
||||
set(OMNITRACE_HIP_VERSION_MINOR ${ROCmVersion_MINOR_VERSION})
|
||||
set(OMNITRACE_HIP_VERSION_PATCH ${ROCmVersion_PATCH_VERSION})
|
||||
set(OMNITRACE_HIP_VERSION ${ROCmVersion_TRIPLE_VERSION})
|
||||
|
||||
if(OMNITRACE_HIP_VERSION_MAJOR GREATER_EQUAL 4 AND OMNITRACE_HIP_VERSION_MINOR
|
||||
GREATER 3)
|
||||
set(roctracer_kfdwrapper_LIBRARY)
|
||||
endif()
|
||||
|
||||
if(NOT roctracer_kfdwrapper_LIBRARY)
|
||||
set(roctracer_kfdwrapper_LIBRARY)
|
||||
endif()
|
||||
|
||||
omnitrace_add_feature(OMNITRACE_ROCM_VERSION "ROCm version used by omnitrace")
|
||||
else()
|
||||
set(OMNITRACE_HIP_VERSION "0.0.0")
|
||||
set(OMNITRACE_HIP_VERSION_MAJOR 0)
|
||||
set(OMNITRACE_HIP_VERSION_MINOR 0)
|
||||
set(OMNITRACE_HIP_VERSION_PATCH 0)
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# HIP
|
||||
@@ -100,7 +149,6 @@ endforeach()
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
if(OMNITRACE_USE_HIP)
|
||||
list(APPEND CMAKE_PREFIX_PATH ${OMNITRACE_DEFAULT_ROCM_PATH})
|
||||
find_package(hip ${omnitrace_FIND_QUIETLY} REQUIRED)
|
||||
omnitrace_target_compile_definitions(omnitrace-hip INTERFACE OMNITRACE_USE_HIP)
|
||||
target_link_libraries(omnitrace-hip INTERFACE hip::host)
|
||||
@@ -113,7 +161,6 @@ endif()
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
if(OMNITRACE_USE_ROCTRACER)
|
||||
list(APPEND CMAKE_PREFIX_PATH ${OMNITRACE_DEFAULT_ROCM_PATH})
|
||||
find_package(roctracer ${omnitrace_FIND_QUIETLY} REQUIRED)
|
||||
omnitrace_target_compile_definitions(omnitrace-roctracer
|
||||
INTERFACE OMNITRACE_USE_ROCTRACER)
|
||||
@@ -128,7 +175,6 @@ endif()
|
||||
#
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
if(OMNITRACE_USE_ROCPROFILER)
|
||||
list(APPEND CMAKE_PREFIX_PATH ${OMNITRACE_DEFAULT_ROCM_PATH})
|
||||
find_package(rocprofiler ${omnitrace_FIND_QUIETLY} REQUIRED)
|
||||
omnitrace_target_compile_definitions(omnitrace-rocprofiler
|
||||
INTERFACE OMNITRACE_USE_ROCPROFILER)
|
||||
@@ -143,7 +189,6 @@ endif()
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
if(OMNITRACE_USE_ROCM_SMI)
|
||||
list(APPEND CMAKE_PREFIX_PATH ${OMNITRACE_DEFAULT_ROCM_PATH})
|
||||
find_package(rocm-smi ${omnitrace_FIND_QUIETLY} REQUIRED)
|
||||
omnitrace_target_compile_definitions(omnitrace-rocm-smi
|
||||
INTERFACE OMNITRACE_USE_ROCM_SMI)
|
||||
@@ -151,36 +196,6 @@ if(OMNITRACE_USE_ROCM_SMI)
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:${rocm-smi_LIBRARY_DIRS}")
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# hip version
|
||||
#
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
if(OMNITRACE_USE_HIP
|
||||
OR OMNITRACE_USE_ROCTRACER
|
||||
OR OMNITRACE_USE_ROCM_SMI)
|
||||
find_package(ROCmVersion REQUIRED)
|
||||
set(OMNITRACE_ROCM_VERSION ${ROCmVersion_FULL_VERSION})
|
||||
set(OMNITRACE_HIP_VERSION_MAJOR ${ROCmVersion_MAJOR_VERSION})
|
||||
set(OMNITRACE_HIP_VERSION_MINOR ${ROCmVersion_MINOR_VERSION})
|
||||
set(OMNITRACE_HIP_VERSION_PATCH ${ROCmVersion_PATCH_VERSION})
|
||||
set(OMNITRACE_HIP_VERSION ${ROCmVersion_TRIPLE_VERSION})
|
||||
if(OMNITRACE_HIP_VERSION_MAJOR GREATER_EQUAL 4 AND OMNITRACE_HIP_VERSION_MINOR
|
||||
GREATER 3)
|
||||
set(roctracer_kfdwrapper_LIBRARY)
|
||||
endif()
|
||||
if(NOT roctracer_kfdwrapper_LIBRARY)
|
||||
set(roctracer_kfdwrapper_LIBRARY)
|
||||
endif()
|
||||
omnitrace_add_feature(OMNITRACE_ROCM_VERSION "ROCm version used by omnitrace")
|
||||
else()
|
||||
set(OMNITRACE_HIP_VERSION "0.0.0")
|
||||
set(OMNITRACE_HIP_VERSION_MAJOR 0)
|
||||
set(OMNITRACE_HIP_VERSION_MINOR 0)
|
||||
set(OMNITRACE_HIP_VERSION_PATCH 0)
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
#
|
||||
# MPI
|
||||
@@ -276,7 +291,8 @@ if(OMNITRACE_BUILD_DYNINST)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
omnitrace_install_tpl(dyninstAPI_RT omnitrace-rt "${PROJECT_BINARY_DIR}")
|
||||
omnitrace_install_tpl(dyninstAPI_RT omnitrace-rt
|
||||
"${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
# for packaging
|
||||
install(
|
||||
|
||||
@@ -12,8 +12,8 @@ option(BUILD_SHARED_LIBS "Build dynamic libraries" ON)
|
||||
|
||||
if(CMAKE_PROJECT_NAME STREQUAL "omnitrace")
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
|
||||
omnitrace_add_option(OMNITRACE_INSTALL_EXAMPLES "Install omnitrace examples" OFF)
|
||||
else()
|
||||
option(OMNITRACE_INSTALL_EXAMPLES "Install omnitrace examples" ON)
|
||||
|
||||
@@ -13,13 +13,13 @@ if(LULESH_BUILD_KOKKOS)
|
||||
kokkos_compilation(PROJECT)
|
||||
elseif(LULESH_USE_HIP AND NOT "${CMAKE_CXX_COMPILER}" MATCHES "hipcc")
|
||||
if(NOT HIPCC_EXECUTABLE)
|
||||
find_package(hip QUIET)
|
||||
find_package(hip QUIET HINTS ${ROCmVersion_DIR} PATHS ${ROCmVersion_DIR})
|
||||
|
||||
find_program(
|
||||
HIPCC_EXECUTABLE
|
||||
NAMES hipcc
|
||||
HINTS ${ROCM_PATH} ENV ROCM_PATH /opt/rocm
|
||||
PATHS ${ROCM_PATH} ENV ROCM_PATH /opt/rocm)
|
||||
HINTS ${ROCmVersion_DIR} ${ROCM_PATH} ENV ROCM_PATH /opt/rocm
|
||||
PATHS ${ROCmVersion_DIR} ${ROCM_PATH} ENV ROCM_PATH /opt/rocm)
|
||||
mark_as_advanced(HIPCC_EXECUTABLE)
|
||||
endif()
|
||||
kokkos_compilation(PROJECT COMPILER ${HIPCC_EXECUTABLE})
|
||||
|
||||
@@ -2,13 +2,13 @@ cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
|
||||
|
||||
project(omnitrace-transpose LANGUAGES CXX)
|
||||
|
||||
find_package(hip QUIET)
|
||||
find_package(hip QUIET HINTS ${ROCmVersion_DIR} PATHS ${ROCmVersion_DIR})
|
||||
|
||||
find_program(
|
||||
HIPCC_EXECUTABLE
|
||||
NAMES hipcc
|
||||
HINTS ${ROCM_PATH} ENV ROCM_PATH /opt/rocm
|
||||
PATHS ${ROCM_PATH} ENV ROCM_PATH /opt/rocm)
|
||||
HINTS ${ROCmVersion_DIR} ${ROCM_PATH} ENV ROCM_PATH /opt/rocm
|
||||
PATHS ${ROCmVersion_DIR} ${ROCM_PATH} ENV ROCM_PATH /opt/rocm NO_CACHE)
|
||||
mark_as_advanced(HIPCC_EXECUTABLE)
|
||||
|
||||
if(NOT HIPCC_EXECUTABLE)
|
||||
|
||||
@@ -32,6 +32,7 @@ THE SOFTWARE.
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <random>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
@@ -46,7 +47,7 @@ using auto_lock_t = std::unique_lock<std::mutex>;
|
||||
auto_lock_t _lk{ print_lock }; \
|
||||
fprintf(stderr, "%s:%d :: HIP error : %s\n", __FILE__, __LINE__, \
|
||||
hipGetErrorString(error_)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
throw std::runtime_error("hip_api_call"); \
|
||||
} \
|
||||
}
|
||||
|
||||
@@ -58,7 +59,7 @@ check_hip_error(void)
|
||||
{
|
||||
auto_lock_t _lk{ print_lock };
|
||||
std::cerr << "Error: " << hipGetErrorString(err) << std::endl;
|
||||
exit(err);
|
||||
throw std::runtime_error("hip_api_call");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
поставляемый
+1
-1
Submodule external/timemory updated: 1c03bec283...127a235bc3
@@ -6,9 +6,9 @@ if(OMNITRACE_BUILD_LTO)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
||||
endif()
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(bin)
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
#include "fwd.hpp"
|
||||
#include "omnitrace.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
static int expect_error = NO_ERROR;
|
||||
static int error_print = 0;
|
||||
|
||||
@@ -513,6 +516,49 @@ get_whole_function_names()
|
||||
#endif
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Helper functions because the syntax for getting a function or module name is unwieldy
|
||||
//
|
||||
std::string_view
|
||||
get_name(procedure_t* _func)
|
||||
{
|
||||
static auto _v = std::unordered_map<procedure_t*, std::string>{};
|
||||
|
||||
auto itr = _v.find(_func);
|
||||
if(itr == _v.end())
|
||||
{
|
||||
_v.emplace(_func, (_func) ? _func->getDemangledName() : std::string{});
|
||||
}
|
||||
|
||||
return _v.at(_func);
|
||||
}
|
||||
|
||||
std::string_view
|
||||
get_name(module_t* _module)
|
||||
{
|
||||
static auto _v = std::unordered_map<module_t*, std::string>{};
|
||||
|
||||
auto itr = _v.find(_module);
|
||||
if(itr == _v.end())
|
||||
{
|
||||
char _name[FUNCNAMELEN + 1];
|
||||
memset(_name, '\0', FUNCNAMELEN + 1);
|
||||
|
||||
if(_module)
|
||||
{
|
||||
_module->getFullName(_name, FUNCNAMELEN);
|
||||
_v.emplace(_module, std::string{ _name });
|
||||
}
|
||||
else
|
||||
{
|
||||
_v.emplace(nullptr, std::string{});
|
||||
}
|
||||
}
|
||||
|
||||
return _v.at(_module);
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// For selective instrumentation (unused)
|
||||
@@ -523,6 +569,69 @@ are_file_include_exclude_lists_empty()
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string
|
||||
get_return_type(procedure_t* func)
|
||||
{
|
||||
if(func && func->isInstrumentable() && func->getReturnType())
|
||||
return func->getReturnType()->getName();
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
auto
|
||||
get_parameter_types(procedure_t* func)
|
||||
{
|
||||
auto _param_names = std::vector<std::string>{};
|
||||
if(func && func->isInstrumentable())
|
||||
{
|
||||
auto* _params = func->getParams();
|
||||
if(_params)
|
||||
{
|
||||
_param_names.reserve(_params->size());
|
||||
for(auto* itr : *_params)
|
||||
{
|
||||
std::string _name = itr->getType()->getName();
|
||||
if(_name.empty()) _name = itr->getName();
|
||||
_param_names.emplace_back(_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _param_names;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// We create a new name that embeds the file and line information in the name
|
||||
//
|
||||
function_signature
|
||||
get_func_file_line_info(module_t* module, procedure_t* func)
|
||||
{
|
||||
using address_t = Dyninst::Address;
|
||||
|
||||
auto _file_name = get_name(module);
|
||||
auto _func_name = get_name(func);
|
||||
auto _return_type = get_return_type(func);
|
||||
auto _param_types = get_parameter_types(func);
|
||||
auto _base_addr = address_t{};
|
||||
auto _last_addr = address_t{};
|
||||
auto _src_lines = std::vector<statement_t>{};
|
||||
|
||||
if(func->getAddressRange(_base_addr, _last_addr) &&
|
||||
module->getSourceLines(_base_addr, _src_lines) && !_src_lines.empty())
|
||||
{
|
||||
auto _row = _src_lines.front().lineNumber();
|
||||
return function_signature(_return_type, _func_name, _file_name, _param_types,
|
||||
{ _row, 0 }, { 0, 0 }, false, true, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return function_signature(_return_type, _func_name, _file_name, _param_types,
|
||||
{ 0, 0 }, { 0, 0 }, false, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Gets information (line number, filename, and column number) about
|
||||
@@ -532,173 +641,84 @@ function_signature
|
||||
get_loop_file_line_info(module_t* module, procedure_t* func, flow_graph_t*,
|
||||
basic_loop_t* loopToInstrument)
|
||||
{
|
||||
std::vector<BPatch_basicBlock*> basic_blocks{};
|
||||
auto basic_blocks = std::vector<BPatch_basicBlock*>{};
|
||||
loopToInstrument->getLoopBasicBlocksExclusive(basic_blocks);
|
||||
|
||||
if(basic_blocks.empty()) return function_signature{ "", "", "" };
|
||||
|
||||
auto base_addr = basic_blocks.front()->getStartAddress();
|
||||
auto last_addr = basic_blocks.front()->getEndAddress();
|
||||
basic_block_t* block = basic_blocks.front();
|
||||
auto* _block = basic_blocks.front();
|
||||
auto _base_addr = _block->getStartAddress();
|
||||
auto _last_addr = _block->getEndAddress();
|
||||
for(const auto& itr : basic_blocks)
|
||||
{
|
||||
if(itr == block) continue;
|
||||
if(itr->dominates(block))
|
||||
if(itr == _block) continue;
|
||||
if(itr->dominates(_block))
|
||||
{
|
||||
base_addr = itr->getStartAddress();
|
||||
last_addr = itr->getEndAddress();
|
||||
block = itr;
|
||||
_base_addr = itr->getStartAddress();
|
||||
_last_addr = itr->getEndAddress();
|
||||
_block = itr;
|
||||
}
|
||||
}
|
||||
|
||||
verbprintf(4, "Loop: size = %lu: base_addr = %lu, last_addr = %lu\n",
|
||||
(unsigned long) (last_addr - base_addr), base_addr, last_addr);
|
||||
auto _file_name = get_name(module);
|
||||
auto _func_name = get_name(func);
|
||||
auto _return_type = get_return_type(func);
|
||||
auto _param_types = get_parameter_types(func);
|
||||
auto _lines_beg = std::vector<statement_t>{};
|
||||
auto _lines_end = std::vector<statement_t>{};
|
||||
|
||||
char fname[FUNCNAMELEN + 1];
|
||||
char mname[FUNCNAMELEN + 1];
|
||||
std::string typeName = {};
|
||||
|
||||
memset(fname, '\0', FUNCNAMELEN + 1);
|
||||
memset(mname, '\0', FUNCNAMELEN + 1);
|
||||
|
||||
module->getFullName(mname, FUNCNAMELEN);
|
||||
func->getName(fname, FUNCNAMELEN);
|
||||
|
||||
auto* returnType = func->getReturnType();
|
||||
|
||||
if(returnType) typeName = returnType->getName();
|
||||
|
||||
auto* params = func->getParams();
|
||||
std::vector<string_t> _params;
|
||||
if(params)
|
||||
{
|
||||
for(auto* itr : *params)
|
||||
{
|
||||
string_t _name = itr->getType()->getName();
|
||||
if(_name.empty()) _name = itr->getName();
|
||||
_params.push_back(_name);
|
||||
}
|
||||
}
|
||||
|
||||
bpvector_t<BPatch_statement> lines{};
|
||||
bpvector_t<BPatch_statement> linesEnd{};
|
||||
|
||||
bool info1 = module->getSourceLines(base_addr, lines);
|
||||
|
||||
string_t filename = mname;
|
||||
|
||||
if(info1)
|
||||
if(module->getSourceLines(_base_addr, _lines_beg))
|
||||
{
|
||||
// filename = lines[0].fileName();
|
||||
int row1 = 0;
|
||||
int col1 = 0;
|
||||
for(auto& itr : lines)
|
||||
int _row1 = 0;
|
||||
int _col1 = 0;
|
||||
for(auto& itr : _lines_beg)
|
||||
{
|
||||
if(itr.lineNumber() > 0)
|
||||
{
|
||||
row1 = itr.lineNumber();
|
||||
col1 = itr.lineOffset();
|
||||
_row1 = itr.lineNumber();
|
||||
_col1 = itr.lineOffset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(row1 == 0 && col1 == 0)
|
||||
return function_signature(typeName, fname, filename, _params);
|
||||
if(_row1 == 0 && _col1 == 0)
|
||||
return function_signature(_return_type, _func_name, _file_name, _param_types);
|
||||
|
||||
int row2 = 0;
|
||||
int col2 = 0;
|
||||
for(auto& itr : lines)
|
||||
int _row2 = 0;
|
||||
int _col2 = 0;
|
||||
for(auto& itr : _lines_beg)
|
||||
{
|
||||
row2 = std::max(row2, itr.lineNumber());
|
||||
col2 = std::max(col2, itr.lineOffset());
|
||||
_row2 = std::max(_row2, itr.lineNumber());
|
||||
_col2 = std::max(_col2, itr.lineOffset());
|
||||
}
|
||||
|
||||
if(col1 < 0) col1 = 0;
|
||||
if(_col1 < 0) _col1 = 0;
|
||||
|
||||
bool info2 = module->getSourceLines(last_addr, linesEnd);
|
||||
verbprintf(4, "size of linesEnd = %lu\n", (unsigned long) linesEnd.size());
|
||||
|
||||
if(info2)
|
||||
if(module->getSourceLines(_last_addr, _lines_end))
|
||||
{
|
||||
for(auto& itr : linesEnd)
|
||||
for(auto& itr : _lines_end)
|
||||
{
|
||||
row2 = std::max(row2, itr.lineNumber());
|
||||
col2 = std::max(col2, itr.lineOffset());
|
||||
_row2 = std::max(_row2, itr.lineNumber());
|
||||
_col2 = std::max(_col2, itr.lineOffset());
|
||||
}
|
||||
if(col2 < 0) col2 = 0;
|
||||
if(row2 < row1) row1 = row2; // Fix for wrong line numbers
|
||||
if(_col2 < 0) _col2 = 0;
|
||||
if(_row2 < _row1) _row1 = _row2; // Fix for wrong line numbers
|
||||
|
||||
return function_signature(typeName, fname, filename, _params, { row1, row2 },
|
||||
{ col1, col2 }, true, info1, info2);
|
||||
return function_signature(_return_type, _func_name, _file_name, _param_types,
|
||||
{ _row1, _row2 }, { _col1, _col2 }, true, true,
|
||||
true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return function_signature(typeName, fname, filename, _params, { row1, 0 },
|
||||
{ col1, 0 }, true, info1, info2);
|
||||
return function_signature(_return_type, _func_name, _file_name, _param_types,
|
||||
{ _row1, 0 }, { _col1, 0 }, true, true, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return function_signature(typeName, fname, filename, _params, { 0, 0 }, { 0, 0 },
|
||||
true, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// We create a new name that embeds the file and line information in the name
|
||||
//
|
||||
function_signature
|
||||
get_func_file_line_info(module_t* module, procedure_t* func)
|
||||
{
|
||||
using address_t = Dyninst::Address;
|
||||
|
||||
char fname[FUNCNAMELEN + 1];
|
||||
char mname[FUNCNAMELEN + 1];
|
||||
string_t typeName = {};
|
||||
|
||||
memset(fname, '\0', FUNCNAMELEN + 1);
|
||||
memset(mname, '\0', FUNCNAMELEN + 1);
|
||||
|
||||
module->getFullName(mname, FUNCNAMELEN);
|
||||
func->getName(fname, FUNCNAMELEN);
|
||||
|
||||
address_t base_addr{};
|
||||
address_t last_addr{};
|
||||
func->getAddressRange(base_addr, last_addr);
|
||||
|
||||
auto* returnType = func->getReturnType();
|
||||
|
||||
if(returnType) typeName = returnType->getName();
|
||||
|
||||
auto* params = func->getParams();
|
||||
std::vector<string_t> _params = {};
|
||||
if(params)
|
||||
{
|
||||
_params.reserve(params->size());
|
||||
for(auto* itr : *params)
|
||||
{
|
||||
string_t _name = itr->getType()->getName();
|
||||
if(_name.empty()) _name = itr->getName();
|
||||
_params.emplace_back(_name);
|
||||
}
|
||||
}
|
||||
|
||||
bpvector_t<BPatch_statement> lines = {};
|
||||
bool info = module->getSourceLines(base_addr, lines);
|
||||
|
||||
string_t filename = mname;
|
||||
|
||||
if(info && !lines.empty())
|
||||
{
|
||||
auto row = lines.front().lineNumber();
|
||||
return function_signature(typeName, fname, filename, _params, { row, 0 },
|
||||
{ 0, 0 }, false, info, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return function_signature(typeName, fname, filename, _params, { 0, 0 }, { 0, 0 },
|
||||
false, false, false);
|
||||
return function_signature(_return_type, _func_name, _file_name, _param_types,
|
||||
{ 0, 0 }, { 0, 0 }, true, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -713,89 +733,69 @@ get_basic_block_file_line_info(module_t* module, procedure_t* func)
|
||||
std::map<basic_block_t*, basic_block_signature> _data{};
|
||||
if(!func) return _data;
|
||||
|
||||
auto* _cfg = func->getCFG();
|
||||
std::set<BPatch_basicBlock*> _basic_blocks{};
|
||||
auto* _cfg = func->getCFG();
|
||||
auto _basic_blocks = std::set<BPatch_basicBlock*>{};
|
||||
_cfg->getAllBasicBlocks(_basic_blocks);
|
||||
|
||||
if(_basic_blocks.empty()) return _data;
|
||||
|
||||
char fname[FUNCNAMELEN + 1];
|
||||
char mname[FUNCNAMELEN + 1];
|
||||
std::string typeName = {};
|
||||
|
||||
memset(fname, '\0', FUNCNAMELEN + 1);
|
||||
memset(mname, '\0', FUNCNAMELEN + 1);
|
||||
|
||||
module->getFullName(mname, FUNCNAMELEN);
|
||||
func->getName(fname, FUNCNAMELEN);
|
||||
|
||||
auto* returnType = func->getReturnType();
|
||||
|
||||
if(returnType) typeName = returnType->getName();
|
||||
|
||||
auto* params = func->getParams();
|
||||
std::vector<string_t> _params;
|
||||
if(params)
|
||||
{
|
||||
for(auto* itr : *params)
|
||||
{
|
||||
string_t _name = itr->getType()->getName();
|
||||
if(_name.empty()) _name = itr->getName();
|
||||
_params.push_back(_name);
|
||||
}
|
||||
}
|
||||
auto _file_name = get_name(module);
|
||||
auto _func_name = get_name(func);
|
||||
auto _return_type = get_return_type(func);
|
||||
auto _param_types = get_parameter_types(func);
|
||||
|
||||
for(auto&& itr : _basic_blocks)
|
||||
{
|
||||
auto base_addr = itr->getStartAddress();
|
||||
auto last_addr = itr->getEndAddress();
|
||||
auto _base_addr = itr->getStartAddress();
|
||||
auto _last_addr = itr->getEndAddress();
|
||||
|
||||
verbprintf(4, "BB: size = %lu: base_addr = %lu, last_addr = %lu\n",
|
||||
(unsigned long) (last_addr - base_addr), base_addr, last_addr);
|
||||
verbprintf(4,
|
||||
"[%s][%s] basic_block: size = %lu: base_addr = %lu, last_addr = %lu\n",
|
||||
_file_name.data(), _func_name.data(),
|
||||
(unsigned long) (_last_addr - _base_addr), _base_addr, _last_addr);
|
||||
|
||||
bpvector_t<BPatch_statement> linesBeg{};
|
||||
bpvector_t<BPatch_statement> linesEnd{};
|
||||
auto _lines_beg = std::vector<statement_t>{};
|
||||
auto _lines_end = std::vector<statement_t>{};
|
||||
|
||||
string_t filename = mname;
|
||||
|
||||
if(module->getSourceLines(base_addr, linesBeg) && !linesBeg.empty())
|
||||
if(module->getSourceLines(_base_addr, _lines_beg) && !_lines_beg.empty())
|
||||
{
|
||||
int row1 = linesBeg.front().lineNumber();
|
||||
int col1 = linesBeg.front().lineOffset();
|
||||
int _row1 = _lines_beg.front().lineNumber();
|
||||
int _col1 = _lines_beg.front().lineOffset();
|
||||
|
||||
verbprintf(4, "size of linesEnd = %lu\n", (unsigned long) linesEnd.size());
|
||||
verbprintf(4, "size of _lines_end = %lu\n",
|
||||
(unsigned long) _lines_end.size());
|
||||
|
||||
if(module->getSourceLines(last_addr, linesEnd) && !linesEnd.empty())
|
||||
if(module->getSourceLines(_last_addr, _lines_end) && !_lines_end.empty())
|
||||
{
|
||||
int row2 = linesEnd.back().lineNumber();
|
||||
int col2 = linesEnd.back().lineOffset();
|
||||
int _row2 = _lines_end.back().lineNumber();
|
||||
int _col2 = _lines_end.back().lineOffset();
|
||||
|
||||
if(row2 < row1) std::swap(row1, row2);
|
||||
if(row1 == row2 && col2 < col1) std::swap(col1, col2);
|
||||
if(_row2 < _row1) std::swap(_row1, _row2);
|
||||
if(_row1 == _row2 && _col2 < _col1) std::swap(_col1, _col2);
|
||||
|
||||
_data.emplace(itr,
|
||||
basic_block_signature{
|
||||
base_addr, last_addr,
|
||||
function_signature(typeName, fname, filename, _params,
|
||||
{ row1, row2 }, { col1, col2 }, true,
|
||||
true, true) });
|
||||
_data.emplace(
|
||||
itr, basic_block_signature{
|
||||
_base_addr, _last_addr,
|
||||
function_signature(_return_type, _func_name, _file_name,
|
||||
_param_types, { _row1, _row2 },
|
||||
{ _col1, _col2 }, true, true, true) });
|
||||
}
|
||||
else
|
||||
{
|
||||
_data.emplace(itr,
|
||||
basic_block_signature{
|
||||
base_addr, last_addr,
|
||||
function_signature(typeName, fname, filename, _params,
|
||||
{ row1, 0 }, { col1, 0 }, true, true,
|
||||
false) });
|
||||
_base_addr, _last_addr,
|
||||
function_signature(_return_type, _func_name, _file_name,
|
||||
_param_types, { _row1, 0 },
|
||||
{ _col1, 0 }, true, true, false) });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_data.emplace(itr,
|
||||
basic_block_signature{
|
||||
base_addr, last_addr,
|
||||
function_signature(typeName, fname, filename, _params) });
|
||||
_data.emplace(itr, basic_block_signature{
|
||||
_base_addr, _last_addr,
|
||||
function_signature(_return_type, _func_name,
|
||||
_file_name, _param_types) });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -861,7 +861,7 @@ find_function(image_t* app_image, const std::string& _name, const strset_t& _ext
|
||||
{
|
||||
if(_name.empty()) return nullptr;
|
||||
|
||||
auto _find = [app_image](const string_t& _f) -> procedure_t* {
|
||||
auto _find = [app_image](const std::string& _f) -> procedure_t* {
|
||||
// Extract the vector of functions
|
||||
bpvector_t<procedure_t*> _found;
|
||||
auto* ret = app_image->findFunction(_f.c_str(), _found, false, true, true);
|
||||
|
||||
@@ -22,25 +22,26 @@
|
||||
|
||||
#include "function_signature.hpp"
|
||||
|
||||
function_signature::function_signature(string_t _ret, const string_t& _name,
|
||||
string_t _file, location_t _row, location_t _col,
|
||||
bool _loop, bool _info_beg, bool _info_end)
|
||||
function_signature::function_signature(std::string_view _ret, std::string_view _name,
|
||||
std::string_view _file, location_t _row,
|
||||
location_t _col, bool _loop, bool _info_beg,
|
||||
bool _info_end)
|
||||
: m_loop(_loop)
|
||||
, m_info_beg(_info_beg)
|
||||
, m_info_end(_info_end)
|
||||
, m_row(std::move(_row))
|
||||
, m_col(std::move(_col))
|
||||
, m_return(std::move(_ret))
|
||||
, m_name(tim::demangle(_name))
|
||||
, m_file(std::move(_file))
|
||||
, m_return(_ret)
|
||||
, m_name(tim::demangle(_name.data()))
|
||||
, m_file(_file)
|
||||
{
|
||||
if(m_file.find('/') != string_t::npos)
|
||||
if(m_file.find('/') != std::string_view::npos)
|
||||
m_file = m_file.substr(m_file.find_last_of('/') + 1);
|
||||
}
|
||||
|
||||
function_signature::function_signature(const string_t& _ret, const string_t& _name,
|
||||
const string_t& _file,
|
||||
const std::vector<string_t>& _params,
|
||||
function_signature::function_signature(std::string_view _ret, std::string_view _name,
|
||||
std::string_view _file,
|
||||
const std::vector<std::string>& _params,
|
||||
location_t _row, location_t _col, bool _loop,
|
||||
bool _info_beg, bool _info_end)
|
||||
: function_signature(_ret, _name, _file, _row, _col, _loop, _info_beg, _info_end)
|
||||
@@ -52,13 +53,13 @@ function_signature::function_signature(const string_t& _ret, const string_t& _na
|
||||
m_params += ")";
|
||||
}
|
||||
|
||||
string_t
|
||||
std::string
|
||||
function_signature::get(function_signature& sig)
|
||||
{
|
||||
return sig.get();
|
||||
}
|
||||
|
||||
string_t
|
||||
std::string
|
||||
function_signature::get(bool _all, bool _save) const
|
||||
{
|
||||
if(!_all && _save && !m_signature.empty()) return m_signature;
|
||||
@@ -103,7 +104,7 @@ function_signature::get(bool _all, bool _save) const
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
string_t
|
||||
std::string
|
||||
function_signature::get_coverage(bool _basic_block) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
@@ -24,49 +24,65 @@
|
||||
|
||||
#include "fwd.hpp"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
struct function_signature
|
||||
{
|
||||
using location_t = std::pair<unsigned long, unsigned long>;
|
||||
|
||||
TIMEMORY_DEFAULT_OBJECT(function_signature)
|
||||
|
||||
function_signature(string_t _ret, const string_t& _name, string_t _file,
|
||||
function_signature(std::string_view _ret, std::string_view _name,
|
||||
std::string_view _file, location_t _row = { 0, 0 },
|
||||
location_t _col = { 0, 0 }, bool _loop = false,
|
||||
bool _info_beg = false, bool _info_end = false);
|
||||
|
||||
function_signature(std::string_view _ret, std::string_view _name,
|
||||
std::string_view _file, const std::vector<std::string>& _params,
|
||||
location_t _row = { 0, 0 }, location_t _col = { 0, 0 },
|
||||
bool _loop = false, bool _info_beg = false,
|
||||
bool _info_end = false);
|
||||
|
||||
function_signature(const string_t& _ret, const string_t& _name, const string_t& _file,
|
||||
const std::vector<string_t>& _params, location_t _row = { 0, 0 },
|
||||
location_t _col = { 0, 0 }, bool _loop = false,
|
||||
bool _info_beg = false, bool _info_end = false);
|
||||
|
||||
function_signature& set_loop_number(uint32_t _n)
|
||||
{
|
||||
m_loop_num = _n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
static string_t get(function_signature& sig);
|
||||
string_t get(bool _all = false, bool _save = true) const;
|
||||
string_t get_coverage(bool _is_basic_block) const;
|
||||
static std::string get(function_signature& sig);
|
||||
std::string get(bool _all = false, bool _save = true) const;
|
||||
std::string get_coverage(bool _is_basic_block) const;
|
||||
|
||||
bool m_loop = false;
|
||||
bool m_info_beg = false;
|
||||
bool m_info_end = false;
|
||||
uint32_t m_loop_num = std::numeric_limits<uint32_t>::max();
|
||||
location_t m_row = { 0, 0 };
|
||||
location_t m_col = { 0, 0 };
|
||||
string_t m_return = {};
|
||||
string_t m_name = {};
|
||||
string_t m_params = "()";
|
||||
string_t m_file = {};
|
||||
mutable string_t m_signature = {};
|
||||
bool m_loop = false;
|
||||
bool m_info_beg = false;
|
||||
bool m_info_end = false;
|
||||
uint32_t m_loop_num = std::numeric_limits<uint32_t>::max();
|
||||
location_t m_row = { 0, 0 };
|
||||
location_t m_col = { 0, 0 };
|
||||
std::string m_return = {};
|
||||
std::string m_name = {};
|
||||
std::string m_params = "()";
|
||||
std::string m_file = {};
|
||||
mutable std::string m_signature = {};
|
||||
|
||||
friend bool operator==(const function_signature& lhs, const function_signature& rhs)
|
||||
{
|
||||
return lhs.get() == rhs.get();
|
||||
}
|
||||
|
||||
friend bool operator<(const function_signature& lhs, const function_signature& rhs)
|
||||
{
|
||||
const auto loop_max = std::numeric_limits<uint32_t>::max();
|
||||
if(lhs.m_loop && !rhs.m_loop) return false;
|
||||
if(!lhs.m_loop && rhs.m_loop) return true;
|
||||
if(lhs.m_loop_num < loop_max && rhs.m_loop_num == loop_max) return false;
|
||||
if(lhs.m_loop_num == loop_max && rhs.m_loop_num < loop_max) return true;
|
||||
return std::tie(lhs.m_file, lhs.m_name, lhs.m_return, lhs.m_params,
|
||||
lhs.m_row.first, lhs.m_col.first, lhs.m_loop_num) <
|
||||
std::tie(rhs.m_file, rhs.m_name, rhs.m_return, rhs.m_params,
|
||||
rhs.m_row.first, rhs.m_col.first, rhs.m_loop_num);
|
||||
}
|
||||
|
||||
template <typename ArchiveT>
|
||||
void serialize(ArchiveT& _ar, const unsigned)
|
||||
{
|
||||
|
||||
@@ -42,11 +42,14 @@
|
||||
#include <BPatch_callbacks.h>
|
||||
#include <BPatch_function.h>
|
||||
#include <BPatch_instruction.h>
|
||||
#include <BPatch_object.h>
|
||||
#include <BPatch_point.h>
|
||||
#include <BPatch_process.h>
|
||||
#include <BPatch_snippet.h>
|
||||
#include <BPatch_statement.h>
|
||||
#include <Instruction.h>
|
||||
#include <Symtab.h>
|
||||
#include <SymtabReader.h>
|
||||
#include <dyntypes.h>
|
||||
|
||||
#include <climits>
|
||||
@@ -66,6 +69,7 @@
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unistd.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#define MUTNAMELEN 1024
|
||||
@@ -111,9 +115,12 @@ using basic_block_t = BPatch_basicBlock;
|
||||
using basic_loop_t = BPatch_basicBlockLoop;
|
||||
using procedure_loc_t = BPatch_procedureLocation;
|
||||
using point_t = BPatch_point;
|
||||
using object_t = BPatch_object;
|
||||
using local_var_t = BPatch_localVar;
|
||||
using sequence_t = BPatch_sequence;
|
||||
using const_expr_t = BPatch_constExpr;
|
||||
using error_level_t = BPatchErrorLevel;
|
||||
using snippet_handle_t = BPatchSnippetHandle;
|
||||
using patch_pointer_t = std::shared_ptr<patch_t>;
|
||||
using snippet_pointer_t = std::shared_ptr<snippet_t>;
|
||||
using call_expr_pointer_t = std::shared_ptr<call_expr_t>;
|
||||
@@ -166,6 +173,11 @@ extern bool debug_print;
|
||||
extern bool instr_print;
|
||||
extern int verbose_level;
|
||||
//
|
||||
// instrumentation settings
|
||||
//
|
||||
extern bool simulate;
|
||||
extern bool include_uninstr;
|
||||
//
|
||||
// string settings
|
||||
//
|
||||
extern string_t main_fname;
|
||||
@@ -297,3 +309,9 @@ error_func_real(error_level_t level, int num, const char* const* params);
|
||||
|
||||
void
|
||||
error_func_fake(error_level_t level, int num, const char* const* params);
|
||||
|
||||
std::string_view
|
||||
get_name(procedure_t* _module);
|
||||
|
||||
std::string_view
|
||||
get_name(module_t* _module);
|
||||
|
||||
@@ -55,44 +55,48 @@ module_function::module_function(module_t* mod, procedure_t* proc)
|
||||
: module{ mod }
|
||||
, function{ proc }
|
||||
, flow_graph{ proc->getCFG() }
|
||||
, module_name{ get_name(module) }
|
||||
, function_name{ get_name(function) }
|
||||
{
|
||||
if(flow_graph)
|
||||
{
|
||||
flow_graph->getAllBasicBlocks(basic_blocks);
|
||||
flow_graph->getOuterLoops(loop_blocks);
|
||||
}
|
||||
|
||||
instructions.reserve(basic_blocks.size());
|
||||
for(const auto& itr : basic_blocks)
|
||||
{
|
||||
std::vector<instruction_t> _instructions{};
|
||||
itr->getInstructions(_instructions);
|
||||
num_instructions += _instructions.size();
|
||||
if(debug_print || verbose_level > 3 || instr_print)
|
||||
instructions.emplace_back(std::move(_instructions));
|
||||
}
|
||||
|
||||
char modname[FUNCNAMELEN];
|
||||
char fname[FUNCNAMELEN];
|
||||
module->getFullName(modname, FUNCNAMELEN);
|
||||
function->getName(fname, FUNCNAMELEN);
|
||||
module_name = modname;
|
||||
function_name = fname;
|
||||
signature = get_func_file_line_info(module, function);
|
||||
|
||||
if(!function->isInstrumentable())
|
||||
{
|
||||
verbprintf(0,
|
||||
verbprintf(1,
|
||||
"Warning! module function generated for un-instrumentable "
|
||||
"function: %s [%s]\n",
|
||||
function_name.c_str(), module_name.c_str());
|
||||
}
|
||||
std::pair<address_t, address_t> _range{};
|
||||
|
||||
auto _range = std::pair<address_t, address_t>{};
|
||||
if(function->getAddressRange(_range.first, _range.second))
|
||||
{
|
||||
start_address = _range.first;
|
||||
address_range = _range.second - _range.first;
|
||||
}
|
||||
|
||||
signature = get_func_file_line_info(module, function);
|
||||
|
||||
if(function->isInstrumentable())
|
||||
{
|
||||
// this information is potentially not available and
|
||||
// appears to be the cause of a segfault in testing
|
||||
// so only attempt to extract it for instrumentable
|
||||
// functions
|
||||
if(flow_graph)
|
||||
{
|
||||
flow_graph->getAllBasicBlocks(basic_blocks);
|
||||
flow_graph->getOuterLoops(loop_blocks);
|
||||
}
|
||||
|
||||
instructions.reserve(basic_blocks.size());
|
||||
for(const auto& itr : basic_blocks)
|
||||
{
|
||||
std::vector<instruction_t> _instructions{};
|
||||
itr->getInstructions(_instructions);
|
||||
num_instructions += _instructions.size();
|
||||
if(debug_print || verbose_level > 3 || instr_print)
|
||||
instructions.emplace_back(std::move(_instructions));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
struct module_function
|
||||
{
|
||||
@@ -117,19 +118,18 @@ public:
|
||||
|
||||
friend bool operator<(const module_function& lhs, const module_function& rhs)
|
||||
{
|
||||
return (lhs.module_name == rhs.module_name)
|
||||
? ((lhs.function_name == rhs.function_name)
|
||||
? (lhs.signature.get() < rhs.signature.get())
|
||||
: (lhs.function_name < rhs.function_name))
|
||||
: (lhs.module_name < rhs.module_name);
|
||||
return std::tie(lhs.module_name, lhs.start_address, lhs.function_name,
|
||||
lhs.address_range, lhs.num_instructions, lhs.signature) <
|
||||
std::tie(rhs.module_name, rhs.start_address, rhs.function_name,
|
||||
rhs.address_range, rhs.num_instructions, rhs.signature);
|
||||
}
|
||||
|
||||
friend bool operator==(const module_function& lhs, const module_function& rhs)
|
||||
{
|
||||
return std::tie(lhs.module_name, lhs.function_name, lhs.signature,
|
||||
lhs.address_range, lhs.num_instructions) ==
|
||||
std::tie(rhs.module_name, rhs.function_name, rhs.signature,
|
||||
rhs.address_range, rhs.num_instructions);
|
||||
return std::tie(lhs.module_name, lhs.start_address, lhs.function_name,
|
||||
lhs.address_range, lhs.num_instructions, lhs.signature) ==
|
||||
std::tie(rhs.module_name, rhs.start_address, rhs.function_name,
|
||||
rhs.address_range, rhs.num_instructions, rhs.signature);
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const module_function& rhs)
|
||||
|
||||
@@ -23,19 +23,23 @@
|
||||
#include "omnitrace.hpp"
|
||||
#include "fwd.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <timemory/config.hpp>
|
||||
#include <timemory/hash.hpp>
|
||||
#include <timemory/manager.hpp>
|
||||
#include <timemory/settings.hpp>
|
||||
#include <timemory/utility/console.hpp>
|
||||
#include <timemory/utility/demangle.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <csignal>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <regex>
|
||||
#include <stdexcept>
|
||||
@@ -43,6 +47,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -70,6 +75,8 @@ size_t min_loop_instructions = (1 << 6); // 64
|
||||
bool werror = false;
|
||||
bool debug_print = false;
|
||||
bool instr_print = false;
|
||||
bool simulate = false;
|
||||
bool include_uninstr = false;
|
||||
int verbose_level = tim::get_env<int>("OMNITRACE_VERBOSE_INSTRUMENT", 0);
|
||||
string_t main_fname = "main";
|
||||
string_t argv0 = {};
|
||||
@@ -103,8 +110,8 @@ bool binary_rewrite = false;
|
||||
bool is_attached = false;
|
||||
bool use_mpi = false;
|
||||
bool is_static_exe = false;
|
||||
bool simulate = false;
|
||||
bool include_uninstr = false;
|
||||
bool force_config = false;
|
||||
bool parse_all_modules = false;
|
||||
size_t batch_size = 50;
|
||||
strset_t extra_libs = {};
|
||||
std::vector<std::pair<uint64_t, string_t>> hash_ids = {};
|
||||
@@ -126,6 +133,8 @@ string_t print_excluded = {};
|
||||
string_t print_available = {};
|
||||
string_t print_overlapping = {};
|
||||
strset_t print_formats = { "txt", "json" };
|
||||
strvec_t libname_suffixes = {};
|
||||
strvec_t libname_fallbacks = {};
|
||||
std::string modfunc_dump_dir = {};
|
||||
auto regex_opts = std::regex_constants::egrep | std::regex_constants::optimize;
|
||||
|
||||
@@ -271,12 +280,6 @@ main(int argc, char** argv)
|
||||
parser.add_argument({ "" }, "");
|
||||
parser.add_argument({ "[DEBUG OPTIONS]" }, "");
|
||||
parser.add_argument({ "" }, "");
|
||||
parser.add_argument({ "--debug" }, "Debug output")
|
||||
.max_count(1)
|
||||
.action([](parser_t& p) {
|
||||
debug_print = p.get<bool>("debug");
|
||||
if(debug_print && !p.exists("verbose")) verbose_level = 256;
|
||||
});
|
||||
parser.add_argument({ "-v", "--verbose" }, "Verbose output")
|
||||
.max_count(1)
|
||||
.action([](parser_t& p) {
|
||||
@@ -289,6 +292,12 @@ main(int argc, char** argv)
|
||||
.dtype("boolean")
|
||||
.max_count(1)
|
||||
.action([](parser_t& p) { werror = p.get<bool>("error"); });
|
||||
parser.add_argument({ "--debug" }, "Debug output")
|
||||
.max_count(1)
|
||||
.action([](parser_t& p) {
|
||||
debug_print = p.get<bool>("debug");
|
||||
if(debug_print && !p.exists("verbose")) verbose_level = 256;
|
||||
});
|
||||
parser
|
||||
.add_argument({ "--simulate" },
|
||||
"Exit after outputting diagnostic "
|
||||
@@ -406,6 +415,16 @@ main(int argc, char** argv)
|
||||
if(instr_mode == "coverage" && !p.exists("coverage"))
|
||||
coverage_mode = CODECOV_FUNCTION;
|
||||
});
|
||||
parser
|
||||
.add_argument(
|
||||
{ "-f", "--force" },
|
||||
"Force the command-line argument configuration, i.e. don't get cute. Useful "
|
||||
"for forcing runtime instrumentation of an executable that [A] Dyninst "
|
||||
"thinks is a library after reading ELF and [B] whose name makes it look like "
|
||||
"a library (e.g. starts with 'lib' and/or ends in '.so', '.so.*', or '.a')")
|
||||
.max_count(1)
|
||||
.action([](parser_t& p) { force_config = p.get<bool>("force"); });
|
||||
|
||||
if(_cmdc == 0)
|
||||
{
|
||||
parser
|
||||
@@ -616,6 +635,14 @@ main(int argc, char** argv)
|
||||
.dtype("int")
|
||||
.action(
|
||||
[](parser_t& p) { min_instructions = p.get<size_t>("min-instructions"); });
|
||||
parser
|
||||
.add_argument({ "-r", "--min-address-range" },
|
||||
"If the address range of a function is less than this value, "
|
||||
"exclude it from instrumentation")
|
||||
.count(1)
|
||||
.dtype("int")
|
||||
.action(
|
||||
[](parser_t& p) { min_address_range = p.get<size_t>("min-address-range"); });
|
||||
parser
|
||||
.add_argument({ "--min-instructions-loop" },
|
||||
"If the number of instructions in a function containing a loop is "
|
||||
@@ -625,14 +652,6 @@ main(int argc, char** argv)
|
||||
.action([](parser_t& p) {
|
||||
min_loop_instructions = p.get<size_t>("min-instructions-loop");
|
||||
});
|
||||
parser
|
||||
.add_argument({ "-r", "--min-address-range" },
|
||||
"If the address range of a function is less than this value, "
|
||||
"exclude it from instrumentation")
|
||||
.count(1)
|
||||
.dtype("int")
|
||||
.action(
|
||||
[](parser_t& p) { min_address_range = p.get<size_t>("min-address-range"); });
|
||||
parser
|
||||
.add_argument({ "--min-address-range-loop" },
|
||||
"If the address range of a function containing a loop is less than "
|
||||
@@ -642,7 +661,13 @@ main(int argc, char** argv)
|
||||
.action([](parser_t& p) {
|
||||
min_loop_address_range = p.get<size_t>("min-address-range-loop");
|
||||
});
|
||||
parser.add_argument({ "--coverage" }, "Enable recording the code coverage")
|
||||
parser
|
||||
.add_argument(
|
||||
{ "--coverage" },
|
||||
"Enable recording the code coverage. If instrumenting in coverage mode ('-M "
|
||||
"converage'), this simply specifies the granularity. If instrumenting in "
|
||||
"trace or sampling mode, this enables recording code-coverage in addition to "
|
||||
"the instrumentation of that mode (if any).")
|
||||
.max_count(1)
|
||||
.choices({ "none", "function", "basic_block" })
|
||||
.action([](parser_t& p) {
|
||||
@@ -691,8 +716,20 @@ main(int argc, char** argv)
|
||||
"Allow dyninst to instrument either multiple functions which overlap (share "
|
||||
"part of same function body) or single functions with multiple entry points. "
|
||||
"For more info, see Section 2 of the DyninstAPI documentation.")
|
||||
.count(0)
|
||||
.action([](parser_t&) { allow_overlapping = true; });
|
||||
.max_count(1)
|
||||
.action(
|
||||
[](parser_t& p) { allow_overlapping = p.get<bool>("allow-overlapping"); });
|
||||
parser
|
||||
.add_argument(
|
||||
{ "--parse-all-modules" },
|
||||
"By default, omnitrace simply requests Dyninst to provide all the procedures "
|
||||
"in the application image. If this option is enabled, omnitrace will iterate "
|
||||
"over all the modules and extract the functions. Theoretically, it should be "
|
||||
"the same but the data is slightly different, possibly due to weak binding "
|
||||
"scopes. In general, enabling option will probably have no visible effect")
|
||||
.max_count(1)
|
||||
.action(
|
||||
[](parser_t& p) { parse_all_modules = p.get<bool>("parse-all-modules"); });
|
||||
|
||||
parser.add_argument({ "" }, "");
|
||||
parser.add_argument({ "[DYNINST OPTIONS]" }, "");
|
||||
@@ -824,6 +861,75 @@ main(int argc, char** argv)
|
||||
!parser.exists("min-instructions") &&
|
||||
!parser.exists("min-address-range-loop"));
|
||||
|
||||
auto _omnitrace_exe_path = tim::dirname(::get_realpath("/proc/self/exe"));
|
||||
verbprintf(4, "omnitrace exe path: %s\n", _omnitrace_exe_path.c_str());
|
||||
|
||||
if(strcmp(::basename(_omnitrace_exe_path.c_str()), "bin") == 0)
|
||||
{
|
||||
libname_suffixes.emplace_back("omnitrace");
|
||||
libname_suffixes.emplace_back("../lib");
|
||||
libname_suffixes.emplace_back("../lib64");
|
||||
libname_suffixes.emplace_back("../lib/omnitrace");
|
||||
libname_suffixes.emplace_back("../lib64/omnitrace");
|
||||
libname_suffixes.emplace_back("lib");
|
||||
libname_suffixes.emplace_back("lib64");
|
||||
libname_suffixes.emplace_back("lib/omnitrace");
|
||||
libname_suffixes.emplace_back("lib64/omnitrace");
|
||||
libname_fallbacks.emplace_back(_omnitrace_exe_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
libname_suffixes.emplace_back("lib");
|
||||
libname_suffixes.emplace_back("lib64");
|
||||
libname_suffixes.emplace_back("lib/omnitrace");
|
||||
libname_suffixes.emplace_back("lib64/omnitrace");
|
||||
libname_fallbacks.emplace_back(tim::get_env<std::string>("PWD", "."));
|
||||
}
|
||||
|
||||
if(_cmdv && _cmdv[0] && strlen(_cmdv[0]) > 0)
|
||||
{
|
||||
auto _is_executable = omnitrace_get_is_executable(_cmdv[0], binary_rewrite);
|
||||
std::string _cmdv_base = ::basename(_cmdv[0]);
|
||||
auto _has_lib_suffix = _cmdv_base.length() > 3 &&
|
||||
(_cmdv_base.find(".so.") != std::string::npos ||
|
||||
_cmdv_base.find(".so") == (_cmdv_base.length() - 3) ||
|
||||
_cmdv_base.find(".a") == (_cmdv_base.length() - 2));
|
||||
auto _has_lib_prefix = _cmdv_base.length() > 3 && _cmdv_base.find("lib") == 0;
|
||||
if(!force_config && !_is_executable && !binary_rewrite &&
|
||||
(_has_lib_prefix || _has_lib_suffix))
|
||||
{
|
||||
fflush(stdout);
|
||||
std::stringstream _separator{};
|
||||
// 18 is approximate length of '[omnitrace][exe] '
|
||||
// 32 is approximate length of 'Warning! "" is not executable!'
|
||||
size_t _width =
|
||||
std::min<size_t>(std::get<0>(tim::utility::console::get_columns()) - 18,
|
||||
strlen(_cmdv[0]) + 32);
|
||||
_separator.fill('=');
|
||||
_separator << "#" << std::setw(_width - 2) << ""
|
||||
<< "#";
|
||||
verbprintf(0, "%s\n", _separator.str().c_str());
|
||||
verbprintf(0, "\n");
|
||||
verbprintf(0, "Warning! '%s' is not executable!\n", _cmdv[0]);
|
||||
verbprintf(0, "Runtime instrumentation is not possible!\n");
|
||||
verbprintf(0, "Switching to binary rewrite mode and assuming '--simulate "
|
||||
"--all-functions'\n");
|
||||
verbprintf(
|
||||
0, "(which will provide an approximation for runtime instrumentation)\n");
|
||||
verbprintf(1, "%s :: (^lib)=%s, (.so$|.a$|.so.*)=%s\n", _cmdv_base.c_str(),
|
||||
(_has_lib_prefix) ? "true" : "false",
|
||||
(_has_lib_suffix) ? "true" : "false");
|
||||
verbprintf(0, "\n");
|
||||
verbprintf(0, "%s\n", _separator.str().c_str());
|
||||
verbprintf(0, "\n");
|
||||
fflush(stdout);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds{ 500 });
|
||||
binary_rewrite = true;
|
||||
simulate = true;
|
||||
include_uninstr = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(binary_rewrite && outfile.empty())
|
||||
{
|
||||
auto _is_local = (get_realpath(cmdv0) ==
|
||||
@@ -1020,6 +1126,22 @@ main(int argc, char** argv)
|
||||
errprintf(-1, "address space for dynamic instrumentation was not created\n");
|
||||
}
|
||||
|
||||
if(dynamic_cast<binary_edit_t*>(addr_space) != nullptr &&
|
||||
dynamic_cast<process_t*>(addr_space) != nullptr)
|
||||
{
|
||||
errprintf(-1, "address space statisfied dynamic_cast<%s> and dynamic_cast<%s>.\n",
|
||||
tim::demangle<binary_edit_t*>().c_str(),
|
||||
tim::demangle<process_t*>().c_str());
|
||||
}
|
||||
|
||||
auto _rewrite = (dynamic_cast<binary_edit_t*>(addr_space) != nullptr &&
|
||||
dynamic_cast<process_t*>(addr_space) == nullptr);
|
||||
if(_rewrite != binary_rewrite)
|
||||
{
|
||||
errprintf(-1, "binary rewrite was %s but has been deduced to be %s\n",
|
||||
(binary_rewrite) ? "ON" : "OFF", (_rewrite) ? "ON" : "OFF");
|
||||
}
|
||||
|
||||
process_t* app_thread = nullptr;
|
||||
binary_edit_t* app_binary = nullptr;
|
||||
|
||||
@@ -1028,8 +1150,8 @@ main(int argc, char** argv)
|
||||
image_t* app_image = addr_space->getImage();
|
||||
bpvector_t<module_t*>* app_modules = app_image->getModules();
|
||||
bpvector_t<procedure_t*>* app_functions = app_image->getProcedures(include_uninstr);
|
||||
bpvector_t<module_t*> modules;
|
||||
bpvector_t<procedure_t*> functions;
|
||||
std::set<module_t*> modules = {};
|
||||
std::set<procedure_t*> functions = {};
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
//
|
||||
@@ -1058,47 +1180,24 @@ main(int argc, char** argv)
|
||||
}
|
||||
};
|
||||
|
||||
if(app_modules && !app_modules->empty())
|
||||
{
|
||||
modules.reserve(app_modules->size());
|
||||
for(auto* itr : *app_modules)
|
||||
{
|
||||
if(!itr->isSystemLib()) modules.emplace_back(itr);
|
||||
}
|
||||
for(auto* itr : modules)
|
||||
{
|
||||
auto* procedures = itr->getProcedures(include_uninstr);
|
||||
if(procedures)
|
||||
{
|
||||
for(auto* pitr : *procedures)
|
||||
{
|
||||
if(!pitr->isInstrumentable()) continue;
|
||||
auto _modfn = module_function{ itr, pitr };
|
||||
module_names.insert(_modfn.module_name);
|
||||
_insert_module_function(available_module_functions, _modfn);
|
||||
_add_overlapping(itr, pitr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
verbprintf(0, "Warning! No modules in application...\n");
|
||||
}
|
||||
|
||||
if(app_functions && !app_functions->empty())
|
||||
{
|
||||
functions.reserve(app_functions->size());
|
||||
for(auto* itr : *app_functions)
|
||||
{
|
||||
if(!itr->getModule()->isSystemLib()) functions.emplace_back(itr);
|
||||
if(itr->getModule() && !itr->getModule()->isSystemLib())
|
||||
{
|
||||
functions.emplace(itr);
|
||||
modules.emplace(itr->getModule());
|
||||
}
|
||||
}
|
||||
verbprintf(2, "Adding %zu procedures found in the app image...\n",
|
||||
functions.size());
|
||||
for(auto* itr : functions)
|
||||
{
|
||||
module_t* mod = itr->getModule();
|
||||
if(mod && itr->isInstrumentable())
|
||||
if(itr->isInstrumentable() || (simulate && include_uninstr))
|
||||
{
|
||||
auto _modfn = module_function{ mod, itr };
|
||||
module_t* mod = itr->getModule();
|
||||
auto _modfn = module_function{ mod, itr };
|
||||
module_names.insert(_modfn.module_name);
|
||||
_insert_module_function(available_module_functions, _modfn);
|
||||
_add_overlapping(mod, itr);
|
||||
@@ -1107,11 +1206,48 @@ main(int argc, char** argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
verbprintf(0, "Warning! No functions in application...\n");
|
||||
verbprintf(
|
||||
0, "Warning! No functions in application. Enabling parsing all modules...\n");
|
||||
parse_all_modules = true;
|
||||
}
|
||||
|
||||
verbprintf(1, "Module size before loading instrumentation library: %lu\n",
|
||||
(long unsigned) modules.size());
|
||||
if(parse_all_modules && app_modules && !app_modules->empty())
|
||||
{
|
||||
for(auto* itr : *app_modules)
|
||||
{
|
||||
if(!itr->isSystemLib()) modules.emplace(itr);
|
||||
}
|
||||
verbprintf(2,
|
||||
"Adding the procedures from %zu modules found in the app image...\n",
|
||||
modules.size());
|
||||
for(auto* itr : modules)
|
||||
{
|
||||
auto* procedures = itr->getProcedures(include_uninstr);
|
||||
if(procedures)
|
||||
{
|
||||
verbprintf(2, "Processing %zu procedures found in the %s module...\n",
|
||||
procedures->size(), get_name(itr).data());
|
||||
for(auto* pitr : *procedures)
|
||||
{
|
||||
if(!pitr->isInstrumentable() && !simulate && !include_uninstr)
|
||||
continue;
|
||||
functions.emplace(pitr);
|
||||
auto _modfn = module_function{ itr, pitr };
|
||||
module_names.insert(_modfn.module_name);
|
||||
_insert_module_function(available_module_functions, _modfn);
|
||||
_add_overlapping(itr, pitr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(parse_all_modules)
|
||||
{
|
||||
verbprintf(0, "Warning! No modules in application...\n");
|
||||
}
|
||||
|
||||
verbprintf(1, "\n");
|
||||
verbprintf(1, "Found %zu functions in %zu modules in instrumentation target\n",
|
||||
functions.size(), modules.size());
|
||||
|
||||
if(debug_print || verbose_level > 2)
|
||||
{
|
||||
@@ -1221,8 +1357,6 @@ main(int argc, char** argv)
|
||||
//
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
auto* main_init = find_function(app_image, "_init");
|
||||
auto* main_fini = find_function(app_image, "_fini");
|
||||
auto* main_func = find_function(app_image, main_fname.c_str());
|
||||
auto* user_start_func = find_function(app_image, "omnitrace_user_start_trace",
|
||||
{ "omnitrace_user_start_thread_trace" });
|
||||
@@ -1383,30 +1517,6 @@ main(int argc, char** argv)
|
||||
//
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
if(!main_func)
|
||||
{
|
||||
if(!main_init && !main_fini)
|
||||
{
|
||||
errprintf(-1, "could not find '%s', '_init' or '_fini', aborting...\n",
|
||||
main_fname.c_str());
|
||||
}
|
||||
else if(!main_init)
|
||||
{
|
||||
errprintf(-1, "could not find '%s' or '_init', aborting...\n",
|
||||
main_fname.c_str());
|
||||
}
|
||||
else if(!main_fini)
|
||||
{
|
||||
errprintf(-1, "could not find '%s' or '_fini', aborting...\n",
|
||||
main_fname.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
verbprintf(0, "using '%s' and '%s' in lieu of '%s'...\n", "_init", "_fini",
|
||||
main_fname.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
using pair_t = std::pair<procedure_t*, string_t>;
|
||||
|
||||
for(const auto& itr :
|
||||
@@ -1423,26 +1533,6 @@ main(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
|
||||
auto check_for_debug_info = [](bool& _has_debug_info, auto* _func) {
|
||||
// This heuristic guesses that debugging info is available if function
|
||||
// is not defined in the DEFAULT_MODULE
|
||||
if(_func && !_has_debug_info)
|
||||
{
|
||||
module_t* _module = _func->getModule();
|
||||
if(_module)
|
||||
{
|
||||
char moduleName[FUNCNAMELEN];
|
||||
_module->getFullName(moduleName, FUNCNAMELEN);
|
||||
if(strcmp(moduleName, "DEFAULT_MODULE") != 0) _has_debug_info = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool has_debug_info = false;
|
||||
check_for_debug_info(has_debug_info, main_func);
|
||||
check_for_debug_info(has_debug_info, main_init);
|
||||
check_for_debug_info(has_debug_info, main_fini);
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
//
|
||||
// Find the entry/exit point of either the main (if executable) or the _init
|
||||
@@ -1460,16 +1550,6 @@ main(int argc, char** argv)
|
||||
main_exit_points = main_func->findPoint(BPatch_exit);
|
||||
verbprintf(2, "Done\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
verbprintf(2, "Finding init entry... ");
|
||||
main_entr_points = main_init->findPoint(BPatch_entry);
|
||||
verbprintf(2, "Done\n");
|
||||
|
||||
verbprintf(2, "Finding fini exit... ");
|
||||
main_exit_points = main_fini->findPoint(BPatch_exit);
|
||||
verbprintf(2, "Done\n");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
//
|
||||
@@ -1535,7 +1615,7 @@ main(int argc, char** argv)
|
||||
if(_libname.empty()) _libname = get_absolute_lib_filepath(itr, "LIBRARY_PATH");
|
||||
if(_libname.empty()) _libname = get_absolute_lib_filepath(itr, "LD_LIBRARY_PATH");
|
||||
}
|
||||
if(_libname.empty()) _libname = "libomnitrace.so";
|
||||
if(_libname.empty()) _libname = "libomnitrace-dl.so";
|
||||
|
||||
// prioritize the user environment arguments
|
||||
auto env_vars = parser.get<strvec_t>("env");
|
||||
@@ -1634,13 +1714,10 @@ main(int argc, char** argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
// in sampling mode, we instrument either main or init + fini
|
||||
for(auto&& itr : { main_func, main_init, main_fini })
|
||||
{
|
||||
if(itr)
|
||||
_insert_module_function(instrumented_module_functions,
|
||||
module_function{ itr->getModule(), itr });
|
||||
}
|
||||
// in sampling mode, we instrument either main or add init and fini callbacks
|
||||
if(main_func)
|
||||
_insert_module_function(instrumented_module_functions,
|
||||
module_function{ main_func->getModule(), main_func });
|
||||
|
||||
for(const auto& itr : available_module_functions)
|
||||
{
|
||||
@@ -1662,6 +1739,11 @@ main(int argc, char** argv)
|
||||
//
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
auto _objs = std::vector<object_t*>{};
|
||||
addr_space->getImage()->getObjects(_objs);
|
||||
auto _init_sequence = sequence_t{ init_names };
|
||||
auto _fini_sequence = sequence_t{ fini_names };
|
||||
|
||||
if(app_thread && is_attached)
|
||||
{
|
||||
assert(app_thread != nullptr);
|
||||
@@ -1674,16 +1756,26 @@ main(int argc, char** argv)
|
||||
if(main_entr_points)
|
||||
{
|
||||
verbprintf(1, "Adding main entry snippets...\n");
|
||||
addr_space->insertSnippet(BPatch_sequence(init_names), *main_entr_points,
|
||||
addr_space->insertSnippet(_init_sequence, *main_entr_points,
|
||||
BPatch_callBefore, BPatch_firstSnippet);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto* itr : _objs)
|
||||
itr->insertInitCallback(_init_sequence);
|
||||
}
|
||||
}
|
||||
|
||||
if(main_exit_points)
|
||||
{
|
||||
verbprintf(1, "Adding main exit snippets...\n");
|
||||
addr_space->insertSnippet(BPatch_sequence(fini_names), *main_exit_points,
|
||||
BPatch_callAfter, BPatch_firstSnippet);
|
||||
addr_space->insertSnippet(_fini_sequence, *main_exit_points, BPatch_callAfter,
|
||||
BPatch_firstSnippet);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto* itr : _objs)
|
||||
itr->insertFiniCallback(_fini_sequence);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
@@ -1716,13 +1808,11 @@ main(int argc, char** argv)
|
||||
|
||||
if(instr_mode != "coverage")
|
||||
{
|
||||
std::map<std::string, std::pair<size_t, size_t>> _pass_info{};
|
||||
const int _pass_verbose_lvl = 0;
|
||||
auto _pass_info = std::map<std::string, std::pair<size_t, size_t>>{};
|
||||
const int _pass_verbose_lvl = 0;
|
||||
for(const auto& itr : instrumented_module_functions)
|
||||
{
|
||||
bool _is_main = itr.function == main_func || itr.function == main_init ||
|
||||
itr.function == main_fini;
|
||||
if(_is_main) continue;
|
||||
if(itr.function == main_func) continue;
|
||||
auto _count = itr(addr_space, entr_trace, exit_trace);
|
||||
_pass_info[itr.module_name].first += _count.first;
|
||||
_pass_info[itr.module_name].second += _count.second;
|
||||
@@ -1756,9 +1846,7 @@ main(int argc, char** argv)
|
||||
const int _covr_verbose_lvl = 1;
|
||||
for(const auto& itr : coverage_module_functions)
|
||||
{
|
||||
bool _is_main = itr.function == main_func || itr.function == main_init ||
|
||||
itr.function == main_fini;
|
||||
if(_is_main) continue;
|
||||
if(itr.function == main_func) continue;
|
||||
itr.register_source(addr_space, reg_src_func, *main_entr_points);
|
||||
auto _count = itr.register_coverage(addr_space, reg_cov_func);
|
||||
_covr_info[itr.module_name].first += _count.first;
|
||||
@@ -1899,22 +1987,18 @@ main(int argc, char** argv)
|
||||
{
|
||||
for(const auto& itr : _modset)
|
||||
{
|
||||
std::stringstream _ss{};
|
||||
_ss << std::boolalpha;
|
||||
_ss << "" << itr.module_name << "] --> [" << itr.function_name << "]["
|
||||
<< itr.num_instructions << "]";
|
||||
_insert(itr.module_name, _ss.str());
|
||||
_insert(itr.module_name, TIMEMORY_JOIN("", "[", itr.module_name,
|
||||
"] --> [", itr.function_name, "][",
|
||||
itr.num_instructions, "]"));
|
||||
}
|
||||
}
|
||||
else if(_mode == "pair+")
|
||||
{
|
||||
for(const auto& itr : _modset)
|
||||
{
|
||||
std::stringstream _ss{};
|
||||
_ss << std::boolalpha;
|
||||
_ss << "[" << itr.module_name << "] --> [" << itr.signature.get() << "]["
|
||||
<< itr.num_instructions << "]";
|
||||
_insert(itr.module_name, _ss.str());
|
||||
_insert(itr.module_name, TIMEMORY_JOIN("", "[", itr.module_name,
|
||||
"] --> [", itr.signature.get(),
|
||||
"][", itr.num_instructions, "]"));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2246,6 +2330,9 @@ get_absolute_lib_filepath(std::string lib_name, const std::string& env_path,
|
||||
std::vector<std::string> suffixes,
|
||||
std::vector<std::string> fallbacks)
|
||||
{
|
||||
if(suffixes.empty()) suffixes = libname_suffixes;
|
||||
if(fallbacks.empty()) fallbacks = libname_fallbacks;
|
||||
|
||||
if(!lib_name.empty() && (!file_exists(lib_name) ||
|
||||
std::regex_match(lib_name, std::regex("^[A-Za-z0-9].*"))))
|
||||
{
|
||||
@@ -2273,6 +2360,7 @@ get_absolute_lib_filepath(std::string lib_name, const std::string& env_path,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(file_exists(lib_name)) break;
|
||||
}
|
||||
|
||||
if(!file_exists(lib_name))
|
||||
@@ -2295,6 +2383,7 @@ bool
|
||||
file_exists(const std::string& name)
|
||||
{
|
||||
struct stat buffer;
|
||||
verbprintf(4, "querying whether file '%s' exists...\n", name.c_str());
|
||||
return (stat(name.c_str(), &buffer) == 0);
|
||||
}
|
||||
|
||||
@@ -2322,22 +2411,8 @@ using tim::dirname;
|
||||
void
|
||||
find_dyn_api_rt()
|
||||
{
|
||||
auto _exe_path = dirname(::get_realpath("/proc/self/exe"));
|
||||
|
||||
strvec_t _suffixes = {};
|
||||
strvec_t _fallbacks = {};
|
||||
|
||||
if(strcmp(::basename(_exe_path.c_str()), "bin") == 0)
|
||||
{
|
||||
_suffixes.emplace_back("omnitrace");
|
||||
_suffixes.emplace_back("../lib");
|
||||
_suffixes.emplace_back("../lib/omnitrace");
|
||||
_fallbacks.emplace_back(_exe_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
_fallbacks.emplace_back(tim::get_env<std::string>("PWD", "."));
|
||||
}
|
||||
strvec_t _suffixes = libname_suffixes;
|
||||
strvec_t _fallbacks = libname_fallbacks;
|
||||
|
||||
std::copy(_dyn_api_rt_paths.begin(), _dyn_api_rt_paths.end(),
|
||||
std::back_inserter(_fallbacks));
|
||||
|
||||
@@ -27,6 +27,11 @@
|
||||
#include "info.hpp"
|
||||
#include "module_function.hpp"
|
||||
|
||||
#include <timemory/utility/filepath.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
inline string_t
|
||||
@@ -153,6 +158,34 @@ private:
|
||||
//
|
||||
//======================================================================================//
|
||||
//
|
||||
static inline bool
|
||||
omnitrace_get_is_executable(std::string_view _cmd, bool _default_v)
|
||||
{
|
||||
bool _is_executable = _default_v;
|
||||
|
||||
if(_cmd.empty())
|
||||
{
|
||||
if(!tim::filepath::exists(std::string{ _cmd }))
|
||||
{
|
||||
verbprintf(
|
||||
0,
|
||||
"Warning! '%s' was not found. Dyninst may fail to open the binary for "
|
||||
"instrumentation...\n",
|
||||
_cmd.data());
|
||||
}
|
||||
|
||||
Dyninst::SymtabAPI::Symtab* _symtab = nullptr;
|
||||
if(Dyninst::SymtabAPI::Symtab::openFile(_symtab, _cmd.data()))
|
||||
{
|
||||
_is_executable = _symtab->isExecutable() && _symtab->isExec();
|
||||
Dyninst::SymtabAPI::Symtab::closeSymtab(_symtab);
|
||||
}
|
||||
}
|
||||
return _is_executable;
|
||||
}
|
||||
//
|
||||
//======================================================================================//
|
||||
//
|
||||
static inline address_space_t*
|
||||
omnitrace_get_address_space(patch_pointer_t& _bpatch, int _cmdc, char** _cmdv,
|
||||
bool _rewrite, int _pid = -1, const string_t& _name = {})
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
function(OMNITRACE_ADD_BIN_TEST)
|
||||
cmake_parse_arguments(
|
||||
TEST
|
||||
"" # options
|
||||
"ADD_INVERSE" # options
|
||||
"NAME;TARGET;TIMEOUT;WORKING_DIRECTORY" # single value args
|
||||
"ARGS;ENVIRONMENT;LABELS;PROPERTIES;PASS_REGEX;FAIL_REGEX;SKIP_REGEX;DEPENDS;COMMAND" # multiple
|
||||
# value args
|
||||
${ARGN})
|
||||
|
||||
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)
|
||||
@@ -25,13 +28,19 @@ function(OMNITRACE_ADD_BIN_TEST)
|
||||
"OMNITRACE_USE_TIMEMORY=ON"
|
||||
"OMNITRACE_USE_SAMPLING=ON"
|
||||
"OMNITRACE_TIME_OUTPUT=OFF"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# common
|
||||
list(APPEND TEST_ENVIRONMENT "OMNITRACE_CI=ON"
|
||||
"OMNITRACE_OUTPUT_PATH=omnitrace-tests-output"
|
||||
"OMNITRACE_OUTPUT_PREFIX=${TEST_NAME}/")
|
||||
"OMNITRACE_OUTPUT_PATH=omnitrace-tests-output")
|
||||
# copy for inverse
|
||||
set(TEST_ENVIRONMENT_INV "${TEST_ENVIRONMENT}")
|
||||
|
||||
# different for regular test and inverse test
|
||||
list(APPEND TEST_ENVIRONMENT "OMNITRACE_OUTPUT_PREFIX=${TEST_NAME}/")
|
||||
list(APPEND TEST_ENVIRONMENT_INV "OMNITRACE_OUTPUT_PREFIX=${TEST_NAME}-inverse/")
|
||||
|
||||
if(TEST_COMMAND)
|
||||
add_test(
|
||||
@@ -56,11 +65,37 @@ function(OMNITRACE_ADD_BIN_TEST)
|
||||
SKIP_REGULAR_EXPRESSION
|
||||
"${TEST_SKIP_REGEX}"
|
||||
${TEST_PROPERTIES})
|
||||
if(TEST_ADD_INVERSE)
|
||||
add_test(
|
||||
NAME ${TEST_NAME}-inverse
|
||||
COMMAND ${TEST_COMMAND} ${TEST_ARGS}
|
||||
WORKING_DIRECTORY ${TEST_WORKING_DIRECTORY})
|
||||
|
||||
set_tests_properties(
|
||||
${TEST_NAME}-inverse
|
||||
PROPERTIES ENVIRONMENT
|
||||
"${TEST_ENVIRONMENT_INV}"
|
||||
TIMEOUT
|
||||
${TEST_TIMEOUT}
|
||||
DEPENDS
|
||||
"${TEST_DEPENDS}"
|
||||
LABELS
|
||||
"omnitrace-bin;${TEST_LABELS}"
|
||||
PASS_REGULAR_EXPRESSION
|
||||
"${TEST_FAIL_REGEX}"
|
||||
FAIL_REGULAR_EXPRESSION
|
||||
"${TEST_PASS_REGEX}"
|
||||
SKIP_REGULAR_EXPRESSION
|
||||
"${TEST_SKIP_REGEX}"
|
||||
WILL_FAIL
|
||||
ON
|
||||
${TEST_PROPERTIES})
|
||||
endif()
|
||||
elseif(TARGET ${TEST_TARGET})
|
||||
add_test(
|
||||
NAME ${TEST_NAME}
|
||||
COMMAND $<TARGET_FILE:${TEST_TARGET}> ${TEST_ARGS}
|
||||
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET}>)
|
||||
WORKING_DIRECTORY ${TEST_WORKING_DIRECTORY})
|
||||
|
||||
set_tests_properties(
|
||||
${TEST_NAME}
|
||||
@@ -79,6 +114,32 @@ function(OMNITRACE_ADD_BIN_TEST)
|
||||
SKIP_REGULAR_EXPRESSION
|
||||
"${TEST_SKIP_REGEX}"
|
||||
${TEST_PROPERTIES})
|
||||
if(TEST_ADD_INVERSE)
|
||||
add_test(
|
||||
NAME ${TEST_NAME}-inverse
|
||||
COMMAND $<TARGET_FILE:${TEST_TARGET}> ${TEST_ARGS}
|
||||
WORKING_DIRECTORY ${TEST_WORKING_DIRECTORY})
|
||||
|
||||
set_tests_properties(
|
||||
${TEST_NAME}-inverse
|
||||
PROPERTIES ENVIRONMENT
|
||||
"${TEST_ENVIRONMENT_INV}"
|
||||
TIMEOUT
|
||||
${TEST_TIMEOUT}
|
||||
DEPENDS
|
||||
"${TEST_DEPENDS}"
|
||||
LABELS
|
||||
"omnitrace-bin;${TEST_LABELS}"
|
||||
PASS_REGULAR_EXPRESSION
|
||||
"${TEST_FAIL_REGEX}"
|
||||
FAIL_REGULAR_EXPRESSION
|
||||
"${TEST_PASS_REGEX}"
|
||||
SKIP_REGULAR_EXPRESSION
|
||||
"${TEST_SKIP_REGEX}"
|
||||
WILL_FAIL
|
||||
ON
|
||||
${TEST_PROPERTIES})
|
||||
endif()
|
||||
elseif(OMNITRACE_BUILD_TESTING)
|
||||
message(FATAL_ERROR "Error! ${TEST_TARGET} does not exist")
|
||||
endif()
|
||||
@@ -103,7 +164,7 @@ omnitrace_add_bin_test(
|
||||
txt
|
||||
xml
|
||||
-v
|
||||
1
|
||||
2
|
||||
--all-functions
|
||||
--
|
||||
ls
|
||||
@@ -113,14 +174,23 @@ omnitrace_add_bin_test(
|
||||
omnitrace_add_bin_test(
|
||||
NAME omnitrace-exe-simulate-ls-check
|
||||
DEPENDS omnitrace-exe-simulate-ls
|
||||
COMMAND ls
|
||||
WORKING_DIRECTORY
|
||||
${PROJECT_BINARY_DIR}/omnitrace-tests-output/omnitrace-exe-simulate-ls
|
||||
COMMAND ls omnitrace-tests-output/omnitrace-exe-simulate-ls
|
||||
TIMEOUT 60
|
||||
PASS_REGEX
|
||||
".*available-instr.json.*available-instr.txt.*available-instr.xml.*excluded-instr.json.*excluded-instr.txt.*excluded-instr.xml.*instrumented-instr.json.*instrumented-instr.txt.*instrumented-instr.xml.*overlapping-instr.json.*overlapping-instr.txt.*overlapping-instr.xml.*"
|
||||
)
|
||||
|
||||
omnitrace_add_bin_test(
|
||||
ADD_INVERSE
|
||||
NAME omnitrace-exe-simulate-lib
|
||||
TARGET omnitrace-exe
|
||||
ARGS --print-available functions -v 2 -- $<TARGET_FILE:omnitrace-user-library>
|
||||
LABELS "simulate"
|
||||
TIMEOUT 120
|
||||
PASS_REGEX
|
||||
"\\\[omnitrace\\\]\\\[exe\\\] Runtime instrumentation is not possible!(.*)\n(.*)\\\[omnitrace\\\]\\\[exe\\\] Switching to binary rewrite mode and assuming '--simulate --all-functions'"
|
||||
)
|
||||
|
||||
omnitrace_add_bin_test(
|
||||
NAME omnitrace-avail-help
|
||||
TARGET omnitrace-avail
|
||||
|
||||
@@ -38,7 +38,7 @@ set_target_properties(
|
||||
omnitrace-dl-library
|
||||
PROPERTIES OUTPUT_NAME omnitrace-dl
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
BUILD_RPATH "\$ORIGIN"
|
||||
INSTALL_RPATH "\$ORIGIN")
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ set_target_properties(
|
||||
omnitrace-user-library
|
||||
PROPERTIES OUTPUT_NAME omnitrace-user
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
BUILD_RPATH "\$ORIGIN"
|
||||
INSTALL_RPATH "\$ORIGIN")
|
||||
|
||||
@@ -178,7 +178,7 @@ set_target_properties(
|
||||
omnitrace-library
|
||||
PROPERTIES OUTPUT_NAME omnitrace
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
INSTALL_RPATH "${OMNITRACE_LIB_INSTALL_RPATH}")
|
||||
|
||||
omnitrace_strip_target(omnitrace-library)
|
||||
|
||||
@@ -32,7 +32,7 @@ set(_base_environment
|
||||
"OMP_PROC_BIND=spread"
|
||||
"OMP_PLACES=threads"
|
||||
"OMP_NUM_THREADS=2"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
)
|
||||
|
||||
set(_lock_environment
|
||||
@@ -45,7 +45,7 @@ set(_lock_environment
|
||||
"OMNITRACE_TIME_OUTPUT=OFF"
|
||||
"OMNITRACE_FLAT_PROFILE=ON"
|
||||
"OMNITRACE_TIMELINE_PROFILE=OFF"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
)
|
||||
|
||||
set(_ompt_environment
|
||||
@@ -57,7 +57,7 @@ set(_ompt_environment
|
||||
"OMP_PROC_BIND=spread"
|
||||
"OMP_PLACES=threads"
|
||||
"OMP_NUM_THREADS=2"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
)
|
||||
|
||||
set(_perfetto_environment
|
||||
@@ -69,7 +69,7 @@ set(_perfetto_environment
|
||||
"OMP_PROC_BIND=spread"
|
||||
"OMP_PLACES=threads"
|
||||
"OMP_NUM_THREADS=2"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
)
|
||||
|
||||
set(_timemory_environment
|
||||
@@ -81,7 +81,7 @@ set(_timemory_environment
|
||||
"OMP_PROC_BIND=spread"
|
||||
"OMP_PLACES=threads"
|
||||
"OMP_NUM_THREADS=2"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
)
|
||||
|
||||
set(_test_environment ${_base_environment} "OMNITRACE_CRITICAL_TRACE=OFF")
|
||||
@@ -95,7 +95,7 @@ set(_python_environment
|
||||
"OMNITRACE_TREE_OUTPUT=OFF"
|
||||
"OMNITRACE_USE_PID=OFF"
|
||||
"OMNITRACE_TIMEMORY_COMPONENTS=trip_count"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
"PYTHONPATH=${PROJECT_BINARY_DIR}/lib/python/site-packages")
|
||||
|
||||
set(_attach_environment
|
||||
@@ -111,7 +111,7 @@ set(_attach_environment
|
||||
"OMP_PROC_BIND=spread"
|
||||
"OMP_PLACES=threads"
|
||||
"OMP_NUM_THREADS=2"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
)
|
||||
|
||||
# -------------------------------------------------------------------------------------- #
|
||||
|
||||
Ссылка в новой задаче
Block a user