blob: 2b580441a8f8135528bd1db14242a7f1768a04e3 [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2011-2014 Google, Inc. All rights reserved.
* Copyright (c) 2003-2010 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of VMware, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
/* Copyright (c) 2003-2007 Determina Corp. */
/*
* globals_shared.h
*
* definitions to be shared with core-external modules
*
*/
#ifndef _GLOBALS_SHARED_H_
#define _GLOBALS_SHARED_H_
/* if not Unix, we assume Windows */
#ifndef UNIX
# ifndef WINDOWS
# define WINDOWS
# endif
#endif
/* DR_API EXPORT TOFILE dr_defines.h */
/* DR_API EXPORT BEGIN */
/****************************************************************************
* GENERAL TYPEDEFS AND DEFINES
*/
/**
* @file dr_defines.h
* @brief Basic defines and type definitions.
*/
#ifdef API_EXPORT_ONLY
/* A client's target operating system and architecture must be specified. */
#if !defined(LINUX) && !defined(WINDOWS) && !defined(MACOS)
# error Target operating system unspecified: must define WINDOWS, LINUX, or MACOS
#endif
#endif
#ifdef API_EXPORT_ONLY
#if defined(X86_32) || defined(X86_64)
# define X86
# if (defined(X86_64) && defined(X86_32)) || defined(ARM_32) || defined(ARM_64)
# error Target architecture over-specified: must define only one
# endif
#elif defined(ARM_32) || defined(ARM_64)
# define ARM
# if defined(X86_32) || defined(X86_64) || (defined(ARM_64) && defined(ARM_32))
# error Target architecture over-specified: must define only one
# endif
#else
# error Target architecture unknown: must define X86_32, X86_64, ARM_32, or ARM_64
#endif
#endif
#if (defined(X86_64) || defined(ARM_64)) && !defined(X64)
# define X64
#endif
#if (defined(LINUX) || defined(MACOS)) && !defined(UNIX)
# define UNIX
#endif
#ifdef API_EXPORT_ONLY
#ifdef WINDOWS
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <winbase.h>
#else
# include <stdio.h>
# include <stdlib.h>
#endif
#include <stdarg.h> /* for varargs */
#endif
/* DR_API EXPORT END */
#include <limits.h> /* for USHRT_MAX */
#ifdef UNIX
# include <sys/types.h> /* Fix for case 5341. */
# include <signal.h>
#endif
/* DR_API EXPORT VERBATIM */
#ifdef WINDOWS
/* allow nameless struct/union */
# pragma warning(disable: 4201)
/* VS2005 warns about comparison operator results being cast to bool (i#523) */
# if _MSC_VER >= 1400 && _MSC_VER < 1500
# pragma warning(disable: 4244)
# endif
#endif
#ifdef WINDOWS
# define DR_EXPORT __declspec(dllexport)
# define LINK_ONCE __declspec(selectany)
# define ALIGN_VAR(x) __declspec(align(x))
# ifndef __cplusplus
# define inline __inline
# endif
# define INLINE_FORCED __forceinline
#else
/* We assume gcc is being used. If the client is using -fvisibility
* (in gcc >= 3.4) to not export symbols by default, setting
* USE_VISIBILITY_ATTRIBUTES will properly export.
*/
# ifdef USE_VISIBILITY_ATTRIBUTES
# define DR_EXPORT __attribute__ ((visibility ("default")))
# else
# define DR_EXPORT
# endif
# define LINK_ONCE __attribute__ ((weak))
# define ALIGN_VAR(x) __attribute__ ((aligned (x)))
# ifndef __cplusplus
# define inline __inline__
# endif
# define INLINE_FORCED inline
#endif
/* DR_API EXPORT END */
/* DR_API EXPORT BEGIN */
#ifdef AVOID_API_EXPORT
/* We want a consistent size so we stay away from MAX_PATH.
* MAX_PATH is 260 on Windows, but 4096 on Linux, should up this.
* FIXME: should undef MAX_PATH and define it to an error-producing value
* and clean up all uses of it
*/
#endif
/** Cross-platform maximum file path length. */
#define MAXIMUM_PATH 260
/* DR_API EXPORT END */
/* DR_API EXPORT VERBATIM */
#ifndef NULL
# define NULL (0)
#endif
#ifndef __cplusplus
# ifndef DR_DO_NOT_DEFINE_bool
# ifdef DR__Bool_EXISTS
/* prefer _Bool as it avoids truncation casting non-zero to zero */
typedef _Bool bool;
# else
/* char-sized for compatibility with C++ */
typedef char bool;
# endif
# endif
# ifndef true
# define true (1)
# endif
# ifndef false
# define false (0)
# endif
#endif
/* on Windows where bool is char casting can truncate non-zero to zero
* so we use this macro
*/
#define CAST_TO_bool(x) (!!(x))
#ifndef DR_DO_NOT_DEFINE_uint
typedef unsigned int uint;
#endif
#ifndef DR_DO_NOT_DEFINE_ushort
typedef unsigned short ushort;
#endif
#ifndef DR_DO_NOT_DEFINE_byte
typedef unsigned char byte;
#endif
#ifndef DR_DO_NOT_DEFINE_sbyte
typedef signed char sbyte;
#endif
typedef byte * app_pc;
typedef void (*generic_func_t) ();
#ifdef WINDOWS
# ifndef DR_DO_NOT_DEFINE_uint64
typedef unsigned __int64 uint64;
# endif
# ifndef DR_DO_NOT_DEFINE_int64
typedef __int64 int64;
# endif
# ifdef X64
typedef __int64 ssize_t;
# else
typedef int ssize_t;
# endif
# define INT64_FORMAT "I64"
#else /* Linux */
# ifdef X64
# ifndef DR_DO_NOT_DEFINE_uint64
typedef unsigned long int uint64;
# endif
# ifndef DR_DO_NOT_DEFINE_int64
typedef long int int64;
# endif
# define INT64_FORMAT "l"
# else
# ifndef DR_DO_NOT_DEFINE_uint64
typedef unsigned long long int uint64;
# endif
# ifndef DR_DO_NOT_DEFINE_int64
typedef long long int int64;
# endif
# define INT64_FORMAT "ll"
# endif
#endif
/* DR_API EXPORT END */
/* DR_API EXPORT BEGIN */
/* a register value: could be of any type; size is what matters. */
#ifdef X64
typedef uint64 reg_t;
#else
typedef uint reg_t;
#endif
/* integer whose size is based on pointers: ptr diff, mask, etc. */
typedef reg_t ptr_uint_t;
#ifdef X64
typedef int64 ptr_int_t;
#else
typedef int ptr_int_t;
#endif
/* for memory region sizes, use size_t */
/**
* Application offset from module base.
* PE32+ modules are limited to 2GB, but not ELF x64 med/large code model.
*/
typedef size_t app_rva_t;
#define PTR_UINT_0 ((ptr_uint_t)0U)
#define PTR_UINT_1 ((ptr_uint_t)1U)
#define PTR_UINT_MINUS_1 ((ptr_uint_t)-1)
#ifdef WINDOWS
typedef ptr_uint_t thread_id_t;
typedef ptr_uint_t process_id_t;
#elif defined(MACOS)
typedef uint64 thread_id_t;
typedef pid_t process_id_t;
#else /* Linux */
typedef pid_t thread_id_t;
typedef pid_t process_id_t;
#endif
#define INVALID_PROCESS_ID PTR_UINT_MINUS_1
#ifdef API_EXPORT_ONLY
#ifdef WINDOWS
/* since a FILE cannot be used outside of the DLL it was created in,
* we have to use HANDLE on Windows
* we hide the distinction behind the file_t type
*/
typedef HANDLE file_t;
/** The sentinel value for an invalid file_t. */
# define INVALID_FILE INVALID_HANDLE_VALUE
/* dr_get_stdout_file and dr_get_stderr_file return errors as
* INVALID_HANDLE_VALUE. We leave INVALID_HANDLE_VALUE as is,
* since it equals INVALID_FILE
*/
/** The file_t value for standard output. */
# define STDOUT (dr_get_stdout_file())
/** The file_t value for standard error. */
# define STDERR (dr_get_stderr_file())
/** The file_t value for standard input. */
# define STDIN (dr_get_stdin_file())
#endif
#endif
#ifdef UNIX
typedef int file_t;
/** The sentinel value for an invalid file_t. */
# define INVALID_FILE -1
/** Allow use of stdout after the application closes it. */
extern file_t our_stdout;
/** Allow use of stderr after the application closes it. */
extern file_t our_stderr;
/** Allow use of stdin after the application closes it. */
extern file_t our_stdin;
/** The file_t value for standard output. */
# define STDOUT our_stdout
/** The file_t value for standard error. */
# define STDERR our_stderr
/** The file_t value for standard error. */
# define STDIN our_stdin
#endif
#ifdef AVOID_API_EXPORT
/* Note that we considered using a 128-bit GUID for the client ID,
* but decided it was unnecessary since the client registration
* routine will complain about conflicting IDs. Also, we're storing
* this value in the registry, so no reason to make it any longer
* than we have to.
*/
#endif
/**
* ID used to uniquely identify a client. This value is set at
* client registration and passed to the client in dr_init().
*/
typedef uint client_id_t;
#ifdef API_EXPORT_ONLY
#ifndef DR_FAST_IR
/**
* Internal structure of opnd_t is below abstraction layer.
* But compiler needs to know field sizes to copy it around
*/
typedef struct {
# ifdef X64
uint black_box_uint;
uint64 black_box_uint64;
# else
uint black_box_uint[3];
# endif
} opnd_t;
/**
* Internal structure of instr_t is below abstraction layer, but we
* provide its size so that it can be used in stack variables
* instead of always allocated on the heap.
*/
typedef struct {
# ifdef X64
uint black_box_uint[26];
# else
uint black_box_uint[16];
# endif
} instr_t;
#else
struct _opnd_t;
typedef struct _opnd_t opnd_t;
struct _instr_t;
typedef struct _instr_t instr_t;
#endif /* !DR_FAST_IR */
#endif /* API_EXPORT_ONLY */
#ifndef IN
# define IN /* marks input param */
#endif
#ifndef OUT
# define OUT /* marks output param */
#endif
#ifndef INOUT
# define INOUT /* marks input+output param */
#endif
/* DR_API EXPORT END */
#ifdef X64
# define POINTER_MAX ULLONG_MAX
# ifndef SSIZE_T_MAX
# define SSIZE_T_MAX LLONG_MAX
# endif
# define POINTER_MAX_32BIT ((ptr_uint_t)UINT_MAX)
#else
# define POINTER_MAX UINT_MAX
# ifndef SSIZE_T_MAX
# define SSIZE_T_MAX INT_MAX
# endif
#endif
#define MAX_CLIENT_LIBS 16
/* FIXME: these macros double-evaluate their args -- if we can't trust
* compiler to do CSE, should we replace w/ inline functions? would need
* separate signed and unsigned versions
*/
#ifndef DR_DO_NOT_DEFINE_MAX_MIN
# define MAX(x,y) ((x) >= (y) ? (x) : (y))
# define MIN(x,y) ((x) <= (y) ? (x) : (y))
#endif
#define PTR_UINT_ABS(x) ((x) < 0 ? -(x) : (x))
/* check if all bits in mask are set in var */
#define TESTALL(mask, var) (((mask) & (var)) == (mask))
/* check if any bit in mask is set in var */
#define TESTANY(mask, var) (((mask) & (var)) != 0)
/* check if a single bit is set in var */
#define TEST TESTANY
#define BOOLS_MATCH(a, b) (!!(a) == !!(b))
/* macros to make conditional compilation look prettier */
#ifdef DEBUG
# define IF_DEBUG(x) x
# define _IF_DEBUG(x) , x
# define IF_DEBUG_(x) x ,
# define IF_DEBUG_ELSE(x, y) x
# define IF_DEBUG_ELSE_0(x) (x)
# define IF_DEBUG_ELSE_NULL(x) (x)
#else
# define IF_DEBUG(x)
# define _IF_DEBUG(x)
# define IF_DEBUG_(x)
# define IF_DEBUG_ELSE(x, y) y
# define IF_DEBUG_ELSE_0(x) 0
# define IF_DEBUG_ELSE_NULL(x) (NULL)
#endif
#ifdef INTERNAL
# define IF_INTERNAL(x) x
# define IF_INTERNAL_ELSE(x,y) x
#else
# define IF_INTERNAL(x)
# define IF_INTERNAL_ELSE(x,y) y
#endif
#ifdef WINDOWS
# define IF_WINDOWS(x) x
# define IF_WINDOWS_(x) x,
# define _IF_WINDOWS(x) , x
# ifdef X64
# define _IF_WINDOWS_X64(x) , x
# else
# define _IF_WINDOWS_X64(x)
# endif
# define IF_WINDOWS_ELSE_0(x) (x)
# define IF_WINDOWS_ELSE(x,y) (x)
# define IF_WINDOWS_ELSE_NP(x,y) x
# define IF_UNIX(x)
# define IF_UNIX_ELSE(x,y) y
# define IF_UNIX_(x)
# define _IF_UNIX(x)
#else
# define IF_WINDOWS(x)
# define IF_WINDOWS_(x)
# define _IF_WINDOWS(x)
# define _IF_WINDOWS_X64(x)
# define IF_WINDOWS_ELSE_0(x) (0)
# define IF_WINDOWS_ELSE(x,y) (y)
# define IF_WINDOWS_ELSE_NP(x,y) y
# define IF_UNIX(x) x
# define IF_UNIX_ELSE(x,y) x
# define IF_UNIX_(x) x,
# define _IF_UNIX(x) , x
#endif
#ifdef LINUX
# define IF_LINUX(x) x
# define IF_LINUX_ELSE(x,y) x
# define IF_LINUX_(x) x,
#else
# define IF_LINUX(x)
# define IF_LINUX_ELSE(x,y) y
# define IF_LINUX_(x)
#endif
#ifdef MACOS
# define IF_MACOS(x) x
# define IF_MACOS_ELSE(x,y) x
# define IF_MACOS_(x) x,
#else
# define IF_MACOS(x)
# define IF_MACOS_ELSE(x,y) y
# define IF_MACOS_(x)
#endif
#ifdef HAVE_MEMINFO_QUERY
# define IF_MEMQUERY(x) x
# define IF_MEMQUERY_(x) x,
# define IF_MEMQUERY_ELSE(x, y) x
# define IF_NO_MEMQUERY(x)
# define IF_NO_MEMQUERY_(x)
#else
# define IF_MEMQUERY(x)
# define IF_MEMQUERY_(x)
# define IF_MEMQUERY_ELSE(x, y) y
# define IF_NO_MEMQUERY(x) x
# define IF_NO_MEMQUERY_(x) x,
#endif
#ifdef VMX86_SERVER
# define IF_VMX86(x) x
# define IF_VMX86_ELSE(x,y) x
# define _IF_VMX86(x) , x
# define IF_NOT_VMX86(x)
#else
# define IF_VMX86(x)
# define IF_VMX86_ELSE(x,y) y
# define _IF_VMX86(x)
# define IF_NOT_VMX86(x) x
#endif
#ifdef UNIX
# ifdef HAVE_TLS
# define IF_HAVE_TLS_ELSE(x, y) x
# define IF_NOT_HAVE_TLS(x)
# else
# define IF_HAVE_TLS_ELSE(x, y) y
# define IF_NOT_HAVE_TLS(x) x
# endif
#else
/* Windows always has TLS. Better to generally define HAVE_TLS instead? */
# define IF_HAVE_TLS_ELSE(x, y) x
# define IF_NOT_HAVE_TLS(x)
#endif
#if defined(WINDOWS) && !defined(NOT_DYNAMORIO_CORE)
# define IF_WINDOWS_AND_CORE(x) x
#else
# define IF_WINDOWS_AND_CORE(x)
#endif
#ifdef PROGRAM_SHEPHERDING
# define IF_PROG_SHEP(x) x
#else
# define IF_PROG_SHEP(x)
#endif
#if defined(PROGRAM_SHEPHERDING) && defined(RCT_IND_BRANCH)
# define IF_RCT_IND_BRANCH(x) x
#else
# define IF_RCT_IND_BRANCH(x)
#endif
#if defined(PROGRAM_SHEPHERDING) && defined(RETURN_AFTER_CALL)
# define IF_RETURN_AFTER_CALL(x) x
# define IF_RETURN_AFTER_CALL_ELSE(x, y) x
#else
# define IF_RETURN_AFTER_CALL(x)
# define IF_RETURN_AFTER_CALL_ELSE(x, y) y
#endif
#ifdef HOT_PATCHING_INTERFACE
# define IF_HOTP(x) x
#else
# define IF_HOTP(x)
#endif
#ifdef CLIENT_INTERFACE
# define IF_CLIENT_INTERFACE(x) x
# define IF_NOT_CLIENT_INTERFACE(x)
# define IF_CLIENT_INTERFACE_ELSE(x, y) x
# define _IF_CLIENT_INTERFACE(x) , x
# define _IF_NOT_CLIENT_INTERFACE(x)
/* _IF_CLIENT_INTERFACE is too long */
# define _IF_CLIENT(x) , x
#else
# define IF_CLIENT_INTERFACE(x)
# define IF_NOT_CLIENT_INTERFACE(x) x
# define IF_CLIENT_INTERFACE_ELSE(x, y) y
# define _IF_CLIENT_INTERFACE(x)
# define _IF_NOT_CLIENT_INTERFACE(x) , x
# define _IF_CLIENT(x)
#endif
#ifdef CUSTOM_TRACES
# define IF_CUSTOM_TRACES(x) x
#else
# define IF_CUSTOM_TRACES(x)
#endif
#ifdef DR_APP_EXPORTS
# define IF_APP_EXPORTS(x) x
#else
# define IF_APP_EXPORTS(x)
#endif
#ifdef GBOP
# define IF_GBOP(x) x
#else
# define IF_GBOP(x)
#endif
#ifdef PROCESS_CONTROL
# define IF_PROC_CTL(x) x
#else
# define IF_PROC_CTL(x)
#endif
#ifdef KSTATS
# define IF_KSTATS(x) x
#else
# define IF_KSTATS(x)
#endif
#ifdef STANDALONE_UNIT_TEST
# define IF_UNIT_TEST_ELSE(x,y) x
#else
# define IF_UNIT_TEST_ELSE(x,y) y
#endif
/* DR_API EXPORT TOFILE dr_defines.h */
/* DR_API EXPORT BEGIN */
#ifdef X86
# define IF_X86(x) x
# define IF_X86_ELSE(x, y) x
# define IF_X86_(x) x,
# define _IF_X86(x) , x
# define IF_NOT_X86(x)
# define _IF_NOT_X86(x)
# ifdef X64
# define IF_X86_32(x)
# define IF_X86_64(x) x
# else
# define IF_X86_32(x) x
# define IF_X86_64(x)
# endif
#else
# define IF_X86(x)
# define IF_X86_ELSE(x, y) y
# define IF_X86_(x)
# define _IF_X86(x)
# define IF_NOT_X86(x) x
# define _IF_NOT_X86(x) , x
# define IF_X86_32(x)
# define IF_X86_64(x)
#endif
#ifdef ARM
# define IF_ARM(x) x
# define IF_ARM_ELSE(x, y) x
# define IF_ARM_(x) x,
# define _IF_ARM(x) , x
# define IF_NOT_ARM(x)
# define _IF_NOT_ARM(x)
#else
# define IF_ARM(x)
# define IF_ARM_ELSE(x, y) y
# define IF_ARM_(x)
# define _IF_ARM(x)
# define IF_NOT_ARM(x) x
# define _IF_NOT_ARM(x) , x
#endif
#ifdef X64
# define IF_X64(x) x
# define IF_X64_ELSE(x, y) x
# define IF_X64_(x) x,
# define _IF_X64(x) , x
# define IF_NOT_X64(x)
# define _IF_NOT_X64(x)
#else
# define IF_X64(x)
# define IF_X64_ELSE(x, y) y
# define IF_X64_(x)
# define _IF_X64(x)
# define IF_NOT_X64(x) x
# define _IF_NOT_X64(x) , x
#endif
#if defined(X86) && defined(X64)
# define IF_X86_X64(x) x
# define IF_X86_X64_ELSE(x, y) x
# define IF_X86_X64_(x) x,
# define _IF_X86_X64(x) , x
# define IF_NOT_X86_X64(x)
# define _IF_NOT_X86_X64(x)
#else
# define IF_X86_X64(x)
# define IF_X86_X64_ELSE(x, y) y
# define IF_X86_X64_(x)
# define _IF_X86_X64(x)
# define IF_NOT_X86_X64(x) x
# define _IF_NOT_X86_X64(x) , x
#endif
/* DR_API EXPORT END */
typedef enum {
SYSLOG_INFORMATION = 0x1,
SYSLOG_WARNING = 0x2,
SYSLOG_ERROR = 0x4,
SYSLOG_CRITICAL = 0x8,
SYSLOG_NONE = 0x0,
SYSLOG_ALL = SYSLOG_INFORMATION | SYSLOG_WARNING | SYSLOG_ERROR | SYSLOG_CRITICAL
} syslog_event_type_t;
#define DYNAMO_OPTION(opt) (ASSERT_OWN_READWRITE_LOCK(IS_OPTION_STRING(opt), \
&options_lock), dynamo_options.opt)
/* For use where we don't want ASSERT defines. Currently only used in FATAL_USAGE_ERROR
* so it can be used in files that require all asserts to be client asserts. */
#define DYNAMO_OPTION_NOT_STRING(opt) (dynamo_options.opt)
#if defined(INTERNAL) || defined(CLIENT_INTERFACE)
#define EXPOSE_INTERNAL_OPTIONS
#endif
#ifdef EXPOSE_INTERNAL_OPTIONS
/* Use only for experimental non-release options */
/* Internal option value can be set on the command line only in INTERNAL builds */
/* We should remove the ASSERT if we convert an internal option into non-internal */
# define INTERNAL_OPTION(opt) ((IS_OPTION_INTERNAL(opt)) ? (DYNAMO_OPTION(opt)) : \
(ASSERT_MESSAGE(CHKLVL_ASSERTS, \
"non-internal option argument "#opt, false), \
DYNAMO_OPTION(opt)))
#else
/* Use only for experimental non-release options,
default value is assumed and command line options are ignored */
/* We could use IS_OPTION_INTERNAL(opt) ? to determine whether an option is defined as INTERNAL in
optionsx.h and have that be the only place to modify to transition between internal and external options.
The compiler should be able to eliminate the inappropriate part of the constant expression,
if the specific option is no longer defined as internal so we don't have to modify the code.
Still I'd rather have explicit uses of DYNAMO_OPTION or INTERNAL_OPTION for now.
*/
# define INTERNAL_OPTION(opt) DEFAULT_INTERNAL_OPTION_VALUE(opt)
#endif /* EXPOSE_INTERNAL_OPTIONS */
#ifdef UNIX
#ifndef DR_DO_NOT_DEFINE_uint32
typedef unsigned int uint32;
#endif
/* Note: Linux paths are longer than the 260 limit on Windows,
yet we can't afford the 4K of PATH_MAX from <limits.h> */
typedef uint64 timestamp_t;
# define NAKED
# define ZHEX32_FORMAT_STRING "%08x"
# define HEX32_FORMAT_STRING "%x"
#else /* WINDOWS */
/* We no longer include windows.h here, in order to more easily include
* this file for types like reg_t in hotpatch_interface.h and not force
* hotpatch compilation to point at windows include directories.
* By not including it here we must define MAX_PATH and include windows.h
* for NOT_DYNAMORIO_CORE in options.c and drmarker.c for share/ compilation.
*/
# define MAX_PATH 260 /* from winbase.h */
#ifndef DR_DO_NOT_DEFINE_uint
typedef unsigned int uint;
#endif
#ifndef DR_DO_NOT_DEFINE_uint32
typedef unsigned int uint32;
#endif
/* NOTE : unsigned __int64 not convertible to double */
typedef unsigned __int64 uint64;
typedef __int64 int64;
# ifdef X64
typedef int64 ssize_t;
# else
typedef int ssize_t;
# endif
/* PR 232882: %I32x printf format code not supported on NT's ntdll */
# ifdef X64
# define ZHEX32_FORMAT_STRING "%08I32x"
# define HEX32_FORMAT_STRING "%I32x"
# else
# define ZHEX32_FORMAT_STRING "%08x"
# define HEX32_FORMAT_STRING "%x"
# endif
/* VC6 doesn't define the standard ULLONG_MAX */
# if _MSC_VER <= 1200 && !defined(ULLONG_MAX)
# define ULLONG_MAX _UI64_MAX
# endif
typedef uint64 timestamp_t;
# define NAKED __declspec( naked )
#endif
#define FIXED_TIMESTAMP_FORMAT "%10" INT64_FORMAT"u"
/* DR_API EXPORT TOFILE dr_defines.h */
/* DR_API EXPORT BEGIN */
#define UINT64_FORMAT_CODE INT64_FORMAT "u"
#define INT64_FORMAT_CODE INT64_FORMAT "d"
#define UINT64_FORMAT_STRING "%" UINT64_FORMAT_CODE
#define INT64_FORMAT_STRING "%" INT64_FORMAT_CODE
#define HEX64_FORMAT_STRING "%" INT64_FORMAT "x"
#define ZHEX64_FORMAT_STRING "%016" INT64_FORMAT "x"
#ifdef API_EXPORT_ONLY
#define ZHEX32_FORMAT_STRING "%08x"
#define HEX32_FORMAT_STRING "%x"
/* Convenience defines for cross-platform printing */
#ifdef X64
# define PFMT ZHEX64_FORMAT_STRING
# define PIFMT HEX64_FORMAT_STRING
# define SZFMT INT64_FORMAT_STRING
#else
# define PFMT ZHEX32_FORMAT_STRING
# define PIFMT HEX32_FORMAT_STRING
# define SZFMT "%d"
#endif
#endif
/* DR_API EXPORT END */
/* workaround for lack of defines stack and assumption in genapi.pl
* that ignored defines are outermost */
/* DR_API EXPORT BEGIN */
#ifdef API_EXPORT_ONLY
#define PFX "0x" PFMT /**< printf format code for pointers */
#define PIFX "0x" PIFMT /**< printf format code for pointer-sized integers */
#endif
#ifndef INFINITE
# define INFINITE 0xFFFFFFFF
#endif
/* DR_API EXPORT END */
/* Statistics are 64-bit for x64, 32-bit for x86, so we don't have overflow
* for pointer-sized stats.
* TODO PR 227994: use per-statistic types for variable bitwidths.
*/
#ifdef X64
typedef int64 stats_int_t;
#else
typedef int stats_int_t;
#endif
/* For printing pointers: we do not use %p as gcc prepends 0x and uses
* lowercase while cl does not prepend, puts leading 0's, and uses uppercase.
* Also, the C standard does not allow min width for %p.
* Two macros:
* - PFMT == Pointer Format == with leading zeros
* - PIFMT == Pointer Integer Format == no leading zeros
* Convenience macros to shrink long lines:
* - PFX == Pointer Format with leading 0x
* - PIFX == Pointer Integer Format with leading 0x
* For printing memory region sizes:
* - SZFMT == Size Format
* - SSZFMT == Signed Size Format
* For printing 32-bit integers as hex we use %x. We could use a macro
* there and then disallow %x, to try and avoid 64-bit printing bugs,
* but it wouldn't be a panacea.
*/
#define L_UINT64_FORMAT_STRING L"%"L_EXPAND_LEVEL(UINT64_FORMAT_CODE)
#ifdef X64
# define PFMT ZHEX64_FORMAT_STRING
# define PIFMT HEX64_FORMAT_STRING
# define SZFMT UINT64_FORMAT_STRING
# define SSZFMT INT64_FORMAT_STRING
# define SZFC UINT64_FORMAT_CODE
# define SSZFC INT64_FORMAT_CODE
#else
# define PFMT ZHEX32_FORMAT_STRING
# define PIFMT HEX32_FORMAT_STRING
# define SZFMT "%u"
# define SSZFMT "%d"
# define SZFC "u"
# define SSZFC "d"
#endif
#define L_PFMT L"%016"L_EXPAND_LEVEL(INT64_FORMAT)L"x"
#define PFX "0x"PFMT
#define PIFX "0x"PIFMT
/* DR_API EXPORT BEGIN */
/* printf codes for {thread,process}_id_t */
#ifdef WINDOWS
# define PIDFMT SZFMT /**< printf format code for process_id_t */
# define TIDFMT SZFMT /**< printf format code for thread_id_t */
#else
# define PIDFMT "%d" /**< printf format code for process_id_t */
# ifdef MACOS
# define TIDFMT UINT64_FORMAT_STRING /**< printf format code for thread_id_t */
# else
# define TIDFMT "%d" /**< printf format code for thread_id_t */
# endif
#endif
/* DR_API EXPORT END */
/* Maximum length of any registry parameter. Note that some are further
* restricted to MAXIMUM_PATH from their usage. */
#define MAX_REGISTRY_PARAMETER 512
#if defined(PARAMS_IN_REGISTRY) || !defined(CLIENT_INTERFACE)
/* Maximum length of option string in the registry */
# define MAX_OPTIONS_STRING 512
# define MAX_CONFIG_VALUE MAX_REGISTRY_PARAMETER
#else
/* Maximum length of option string from config file.
* For CLIENT_INTERFACE we need more than 512 bytes to fit multiple options
* w/ paths. However, we have stack buffers in config.c and options.c
* (look for MAX_OPTION_LENGTH there), so we can't make this too big
* unless we increase the default -stack_size even further.
* N.B.: there is a separate define in dr_config.h, DR_MAX_OPTIONS_LENGTH.
*/
# define MAX_OPTIONS_STRING 2048
# define MAX_CONFIG_VALUE MAX_OPTIONS_STRING
#endif
/* Maximum length of any individual list option's string */
#define MAX_LIST_OPTION_LENGTH MAX_OPTIONS_STRING
/* Maximum length of the path secified by a path option */
#define MAX_PATH_OPTION_LENGTH MAXIMUM_PATH
/* Maximum length of any individual option. */
#define MAX_OPTION_LENGTH MAX_OPTIONS_STRING
#define MAX_PARAMNAME_LENGTH 64
/* Arbitrary debugging-only module name length maximum */
#define MAX_MODNAME_INTERNAL 64
/* Maximum string representation of a DWORD:
* 0x80000000 = -2147483648 -> 11 characters + 1 for null termination
*/
#define MAX_DWORD_STRING_LENGTH 12
typedef char pathstring_t[MAX_PATH_OPTION_LENGTH];
/* The liststring_t type is assumed to contain ;-separated values that are
* appended to if multiple option instances are specified
*/
typedef char liststring_t[MAX_LIST_OPTION_LENGTH];
/* convenience macros for secure string buffer operations */
#define BUFFER_SIZE_BYTES(buf) sizeof(buf)
#define BUFFER_SIZE_ELEMENTS(buf) (BUFFER_SIZE_BYTES(buf) / sizeof(buf[0]))
#define BUFFER_LAST_ELEMENT(buf) buf[BUFFER_SIZE_ELEMENTS(buf) - 1]
#define NULL_TERMINATE_BUFFER(buf) BUFFER_LAST_ELEMENT(buf) = 0
#define BUFFER_ROOM_LEFT_W(wbuf) (BUFFER_SIZE_ELEMENTS(wbuf) - wcslen(wbuf) - 1)
#define BUFFER_ROOM_LEFT(abuf) (BUFFER_SIZE_ELEMENTS(abuf) - strlen(abuf) - 1)
/* strncat() calls require termination after each to be safe, especially if
* cating repeatedly. For example see hotpatch.c:hotp_load_hotp_dlls().
*/
#define CAT_AND_TERMINATE(buf, str) do { \
strncat(buf, str, BUFFER_ROOM_LEFT(buf)); \
NULL_TERMINATE_BUFFER(buf); \
} while(0)
/* platform-independent */
#define EXPANDSTR(x) #x
#define STRINGIFY(x) EXPANDSTR(x)
/* Allow custom builds to specify the product name */
#ifdef CUSTOM_PRODUCT_NAME
# define PRODUCT_NAME STRINGIFY(CUSTOM_PRODUCT_NAME)
#else
# define PRODUCT_NAME "DynamoRIO"
#endif
/* PR 323321: split eventlog from reg name so we can use longer name in reg.
* Jim's original comment here about "alphanum only" and memories
* of issues w/ eventlog Araksha => Determin[a] have made us cautious
* (though in my tests on win2k the longer name worked fine for eventlog).
*/
/* i#80: I thought about flattening the reg key but simpler to just
* have two DynamoRIO levels
*/
#define COMPANY_NAME "DynamoRIO" /* used for reg key */
#define COMPANY_NAME_EVENTLOG "DynamoRIO" /* used for event log */
/* used in (c) stmt in log file and in resources */
#define COMPANY_LONG_NAME "DynamoRIO developers"
#define BUG_REPORT_URL "http://dynamorio.org/issues/"
#ifdef BUILD_NUMBER
# define BUILD_NUMBER_STRING "build "STRINGIFY(BUILD_NUMBER)
#else
# define BUILD_NUMBER_STRING "custom build"
# define BUILD_NUMBER (0)
#endif
#ifdef VERSION_NUMBER
# define VERSION_NUMBER_STRING "version "STRINGIFY(VERSION_NUMBER)
#else
# define VERSION_NUMBER_STRING "internal version"
# define VERSION_NUMBER (0.0)
#endif
#ifdef HOT_PATCHING_INTERFACE
# define HOT_PATCHING_DLL_CACHE_PATH "\\lib\\hotp\\"
# define HOTP_MODES_FILENAME "ls-modes.cfg"
# define HOTP_POLICIES_FILENAME "ls-defs.cfg"
#endif
/* FIXME: the environment vars need to be renamed - it will be a pain */
#define DYNAMORIO_VAR_CONFIGDIR_ID DYNAMORIO_CONFIGDIR
#define DYNAMORIO_VAR_HOME_ID DYNAMORIO_HOME
#define DYNAMORIO_VAR_LOGDIR_ID DYNAMORIO_LOGDIR
#define DYNAMORIO_VAR_OPTIONS_ID DYNAMORIO_OPTIONS
#define DYNAMORIO_VAR_AUTOINJECT_ID DYNAMORIO_AUTOINJECT
#define DYNAMORIO_VAR_UNSUPPORTED_ID DYNAMORIO_UNSUPPORTED
#define DYNAMORIO_VAR_RUNUNDER_ID DYNAMORIO_RUNUNDER
#define DYNAMORIO_VAR_CMDLINE_ID DYNAMORIO_CMDLINE
#define DYNAMORIO_VAR_ONCRASH_ID DYNAMORIO_ONCRASH
#define DYNAMORIO_VAR_SAFEMARKER_ID DYNAMORIO_SAFEMARKER
/* NT only, value should be all CAPS and specifies a boot option to match */
#define DYNAMORIO_VAR_CACHE_ROOT_ID DYNAMORIO_CACHE_ROOT
/* we have to create our own properly secured directory, that allows
* only trusted producers to create DLLs, and all publishers to read
* them. Note that per-user directories may also be created by the trusted component
* allowing users to safely use their own private caches.
*/
#define DYNAMORIO_VAR_CACHE_SHARED_ID DYNAMORIO_CACHE_SHARED
/* a directory giving full write privileges to Everyone. Therefore
* none of its contents can be trusted without explicit verification.
* Expected to be a subdirectory of DYNAMORIO_CACHE_ROOT.
*/
/* Location for persisted caches; FIXME: currently the same as the ASLR sharing dir */
#define DYNAMORIO_VAR_PERSCACHE_ROOT_ID DYNAMORIO_CACHE_ROOT
/* FIXME case 9651: security model, etc. */
#define DYNAMORIO_VAR_PERSCACHE_SHARED_ID DYNAMORIO_CACHE_SHARED
/* case 10255: use a suffix to distinguish from ASLR files in same dir
* DR persisted cache => "dpc"
*/
#define PERSCACHE_FILE_SUFFIX "dpc"
#ifdef HOT_PATCHING_INTERFACE
# define DYNAMORIO_VAR_HOT_PATCH_POLICES_ID DYNAMORIO_HOT_PATCH_POLICIES
# define DYNAMORIO_VAR_HOT_PATCH_MODES_ID DYNAMORIO_HOT_PATCH_MODES
#endif
#ifdef PROCESS_CONTROL
# define DYNAMORIO_VAR_APP_PROCESS_WHITELIST_ID DYNAMORIO_APP_PROCESS_WHITELIST
# define DYNAMORIO_VAR_ANON_PROCESS_WHITELIST_ID DYNAMORIO_ANON_PROCESS_WHITELIST
# define DYNAMORIO_VAR_APP_PROCESS_BLACKLIST_ID DYNAMORIO_APP_PROCESS_BLACKLIST
# define DYNAMORIO_VAR_ANON_PROCESS_BLACKLIST_ID DYNAMORIO_ANON_PROCESS_BLACKLIST
#endif
#define DYNAMORIO_VAR_CONFIGDIR STRINGIFY(DYNAMORIO_VAR_CONFIGDIR_ID)
#define DYNAMORIO_VAR_HOME STRINGIFY(DYNAMORIO_VAR_HOME_ID)
#define DYNAMORIO_VAR_LOGDIR STRINGIFY(DYNAMORIO_VAR_LOGDIR_ID)
#define DYNAMORIO_VAR_OPTIONS STRINGIFY(DYNAMORIO_VAR_OPTIONS_ID)
#define DYNAMORIO_VAR_AUTOINJECT STRINGIFY(DYNAMORIO_VAR_AUTOINJECT_ID)
#define DYNAMORIO_VAR_UNSUPPORTED STRINGIFY(DYNAMORIO_VAR_UNSUPPORTED_ID)
#define DYNAMORIO_VAR_RUNUNDER STRINGIFY(DYNAMORIO_VAR_RUNUNDER_ID)
#define DYNAMORIO_VAR_CMDLINE STRINGIFY(DYNAMORIO_VAR_CMDLINE_ID)
#define DYNAMORIO_VAR_ONCRASH STRINGIFY(DYNAMORIO_VAR_ONCRASH_ID)
#define DYNAMORIO_VAR_SAFEMARKER STRINGIFY(DYNAMORIO_VAR_SAFEMARKER_ID)
#define DYNAMORIO_VAR_CACHE_ROOT STRINGIFY(DYNAMORIO_VAR_CACHE_ROOT_ID)
#define DYNAMORIO_VAR_CACHE_SHARED STRINGIFY(DYNAMORIO_VAR_CACHE_SHARED_ID)
#define DYNAMORIO_VAR_PERSCACHE_ROOT STRINGIFY(DYNAMORIO_VAR_PERSCACHE_ROOT_ID)
#define DYNAMORIO_VAR_PERSCACHE_SHARED STRINGIFY(DYNAMORIO_VAR_PERSCACHE_SHARED_ID)
#ifdef HOT_PATCHING_INTERFACE
# define DYNAMORIO_VAR_HOT_PATCH_POLICIES STRINGIFY(DYNAMORIO_VAR_HOT_PATCH_POLICES_ID)
# define DYNAMORIO_VAR_HOT_PATCH_MODES STRINGIFY(DYNAMORIO_VAR_HOT_PATCH_MODES_ID)
#endif
#ifdef PROCESS_CONTROL
# define DYNAMORIO_VAR_APP_PROCESS_WHITELIST \
STRINGIFY(DYNAMORIO_VAR_APP_PROCESS_WHITELIST_ID)
# define DYNAMORIO_VAR_ANON_PROCESS_WHITELIST \
STRINGIFY(DYNAMORIO_VAR_ANON_PROCESS_WHITELIST_ID)
# define DYNAMORIO_VAR_APP_PROCESS_BLACKLIST \
STRINGIFY(DYNAMORIO_VAR_APP_PROCESS_BLACKLIST_ID)
# define DYNAMORIO_VAR_ANON_PROCESS_BLACKLIST \
STRINGIFY(DYNAMORIO_VAR_ANON_PROCESS_BLACKLIST_ID)
#endif
#ifdef UNIX
# define DYNAMORIO_VAR_EXE_PATH "DYNAMORIO_EXE_PATH"
# define DYNAMORIO_VAR_EXECVE "DYNAMORIO_POST_EXECVE"
# define DYNAMORIO_VAR_EXECVE_LOGDIR "DYNAMORIO_EXECVE_LOGDIR"
# define L_IF_WIN(x) x
#else /* WINDOWS */
# define EXPAND_LEVEL(str) str /* expand one level */
# define L_EXPAND_LEVEL(str) L(str)
# define L(str) L ## str
# define LCONCAT(wstr,str) EXPAND_LEVEL(wstr)L("\\")L(str)
# define L_IF_WIN(x) L_EXPAND_LEVEL(x)
/* unicode versions of shared names*/
# define L_DYNAMORIO_VAR_CONFIGDIR L_EXPAND_LEVEL(DYNAMORIO_VAR_CONFIGDIR)
# define L_DYNAMORIO_VAR_HOME L_EXPAND_LEVEL(DYNAMORIO_VAR_HOME)
# define L_DYNAMORIO_VAR_LOGDIR L_EXPAND_LEVEL(DYNAMORIO_VAR_LOGDIR)
# define L_DYNAMORIO_VAR_OPTIONS L_EXPAND_LEVEL(DYNAMORIO_VAR_OPTIONS)
# define L_DYNAMORIO_VAR_AUTOINJECT L_EXPAND_LEVEL(DYNAMORIO_VAR_AUTOINJECT)
# define L_DYNAMORIO_VAR_UNSUPPORTED L_EXPAND_LEVEL(DYNAMORIO_VAR_UNSUPPORTED)
# define L_DYNAMORIO_VAR_RUNUNDER L_EXPAND_LEVEL(DYNAMORIO_VAR_RUNUNDER)
# define L_DYNAMORIO_VAR_CMDLINE L_EXPAND_LEVEL(DYNAMORIO_VAR_CMDLINE)
# define L_DYNAMORIO_VAR_ONCRASH L_EXPAND_LEVEL(DYNAMORIO_VAR_ONCRASH)
# define L_DYNAMORIO_VAR_SAFEMARKER L_EXPAND_LEVEL(DYNAMORIO_VAR_SAFEMARKER)
# define L_DYNAMORIO_VAR_CACHE_ROOT L_EXPAND_LEVEL(DYNAMORIO_VAR_CACHE_ROOT)
# define L_DYNAMORIO_VAR_CACHE_SHARED L_EXPAND_LEVEL(DYNAMORIO_VAR_CACHE_SHARED)
# ifdef HOT_PATCHING_INTERFACE
# define L_DYNAMORIO_VAR_HOT_PATCH_POLICIES L_EXPAND_LEVEL(DYNAMORIO_VAR_HOT_PATCH_POLICIES)
# define L_DYNAMORIO_VAR_HOT_PATCH_MODES L_EXPAND_LEVEL(DYNAMORIO_VAR_HOT_PATCH_MODES)
# endif
# ifdef PROCESS_CONTROL
# define L_DYNAMORIO_VAR_APP_PROCESS_WHITELIST \
L_EXPAND_LEVEL(DYNAMORIO_VAR_APP_PROCESS_WHITELIST)
# define L_DYNAMORIO_VAR_ANON_PROCESS_WHITELIST \
L_EXPAND_LEVEL(DYNAMORIO_VAR_ANON_PROCESS_WHITELIST)
# define L_DYNAMORIO_VAR_APP_PROCESS_BLACKLIST \
L_EXPAND_LEVEL(DYNAMORIO_VAR_APP_PROCESS_BLACKLIST)
# define L_DYNAMORIO_VAR_ANON_PROCESS_BLACKLIST \
L_EXPAND_LEVEL(DYNAMORIO_VAR_ANON_PROCESS_BLACKLIST)
# endif
# define L_PRODUCT_NAME L_EXPAND_LEVEL(PRODUCT_NAME)
# define L_COMPANY_NAME L_EXPAND_LEVEL(COMPANY_NAME)
# define L_COMPANY_LONG_NAME L_EXPAND_LEVEL(COMPANY_LONG_NAME)
/* event log registry keys */
# define EVENTLOG_HIVE HKEY_LOCAL_MACHINE
# define EVENTLOG_NAME COMPANY_NAME_EVENTLOG
# define EVENTSOURCE_NAME PRODUCT_NAME /* should be different than logfile name */
# define EVENTLOG_REGISTRY_SUBKEY "System\\CurrentControlSet\\Services\\EventLog"
# define L_EVENTLOG_REGISTRY_SUBKEY L_EXPAND_LEVEL(EVENTLOG_REGISTRY_SUBKEY)
# define L_EVENTLOG_REGISTRY_KEY L"\\Registry\\Machine\\"L_EXPAND_LEVEL(EVENTLOG_REGISTRY_SUBKEY)
# define L_EVENT_LOG_KEY LCONCAT(L_EVENTLOG_REGISTRY_KEY,EVENTLOG_NAME)
# define L_EVENT_LOG_SUBKEY LCONCAT(L_EVENTLOG_REGISTRY_SUBKEY,EVENTLOG_NAME)
# define L_EVENT_LOG_NAME L_EXPAND_LEVEL(EVENTLOG_NAME)
# define L_EVENT_SOURCE_NAME L_EXPAND_LEVEL(EVENTSOURCE_NAME)
# define L_EVENT_SOURCE_KEY LCONCAT(L_EVENT_LOG_KEY, EVENTSOURCE_NAME)
# define L_EVENT_SOURCE_SUBKEY LCONCAT(L_EVENT_LOG_SUBKEY, EVENTSOURCE_NAME)
# define EVENT_LOG_KEY LCONCAT(L_EXPAND_LEVEL(EVENTLOG_REGISTRY_SUBKEY),EVENTLOG_NAME)
# define EVENT_SOURCE_KEY LCONCAT(EVENT_LOG_KEY,EVENTSOURCE_NAME)
/* Log key values (NOTE the values here are the values our installer uses,
* not sure what all of them mean). FIXME would be nice if these were
* shared with the installer config file. Only used by DRcontrol (via
* share/config.c) to set up new eventlogs (mainly for vista where our
* installer doesn't work yet xref case 8482).*/
# define L_EVENT_FILE_VALUE_NAME L"File"
# define L_EVENT_FILE_NAME_PRE_VISTA \
L"%SystemRoot%\\system32\\config\\"L_EXPAND_LEVEL(EVENTLOG_NAME)L".evt"
# define L_EVENT_FILE_NAME_VISTA \
L"%SystemRoot%\\system32\\winevt\\logs\\"L_EXPAND_LEVEL(EVENTLOG_NAME)L".elf"
# define L_EVENT_MAX_SIZE_NAME L"MaxSize"
# define EVENT_MAX_SIZE 0x500000
# define L_EVENT_RETENTION_NAME L"Retention"
# define EVENT_RETENTION 0
/* Src key values */
# define L_EVENT_TYPES_SUPPORTED_NAME L"TypesSupported"
# define EVENT_TYPES_SUPPORTED 0x7 /* info | warning | error */
# define L_EVENT_CATEGORY_COUNT_NAME L"CategoryCount"
# define EVENT_CATEGORY_COUNT 0
# define L_EVENT_CATEGORY_FILE_NAME L"CategoryMessageFile"
# define L_EVENT_MESSAGE_FILE L"EventMessageFile"
/* shared object directory base */
# define BASE_NAMED_OBJECTS L"\\BaseNamedObjects"
/* base root in global object namespace, not in BaseNamedObjects or Sessions */
# define DYNAMORIO_SHARED_OBJECT_BASE L("\\")L_EXPAND_LEVEL(COMPANY_NAME)
/* shared object directory for shared DLL cache */
# define DYNAMORIO_SHARED_OBJECT_DIRECTORY LCONCAT(DYNAMORIO_SHARED_OBJECT_BASE, "SharedCache")
/* registry */
# define DYNAMORIO_REGISTRY_BASE_SUBKEY "Software\\"COMPANY_NAME"\\"PRODUCT_NAME
# define DYNAMORIO_REGISTRY_BASE L"\\Registry\\Machine\\Software\\"L_EXPAND_LEVEL(COMPANY_NAME)L("\\")L_EXPAND_LEVEL(PRODUCT_NAME)
# define DYNAMORIO_REGISTRY_HIVE HKEY_LOCAL_MACHINE
# define DYNAMORIO_REGISTRY_KEY DYNAMORIO_REGISTRY_BASE_SUBKEY
# define L_DYNAMORIO_REGISTRY_KEY L"Software\\"L_EXPAND_LEVEL(COMPANY_NAME)L"\\"L_EXPAND_LEVEL(PRODUCT_NAME)
# define INJECT_ALL_HIVE HKEY_LOCAL_MACHINE
# define INJECT_ALL_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows"
# define INJECT_ALL_SUBKEY "AppInit_DLLs"
/* introduced on Vista */
# define INJECT_ALL_LOAD_SUBKEY "LoadAppInit_DLLs"
/* introduced on Windows 7/2008 R2 */
# define INJECT_ALL_SIGN_SUBKEY "RequireSignedAppInit_DLLs"
# define INJECT_ALL_HIVE_L L"\\Registry\\Machine\\"
# define INJECT_ALL_KEY_L L_EXPAND_LEVEL(INJECT_ALL_KEY)
# define INJECT_ALL_SUBKEY_L L_EXPAND_LEVEL(INJECT_ALL_SUBKEY)
# define INJECT_ALL_LOAD_SUBKEY_L L_EXPAND_LEVEL(INJECT_ALL_LOAD_SUBKEY)
# define INJECT_ALL_SIGN_SUBKEY_L L_EXPAND_LEVEL(INJECT_ALL_SIGN_SUBKEY)
# define INJECT_DLL_NAME "drpreinject.dll"
# define INJECT_DLL_8_3_NAME "DRPREI~1.DLL"
# define INJECT_HELPER_DLL1_NAME "drearlyhelp1.dll"
# define INJECT_HELPER_DLL2_NAME "drearlyhelp2.dll"
# define DEBUGGER_INJECTION_HIVE HKEY_LOCAL_MACHINE
# define DEBUGGER_INJECTION_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"
# define DEBUGGER_INJECTION_VALUE_NAME "Debugger"
# define DEBUGGER_INJECTION_HIVE_L L"\\Registry\\Machine\\"
# define DEBUGGER_INJECTION_KEY_L L_EXPAND_LEVEL(DEBUGGER_INJECTION_KEY)
# define DEBUGGER_INJECTION_VALUE_NAME_L L_EXPAND_LEVEL(DEBUGGER_INJECTION_VALUE_NAME)
# define DRINJECT_NAME "drinject.exe"
/* shared module uses SVCHOST_NAME and EXE_SUFFIX separately */
# define SVCHOST_NAME "svchost"
# define EXE_SUFFIX ".exe"
# define L_EXE_SUFFIX L_EXPAND_LEVEL(EXE_SUFFIX)
# define SVCHOST_EXE_NAME SVCHOST_NAME EXE_SUFFIX
# define L_SVCHOST_EXE_NAME L_EXPAND_LEVEL(SVCHOST_NAME) L_EXPAND_LEVEL(EXE_SUFFIX)
/* for processview, etc */
# define DYNAMORIO_LIBRARY_NAME "dynamorio.dll"
# define DLLPATH_RELEASE "\\lib\\release\\"DYNAMORIO_LIBRARY_NAME
# define DLLPATH_DEBUG "\\lib\\debug\\"DYNAMORIO_LIBRARY_NAME
# define DLLPATH_PROFILE "\\lib\\profile\\"DYNAMORIO_LIBRARY_NAME
# define L_DYNAMORIO_LIBRARY_NAME L_EXPAND_LEVEL(DYNAMORIO_LIBRARY_NAME)
# define L_DLLPATH_RELEASE L"\\lib\\release\\"L_DYNAMORIO_LIBRARY_NAME
# define L_DLLPATH_DEBUG L"\\lib\\debug\\"L_DYNAMORIO_LIBRARY_NAME
# define L_DLLPATH_PROFILE L"\\lib\\profile\\"L_DYNAMORIO_LIBRARY_NAME
# define INJECT_ALL_DLL_SUBPATH "\\lib\\"INJECT_DLL_8_3_NAME
# define L_INJECT_ALL_DLL_SUBPATH L"\\lib\\"L_EXPAND_LEVEL(INJECT_DLL_8_3_NAME)
enum DLL_TYPE {
DLL_NONE,
DLL_UNKNOWN,
DLL_RELEASE,
DLL_DEBUG,
DLL_PROFILE,
DLL_CUSTOM,
DLL_PATHHAS
};
#endif /* WINDOWS */
#ifdef STANDALONE_UNIT_TEST
# define UNIT_TEST_EXE_NAME ("unit_tests" IF_WINDOWS(".exe"))
#endif
/* DYNAMORIO_RUNUNDER controls the injection technique and process naming,
* it is a bitmask of the values below:
* RUNUNDER_ON:
* take over the app indicated by the corresponding app-specific
* subkey; when this is a global param, it only acts as a default for
* subkeys which don't explicitly set RUNUNDER. indicates current
* default takeover method via the preinjector / AppInit_DLLs
* RUNUNDER_ALL:
* use as a global parameter only, for doing "run all". exclude with
* app-specific RUNUNDER_OFF. You need to use in conjuction with ON
*
*
* RUNUNDER_EXPLICIT:
* indicates that the app will use the alternate injection technique
* currently via -follow_explicit_children, but might change to drinject
* in the per-executable debugger registry key at some point
*
*
* RUNUNDER_COMMANDLINE_MATCH:
* indicates that the process command line must exactly match the
* value in the DYNAMORIO_CMDLINE app-specific subkey, or else no
* takeover will be done. Note that only a single instance of
* a given executable name can be controlled this way.
*
* RUNUNDER_COMMANDLINE_DISPATCH:
* marks that the processes with this executable name should be
* differentiated by their canonicalized commandline. For example,
* different dllhost instances will get their own different subkeys,
* just the way the svchost.exe instances have full sets of option
* keys.
*
* RUNUNDER_COMMANDLINE_NO_STRIP:
* this flag is used only in conjunction with
* RUNUNDER_COMMANDLINE_DISPATCH. Our default canonicalization rule
* strips the first argument on the commandline for historic reasons.
* Since that was the way we had previously hardcoded the names for
* say "svchost.exe-netsvcs". In case we actually want to dispatch
* on a single argument - which would be the case for say msiexec.exe
* /v then this flag is needed.
*
* RUNUNDER_ONCE:
* is used by staging mode to specify that the executable corresponding
* to the current process shouldn't run under DR the next time, i.e.,
* turn off its RUNUNDER_ON flag after checking it for the current process.
* This is needed to prevent perpetual crash-&-boot cycles due to DR failure.
* See case 3702.
**/
enum {
/* FIXME: keep in mind that we only read decimal values */
RUNUNDER_OFF = 0x00, /* 0 */
RUNUNDER_ON = 0x01, /* 1 */
RUNUNDER_ALL = 0x02, /* 2 */
/* Dummy field to keep track of which processes were RUNUNDER_EXPLICIT
* before we moved to -follow_systemwide by default (for -early_injection)
* (note this was the old RUNUNDER_EXPLICIT value) */
RUNUNDER_FORMERLY_EXPLICIT = 0x04, /* 4 */
RUNUNDER_COMMANDLINE_MATCH = 0x08, /* 8 */
RUNUNDER_COMMANDLINE_DISPATCH = 0x10, /* 16 */
RUNUNDER_COMMANDLINE_NO_STRIP = 0x20, /* 32 */
RUNUNDER_ONCE = 0x40, /* 64 */
RUNUNDER_EXPLICIT = 0x80, /* 128 */
};
/* A bitmask of possible actions to take on a nudge. Accessed via
* NUDGE_GENERIC(name) Recommended to always pass -nudge opt so to
* synchronize options first. For many state transition nudge's
* option change will trigger any other actions: e.g. start
* protecting, simulate attack, etc.. Only pulse-like events that
* should be acted on only once need separate handling here. Not all
* combinations are meaningful, and the order of execution is not
* determined from the order in the definitions.
*/
/* To use as an iterator define NUDGE_DEF(name, comment) */
/* CAUTION: DO NOT change ordering of the nudge definitions for non-NYI, i.e.,
* implemented nudges. These numbers correspond to specific masks
* that are used by the nodemanager/drcontrol (thus QA). Will lead to
* a lot of unwanted confusion.
*/
#define NUDGE_DEFINITIONS() \
/* Control nudges */ \
NUDGE_DEF(opt, "Synchronize dynamic options") \
NUDGE_DEF(reset, "Reset code caches") /* flush & delete */ \
NUDGE_DEF(detach, "Detach") \
NUDGE_DEF(mode, "Liveshield mode update") \
NUDGE_DEF(policy, "Liveshield policy update") \
NUDGE_DEF(lstats, "Liveshield statistics NYI") \
NUDGE_DEF(process_control, "Process control nudge") /* Case 8594. */ \
NUDGE_DEF(upgrade, "DR upgrade NYI case 4179") \
NUDGE_DEF(kstats, "Dump kstats in log or kstat file NYI") \
/* internal options */ \
NUDGE_DEF(stats, "Dump internal stats in logfiles NYI") \
NUDGE_DEF(invalidate, "Invalidate code caches NYI") /* flush */ \
/* stress testing */ \
NUDGE_DEF(recreate_pc, "Recreate PC NYI") \
NUDGE_DEF(recreate_state, "Recreate state NYI") \
NUDGE_DEF(reattach, "Reattach - almost detach, NYI") \
/* diagnostics */ \
NUDGE_DEF(diagnose, "Request diagnostic file NYI") \
NUDGE_DEF(ldmp, "Dump core") \
NUDGE_DEF(freeze, "Freeze coarse units") \
NUDGE_DEF(persist, "Persist coarse units") \
/* client nudge */ \
NUDGE_DEF(client, "Client nudge") \
/* security testing */ \
NUDGE_DEF(violation, "Simulate a security violation") \
/* ADD NEW NUDGE_DEFs only immediately above this line */ \
/* Since these are used as a bitmask only 32 types can be supported:
* but on Linux only 28. If we want more we can simply use the client_arg
* field to multiplex.
*/
typedef enum {
#define NUDGE_DEF(name, comment) NUDGE_DR_##name,
NUDGE_DEFINITIONS()
#undef NUDGE_DEF
NUDGE_DR_PARAMETRIZED_END
} nudge_generic_type_t;
/* note that these are bitmask values */
#define NUDGE_GENERIC(name) (1 << (NUDGE_DR_##name))
/* On Linux only 2 bits for this */
#define NUDGE_ARG_VERSION_1 1
#define NUDGE_ARG_CURRENT_VERSION NUDGE_ARG_VERSION_1
/* nudge_arg_t flags
* On Linux only 2 bits for these
*/
enum {
NUDGE_IS_INTERNAL = 0x01, /* nudge is internally generated */
#ifdef WINDOWS
NUDGE_NUDGER_FREE_STACK = 0x02, /* nudger will free the nudge thread's stack so the
* nudge thread itself shouldn't */
NUDGE_FREE_ARG = 0x04, /* nudge arg is in a separate allocation and should
* be freed by the nudge thread */
#endif
};
typedef struct {
#ifdef UNIX
/* We only have room for 16 bytes that we control, 24 bytes total.
* Note that the kernel does NOT copy the huge amount of padding
* at the tail end of siginfo_t so we cannot use that.
*/
int ignored1; /* siginfo_t.si_signo: kernel sets so we cannot use */
/* These make up the siginfo_t.si_errno field. Since version starts
* at 1, this field will never be 0 for a nudge signal, but is always
* 0 for a libc sigqueue()-generated signal.
*/
uint nudge_action_mask:28;
uint version:2;
uint flags:2;
int ignored2; /* siginfo_t.si_code: has meaning to kernel so we avoid using */
#else
uint version; /* version number for future proofing */
uint nudge_action_mask; /* drawn from NUDGE_DEFS above */
uint flags; /* flags drawn from above enum */
#endif
client_id_t client_id; /* unique ID identifying client */
uint64 client_arg; /* argument for a client nudge */
#ifdef WIN32
/* Add future arguments for nudge actions here.
* There is no room for more Linux arguments.
*/
#endif
} nudge_arg_t;
#ifdef UNIX
/* i#61/PR 211530: Linux nudges.
* We pick a signal that is very unlikely to be sent asynchronously by
* the app, and for which we can distinguish synch from asynch by
* looking at the interrupted pc.
*/
# define NUDGESIG_SIGNUM SIGILL
#endif
/* Define AVOID_API_EXPORT here rather than in configure.h.
* This way it will just be used for compling dr code and not for
* genapi.pl which generates client header files. In otherwords, this allows
* having code that isn't visible in the client headers but is visible for dr
* builds. This helps sharing types and code between dr and client, but with
* some hidden extras for dr builds.
*/
#define AVOID_API_EXPORT 1
#ifdef HOT_PATCHING_INTERFACE
/* These type definitions define the hot patch interface between the core &
* the node manager.
* CAUTION: Any changes to this can break the hot patch interface between the
* core and the node manager.
*/
/* All hot patch policy IDs must be of the form XXXX.XXXX; this ID is used to
* generate the threat ID for a given hot patch violation.
*/
#define HOTP_POLICY_ID_LENGTH 9
/* DR_API EXPORT TOFILE dr_probe.h */
/* DR_API EXPORT BEGIN */
/** Describes the status of a probe at any given point. The status is returned
* by dr_register_probes() in the dr_probe_desc_t structure for each probe
* specified. It can be obtained for individual probes by calling
* dr_get_probe_status().
*/
typedef enum {
/* Error codes. */
/** Exceptions during callback execution and other unknown errors. */
DR_PROBE_STATUS_ERROR = 1,
/** An invalid or unknown probe ID was specified with dr_get_probe_status(). */
DR_PROBE_STATUS_INVALID_ID = 2,
/* All the invalid states listed below may arise statically (at the
* time of parsing the probes, i.e., inside dr_register_probes() or
* dynamically (i.e., when modules are loaded or unloaded)).
*/
/** The numeric virtual address specified for the probe insertion location
* or the callback function is invalid.
*/
DR_PROBE_STATUS_INVALID_VADDR = 3,
/** The pointer to the name of the library containing the probe insertion
* location or the callback function is invalid or the library containing
* the callback function can't be loaded.
*/
DR_PROBE_STATUS_INVALID_LIB = 4,
/** The library offset for either the probe insertion location or the
* callback function is invalid; for ex., if the offset is out of bounds.
*/
DR_PROBE_STATUS_INVALID_LIB_OFFS = 5,
/** The pointer to the name of the exported function, where the probe is to
* be inserted or which is the callback function, is invalid or the exported
* function doesn't exist.
*/
DR_PROBE_STATUS_INVALID_FUNC = 6,
/* Codes for pending cases, i.e., valid probes haven't been inserted
* because certain events haven't transpired.
*/
/** The numeric virtual address specified for the probe insertion location
* or the callback function isn't executable. This may be so at the time
* of probe registration or latter if the memory protections are changed.
* An inserted probe might reach this state if the probe insertion point or
* the callback function is made non-executable after being executable.
*/
DR_PROBE_STATUS_VADDR_NOT_EXEC = 7,
/** The library where the probe is to be inserted isn't in the process. */
DR_PROBE_STATUS_LIB_NOT_SEEN = 8,
/** Execution hasn't reached the probe insertion point yet. This is valid
* for Code Manipulation mode only because in that mode probes are inserted
* only in the dynamic instruction stream.
*/
DR_PROBE_STATUS_WAITING_FOR_EXEC = 9,
/** Either the library where the probe is to be inserted has been unloaded
* or the library containing the callback function has been unloaded.
*/
DR_PROBE_STATUS_LIB_UNLOADED = 10,
/* Miscellaneous status codes. */
/** Probe was successfully inserted. */
DR_PROBE_STATUS_INJECTED = 11,
/** One or more aspects of the probe aren't supported as of now. */
DR_PROBE_STATUS_UNSUPPORTED = 12,
# ifdef AVOID_API_EXPORT
/* DON'T CHANGE THE VALUES OF THE DR_* CONSTANTS DEFINED ABOVE. They are
* exported to clients, whereas constants in this ifdef aren't. Any change
* to those values will likely break old clients with newer versions of DR
* (backward compatibility). New status codes should go after
* DR_PROBE_STATUS_UNSUPPORTED.
*/
/* Note: constants are numbered to prevent the compiler from resetting the
* sequence based on the symbolic assignments below. HOTP_INJECT_DETECT
* ended up getting the same number as one the values above! Ditto with
* HOTP_INJECT_OFF. Though these duplications only broke the tools build
* they can cause subtle runtime errors, so forcing numbers.
*/
/* The constants below are used only for LiveShields. */
/* Defines the current injection status of a policy, i.e., was it injected
* or not, why and why not? Today we don't distinguish the reasons for
* error cases, i.e., all of them are rolled into one.
*
* Constants list from most important status to least, from a reporting
* point of view; don't change this arbitrarily.
*
* CAUTION: Any changes to this will break drview, so they must be kept in
* sync.
*/
/* Deactivation, exception, error, etc. */
HOTP_INJECT_ERROR = DR_PROBE_STATUS_ERROR,
/* Completely injected in protect mode. */
HOTP_INJECT_PROTECT = DR_PROBE_STATUS_INJECTED,
/* Completely injected in detect mode. Not applicable to probes as they
* don't have detectors. Restart numbering at 100 to give enough room for
* future probe status constants.
*/
HOTP_INJECT_DETECT = 100,
/* One or more patch points in a vulnerability have been patched, but not
* all, yet. N/A to probes as they can't group multiple patch points.
*/
HOTP_INJECT_IN_PROGRESS = 101,
/* Vulnerability was matched and is ready for injection, but no patch point
* has been seen yet.
*/
HOTP_INJECT_PENDING = DR_PROBE_STATUS_WAITING_FOR_EXEC,
/* Vulnerability hasn't been matched yet. May mean that it is not yet
* vulnerable (because all dlls haven't been loaded) or just not vulnerable
* at all; there is no way to distinguish between the two.
*/
HOTP_INJECT_NO_MATCH = DR_PROBE_STATUS_LIB_NOT_SEEN,
/*
TODO: must distinguish between no match & vulnerable vs. no match & not
vulnerable; future work if needed.
HOTP_INJECT_NO_MATCH_VULNERABLE,
HOTP_INJECT_NO_MATCH_NOT_VULNERABLE,
*/
HOTP_INJECT_OFF = 102 /* Policy has been turned off, so no injection. */
# endif /* AVOID_API_EXPORT */
} dr_probe_status_t;
/* DR_API EXPORT END */
typedef dr_probe_status_t hotp_inject_status_t;
/* Modes are at a policy level, not a vulnerability level, even though the
* core organizes things at the vulnerability level.
*/
typedef enum {
HOTP_MODE_OFF = 0,
HOTP_MODE_DETECT = 1,
HOTP_MODE_PROTECT = 2
} hotp_policy_mode_t;
/* This structure is used to form a table that contains the status of all
* active policies. This is separated out into a separate table, as opposed
* to being part of the hotp_vul_info_t and thus part of the global
* vulnerability table, because the node manager will be directly reading
* this information from the core's memory. Thus, this structure serves
* as a container to expose only that data which will be needed by the node
* manager from the core regarding hot patches.
*/
typedef struct {
/* polciy_id is the same as the one in hotp_vul_t. Duplicated because can't
* have this pointing to the hopt_vul_t structure because the node manager
* will have to chase the pointer for each element to read it rather than a
* single block of memory.
*/
char policy_id[HOTP_POLICY_ID_LENGTH + 1];
hotp_inject_status_t inject_status;
/* This is the same as the one in hotp_vul_t. Duplicated for the same
* reason policy_id (see above) was. Can't have the hotp_vul_t structure
* pointing here too because that struct/table needs to be initialized for
* the policy status table to be created; catch-22.
* Fix for case 5484, where the node manager wasn't able to tell if an
* inject status was for a policy that was turned on or off.
*/
hotp_policy_mode_t mode;
} hotp_policy_status_t;
/* Node manager should read either this struct first or the first two elements
* in it. Then it should read the rest. Note: 'size' refers to the size of
* both this struct and the size of the policy_status_array in bytes.
*/
typedef struct {
/* This is the crc for the whole table, except itself, i.e., the crc
* computation starts from 'size'. This is needed otherwise writing the
* crc value itself will change the crc of the table! Can get past it
* by doing crc twice, but it is needlessly expensive.
*
* CAUTION: don't not move crc and size around as it can cause both the
* node manager & the core to break.
*/
uint crc;
uint size; /* Size of this struct plus the table. */
uint num_policies;
hotp_policy_status_t *policy_status_array;
} hotp_policy_status_table_t;
#endif /* ifdef HOT_PATCHING_INTERFACE */
/* These constants & macros are used by core, share and preinject, so this is
* the only place they will build for win32 and linux! */
/* return codes for [gs]et_parameter style functions
* failure == 0 for compatibility with get_parameter()
* if GET_PARAMETER_NOAPPSPECIFIC is returned, that means the
* parameter returned is from the global options, because there
* was no app-specific key present.
* Note: constants shouldn't be added to this enum without checking whether
* the macros below will work; they should if errors are all negative and
* valid codes are all positive.
*/
enum {
GET_PARAMETER_BUF_TOO_SMALL = -1,
GET_PARAMETER_FAILURE = 0,
GET_PARAMETER_SUCCESS = 1,
GET_PARAMETER_NOAPPSPECIFIC = 2,
SET_PARAMETER_FAILURE = GET_PARAMETER_FAILURE,
SET_PARAMETER_SUCCESS = GET_PARAMETER_SUCCESS
};
#define IS_GET_PARAMETER_FAILURE(x) ((x) <= 0 )
#define IS_GET_PARAMETER_SUCCESS(x) ((x) > 0 )
/* X86 only but no ifdef since hotp builds don't set that define */
/* User-mode machine context.
* We have it here instead of in arch_exports.h so that we
* can expose it to hotpatch_interface.h.
*
* If any field offsets are changed, or fields are added, update
* the following:
* - OFFSET defines in arch/arch.h and their uses in fcache_{enter,return}
* - DR_MCONTEXT_SIZE and PUSH_DR_MCONTEXT in arch/x86.asm
* - clean call layout of dr_mcontext_t on the stack in arch/mangle.c
* - interception layout of dr_mcontext_t on the stack in win32/callback.c
* - context_to_mcontext (and vice versa) in win32/ntdll.c
* - sigcontext_to_mcontext (and vice versa) in unix/signal.c
* - dump_mcontext in arch/arch.c
* - inject_into_thread in win32/inject.c
* Also, hotp_context_t exposes the dr_mcontext_t struct to hot patches,
* so be careful when changing any field offsets.
*
* FIXME: remove eax-ebx-ecx-edx and use the local_state_t
* version from within DR as well as from the ibl (case 3701).
*
* PR 264138: for xmm fields, we do NOT specify 16-byte alignment for
* our own, to avoid the 8-byte padding at the end for 32-bit mode
* that we don't want to manually insert for our hand-rolled structs
* on the stack.
* It's ok for the client version to have padding as dr_get_mcontext copies,
* but we don't currently assume alignment of client-declared dr_mcontext_t,
* so we have no alignment declarations there at the moment either.
*/
/* DR_API EXPORT TOFILE dr_defines.h */
/* DR_API EXPORT BEGIN */
/** 128-bit XMM register. */
typedef union _dr_xmm_t {
#ifdef X64
uint64 u64[2]; /**< Representation as 2 64-bit integers. */
#endif
uint u32[4]; /**< Representation as 4 32-bit integers. */
byte u8[16]; /**< Representation as 16 8-bit integers. */
reg_t reg[IF_X64_ELSE(2,4)]; /**< Representation as 2 or 4 registers. */
} dr_xmm_t;
/** 256-bit YMM register. */
typedef union _dr_ymm_t {
#ifdef AVOID_API_EXPORT
/* We avoid having 8-byte-aligned fields here for 32-bit: they cause
* cl to add padding in app_state_at_intercept_t and unprotected_context_t,
* which messes up our interception stack layout and our x86.asm offsets.
* We don't access these very often, so we just omit this field.
*
* With the new dr_mcontext_t's size field pushing its ymm field to 0x44
* having an 8-byte-aligned field here adds 4 bytes padding.
* We could shrink PRE_XMM_PADDING for client header files but simpler
* to just have u64 only be there for 64-bit for clients.
* We do the same thing for dr_xmm_t just to look consistent.
*/
#endif
#ifdef API_EXPORT_ONLY
#ifdef X64
uint64 u64[4]; /**< Representation as 4 64-bit integers. */
#endif
#endif
uint u32[8]; /**< Representation as 8 32-bit integers. */
byte u8[32]; /**< Representation as 32 8-bit integers. */
reg_t reg[IF_X64_ELSE(4,8)]; /**< Representation as 4 or 8 registers. */
} dr_ymm_t;
#ifdef AVOID_API_EXPORT
/* If this is increased, you'll probably need to increase the size of
* inject_into_thread's buf and INTERCEPTION_CODE_SIZE (for Windows).
* Also, update NUM_XMM_SLOTS in x86.asm and get_xmm_caller_saved.
* i#437: YMM is an extension of XMM from 128-bit to 256-bit without
* adding new ones, so code operating on XMM often also operates on YMM,
* and thus some *XMM* macros also apply to *YMM*.
*/
#endif
#ifdef X64
# ifdef WINDOWS
# define NUM_XMM_SLOTS 6 /**< Number of [xy]mm reg slots in dr_mcontext_t */ /*xmm0-5*/
# else
# define NUM_XMM_SLOTS 16 /**< Number of [xy]mm reg slots in dr_mcontext_t */ /*xmm0-15*/
# endif
# define PRE_XMM_PADDING 16 /**< Bytes of padding before xmm/ymm dr_mcontext_t slots */
#else
# define NUM_XMM_SLOTS 8 /**< Number of [xy]mm reg slots in dr_mcontext_t */ /*xmm0-7*/
# define PRE_XMM_PADDING 24 /**< Bytes of padding before xmm/ymm dr_mcontext_t slots */
#endif
/** Values for the flags field of dr_mcontext_t */
typedef enum {
/**
* Selects the xdi, xsi, xbp, xbx, xdx, xcx, xax, and r8-r15 fields (i.e.,
* all of the general-purpose registers excluding xsp, xip, and xflags).
*/
DR_MC_INTEGER = 0x01,
/**
* Selects the xsp, xflags, and xip fields.
* \note: The xip field is only honored as an input for
* dr_redirect_execution(), and as an output for system call
* events.
*/
DR_MC_CONTROL = 0x02,
/**
* Selects the ymm (and xmm) fields. This flag is ignored unless
* dr_mcontext_xmm_fields_valid() returns true. If
* dr_mcontext_xmm_fields_valid() returns false, the application values of
* the multimedia registers remain in the registers themselves.
*/
DR_MC_MULTIMEDIA = 0x04,
/** Selects all fields */
DR_MC_ALL = (DR_MC_INTEGER | DR_MC_CONTROL | DR_MC_MULTIMEDIA),
} dr_mcontext_flags_t;
/**
* Machine context structure.
*/
typedef struct _dr_mcontext_t {
/**
* The size of this structure. This field must be set prior to filling
* in the fields to support forward compatibility.
*/
size_t size;
/**
* The valid fields of this structure. This field must be set prior to
* filling in the fields. For input requests (dr_get_mcontext()), this
* indicates which fields should be written. Writing the multimedia fields
* frequently can incur a performance hit. For output requests
* (dr_set_mcontext() and dr_redirect_execution()), this indicates which
* fields will be copied to the actual context.
*/
dr_mcontext_flags_t flags;
#include "mcxtx.h"
} dr_mcontext_t;
/* DR_API EXPORT END */
/* Internal machine context structure */
typedef struct _priv_mcontext_t {
#include "mcxtx.h"
} priv_mcontext_t;
/* PR 306394: for 32-bit xmm0-7 are caller-saved, and are touched by
* libc routines invoked by DR in some Linux systems (xref i#139),
* so they should be saved in 32-bit Linux.
*/
/* Xref i#139:
* XMM register preservation will cause extra runtime overhead.
* We test it over 32-bit SPEC2006 on a 64-bit Debian Linux, which shows
* that DR with xmm preservation adds negligible overhead over DR without
* xmm preservation.
* It means xmm preservation would have little performance impact over
* DR base system. This is mainly because DR's own operations' overhead
* is much higher than the context switch overhead.
* However, if a program is running with a DR client which performs many
* clean calls (one or more per basic block), xmm preservation may
* have noticable impacts, i.e. pushing bbs over the max size limit,
* and could have a noticeable performance hit.
*/
/* We now save everything but we keep separate NUM_XMM_SLOTS vs NUM_XMM_SAVED
* in case we go back to not saving some slots in the future: e.g., w/o
* CLIENT_INTERFACE we could control our own libs enough to avoid some saves.
*/
#define NUM_XMM_SAVED NUM_XMM_SLOTS
#endif /* ifndef _GLOBALS_SHARED_H_ */