Update the rocprof-sys-rt library (#786)

Derived from Dyninst_RT 13.0.0
This commit is contained in:
David Galiffi
2025-09-03 09:19:43 -04:00
committed by GitHub
parent 2da209da7f
commit a57fd50865
31 changed files with 464 additions and 2574 deletions
@@ -14,102 +14,37 @@ set(NEED_NATIVE_ASSEMBLER ON)
include(cmake/platform.cmake)
set(SRC_LIST src/RTcommon.c src/RTmemEmulator.c)
set(_public_headers h/dyninstAPI_RT.h h/dyninstRTExport.h)
if(PLATFORM MATCHES freebsd)
set(_private_headers src/RTcommon.h src/RTheap.h src/RTthread.h)
set(_sources src/RTcommon.c src/RTheap.c src/RTthread.c)
if(PLATFORM MATCHES linux)
set(_static_sources src/RTstatic_ctors_dtors_begin.c src/RTstatic_ctors_dtors_end.c)
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
_sources
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)
list(APPEND _sources src/RTthread-x86-64.c src/RTtlsgetaddr-x86.S)
list(APPEND _static_sources src/RTstatic_ctors_dtors-x86.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_ASSEMBLER)
set_source_files_properties(${SRC_ASSEMBLY} PROPERTIES LANGUAGE ASM)
else()
set_source_files_properties(${SRC_ASSEMBLY} PROPERTIES LANGUAGE C)
endif()
file(GLOB _source_assembly "src/*.S")
# 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()
if(NEED_NATIVE_ASSEMBLER)
set_source_files_properties(${_source_assembly} PROPERTIES LANGUAGE ASM)
else()
set_source_files_properties(${_source_assembly} PROPERTIES LANGUAGE C)
endif()
add_library(rocprofiler-systems-rt-library SHARED)
@@ -118,7 +53,7 @@ add_library(
ALIAS rocprofiler-systems-rt-library
)
target_sources(rocprofiler-systems-rt-library PRIVATE ${SRC_LIST})
target_sources(rocprofiler-systems-rt-library PRIVATE ${_sources})
target_include_directories(
rocprofiler-systems-rt-library
PRIVATE
@@ -1,197 +0,0 @@
/*
* 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_) */
@@ -31,6 +31,33 @@
#ifndef COMPILER_ANNOTATIONS_H
#define COMPILER_ANNOTATIONS_H
/***********************************************************************
*
* INTERNAL HELPER MACROS
*
* Determine if compiler supports __has_cpp_attrribute and __has_c_attribute,
* and check if the attribute can be used without warning giving the language
* version the attribute was introduced (clang and gcc <=6 report true but warn
* if attribute is used). The DYNSINT_STD_FOR_VER_HAS_X_ATTRIBUTES parameter
* is the minumum version of the language that the attribute was introduced.
*/
#if defined(__cplusplus) && defined(__has_cpp_attribute)
# define DYNINST_HAS_HAS_CPP_ATTRIBUTE 1
# define DYNINST_STD_FOR_VER_HAS_CPP_ATTRIBUTE(minV) \
(__GNUC__ > 6 || __cplusplus >= (minV))
#else
# define DYNINST_HAS_HAS_CPP_ATTRIBUTE 0
# define DYNINST_STD_FOR_VER_HAS_CPP_ATTRIBUTE(minV) 0
#endif
#if defined(__STDC_VERSION__) && defined(__has_c_attribute)
# define DYNINST_HAS_HAS_C_ATTRIBUTE 1
# define DYNINST_STD_FOR_VER_HAS_C_ATTRIBUTE(minV) \
(__GNUC__ > 6 || __STDC_VERSION__ >= (minV))
#else
# define DYNINST_HAS_HAS_C_ATTRIBUTE 0
# define DYNINST_STD_FOR_VER_HAS_C_ATTRIBUTE(minV) 0
#endif
/***********************************************************************
*
* DYNINST_FALLTHROUGH
@@ -52,30 +79,32 @@
* }
*/
#if defined(__cpluscplus) && defined(__has_cpp_attribute)
# if __has_cpp_attribute(fallthrough)
#if DYNINST_HAS_HAS_CPP_ATTRIBUTE
# if __has_cpp_attribute(fallthrough) && DYNINST_STD_FOR_VER_HAS_CPP_ATTRIBUTE(201703)
# 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)
#elif DYNINST_HAS_HAS_C_ATTRIBUTE
# if __has_c_attribute(fallthrough) && DYNINST_STD_FOR_VER_HAS_C_ATTRIBUTE(202311L)
# define DYNINST_FALLTHROUGH [[fallthrough]]
# elif __STDC_VERSION__ > 201710
// scoped attribute names are only valid in C starting with 2x
# elif __STDC_VERSION__ >= 202311L
// scoped attribute names not valid in C until C23 (:: is not a token)
# 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)
#endif
#if !defined(DYNINST_FALLTHROUGH) && 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
# elif __cplusplus || __STDC_VERSION__ >= 202311L
// scoped attribute names not valid in C until C23 (:: is not a token)
# if __has_attribute(gcc::fallthrough)
# define DYNINST_FALLTHROUGH __attribute__((gcc::fallthrough))
# elif __has_attribute(clang::fallthrough)
@@ -91,6 +120,39 @@
} while(0)
#endif
/***********************************************************************
*
* DYNINST_DEPRECATED(msg)
*
* Adds an annotation to a function, method, variable or type that it is
* deprecated, and will produce a warning if it used. The parameter msg
* must be a quoted string.
*
* The annotation should be placed before the definition or declaration.
* For example:
*
* DYNINST_DEPRECRATED("Use NewFoo") int Foo();
*/
#if DYNINST_HAS_HAS_CPP_ATTRIBUTE && DYNINST_STD_FOR_VER_HAS_CPP_ATTRIBUTE(201402L)
# if __has_cpp_attribute(deprecated)
# define DYNINST_DEPRECATED(msg) [[deprecated(msg)]]
# endif
#elif DYNINST_HAS_HAS_C_ATTRIBUTE && DYNINST_STD_FOR_VER_HAS_C_ATTRIBUTE(202311L)
# if __has_c_attribute(deprecated)
# define DYNINST_DEPRECATED(msg) [[deprecated(msg)]]
# endif
#endif
#if !defined(DYNINST_DEPRECATED) && defined(__has_attribute)
# if __has_attribute(deprecated)
# define DYNINST_DEPRECATED(msg) __attribute__((deprecated(msg)))
# endif
#endif
#if !defined(DYNINST_DEPRECATED)
# define DYNINST_DEPRECATED(msg)
#endif
/***********************************************************************
*
* DYNINST_PRINTF_ANNOTATION(fmtIndex, argIndex)
@@ -0,0 +1,244 @@
/*
* 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_DIAGNOSTICS_H
#define COMPILER_DIAGNOSTICS_H
// This file defines macros to suppress compiler diagnostics for a region of
// code. They are used to suppress diagnostic that are due to 1) non-standard
// code and 2) the compiler produced false positives. They expand to nothing
// if not applicable with the current compiler.
//
// The macros to begin and end the region take the form:
//
// DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_<code>
// DYNINST_DIAGNOSTIC_END_SUPPRESS_<code>
//
// They should be place on a lines of their own without trailing '()' or ';'.
//
// Currently defined value for <code> are
//
// FLEX_ARRAY
// warning about C flexible arrays in C++
// VLA
// warning about C VLAs (variable length arrays) in C++
// VLA_EXTENSION
// clang warning about C VLAs in C++ if VLA is suppressed
// VLA_ALL`
// both of the above
// VLA_GCC_PRAGMA_BUG
// gcc <9, 11.0, and 11.1 workaround macro
// LOGICAL_OP
// warning about duplicate subexpressions in a logical expression
// Is a false positive due compiler checks after macro/constant
// propagation (eg. (x == a && x == b) if a and b are distinct
// constants with the same physical value. Only gcc 6-8.
// DUPLICATED_BRANCHES
// similar to LOGICAL_OP except the expressions are the
// conditionals of a chain of if/then/else's. Only gcc 7-8.
// UNUSED_VARIABLE
// clang <10 warns about variables defined solely for RIAA (locks)
// MAYBE_UNINITIALIZED
// gcc 12 warns that boost::optional::value_or may use an
// unitialized value when value_or checks if it is initialized.
//
// Macros to silence unused variable warnings
//
// DYNINST_SUPPRESS_UNUSED_VARIABLE(var)
// indicate that variable var OK to be unused
//
// Define DYNINST_DIAGNOSTIC_NO_SUPPRESSIONS to prevents suppressions.
// Define compiler specific suppression codes, an undefined value represents no
// suppression required. Suppression code macro names have the form
//
// DYNINST_SUPPRESS_CODE_<code>
//
#if defined(__GNUC__) && !defined(__clang__)
# define DYNINST_SUPPRESS_CODE_FLEX_ARRAY "-Wpedantic"
# define DYNINST_SUPPRESS_CODE_VLA "-Wvla"
# if __GNUC__ < 9
# define DYNINST_SUPPRESS_CODE_LOGICAL_OP "-Wlogical-op"
# endif
# if __GNUC__ >= 7 && __GNUC__ < 9
# define DYNINST_SUPPRESS_CODE_DUPLICATED_BRANCHES "-Wduplicated-branches"
# endif
# if __GNUC__ == 12
# define DYNINST_SUPPRESS_CODE_MAYBE_UNINITIALIZED "-Wmaybe-uninitialized"
# endif
#elif defined(__clang__)
# define DYNINST_SUPPRESS_CODE_FLEX_ARRAY "-Wpedantic"
# define DYNINST_SUPPRESS_CODE_VLA "-Wvla"
# define DYNINST_SUPPRESS_CODE_VLA_EXTENSION "-Wvla-extension"
# if __clang_major__ < 10
# define DYNINST_SUPPRESS_CODE_UNUSED_VARIABLE "-Wunused-variable"
# endif
#elif defined(_MSC_VER)
# define DYNINST_SUPPRESS_CODE_FLEX_ARRAY 4200
#endif
// Define DYNISNT_DIAGNOSTIC_BEGIN/END macros, expands to nothing if code undefined
#ifdef DYNINST_SUPPRESS_CODE_FLEX_ARRAY
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_FLEX_ARRAY \
DYNINST_DIAGNOSTIC_PUSH_SUPPRESS_CODE(FLEX_ARRAY)
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_FLEX_ARRAY DYNINST_DIAGNOSTIC_POP
#else
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_FLEX_ARRAY
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_FLEX_ARRAY
#endif
#ifdef DYNINST_SUPPRESS_CODE_VLA
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_VLA \
DYNINST_DIAGNOSTIC_PUSH_SUPPRESS_CODE(VLA)
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_VLA DYNINST_DIAGNOSTIC_POP
#else
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_VLA
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_VLA
#endif
#ifdef DYNINST_SUPPRESS_CODE_VLA_EXTENSION
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_VLA_EXTENSION \
DYNINST_DIAGNOSTIC_PUSH_SUPPRESS_CODE(VLA_EXTENSION)
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_VLA_EXTENSION DYNINST_DIAGNOSTIC_POP
#else
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_VLA_EXTENSION
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_VLA_EXTENSION
#endif
#define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_VLA_ALL \
DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_VLA DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_VLA_EXTENSION
#define DYNINST_DIAGNOSTIC_END_SUPPRESS_VLA_ALL \
DYNINST_DIAGNOSTIC_END_SUPPRESS_VLA DYNINST_DIAGNOSTIC_END_SUPPRESS_VLA_EXTENSION
// Suppressions to work around compiler specific diagnostic bugs
#ifdef DYNINST_SUPPRESS_CODE_LOGICAL_OP
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_LOGICAL_OP \
DYNINST_DIAGNOSTIC_PUSH_SUPPRESS_CODE(LOGICAL_OP)
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_LOGICAL_OP DYNINST_DIAGNOSTIC_POP
#else
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_LOGICAL_OP
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_LOGICAL_OP
#endif
#ifdef DYNINST_SUPPRESS_CODE_DUPLICATED_BRANCHES
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_DUPLICATED_BRANCHES \
DYNINST_DIAGNOSTIC_PUSH_SUPPRESS_CODE(DUPLICATED_BRANCHES)
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_DUPLICATED_BRANCHES DYNINST_DIAGNOSTIC_POP
#else
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_DUPLICATED_BRANCHES
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_DUPLICATED_BRANCHES
#endif
#ifdef DYNINST_SUPPRESS_CODE_UNUSED_VARIABLE
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_UNUSED_VARIABLE \
DYNINST_DIAGNOSTIC_PUSH_SUPPRESS_CODE(UNUSED_VARIABLE)
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_UNUSED_VARIABLE DYNINST_DIAGNOSTIC_POP
#else
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_UNUSED_VARIABLE
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_UNUSED_VARIABLE
#endif
#ifdef DYNINST_SUPPRESS_CODE_MAYBE_UNINITIALIZED
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_MAYBE_UNINITIALIZED \
DYNINST_DIAGNOSTIC_PUSH_SUPPRESS_CODE(MAYBE_UNINITIALIZED)
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_MAYBE_UNINITIALIZED DYNINST_DIAGNOSTIC_POP
#else
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_MAYBE_UNINITIALIZED
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_MAYBE_UNINITIALIZED
#endif
// gcc <9, 11.0 and 11.1 (there may be others) have a bug where 'pragma
// diagnostic ignores' do not take affect until the next line, so this is a
// workaround for the suppression and VLA are in the same macro
#if defined(__GNUC__) && !defined(__clang__) && \
(__GNUC__ < 9 || __GNUC__ == 11 && __GNUC_MINOR__ < 2)
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_VLA_GCC_PRAGMA_BUG \
DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_VLA
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_VLA_GCC_PRAGMA_BUG \
DYNINST_DIAGNOSTIC_END_SUPPRESS_VLA
#else
# define DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_VLA_GCC_PRAGMA_BUG
# define DYNINST_DIAGNOSTIC_END_SUPPRESS_VLA_GCC_PRAGMA_BUG
#endif
// Create pragma from parameters
#define DYNINST_Pragma(x) _Pragma(#x)
// Create compiler specific macros
//
// DYNINST_DIAGNOSTIC_Pragma(x) - diagnostic pragma for x which is unquoted
// DYNINST_DIAGNOSTIC_SUPPRESS(x) - diagnostic pragma to suppress warning x:
// quoted string (gcc), number (MSVC)
#ifndef DYNINST_DIAGNOSTIC_NO_SUPPRESSIONS
# if defined(__GNUC__)
# define DYNINST_DIAGNOSTIC_Pragma(x) DYNINST_Pragma(GCC diagnostic x)
# define DYNINST_DIAGNOSTIC_SUPPRESS(x) DYNINST_DIAGNOSTIC_Pragma(ignored x)
# elif defined(_MSC_VER)
# define DYNINST_DIAGNOSTIC_Pragma(x) DYNINST_Pragma(warning(x))
# define DYNINST_DIAGNOSTIC_SUPPRESS(x) DYNINST_DIAGNOSTIC_Pragma(disable : x)
# endif
#endif
// if not defined, expand to nothing
#ifndef DYNINST_DIAGNOSTIC_Pragma
# define DYNINST_DIAGNOSTIC_Pragma(x)
#endif
#ifndef DYNINST_DIAGNOSTIC_SUPPRESS
# define DYNINST_DIAGNOSTIC_SUPPRESS(x)
#endif
// Define macros in terms of compiler specific macros
//
// DYNINST_DIAGNOSTIC_POP - pop stack of pushed diagnostic state
// DYNINST_DIAGNOSTIC_PUSH - push current diagnostic state on stack
// DYNINST_DIAGNOSTIC_PUSH_SUPPRESS(x) - push diagnostic state and add
// suppression x
#define DYNINST_DIAGNOSTIC_POP DYNINST_DIAGNOSTIC_Pragma(pop)
#define DYNINST_DIAGNOSTIC_PUSH DYNINST_DIAGNOSTIC_Pragma(push)
#define DYNINST_DIAGNOSTIC_PUSH_SUPPRESS(x) \
DYNINST_DIAGNOSTIC_PUSH \
DYNINST_DIAGNOSTIC_SUPPRESS(x)
#define DYNINST_DIAGNOSTIC_PUSH_SUPPRESS_CODE(x) \
DYNINST_DIAGNOSTIC_PUSH_SUPPRESS(DYNINST_SUPPRESS_CODE_##x)
// use the variable in a void expression to indicate use
#ifndef DYNINST_DIAGNOSTIC_NO_SUPPRESSIONS
# define DYNINST_SUPPRESS_UNUSED_VARIABLE(var) (void) (var)
#endif
// if not defined, expand to nothing
#ifndef DYNINST_SUPPRESS_UNUSED_VARIABLE
# define DYNINST_SUPPRESS_UNUSED_VARIABLE(var)
#endif
#endif /* COMPILER_DIAGNOSTICS_H */
@@ -53,13 +53,11 @@
#define DYNINST_BREAKPOINT_SIGNUM (SIGRTMIN + 4)
#include "dyninstRTExport.h"
#include "h/compiler_diagnostics.h"
#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;
@@ -191,15 +189,10 @@ typedef struct
#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
// Suppress warning about flexible array members not valid in C++
// FIXME: invalid flexible array member, traps[], in structure below
DYNINST_DIAGNOSTIC_BEGIN_SUPPRESS_FLEX_ARRAY
struct trap_mapping_header
{
uint32_t signature;
@@ -211,9 +204,8 @@ struct trap_mapping_header
trapMapping_t
traps[]; // Don't change this to a pointer, despite any compiler warnings
};
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#endif
DYNINST_DIAGNOSTIC_END_SUPPRESS_FLEX_ARRAY
#define MAX_MEMORY_MAPPER_ELEMENTS 1024
@@ -278,7 +270,5 @@ struct MemoryMapper64
DLLEXPORT extern struct MemoryMapper RTmemoryMapper;
extern int RTuntranslatedEntryCounter;
#include "dyninstRTExport.h"
#endif /* _DYNINSTAPI_RT_H */
@@ -27,7 +27,6 @@
* 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
@@ -36,6 +35,8 @@
libraries.
*/
# include <stddef.h>
# if !defined(DLLEXPORT)
# if defined(_MSC_VER)
/* If we're on Windows, we need to explicetely export these functions: */
@@ -63,7 +64,7 @@ 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();
DYNINSTthreadCount(void);
/**
* These function implement a locking mechanism that can be used by
@@ -106,21 +107,15 @@ dyninst_unlock(dyninst_lock_t* lock);
**/
DLLEXPORT void
DYNINSTsafeBreakPoint();
DYNINSTsafeBreakPoint(void);
DLLEXPORT void
DYNINSTinit();
DYNINSTinit(void);
DLLEXPORT void
DYNINST_snippetBreakpoint();
DYNINST_snippetBreakpoint(void);
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
@@ -40,6 +40,7 @@
# endif
# ifndef FILE__
# include <string.h>
# if defined(_MSC_VER)
# define FILE__ \
(strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
@@ -49,12 +50,13 @@
# endif
# endif
# if defined(_POWER) && !defined(__GNUC__)
# define XLC
# endif
# ifdef __cplusplus
# include <unordered_map>
# include <unordered_set>
# include <functional>
# include <memory>
# include <unordered_map>
# include <unordered_set>
# include <utility>
// NB: std::hash has overloads for [un]scoped enums
template <typename Key, typename Value, typename Hash = std::hash<Key>,
@@ -67,45 +69,50 @@ template <typename Key, typename Hash = std::hash<Key>,
using dyn_hash_set = std::unordered_set<Key, Hash, Comp, Alloc>;
// We require C++11 thread_local support
# define dyn_tls thread_local
# define dyn_tls thread_local
namespace Dyninst
{
# if defined(_WIN64)
# if defined(_WIN64)
typedef uintptr_t Address;
typedef uintptr_t Offset;
# else
# else
typedef unsigned long Address;
typedef unsigned long Offset;
# endif
# endif
# if defined(_MSC_VER)
static constexpr Address ADDR_NULL{ 0 };
# 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
# 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
# define NULL_PID -1
# define NULL_LWP -1
# define NULL_THR_ID -1
# ifndef INVALID_HANDLE_VALUE
# define INVALID_HANDLE_VALUE -1
# endif
# endif
# endif
int
ThrIDToTid(Dyninst::THR_ID id);
inline int
ThrIDToTid(Dyninst::THR_ID id)
{
return id;
}
} // namespace Dyninst
namespace Dyninst
@@ -119,4 +126,9 @@ typedef enum
} OSType;
}
# else
# define ADDR_NULL (0)
typedef unsigned long Address;
# endif
#endif
@@ -28,36 +28,22 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "src/RTthread.h"
#ifndef unaligned_memory_access_h_
#define unaligned_memory_access_h_
/**
* atomic_set will do the following atomically:
* if (*val == 0) {
* *val = 1;
* return 1;
* }
* return 0;
/*
* C language - functions
*/
/* CAST_WITHOUT_ALIGNMENT_WARNING(toType, addr)
*
**/
* C language macro that casts the expression addr to type toType
* without producing a warning that alignment of the new pointer type is
* larger than the current pointer type.
*
* WARNING: The caller is responsible to ensure that the alignment is
* correct or use memcpy if the pointer is dereferenced.
*/
#define CAST_WITHOUT_ALIGNMENT_WARNING(toType, addr) (toType)(void*)(addr)
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;
}
#endif
@@ -203,12 +203,9 @@
# 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
@@ -138,14 +138,14 @@ int fakeTickCount;
static TLS_VAR short DYNINST_tls_tramp_guard = 1;
DLLEXPORT int
DYNINST_lock_tramp_guard()
DYNINST_lock_tramp_guard(void)
{
if(!DYNINST_tls_tramp_guard) return 0;
DYNINST_tls_tramp_guard = 0;
return 1;
}
DLLEXPORT void
DYNINST_unlock_tramp_guard()
DYNINST_unlock_tramp_guard(void)
{
DYNINST_tls_tramp_guard = 1;
}
@@ -160,7 +160,7 @@ DECLARE_DYNINST_LOCK(DYNINST_trace_lock);
**/
double DYNINSTdummydouble = 4321.71;
static void
initFPU()
initFPU(void)
{
double x = 17.1234;
DYNINSTdummydouble *= x;
@@ -171,15 +171,13 @@ initFPU()
* all platforms that support binary rewriting, but before DYNINSTinit
**/
void
DYNINSTBaseInit()
DYNINSTBaseInit(void)
{
#if defined(cap_mutatee_traps)
DYNINSTinitializeTrapHandler();
#endif
DYNINST_unlock_tramp_guard();
DYNINSThasInitialized = 1;
RTuntranslatedEntryCounter = 0;
}
/**
@@ -195,7 +193,7 @@ DYNINSTBaseInit()
* libraries don't call this.
**/
void
DYNINSTinit()
DYNINSTinit(void)
{
rtdebug_printf("%s[%d]: DYNINSTinit: welcome to DYNINSTinit()\n", __FILE__,
__LINE__);
@@ -226,14 +224,14 @@ DYNINSTinit()
* cases (MT in particular)
**/
int
DYNINSTreturnZero()
DYNINSTreturnZero(void)
{
return 0;
}
/* Used to by dyninst breakpoint snippet */
void
DYNINST_snippetBreakpoint()
DYNINST_snippetBreakpoint(void)
{
tc_lock_lock(&DYNINST_trace_lock);
@@ -250,7 +248,7 @@ DYNINST_snippetBreakpoint()
/* Used to instrument (and report) the entry of fork */
DLLEXPORT void
DYNINST_instForkEntry()
DYNINST_instForkEntry(void)
{
tc_lock_lock(&DYNINST_trace_lock);
@@ -717,12 +715,10 @@ rtdebug_printf(const char* format, ...)
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)
@@ -808,7 +804,7 @@ dyninstTrapTranslate(void* source, volatile unsigned long* table_used,
}
DLLEXPORT void
DYNINSTtrapFunction()
DYNINSTtrapFunction(void)
{
__asm__ __volatile__("nop\n" :::);
}
@@ -35,25 +35,26 @@
#include "h/compiler_annotations.h"
#include "h/dyninstAPI_RT.h"
#include <stdarg.h>
#include <stddef.h>
void
DYNINSTtrapFunction();
DYNINSTtrapFunction(void);
void
DYNINSTbreakPoint();
DYNINSTbreakPoint(void);
/* Use a signal that is safe if we're not attached. */
void
DYNINSTsafeBreakPoint();
DYNINSTsafeBreakPoint(void);
void
DYNINSTinit();
DYNINSTinit(void);
int
DYNINSTreturnZero();
DYNINSTreturnZero(void);
int
DYNINSTwriteEvent(void* ev, size_t sz);
int
DYNINSTasyncConnect(int pid);
int
DYNINSTinitializeTrapHandler();
DYNINSTinitializeTrapHandler(void);
void*
dyninstTrapTranslate(void* source, volatile unsigned long* table_used,
volatile unsigned long* table_version,
@@ -1,729 +0,0 @@
/*
* 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;
}
*/
@@ -1,85 +0,0 @@
/*
* 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;
}
@@ -31,7 +31,10 @@
/* $Id: RTheap-linux.c,v 1.9 2008/01/31 18:01:54 legendre Exp $ */
/* RTheap-linux.c: Linux-specific heap components */
#define _GNU_SOURCE
#include "RTheap.h"
#include "dyntypes.h"
#include <assert.h>
#include <fcntl.h> /* open() */
#include <stdio.h>
@@ -1,153 +0,0 @@
/*
* 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;
}
@@ -31,6 +31,8 @@
/* $Id: RTheap.c,v 1.25 2006/05/03 00:31:25 jodom Exp $ */
/* RTheap.c: platform-generic heap management */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#if !defined(os_windows) /* ccw 15 may 2000 : 29 mar 2001 */
@@ -48,6 +50,7 @@ getpagesize();
#endif
#include <assert.h>
#include "h/unaligned_memory_access.h"
#include "src/RTcommon.h"
#include "src/RTheap.h"
@@ -148,7 +151,7 @@ DYNINSTos_malloc(size_t nbytes, void* lo_addr, void* hi_addr)
}
/* define new heap */
node = (heapList_t*) (ret_heap + size);
node = CAST_WITHOUT_ALIGNMENT_WARNING(heapList_t*, (ret_heap + size));
node->heap.ret_addr = (void*) ret_heap;
node->heap.addr = heap;
node->heap.len = size_heap;
@@ -160,7 +163,7 @@ DYNINSTos_malloc(size_t nbytes, void* lo_addr, void* hi_addr)
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);
node = CAST_WITHOUT_ALIGNMENT_WARNING(heapList_t*, (heap + size));
/* define new heap */
node->heap.addr = heap;
@@ -33,6 +33,7 @@
#ifndef _RT_HEAP_H
#define _RT_HEAP_H
#include "dyntypes.h"
#include "h/dyninstAPI_RT.h" /* RT_Boolean, Address */
#if defined(os_linux) || defined(os_freebsd)
@@ -71,7 +72,7 @@ extern int DYNINSTheap_mmapFlags;
RT_Boolean
DYNINSTheap_useMalloc(void* lo, void* hi);
int
DYNINSTheap_mmapFdOpen();
DYNINSTheap_mmapFdOpen(void);
void
DYNINSTheap_mmapFdClose(int fd);
int
@@ -33,9 +33,12 @@
* RTlinux.c: mutatee-side library function specific to Linux
************************************************************************/
#define _GNU_SOURCE
#include "h/dyninstAPI_RT.h"
#include "src/RTcommon.h"
#include "src/RTthread.h"
#include "unaligned_memory_access.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>
@@ -46,11 +49,8 @@
#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>
@@ -114,7 +114,7 @@ t_kill(int pid, int sig)
}
void
DYNINSTbreakPoint()
DYNINSTbreakPoint(void)
{
if(DYNINSTstaticMode) return;
// Call into a funtion that contains a
@@ -131,7 +131,7 @@ uncaught_breakpoint(int sig)
}
void
DYNINSTsafeBreakPoint()
DYNINSTsafeBreakPoint(void)
{
if(DYNINSTstaticMode) return;
@@ -141,7 +141,7 @@ DYNINSTsafeBreakPoint()
}
void
mark_heaps_exec()
mark_heaps_exec(void)
{
/* Grab the page size, to align the heap pointer. */
long int pageSize = sysconf(_SC_PAGESIZE);
@@ -215,7 +215,7 @@ typedef struct dlopen_args
void* (*DYNINST_do_dlopen)(dlopen_args_t*) = NULL;
static int
get_dlopen_error()
get_dlopen_error(void)
{
char* err_str;
err_str = dlerror();
@@ -278,7 +278,7 @@ DYNINSTloadLibrary(char* libname)
#endif
// Define this value so that we can compile on a system that doesn't have
// gettid and still run on one that does.
// gettid and still run on one that does.
#if !defined(SYS_gettid)
# if defined(arch_x86)
@@ -290,7 +290,7 @@ DYNINSTloadLibrary(char* libname)
#endif
int
dyn_lwp_self()
dyn_lwp_self(void)
{
static int gettid_not_valid = 0;
int result;
@@ -307,7 +307,7 @@ dyn_lwp_self()
}
int
dyn_pid_self()
dyn_pid_self(void)
{
return getpid();
}
@@ -315,7 +315,7 @@ dyn_pid_self()
dyntid_t (*DYNINST_pthread_self)(void);
dyntid_t
dyn_pthread_self()
dyn_pthread_self(void)
{
dyntid_t me;
if(DYNINSTstaticMode)
@@ -373,12 +373,10 @@ DYNINST_am_initial_thread(dyntid_t tid)
# 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
// aarch64 pc is not one of 31 GPRs, but an independent reg
# define UC_PC(x) x->uc_mcontext.pc
# endif // UC_PC
@@ -430,8 +428,9 @@ dyninstTrapHandler(int sig, siginfo_t* sg, ucontext_t* context)
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);
trap_to = dyninstTrapTranslate(
orig_ip, CAST_WITHOUT_ALIGNMENT_WARNING(unsigned long*, &hdr->num_entries),
&zero, &mapping, &one);
}
else
{
@@ -445,33 +444,12 @@ dyninstTrapHandler(int sig, siginfo_t* sg, ucontext_t* context)
# 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()
r_debugCheck(void)
{
# 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
assert(_r_debug.r_map);
}
# define NUM_LIBRARIES 512 // Important, max number of rewritten libraries
@@ -494,11 +472,11 @@ static unsigned all_headers_current[NUM_LIBRARIES_BITMASK_SIZE];
static unsigned all_headers_last[NUM_LIBRARIES_BITMASK_SIZE];
static int
parse_libs();
parse_libs(void);
static int
parse_link_map(struct link_map* l);
static void
clear_unloaded_libs();
clear_unloaded_libs(void);
static void
set_bit(unsigned* bit_mask, int bit, char value);
@@ -554,7 +532,7 @@ done:
# if !defined(arch_aarch64)
static int
parse_libs()
parse_libs(void)
{
struct link_map* l_current;
@@ -639,7 +617,7 @@ parse_link_map(struct link_map* l)
}
static void
clear_unloaded_libs()
clear_unloaded_libs(void)
{
unsigned i;
for(i = 0; i < NUM_LIBRARIES_BITMASK_SIZE; i++)
@@ -757,13 +735,13 @@ get_next_set_bitmask(unsigned* bit_mask, int last_pos)
* function runDYNINSTBaseInit(). See DYNINSTglobal_ctors_handler.
*/
extern void
r_debugCheck();
r_debugCheck(void);
extern void
DYNINSTBaseInit();
DYNINSTBaseInit(void);
void
runDYNINSTBaseInit() __attribute__((constructor));
runDYNINSTBaseInit(void) __attribute__((constructor));
void
runDYNINSTBaseInit()
runDYNINSTBaseInit(void)
{
r_debugCheck();
DYNINSTBaseInit();
@@ -1,205 +0,0 @@
/*
* 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);
}
}
}
@@ -33,6 +33,8 @@
* RTposix.c: runtime instrumentation functions for generic posix.
************************************************************************/
#define _GNU_SOURCE
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
@@ -56,7 +58,7 @@
#if !(defined(arch_power) && defined(os_linux))
void
RTmutatedBinary_init()
RTmutatedBinary_init(void)
{
return;
}
@@ -81,7 +83,7 @@ struct passwd* passwd_info = NULL;
#endif
void
libdyninstAPI_RT_init()
libdyninstAPI_RT_init(void)
{
static int initCalledOnce = 0;
@@ -198,7 +200,7 @@ DYNINSTasyncConnect(int pid)
}
int
DYNINSTasyncDisconnect()
DYNINSTasyncDisconnect(void)
{
if(DYNINSTstaticMode) return 0;
rtdebug_printf("%s[%d]: welcome to DYNINSTasyncDisconnect\n", __FILE__, __LINE__);
@@ -281,7 +283,7 @@ extern void
dyninstTrapHandler(int sig, siginfo_t* info, void* context);
int
DYNINSTinitializeTrapHandler()
DYNINSTinitializeTrapHandler(void)
{
int result;
struct sigaction new_handler;
@@ -32,6 +32,8 @@
* RTsignal.c: C-language signal handling code
************************************************************************/
#define _GNU_SOURCE
#include <signal.h>
#include <stdio.h>
@@ -1,82 +0,0 @@
/*
* 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
@@ -1,102 +0,0 @@
/*
* 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
@@ -1,72 +0,0 @@
/*
* 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
@@ -39,7 +39,7 @@ extern void (*DYNINSTctors_end)(void);
extern void (*DYNINSTdtors_end)(void);
extern void
DYNINSTBaseInit();
DYNINSTBaseInit(void);
typedef struct
{
@@ -66,7 +66,7 @@ typedef struct
*/
void
DYNINSTglobal_ctors_handler()
DYNINSTglobal_ctors_handler(void)
{
void (**ctor)(void) = &DYNINSTctors_begin;
@@ -82,7 +82,7 @@ DYNINSTglobal_ctors_handler()
}
void
DYNINSTglobal_dtors_handler()
DYNINSTglobal_dtors_handler(void)
{
void (**dtor)(void) = &DYNINSTdtors_begin;
@@ -95,7 +95,7 @@ DYNINSTglobal_dtors_handler()
}
void
DYNINSTglobal_irel_handler()
DYNINSTglobal_irel_handler(void)
{
if(sizeof(long) == 8)
{
@@ -1,41 +0,0 @@
/*
* 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;
}
@@ -1,9 +0,0 @@
#include "RTconst.h"
#include "../../dyninstAPI/src/inst-power.h"
.machine "push"
#ifndef __clang__
.machine "ppc"
#endif
.machine "pop"
.section .note.GNU-stack,"",@progbits
@@ -1,77 +0,0 @@
.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
@@ -35,11 +35,11 @@
#include "h/dyninstRTExport.h"
DLLEXPORT dyntid_t
dyn_pthread_self(); /*Thread library identifier*/
dyn_pthread_self(void); /*Thread library identifier*/
int
dyn_lwp_self(); /*LWP used by the kernel identifier*/
dyn_lwp_self(void); /*LWP used by the kernel identifier*/
int
dyn_pid_self(); /*PID identifier representing the containing process*/
dyn_pid_self(void); /*PID identifier representing the containing process*/
extern int DYNINST_multithread_capable;
@@ -1,565 +0,0 @@
/*
* 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());
}
}
@@ -20,4 +20,4 @@ _section_.text:
.csect .data[RW],3
.llong _section_.text
.section .note.GNU-stack,"",@progbits
.section .note.GNU-stack,"",@progbits