Update the rocprof-sys-rt library (#786)
Derived from Dyninst_RT 13.0.0
This commit is contained in:
@@ -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
|
||||
|
||||
+16
-30
@@ -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>
|
||||
|
||||
|
||||
-82
@@ -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
|
||||
-102
@@ -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
|
||||
-72
@@ -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
|
||||
+4
-4
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user