Build omnitrace-rt library (#355)
* Build omnitrace-rt library
- Explicitly build dyninstAPI_RT as omnitrace-rt so that the SONAME in the ELF is omnitrace-rt instead of dyninstAPI_RT
- Create symbolic link lib/omnitrace/libdyninstAPI_RT.so which points to lib/libomnitrace-rt.so
- Simplify build tree location of libomnitrace-rt.so since it is ../lib from the bin directory even in the build tree
- Update dyninst submodule with minor tweaks to dyninstAPI_RT/CMakeLists.txt
* Update source/lib/omnitrace-rt/cmake/platform.cmake
* Use ftpmirror.gnu.org instead of ftp.gnu.org
- in timemory and dyninst submodules
- minor .clang-tidy tweak
[ROCm/rocprofiler-systems commit: 0cf017251e]
Cette révision appartient à :
révisé par
GitHub
Parent
65f46fde8c
révision
8ad58c5d28
@@ -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,\
|
||||
|
||||
@@ -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}:$<TARGET_FILE_DIR:Dyninst::dyninstAPI_RT>:${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$<TARGET_FILE_NAME:Dyninst::dyninstAPI_RT>:$<TARGET_FILE:Dyninst::dyninstAPI_RT>"
|
||||
)
|
||||
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(
|
||||
|
||||
+1
-1
Sous-module projects/rocprofiler-systems/external/dyninst mis-à-jour : d3ab0a71e9...dedad14f55
+1
-1
Sous-module projects/rocprofiler-systems/external/timemory mis-à-jour : 227559ad27...86d2d12a8b
@@ -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)")
|
||||
|
||||
+19
-10
@@ -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<std::string>("DYNINSTAPI_RT_LIB"),
|
||||
tim::get_env<std::string>("DYNINST_REWRITER_PATHS"),
|
||||
tim::get_env<std::string>("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<std::string>("DYNINSTAPI_RT_LIB"),
|
||||
tim::get_env<std::string>("DYNINST_REWRITER_PATHS"),
|
||||
tim::get_env<std::string>("LD_LIBRARY_PATH")),
|
||||
":");
|
||||
strvec_t bin_search_paths = tim::delimit(tim::get_env<std::string>("PATH"), ":");
|
||||
|
||||
#if defined(DYNINST_API_RT)
|
||||
auto _dyn_api_rt_paths = tim::delimit(DYNINST_API_RT, ":");
|
||||
#else
|
||||
auto _dyn_api_rt_paths = std::vector<std::string>{};
|
||||
#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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -77,4 +77,5 @@ add_subdirectory(binary)
|
||||
|
||||
add_subdirectory(omnitrace)
|
||||
add_subdirectory(omnitrace-dl)
|
||||
add_subdirectory(omnitrace-rt)
|
||||
add_subdirectory(omnitrace-user)
|
||||
|
||||
@@ -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 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/h>)
|
||||
target_compile_definitions(omnitrace-rt-library PRIVATE ${UNIFIED_DEFINES})
|
||||
target_link_libraries(
|
||||
omnitrace-rt-library
|
||||
PUBLIC $<BUILD_INTERFACE:${dl_LIBRARY}>
|
||||
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 ../$<TARGET_FILE_NAME:omnitrace-rt-library>
|
||||
${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})
|
||||
Fichier exécutable
+74
@@ -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
|
||||
@@ -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)
|
||||
Fichier exécutable
+681
@@ -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 <bothner@cygnus.com>.
|
||||
# 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/^ //' <<EOF >dummy.c
|
||||
#include <sys/systemcfg.h>
|
||||
|
||||
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/^ //' <<EOF >dummy.c
|
||||
#include <unistd.h>
|
||||
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 <<EOF
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
#ifdef __ELF__
|
||||
printf ("%s-unknown-linux\n", argv[1]);
|
||||
#else
|
||||
printf ("%s-unknown-linuxaout\n", argv[1]);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy 2>/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' </usr/options/cb.name)
|
||||
echo ${UNAME_MACHINE}-unknown-isc$UNAME_REL
|
||||
elif /bin/uname -X 2>/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 <<EOF
|
||||
#ifdef _SEQUENT_
|
||||
# include <sys/types.h>
|
||||
# include <sys/utsname.h>
|
||||
#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 <sys/param.h>
|
||||
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
|
||||
@@ -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 <stdint.h>
|
||||
# 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 <stdint.h>
|
||||
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 <limits.h>
|
||||
# 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_) */
|
||||
@@ -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 */
|
||||
@@ -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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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 */
|
||||
@@ -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 <msg> (of <msg_size> 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
|
||||
@@ -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 <windows.h>
|
||||
# include <winsock2.h>
|
||||
# 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 <unordered_map>
|
||||
# include <unordered_set>
|
||||
|
||||
// NB: std::hash has overloads for [un]scoped enums
|
||||
template <typename Key, typename Value, typename Hash = std::hash<Key>,
|
||||
typename Comp = std::equal_to<Key>,
|
||||
typename Alloc = std::allocator<std::pair<const Key, Value>>>
|
||||
using dyn_hash_map = std::unordered_map<Key, Value, Hash, Comp, Alloc>;
|
||||
|
||||
template <typename Key, typename Hash = std::hash<Key>,
|
||||
typename Comp = std::equal_to<Key>, typename Alloc = std::allocator<Key>>
|
||||
using dyn_hash_set = std::unordered_set<Key, Hash, Comp, Alloc>;
|
||||
|
||||
// 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
|
||||
@@ -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 <string>
|
||||
|
||||
# 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
|
||||
@@ -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
|
||||
@@ -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 <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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" :::);
|
||||
}
|
||||
@@ -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 <stdarg.h>
|
||||
|
||||
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
|
||||
@@ -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 <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <link.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* FreeBSD libc has stubs so a static version shouldn't need libpthreads */
|
||||
#include <pthread.h>
|
||||
|
||||
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 <ucontext.h>
|
||||
|
||||
# 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 <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
*/
|
||||
@@ -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 <assert.h>
|
||||
#include <fcntl.h> /* open() */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* str* */
|
||||
#include <sys/mman.h> /* mmap() */
|
||||
#include <sys/stat.h> /* open() */
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h> /* read() */
|
||||
#include <unistd.h> /* 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;
|
||||
}
|
||||
@@ -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 <assert.h>
|
||||
#include <fcntl.h> /* open() */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* str* */
|
||||
#include <sys/mman.h> /* mmap() */
|
||||
#include <sys/stat.h> /* open() */
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h> /* read() */
|
||||
#include <unistd.h> /* 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
|
||||
*/
|
||||
}
|
||||
@@ -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 <stdlib.h>
|
||||
#include <windows.h>
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#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 <errno.h>
|
||||
# include <fcntl.h> /* open() */
|
||||
# include <sys/stat.h> /* open() */
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
#else
|
||||
extern int
|
||||
getpagesize();
|
||||
#endif
|
||||
#include <assert.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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 <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if !defined(DYNINST_RT_STATIC_LIB)
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <gnu/libc-version.h>
|
||||
#include <link.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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 <pthread.h>
|
||||
#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 <ucontext.h>
|
||||
|
||||
// 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 <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
*/
|
||||
@@ -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 <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# include <unistd.h>
|
||||
# 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <memory.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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. <pid> 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
+82
@@ -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 <assert.h>
|
||||
|
||||
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
|
||||
+102
@@ -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
|
||||
+72
@@ -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 <stdint.h>
|
||||
|
||||
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
|
||||
+129
@@ -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 <stdint.h>
|
||||
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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 <stdbool.h>
|
||||
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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 <assert.h>
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
@@ -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 <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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 <Dbghelp.h>
|
||||
#include <Psapi.h>
|
||||
#include <WS2tcpip.h>
|
||||
#include <WinSock2.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <limits.h>
|
||||
#include <mmsystem.h>
|
||||
#include <process.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <windows.h>
|
||||
|
||||
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. <pid> 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());
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Référencer dans un nouveau ticket
Bloquer un utilisateur