duran 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.rdoc +11 -0
- data/Rakefile +29 -0
- data/VERSION +1 -0
- data/client_src/dr_include/dr_api.h +102 -0
- data/client_src/dr_include/dr_app.h +92 -0
- data/client_src/dr_include/dr_config.h +650 -0
- data/client_src/dr_include/dr_defines.h +391 -0
- data/client_src/dr_include/dr_events.h +1057 -0
- data/client_src/dr_include/dr_ir_instr.h +1214 -0
- data/client_src/dr_include/dr_ir_instrlist.h +149 -0
- data/client_src/dr_include/dr_ir_macros.h +2426 -0
- data/client_src/dr_include/dr_ir_opcodes.h +768 -0
- data/client_src/dr_include/dr_ir_opnd.h +1170 -0
- data/client_src/dr_include/dr_ir_utils.h +708 -0
- data/client_src/dr_include/dr_proc.h +327 -0
- data/client_src/dr_include/dr_tools.h +1304 -0
- data/client_src/duran.c +57 -0
- data/client_src/extconf.rb +28 -0
- data/lib/duran.rb +18 -0
- data/lib/duran/app.rb +8 -0
- data/lib/duran/defines.rb +39 -0
- data/lib/duran/events.rb +156 -0
- data/lib/duran/ir_opcodes.rb +616 -0
- data/lib/duran/ir_opnd.rb +329 -0
- data/lib/duran/ir_utils.rb +133 -0
- data/lib/duran/proc.rb +49 -0
- data/lib/duran/structs.rb +20 -0
- data/lib/duran/structs/exception.rb +23 -0
- data/lib/duran/structs/fault_fragment_info.rb +34 -0
- data/lib/duran/structs/instruction.rb +15 -0
- data/lib/duran/structs/machine_context.rb +80 -0
- data/lib/duran/structs/memory_info.rb +12 -0
- data/lib/duran/structs/module_data.rb +61 -0
- data/lib/duran/structs/module_names.rb +24 -0
- data/lib/duran/structs/operand.rb +15 -0
- data/lib/duran/structs/restore_state_info.rb +30 -0
- data/lib/duran/structs/signal_info.rb +41 -0
- data/lib/duran/structs/tracedump.rb +50 -0
- data/lib/duran/tools.rb +214 -0
- metadata +104 -0
@@ -0,0 +1,391 @@
|
|
1
|
+
/* **********************************************************
|
2
|
+
* Copyright (c) 2002-2009 VMware, Inc. All rights reserved.
|
3
|
+
* **********************************************************/
|
4
|
+
|
5
|
+
/*
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
7
|
+
* modification, are permitted provided that the following conditions are met:
|
8
|
+
*
|
9
|
+
* * Redistributions of source code must retain the above copyright notice,
|
10
|
+
* this list of conditions and the following disclaimer.
|
11
|
+
*
|
12
|
+
* * Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
* this list of conditions and the following disclaimer in the documentation
|
14
|
+
* and/or other materials provided with the distribution.
|
15
|
+
*
|
16
|
+
* * Neither the name of VMware, Inc. nor the names of its contributors may be
|
17
|
+
* used to endorse or promote products derived from this software without
|
18
|
+
* specific prior written permission.
|
19
|
+
*
|
20
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
|
24
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
25
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
26
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
27
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
28
|
+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
29
|
+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
30
|
+
* DAMAGE.
|
31
|
+
*/
|
32
|
+
|
33
|
+
#ifndef _DR_DEFINES_H_
|
34
|
+
#define _DR_DEFINES_H_ 1
|
35
|
+
|
36
|
+
/****************************************************************************
|
37
|
+
* GENERAL TYPEDEFS AND DEFINES
|
38
|
+
*/
|
39
|
+
|
40
|
+
/**
|
41
|
+
* @file dr_defines.h
|
42
|
+
* @brief Basic defines and type definitions.
|
43
|
+
*/
|
44
|
+
|
45
|
+
/* A client's target operating system and architecture must be specified. */
|
46
|
+
#if (!defined(LINUX) && !defined(WINDOWS)) || (defined(LINUX) && defined(WINDOWS))
|
47
|
+
# error Target operating system unspecified: must define either WINDOWS xor LINUX
|
48
|
+
#endif
|
49
|
+
|
50
|
+
#if (!defined(X86_64) && !defined(X86_32)) || (defined(X86_64) && defined(X86_32))
|
51
|
+
# error Target architecture unspecified: must define either X86_64 xor X86_32
|
52
|
+
#endif
|
53
|
+
|
54
|
+
#if defined(X86_64) && !defined(X64)
|
55
|
+
# define X64
|
56
|
+
#endif
|
57
|
+
|
58
|
+
#ifdef WINDOWS
|
59
|
+
# define WIN32_LEAN_AND_MEAN
|
60
|
+
# include <windows.h>
|
61
|
+
# include <winbase.h>
|
62
|
+
#else
|
63
|
+
# include <stdio.h>
|
64
|
+
# include <stdlib.h>
|
65
|
+
#endif
|
66
|
+
|
67
|
+
#ifdef WINDOWS
|
68
|
+
/* allow nameless struct/union */
|
69
|
+
# pragma warning(disable: 4201)
|
70
|
+
#endif
|
71
|
+
|
72
|
+
#ifdef WINDOWS
|
73
|
+
# define DR_EXPORT __declspec(dllexport)
|
74
|
+
# define LINK_ONCE __declspec(selectany)
|
75
|
+
# define ALIGN_VAR(x) __declspec(align(x))
|
76
|
+
# define inline __inline
|
77
|
+
# define INLINE_FORCED __forceinline
|
78
|
+
#else
|
79
|
+
/* We assume gcc is being used. If the client is using -fvisibility
|
80
|
+
* (in gcc >= 3.4) to not export symbols by default, setting
|
81
|
+
* USE_VISIBILITY_ATTRIBUTES will properly export.
|
82
|
+
*/
|
83
|
+
# ifdef USE_VISIBILITY_ATTRIBUTES
|
84
|
+
# define DR_EXPORT __attribute__ ((visibility ("default")))
|
85
|
+
# else
|
86
|
+
# define DR_EXPORT
|
87
|
+
# endif
|
88
|
+
# define LINK_ONCE __attribute__ ((weak))
|
89
|
+
# define ALIGN_VAR(x) __attribute__ ((aligned (x)))
|
90
|
+
# define inline __inline__
|
91
|
+
# define INLINE_FORCED inline
|
92
|
+
#endif
|
93
|
+
|
94
|
+
/** Cross-platform maximum file path length. */
|
95
|
+
#define MAXIMUM_PATH 260
|
96
|
+
|
97
|
+
|
98
|
+
#ifndef NULL
|
99
|
+
# define NULL (0)
|
100
|
+
#endif
|
101
|
+
|
102
|
+
#ifndef __cplusplus
|
103
|
+
# ifndef DR_DO_NOT_DEFINE_bool
|
104
|
+
typedef int bool;
|
105
|
+
# endif
|
106
|
+
# define true (1)
|
107
|
+
# define false (0)
|
108
|
+
#endif
|
109
|
+
|
110
|
+
#ifndef DR_DO_NOT_DEFINE_uint
|
111
|
+
typedef unsigned int uint;
|
112
|
+
#endif
|
113
|
+
#ifndef DR_DO_NOT_DEFINE_ushort
|
114
|
+
typedef unsigned short ushort;
|
115
|
+
#endif
|
116
|
+
#ifndef DR_DO_NOT_DEFINE_byte
|
117
|
+
typedef unsigned char byte;
|
118
|
+
#endif
|
119
|
+
#ifndef DR_DO_NOT_DEFINE_sbyte
|
120
|
+
typedef signed char sbyte;
|
121
|
+
#endif
|
122
|
+
typedef byte * app_pc;
|
123
|
+
|
124
|
+
typedef void (*generic_func_t) ();
|
125
|
+
|
126
|
+
#ifdef WINDOWS
|
127
|
+
# ifndef DR_DO_NOT_DEFINE_uint64
|
128
|
+
typedef unsigned __int64 uint64;
|
129
|
+
# endif
|
130
|
+
# ifndef DR_DO_NOT_DEFINE_int64
|
131
|
+
typedef __int64 int64;
|
132
|
+
# endif
|
133
|
+
# ifdef X64
|
134
|
+
typedef __int64 ssize_t;
|
135
|
+
# else
|
136
|
+
typedef int ssize_t;
|
137
|
+
# endif
|
138
|
+
# define INT64_FORMAT "I64"
|
139
|
+
#else /* Linux */
|
140
|
+
# ifdef X64
|
141
|
+
# ifndef DR_DO_NOT_DEFINE_uint64
|
142
|
+
typedef unsigned long int uint64;
|
143
|
+
# endif
|
144
|
+
# ifndef DR_DO_NOT_DEFINE_int64
|
145
|
+
typedef long int int64;
|
146
|
+
# endif
|
147
|
+
# define INT64_FORMAT "l"
|
148
|
+
# else
|
149
|
+
# ifndef DR_DO_NOT_DEFINE_uint64
|
150
|
+
typedef unsigned long long int uint64;
|
151
|
+
# endif
|
152
|
+
# ifndef DR_DO_NOT_DEFINE_int64
|
153
|
+
typedef long long int int64;
|
154
|
+
# endif
|
155
|
+
# define INT64_FORMAT "ll"
|
156
|
+
# endif
|
157
|
+
#endif
|
158
|
+
|
159
|
+
/* a register value: could be of any type; size is what matters. */
|
160
|
+
#ifdef X64
|
161
|
+
typedef uint64 reg_t;
|
162
|
+
#else
|
163
|
+
typedef uint reg_t;
|
164
|
+
#endif
|
165
|
+
/* integer whose size is based on pointers: ptr diff, mask, etc. */
|
166
|
+
typedef reg_t ptr_uint_t;
|
167
|
+
#ifdef X64
|
168
|
+
typedef int64 ptr_int_t;
|
169
|
+
#else
|
170
|
+
typedef int ptr_int_t;
|
171
|
+
#endif
|
172
|
+
/* for memory region sizes, use size_t */
|
173
|
+
|
174
|
+
#ifdef WINDOWS
|
175
|
+
typedef ptr_uint_t thread_id_t;
|
176
|
+
typedef ptr_uint_t process_id_t;
|
177
|
+
#else /* Linux */
|
178
|
+
typedef pid_t thread_id_t;
|
179
|
+
typedef pid_t process_id_t;
|
180
|
+
#endif
|
181
|
+
|
182
|
+
#ifdef WINDOWS
|
183
|
+
/* since a FILE cannot be used outside of the DLL it was created in,
|
184
|
+
* we have to use HANDLE on Windows
|
185
|
+
* we hide the distinction behind the file_t type
|
186
|
+
*/
|
187
|
+
typedef HANDLE file_t;
|
188
|
+
/** The sentinel value for an invalid file_t. */
|
189
|
+
# define INVALID_FILE INVALID_HANDLE_VALUE
|
190
|
+
/* dr_get_stdout_file and dr_get_stderr_file return errors as
|
191
|
+
* INVALID_HANDLE_VALUE. We leave INVALID_HANDLE_VALUE as is,
|
192
|
+
* since it equals INVALID_FILE
|
193
|
+
*/
|
194
|
+
/** The file_t value for standard output. */
|
195
|
+
# define STDOUT (dr_get_stdout_file())
|
196
|
+
/** The file_t value for standard error. */
|
197
|
+
# define STDERR (dr_get_stderr_file())
|
198
|
+
/** The file_t value for standard input. */
|
199
|
+
# define STDIN (dr_get_stdin_file())
|
200
|
+
#endif
|
201
|
+
|
202
|
+
#ifdef LINUX
|
203
|
+
typedef int file_t;
|
204
|
+
/** The sentinel value for an invalid file_t. */
|
205
|
+
# define INVALID_FILE -1
|
206
|
+
/** Allow use of stdout after the application closes it. */
|
207
|
+
extern file_t our_stdout;
|
208
|
+
/** Allow use of stderr after the application closes it. */
|
209
|
+
extern file_t our_stderr;
|
210
|
+
/** Allow use of stdin after the application closes it. */
|
211
|
+
extern file_t our_stdin;
|
212
|
+
/** The file_t value for standard output. */
|
213
|
+
# define STDOUT (our_stdout == INVALID_FILE ? stdout->_fileno : our_stdout)
|
214
|
+
/** The file_t value for standard error. */
|
215
|
+
# define STDERR (our_stderr == INVALID_FILE ? stderr->_fileno : our_stderr)
|
216
|
+
/** The file_t value for standard error. */
|
217
|
+
# define STDIN (our_stdin == INVALID_FILE ? stdin->_fileno : our_stdin)
|
218
|
+
#endif
|
219
|
+
|
220
|
+
/**
|
221
|
+
* ID used to uniquely identify a client. This value is set at
|
222
|
+
* client registration and passed to the client in dr_init().
|
223
|
+
*/
|
224
|
+
typedef uint client_id_t;
|
225
|
+
|
226
|
+
/**
|
227
|
+
* Internal structure of opnd_t is below abstraction layer.
|
228
|
+
* But compiler needs to know field sizes to copy it around
|
229
|
+
*/
|
230
|
+
typedef struct {
|
231
|
+
#ifdef X64
|
232
|
+
uint black_box_uint;
|
233
|
+
uint64 black_box_uint64;
|
234
|
+
#else
|
235
|
+
uint black_box_uint[3];
|
236
|
+
#endif
|
237
|
+
} opnd_t;
|
238
|
+
|
239
|
+
/**
|
240
|
+
* Internal structure of instr_t is below abstraction layer, but we
|
241
|
+
* provide its size so that it can be used in stack variables
|
242
|
+
* instead of always allocated on the heap.
|
243
|
+
*/
|
244
|
+
typedef struct {
|
245
|
+
#ifdef X64
|
246
|
+
uint black_box_uint[26];
|
247
|
+
#else
|
248
|
+
uint black_box_uint[16];
|
249
|
+
#endif
|
250
|
+
} instr_t;
|
251
|
+
|
252
|
+
# define IN /* marks input param */
|
253
|
+
# define OUT /* marks output param */
|
254
|
+
# define INOUT /* marks input+output param */
|
255
|
+
|
256
|
+
|
257
|
+
#ifdef X64
|
258
|
+
# define IF_X64(x) x
|
259
|
+
# define IF_X64_ELSE(x, y) x
|
260
|
+
# define IF_X64_(x) x,
|
261
|
+
# define _IF_X64(x) , x
|
262
|
+
# define IF_NOT_X64(x)
|
263
|
+
# define _IF_NOT_X64(x)
|
264
|
+
#else
|
265
|
+
# define IF_X64(x)
|
266
|
+
# define IF_X64_ELSE(x, y) y
|
267
|
+
# define IF_X64_(x)
|
268
|
+
# define _IF_X64(x)
|
269
|
+
# define IF_NOT_X64(x) x
|
270
|
+
# define _IF_NOT_X64(x) , x
|
271
|
+
#endif
|
272
|
+
|
273
|
+
#define UINT64_FORMAT_CODE INT64_FORMAT"u"
|
274
|
+
#define INT64_FORMAT_CODE INT64_FORMAT"d"
|
275
|
+
#define UINT64_FORMAT_STRING "%"UINT64_FORMAT_CODE
|
276
|
+
#define INT64_FORMAT_STRING "%"INT64_FORMAT_CODE
|
277
|
+
#define HEX64_FORMAT_STRING "%"INT64_FORMAT"x"
|
278
|
+
#define ZHEX64_FORMAT_STRING "%016"INT64_FORMAT"x"
|
279
|
+
#define ZHEX32_FORMAT_STRING "%08x"
|
280
|
+
#define HEX32_FORMAT_STRING "%x"
|
281
|
+
/* Convenience defines for cross-platform printing */
|
282
|
+
#ifdef X64
|
283
|
+
# define PFMT ZHEX64_FORMAT_STRING
|
284
|
+
# define PIFMT HEX64_FORMAT_STRING
|
285
|
+
# define SZFMT INT64_FORMAT_STRING
|
286
|
+
#else
|
287
|
+
# define PFMT ZHEX32_FORMAT_STRING
|
288
|
+
# define PIFMT HEX32_FORMAT_STRING
|
289
|
+
# define SZFMT "%d"
|
290
|
+
#endif
|
291
|
+
|
292
|
+
#define PFX "0x"PFMT
|
293
|
+
#define PIFX "0x"PIFMT
|
294
|
+
|
295
|
+
/** 128-bit XMM register. */
|
296
|
+
typedef union _dr_xmm_t {
|
297
|
+
uint64 u64[2]; /**< Representation as 2 64-bit integers. */
|
298
|
+
uint u32[4]; /**< Representation as 4 32-bit integers. */
|
299
|
+
byte u8[16]; /**< Representation as 8 8-bit integers. */
|
300
|
+
reg_t reg[IF_X64_ELSE(2,4)]; /**< Representation as 2 or 4 registers. */
|
301
|
+
} dr_xmm_t;
|
302
|
+
|
303
|
+
#ifdef X64
|
304
|
+
# ifdef WINDOWS
|
305
|
+
# define NUM_XMM_SLOTS 6 /** Number of xmm reg slots in dr_mcontext_t */ /* xmm0-5 */
|
306
|
+
# else
|
307
|
+
# define NUM_XMM_SLOTS 16 /** Number of xmm reg slots in dr_mcontext_t */ /* xmm0-15 */
|
308
|
+
# endif
|
309
|
+
#else
|
310
|
+
# define NUM_XMM_SLOTS 8 /** Number of xmm reg slots in dr_mcontext_t */ /* xmm0-7 */
|
311
|
+
#endif
|
312
|
+
|
313
|
+
/**
|
314
|
+
* Machine context structure.
|
315
|
+
*/
|
316
|
+
typedef struct _dr_mcontext_t {
|
317
|
+
union {
|
318
|
+
reg_t xdi; /**< platform-independent name for full rdi/edi register */
|
319
|
+
reg_t IF_X64_ELSE(rdi, edi); /**< platform-dependent name for rdi/edi register */
|
320
|
+
}; /* anonymous union of alternative names for rdi/edi register */
|
321
|
+
union {
|
322
|
+
reg_t xsi; /**< platform-independent name for full rsi/esi register */
|
323
|
+
reg_t IF_X64_ELSE(rsi, esi); /**< platform-dependent name for rsi/esi register */
|
324
|
+
}; /* anonymous union of alternative names for rsi/esi register */
|
325
|
+
union {
|
326
|
+
reg_t xbp; /**< platform-independent name for full rbp/ebp register */
|
327
|
+
reg_t IF_X64_ELSE(rbp, ebp); /**< platform-dependent name for rbp/ebp register */
|
328
|
+
}; /* anonymous union of alternative names for rbp/ebp register */
|
329
|
+
union {
|
330
|
+
reg_t xsp; /**< platform-independent name for full rsp/esp register */
|
331
|
+
reg_t IF_X64_ELSE(rsp, esp); /**< platform-dependent name for rsp/esp register */
|
332
|
+
}; /* anonymous union of alternative names for rsp/esp register */
|
333
|
+
union {
|
334
|
+
reg_t xbx; /**< platform-independent name for full rbx/ebx register */
|
335
|
+
reg_t IF_X64_ELSE(rbx, ebx); /**< platform-dependent name for rbx/ebx register */
|
336
|
+
}; /* anonymous union of alternative names for rbx/ebx register */
|
337
|
+
union {
|
338
|
+
reg_t xdx; /**< platform-independent name for full rdx/edx register */
|
339
|
+
reg_t IF_X64_ELSE(rdx, edx); /**< platform-dependent name for rdx/edx register */
|
340
|
+
}; /* anonymous union of alternative names for rdx/edx register */
|
341
|
+
union {
|
342
|
+
reg_t xcx; /**< platform-independent name for full rcx/ecx register */
|
343
|
+
reg_t IF_X64_ELSE(rcx, ecx); /**< platform-dependent name for rcx/ecx register */
|
344
|
+
}; /* anonymous union of alternative names for rcx/ecx register */
|
345
|
+
union {
|
346
|
+
reg_t xax; /**< platform-independent name for full rax/eax register */
|
347
|
+
reg_t IF_X64_ELSE(rax, eax); /**< platform-dependent name for rax/eax register */
|
348
|
+
}; /* anonymous union of alternative names for rax/eax register */
|
349
|
+
#ifdef X64
|
350
|
+
reg_t r8; /**< r8 register. \note For 64-bit DR builds only. */
|
351
|
+
reg_t r9; /**< r9 register. \note For 64-bit DR builds only. */
|
352
|
+
reg_t r10; /**< r10 register. \note For 64-bit DR builds only. */
|
353
|
+
reg_t r11; /**< r11 register. \note For 64-bit DR builds only. */
|
354
|
+
reg_t r12; /**< r12 register. \note For 64-bit DR builds only. */
|
355
|
+
reg_t r13; /**< r13 register. \note For 64-bit DR builds only. */
|
356
|
+
reg_t r14; /**< r14 register. \note For 64-bit DR builds only. */
|
357
|
+
reg_t r15; /**< r15 register. \note For 64-bit DR builds only. */
|
358
|
+
#endif
|
359
|
+
/**
|
360
|
+
* The SSE registers xmm0-xmm5 (-xmm15 on Linux) are volatile
|
361
|
+
* (caller-saved) for 64-bit and WOW64, and are actually zeroed out on
|
362
|
+
* Windows system calls. These fields are ignored for 32-bit processes
|
363
|
+
* that are not WOW64, or if the underlying processor does not support
|
364
|
+
* SSE. Use dr_mcontext_xmm_fields_valid() to determine whether the
|
365
|
+
* fields are valid.
|
366
|
+
*/
|
367
|
+
dr_xmm_t xmm[NUM_XMM_SLOTS];
|
368
|
+
union {
|
369
|
+
reg_t xflags; /**< platform-independent name for full rflags/eflags register */
|
370
|
+
reg_t IF_X64_ELSE(rflags, eflags); /**< platform-dependent name for
|
371
|
+
rflags/eflags register */
|
372
|
+
}; /* anonymous union of alternative names for rflags/eflags register */
|
373
|
+
/*
|
374
|
+
* Anonymous union of alternative names for the program counter /
|
375
|
+
* instruction pointer (eip/rip). This field is not always set or
|
376
|
+
* read by all API routines.
|
377
|
+
*/
|
378
|
+
union {
|
379
|
+
byte *xip; /**< platform-independent name for full rip/eip register */
|
380
|
+
byte *pc; /**< platform-independent alt name for full rip/eip register */
|
381
|
+
byte *IF_X64_ELSE(rip, eip); /**< platform-dependent name for rip/eip register */
|
382
|
+
};
|
383
|
+
} dr_mcontext_t;
|
384
|
+
|
385
|
+
|
386
|
+
typedef struct _instr_list_t instrlist_t;
|
387
|
+
typedef struct _module_data_t module_data_t;
|
388
|
+
|
389
|
+
|
390
|
+
|
391
|
+
#endif /* _DR_DEFINES_H_ */
|
@@ -0,0 +1,1057 @@
|
|
1
|
+
/* **********************************************************
|
2
|
+
* Copyright (c) 2002-2009 VMware, Inc. All rights reserved.
|
3
|
+
* **********************************************************/
|
4
|
+
|
5
|
+
/*
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
7
|
+
* modification, are permitted provided that the following conditions are met:
|
8
|
+
*
|
9
|
+
* * Redistributions of source code must retain the above copyright notice,
|
10
|
+
* this list of conditions and the following disclaimer.
|
11
|
+
*
|
12
|
+
* * Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
* this list of conditions and the following disclaimer in the documentation
|
14
|
+
* and/or other materials provided with the distribution.
|
15
|
+
*
|
16
|
+
* * Neither the name of VMware, Inc. nor the names of its contributors may be
|
17
|
+
* used to endorse or promote products derived from this software without
|
18
|
+
* specific prior written permission.
|
19
|
+
*
|
20
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
|
24
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
25
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
26
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
27
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
28
|
+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
29
|
+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
30
|
+
* DAMAGE.
|
31
|
+
*/
|
32
|
+
|
33
|
+
#ifndef _DR_EVENTS_H_
|
34
|
+
#define _DR_EVENTS_H_ 1
|
35
|
+
|
36
|
+
|
37
|
+
/**************************************************
|
38
|
+
* ROUTINES TO REGISTER EVENT CALLBACKS
|
39
|
+
*/
|
40
|
+
/**
|
41
|
+
* @file dr_events.h
|
42
|
+
* @brief Event callback registration routines.
|
43
|
+
*/
|
44
|
+
|
45
|
+
|
46
|
+
/**
|
47
|
+
* Registers a callback function for the process exit event. DR calls
|
48
|
+
* \p func when the process exits.
|
49
|
+
*
|
50
|
+
* On Linux, SYS_execve does NOT result in an exit event, but it WILL
|
51
|
+
* result in the client library being reloaded and its dr_init()
|
52
|
+
* routine being called.
|
53
|
+
*/
|
54
|
+
void
|
55
|
+
dr_register_exit_event(void (*func)(void));
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Unregister a callback function for the process exit event.
|
59
|
+
* \return true if unregistration is successful and false if it is not
|
60
|
+
* (e.g., \p func was not registered).
|
61
|
+
*/
|
62
|
+
bool
|
63
|
+
dr_unregister_exit_event(void (*func)(void));
|
64
|
+
/**
|
65
|
+
* Flags controlling the behavior of basic blocks and traces when emitted
|
66
|
+
* into the code cache. For multiple clients, the flags returned by each
|
67
|
+
* client are or-ed together.
|
68
|
+
*/
|
69
|
+
typedef enum {
|
70
|
+
/** Emit as normal. */
|
71
|
+
DR_EMIT_DEFAULT = 0,
|
72
|
+
/**
|
73
|
+
* Store translation information at emit time rather than calling
|
74
|
+
* the basic block or trace event later to recreate the
|
75
|
+
* information. Note that even if a standalone basic block has
|
76
|
+
* stored translations, if when it is added to a trace it does not
|
77
|
+
* request storage (and the trace callback also does not request
|
78
|
+
* storage) then the basic block callback may still be called to
|
79
|
+
* translate for the trace.
|
80
|
+
*
|
81
|
+
* \sa #dr_register_bb_event()
|
82
|
+
*/
|
83
|
+
DR_EMIT_STORE_TRANSLATIONS = 0x01,
|
84
|
+
} dr_emit_flags_t;
|
85
|
+
|
86
|
+
|
87
|
+
/**
|
88
|
+
* Registers a callback function for the basic block event. DR calls
|
89
|
+
* \p func before inserting a new basic block into the code cache.
|
90
|
+
* When adding a basic block to a new trace, DR calls \p func again
|
91
|
+
* with \p for_trace set to true, giving the client the opportunity to
|
92
|
+
* keep its same instrumentation in the trace, or to change it. The
|
93
|
+
* original basic block's instrumentation is unchanged by whatever
|
94
|
+
* action is taken in the \p for_trace call.
|
95
|
+
*
|
96
|
+
* DR may call \p func again if it needs to translate from code cache
|
97
|
+
* addresses back to application addresses, which happens on faulting
|
98
|
+
* instructions as well as in certain situations involving suspended
|
99
|
+
* threads or forcibly relocated threads. The \p translating
|
100
|
+
* parameter distinguishes the two types of calls and is further
|
101
|
+
* explained below.
|
102
|
+
*
|
103
|
+
* - \p drcontext is a pointer to the input program's machine context.
|
104
|
+
* Clients should not inspect or modify the context; it is provided as
|
105
|
+
* an opaque pointer (i.e., <tt>void *</tt>) to be passed to API
|
106
|
+
* routines that require access to this internal data.
|
107
|
+
* drcontext is specific to the current thread, but in normal
|
108
|
+
* configurations the basic block being created is thread-shared: thus,
|
109
|
+
* when allocating data structures with the same lifetime as the
|
110
|
+
* basic block, usually global heap (#dr_global_alloc()) is a better
|
111
|
+
* choice than heap tied to the thread that happened to first create
|
112
|
+
* the basic block (#dr_thread_alloc()). Thread-private heap is fine
|
113
|
+
* for temporary structures such as instr_t and instrlist_t.
|
114
|
+
*
|
115
|
+
* - \p tag is a unique identifier for the basic block fragment.
|
116
|
+
* - \p bb is a pointer to the list of instructions that comprise the
|
117
|
+
* basic block. Clients can examine, manipulate, or completely
|
118
|
+
* replace the instructions in the list.
|
119
|
+
*
|
120
|
+
* - \p translating indicates whether this callback is for basic block
|
121
|
+
* creation (false) or is for address translation (true). This is
|
122
|
+
* further explained below.
|
123
|
+
*
|
124
|
+
* \return a #dr_emit_flags_t flag.
|
125
|
+
*
|
126
|
+
* The user is free to inspect and modify the block before it
|
127
|
+
* executes, but must adhere to the following restrictions:
|
128
|
+
* - If there is more than one non-meta branch, only the last can be
|
129
|
+
* conditional.
|
130
|
+
* - A non-meta conditional branch or direct call must be the final
|
131
|
+
* instruction in the block.
|
132
|
+
* - There can only be one indirect branch (call, jump, or return) in
|
133
|
+
* a basic block, and it must be the final instruction in the
|
134
|
+
* block.
|
135
|
+
* - The exit control-flow of a block ending in a system call or
|
136
|
+
* int instruction cannot be changed, nor can instructions be inserted
|
137
|
+
* after the system call or int instruction itself, unless
|
138
|
+
* the system call or int instruction is removed entirely.
|
139
|
+
* - The number of an interrupt cannot be changed. (Note that the
|
140
|
+
* parameter to a system call, normally kept in the eax register, can
|
141
|
+
* be freely changed in a basic block: but not in a trace.)
|
142
|
+
* - A system call or interrupt instruction can only be added
|
143
|
+
* if it satisfies the above constraints: i.e., if it is the final
|
144
|
+
* instruction in the block and the only system call or interrupt.
|
145
|
+
* - The block's application source code (as indicated by the
|
146
|
+
* translation targets, set by #instr_set_translation()) must remain
|
147
|
+
* within the original bounds of the block (the one exception to this
|
148
|
+
* is that a jump can translate to its target). Otherwise, DR's cache
|
149
|
+
* consistency algorithms cannot guarantee to properly invalidate the
|
150
|
+
* block if the source application code is modified. To send control
|
151
|
+
* to other application code regions, truncate the block and use a
|
152
|
+
* direct jump to target the desired address, which will then
|
153
|
+
* materialize in the subsequent block, rather than embedding the
|
154
|
+
* desired instructions in this block.
|
155
|
+
* - There is a limit on the size of a basic block in the code cache.
|
156
|
+
* DR performs its own modifications, especially on memory writes for
|
157
|
+
* cache consistency of self-modifying (or false sharing) code
|
158
|
+
* regions. If an assert fires in debug build indicating a limit was
|
159
|
+
* reached, either truncate blocks or use the -max_bb_instrs runtime
|
160
|
+
* option to ask DR to make them smaller.
|
161
|
+
*
|
162
|
+
* To support transparent fault handling, DR must translate a fault in the
|
163
|
+
* code cache into a fault at the corresponding application address. DR
|
164
|
+
* must also be able to translate when a suspended thread is examined by
|
165
|
+
* the application or by DR itself for internal synchronization purposes.
|
166
|
+
* If the client is only adding observational instrumentation (i.e., meta
|
167
|
+
* instructions: see #instr_set_ok_to_mangle()) (which should not fault) and
|
168
|
+
* is not modifying, reordering, or removing application instructions,
|
169
|
+
* these details can be ignored. In that case the client should return
|
170
|
+
* #DR_EMIT_DEFAULT and set up its basic block callback to be deterministic
|
171
|
+
* and idempotent. If the client is performing modifications, then in
|
172
|
+
* order for DR to properly translate a code cache address the client must
|
173
|
+
* use #instr_set_translation() in the basic block creation callback to set
|
174
|
+
* the corresponding application address (the address that should be
|
175
|
+
* presented to the application as the faulting address, or the address
|
176
|
+
* that should be restarted after a suspend) for each modified instruction
|
177
|
+
* and each added non-meta instruction (see #instr_set_ok_to_mangle()).
|
178
|
+
*
|
179
|
+
* There are two methods for using the translated addresses:
|
180
|
+
*
|
181
|
+
* -# Return #DR_EMIT_STORE_TRANSLATIONS from the basic block creation
|
182
|
+
* callback. DR will then store the translation addresses and use
|
183
|
+
* the stored information on a fault. The basic block callback for
|
184
|
+
* \p tag will not be called with \p translating set to true. Note
|
185
|
+
* that unless #DR_EMIT_STORE_TRANSLATIONS is also returned for \p
|
186
|
+
* for_trace calls (or #DR_EMIT_STORE_TRANSLATIONS is returned in
|
187
|
+
* the trace callback), each constituent block comprising the trace
|
188
|
+
* will need to be re-created with both \p for_trace and \p
|
189
|
+
* translating set to true. Storing translations uses additional
|
190
|
+
* memory that can be significant: up to 20% in some cases, as it
|
191
|
+
* prevents DR from using its simple data structures and forces it
|
192
|
+
* to fall back to its complex, corner-case design. This is why DR
|
193
|
+
* does not store all translations by default.
|
194
|
+
* -# Return #DR_EMIT_DEFAULT from the basic block creation callback.
|
195
|
+
* DR will then call the callback again during fault translation
|
196
|
+
* with \p translating set to true. All modifications to \p bb
|
197
|
+
* that were performed on the creation callback must be repeated on
|
198
|
+
* the translating callback. This option is only posible when
|
199
|
+
* basic block modifications are deterministic and idempotent, but
|
200
|
+
* it saves memory. Naturally, global state changes triggered by
|
201
|
+
* block creation should be wrapped in checks for \p translating
|
202
|
+
* being false. Even in this case, #instr_set_translation() should
|
203
|
+
* be called for non-meta instructions even when \p translating is
|
204
|
+
* false, as DR may decide to store the translations at creation
|
205
|
+
* time for reasons of its own.
|
206
|
+
*
|
207
|
+
* Furthermore, if the client's modifications change any part of the
|
208
|
+
* machine state besides the program counter, the client should use
|
209
|
+
* #dr_register_restore_state_event() or
|
210
|
+
* #dr_register_restore_state_ex_event() to restore the registers and
|
211
|
+
* application memory to their original application values.
|
212
|
+
*
|
213
|
+
* For meta instructions that do not reference application memory
|
214
|
+
* (i.e., they should not fault), leave the translation field as NULL.
|
215
|
+
* A NULL value instructs DR to use the subsequent non-meta
|
216
|
+
* instruction's translation as the application address, and to fail
|
217
|
+
* when translating the full state. Since the full state will only be
|
218
|
+
* needed when relocating a thread (as stated, there will not be a
|
219
|
+
* fault here), failure indicates that this is not a valid relocation
|
220
|
+
* point, and DR's thread synchronization scheme will use another
|
221
|
+
* spot. If the translation field is set to a non-NULL value, the
|
222
|
+
* client should be willing to also restore the rest of the machine
|
223
|
+
* state at that point (restore spilled registers, etc.) via
|
224
|
+
* #dr_register_restore_state_event() or
|
225
|
+
* #dr_register_restore_state_ex_event(). This is necessary for meta
|
226
|
+
* instructions that reference application memory. DR takes care of
|
227
|
+
* such potentially-faulting instructions added by its own API
|
228
|
+
* routines (#dr_insert_clean_call() arguments that reference
|
229
|
+
* application data, #dr_insert_mbr_instrumentation()'s read of
|
230
|
+
* application indirect branch data, etc.)
|
231
|
+
*
|
232
|
+
* \note In order to present a more straightforward code stream to clients,
|
233
|
+
* this release of DR disables several internal optimizations. As a result,
|
234
|
+
* some applications may see a performance degradation. Applications making
|
235
|
+
* heavy use of system calls are the most likely to be affected.
|
236
|
+
* Future releases may allow clients some control over performance versus
|
237
|
+
* visibility.
|
238
|
+
*
|
239
|
+
* \note If multiple clients are present, the instruction list for a
|
240
|
+
* basic block passed to earlier-registered clients will contain the
|
241
|
+
* instrumentation and modifications put in place by later-registered
|
242
|
+
* clients.
|
243
|
+
*
|
244
|
+
* \note Basic blocks can be deleted due to hitting capacity limits or
|
245
|
+
* cache consistency events (when the source application code of a
|
246
|
+
* basic block is modified). In that case, the client will see a new
|
247
|
+
* basic block callback if the block is then executed again after
|
248
|
+
* deletion. The deletion event (#dr_register_delete_event()) will be
|
249
|
+
* raised at deletion time.
|
250
|
+
*
|
251
|
+
* \note If the -thread_private runtime option is specified, clients
|
252
|
+
* should expect to see duplicate tags for separate threads, albeit
|
253
|
+
* with different dcrcontext values. Additionally, DR employs a
|
254
|
+
* cache-sizing algorithm for thread private operation that
|
255
|
+
* proactively deletes fragments. Even with thread-shared caches
|
256
|
+
* enabled, however, certain situations cause DR to emit
|
257
|
+
* thread-private basic blocks (e.g., self-modifying code). In this
|
258
|
+
* case, clients should be prepared to see duplicate tags without an
|
259
|
+
* intermediate deletion.
|
260
|
+
*/
|
261
|
+
void
|
262
|
+
dr_register_bb_event(dr_emit_flags_t (*func)
|
263
|
+
(void *drcontext, void *tag, instrlist_t *bb,
|
264
|
+
bool for_trace, bool translating));
|
265
|
+
|
266
|
+
/**
|
267
|
+
* Unregister a callback function for the basic block event.
|
268
|
+
* \return true if unregistration is successful and false if it is not
|
269
|
+
* (e.g., \p func was not registered).
|
270
|
+
*
|
271
|
+
* \note We do not recommend unregistering for the basic block event
|
272
|
+
* unless it aways returned #DR_EMIT_STORE_TRANSLATIONS (including
|
273
|
+
* when \p for_trace is true, or if the client has a trace creation
|
274
|
+
* callback that returns #DR_EMIT_STORE_TRANSLATIONS). Unregistering
|
275
|
+
* can prevent proper state translation on a later fault or other
|
276
|
+
* translation event for this basic block or for a trace that includes
|
277
|
+
* this basic block. Instead of unregistering, turn the event
|
278
|
+
* callback into a nop.
|
279
|
+
*/
|
280
|
+
bool
|
281
|
+
dr_unregister_bb_event(dr_emit_flags_t (*func)
|
282
|
+
(void *drcontext, void *tag, instrlist_t *bb,
|
283
|
+
bool for_trace, bool translating));
|
284
|
+
|
285
|
+
/**
|
286
|
+
* Registers a callback function for the trace event. DR calls \p func
|
287
|
+
* before inserting a new trace into the code cache. DR may call \p func
|
288
|
+
* again if it needs to translate from code cache addresses back to
|
289
|
+
* application addresses, which happens on faulting instructions as well as
|
290
|
+
* in certain situations involving suspended threads or forcibly relocated
|
291
|
+
* threads. The \p translating parameter distinguishes the two types of
|
292
|
+
* calls and behaves identically to the same parameter in the basic
|
293
|
+
* block callback: see #dr_register_bb_event() for further details.
|
294
|
+
*
|
295
|
+
* Traces are not built if the -disable_traces runtime option
|
296
|
+
* is specified.
|
297
|
+
*
|
298
|
+
* - \p drcontext is a pointer to the input program's machine context.
|
299
|
+
* Clients should not inspect or modify the context; it is provided as
|
300
|
+
* an opaque pointer (i.e., <tt>void *</tt>) to be passed to API
|
301
|
+
* routines that require access to this internal data.
|
302
|
+
* - \p tag is a unique identifier for the trace fragment.
|
303
|
+
* - \p trace is a pointer to the list of instructions that comprise the
|
304
|
+
* trace.
|
305
|
+
* - \p translating indicates whether this callback is for trace creation
|
306
|
+
* (false) or is for fault address recreation (true). This is further
|
307
|
+
* explained below.
|
308
|
+
*
|
309
|
+
* \return a #dr_emit_flags_t flag.
|
310
|
+
*
|
311
|
+
* The user is free to inspect and modify the trace before it
|
312
|
+
* executes, with certain restrictions on introducing control-flow
|
313
|
+
* that include those for basic blocks (see dr_register_bb_event()).
|
314
|
+
* Additional restrictions unique to traces also apply:
|
315
|
+
* - Only one non-meta direct branch that targets the subsequent block
|
316
|
+
* in the trace can be present in each block.
|
317
|
+
* - Each block must end with a non-meta control transfer.
|
318
|
+
* - The parameter to a system call, normally kept in the eax register,
|
319
|
+
* cannot be changed.
|
320
|
+
* - A system call or interrupt instruction cannot be added.
|
321
|
+
*
|
322
|
+
* If hitting a size limit due to extensive instrumentation, reduce
|
323
|
+
* the -max_trace_bbs option to start with a smaller trace.
|
324
|
+
*
|
325
|
+
* The basic block restrictions on modifying application source code
|
326
|
+
* apply to traces as well. If the user wishes to change which basic
|
327
|
+
* blocks comprise the trace, either the
|
328
|
+
* #dr_register_end_trace_event() should be used or the \p for_trace
|
329
|
+
* basic block callbacks should modify their continuation addresses
|
330
|
+
* via direct jumps.
|
331
|
+
*
|
332
|
+
* All of the comments for #dr_register_bb_event() regarding
|
333
|
+
* transparent fault handling and state translation apply to the trace
|
334
|
+
* callback as well. Please read those comments carefully.
|
335
|
+
*
|
336
|
+
* \note As each basic block is added to a new trace, the basic block
|
337
|
+
* callback (see #dr_register_bb_event()) is called with its \p
|
338
|
+
* for_trace parameter set to true. In order to preserve basic block
|
339
|
+
* instrumentation inside of traces, a client need only act
|
340
|
+
* identically with respect to the \p for_trace parameter; it can
|
341
|
+
* ignore the trace event if its goal is to place instrumentation
|
342
|
+
* on all code.
|
343
|
+
*
|
344
|
+
* \note Certain control flow modifications applied to a basic block
|
345
|
+
* can prevent it from becoming part of a trace: e.g., adding
|
346
|
+
* additional non-meta control transfers.
|
347
|
+
*
|
348
|
+
* \note If multiple clients are present, the instruction list for a
|
349
|
+
* trace passed to earlier-registered clients will contain the
|
350
|
+
* instrumentation and modifications put in place by later-registered
|
351
|
+
* clients; similarly for each constituent basic block.
|
352
|
+
*
|
353
|
+
* \note Traces can be deleted due to hitting capacity limits or cache
|
354
|
+
* consistency events (when the source application code of a trace is
|
355
|
+
* modified). In that case, the client will see a new trace callback
|
356
|
+
* if a new trace containing that code is created again after
|
357
|
+
* deletion. The deletion event (#dr_register_delete_event()) will be
|
358
|
+
* raised at deletion time.
|
359
|
+
*/
|
360
|
+
void
|
361
|
+
dr_register_trace_event(dr_emit_flags_t (*func)
|
362
|
+
(void *drcontext, void *tag, instrlist_t *trace,
|
363
|
+
bool translating));
|
364
|
+
|
365
|
+
/**
|
366
|
+
* Unregister a callback function for the trace event.
|
367
|
+
* \return true if unregistration is successful and false if it is not
|
368
|
+
* (e.g., \p func was not registered).
|
369
|
+
*
|
370
|
+
* \note We do not recommend unregistering for the trace event unless it
|
371
|
+
* always returned #DR_EMIT_STORE_TRANSLATIONS, as doing so can prevent
|
372
|
+
* proper state translation on a later fault or other translation event.
|
373
|
+
* Instead of unregistering, turn the event callback into a nop.
|
374
|
+
*/
|
375
|
+
bool
|
376
|
+
dr_unregister_trace_event(dr_emit_flags_t (*func)
|
377
|
+
(void *drcontext, void *tag, instrlist_t *trace,
|
378
|
+
bool translating));
|
379
|
+
|
380
|
+
/**
|
381
|
+
* DR will call the end trace event if it is registered prior to
|
382
|
+
* adding each basic block to a trace being generated. The return
|
383
|
+
* value of the event callback should be from the
|
384
|
+
* dr_custom_trace_action_t enum.
|
385
|
+
*
|
386
|
+
* \note DR treats CUSTOM_TRACE_CONTINUE as an advisement only. Certain
|
387
|
+
* fragments are not suitable to be included in a trace and if DR runs
|
388
|
+
* into one it will end the trace regardless of what the client returns
|
389
|
+
* through the event callback.
|
390
|
+
*/
|
391
|
+
typedef enum {
|
392
|
+
CUSTOM_TRACE_DR_DECIDES,
|
393
|
+
CUSTOM_TRACE_END_NOW,
|
394
|
+
CUSTOM_TRACE_CONTINUE
|
395
|
+
} dr_custom_trace_action_t;
|
396
|
+
|
397
|
+
|
398
|
+
|
399
|
+
/**
|
400
|
+
* Registers a callback function for the end-trace event. DR calls \p
|
401
|
+
* func before extending a trace with a new basic block. The \p func
|
402
|
+
* should return one of the #dr_custom_trace_action_t enum values.
|
403
|
+
*/
|
404
|
+
void
|
405
|
+
dr_register_end_trace_event(dr_custom_trace_action_t (*func)
|
406
|
+
(void *drcontext, void *tag, void *next_tag));
|
407
|
+
|
408
|
+
/**
|
409
|
+
* Unregister a callback function for the end-trace event.
|
410
|
+
* \return true if unregistration is successful and false if it is not
|
411
|
+
* (e.g., \p func was not registered).
|
412
|
+
*/
|
413
|
+
bool
|
414
|
+
dr_unregister_end_trace_event(dr_custom_trace_action_t (*func)
|
415
|
+
(void *drcontext, void *tag, void *next_tag));
|
416
|
+
|
417
|
+
/**
|
418
|
+
* Registers a callback function for the fragment deletion event. DR
|
419
|
+
* calls \p func whenever it removes a fragment from the code cache.
|
420
|
+
* Due to DR's high-performance non-precise flushing, a fragment
|
421
|
+
* can be made inaccessible but not actually freed for some time.
|
422
|
+
* A new fragment can thus be created before the deletion event
|
423
|
+
* for the old fragment is raised. We recommended using a counter
|
424
|
+
* to ignore subsequent deletion events when using per-fragment
|
425
|
+
* data structures and duplicate fragments are seen.
|
426
|
+
*
|
427
|
+
* \note drcontext may be NULL when thread-shared fragments are being
|
428
|
+
* deleted during process exit. For this reason, thread-private
|
429
|
+
* heap should not be used for data structures intended to be freed
|
430
|
+
* at thread-shared fragment deletion.
|
431
|
+
*/
|
432
|
+
void
|
433
|
+
dr_register_delete_event(void (*func)(void *drcontext, void *tag));
|
434
|
+
|
435
|
+
/**
|
436
|
+
* Unregister a callback function for the fragment deletion event.
|
437
|
+
* \return true if unregistration is successful and false if it is not
|
438
|
+
* (e.g., \p func was not registered).
|
439
|
+
*/
|
440
|
+
bool
|
441
|
+
dr_unregister_delete_event(void (*func)(void *drcontext, void *tag));
|
442
|
+
|
443
|
+
/**
|
444
|
+
* Registers a callback function for the machine state restoration event.
|
445
|
+
* DR calls \p func whenever it needs to translate a code cache machine
|
446
|
+
* context from the code cache to its corresponding original application
|
447
|
+
* context. DR needs to translate when instructions fault in the cache as
|
448
|
+
* well as when a suspended thread is examined or relocated for internal
|
449
|
+
* purposes.
|
450
|
+
*
|
451
|
+
* If a client is only adding instrumentation (meta-code: see
|
452
|
+
* #instr_ok_to_mangle()) that does not reference application memory,
|
453
|
+
* and is not reordering or removing application instructions, then it
|
454
|
+
* need not register for this event. If, however, a client is
|
455
|
+
* modifying application code or is adding code that can fault, the
|
456
|
+
* client must be capable of restoring the original context.
|
457
|
+
*
|
458
|
+
* When DR needs to translate a code cache context, DR recreates the
|
459
|
+
* faulting instruction's containing fragment, storing translation
|
460
|
+
* information along the way, by calling the basic block and/or trace event
|
461
|
+
* callbacks with the \p translating parameter set to true. DR uses the
|
462
|
+
* recreated code to identify the application instruction (\p mcontext.pc)
|
463
|
+
* corresponding to the faulting code cache instruction. If the client
|
464
|
+
* asked to store translation information by returning
|
465
|
+
* #DR_EMIT_STORE_TRANSLATIONS from the basic block or trace event
|
466
|
+
* callback, then this step of re-calling the event callback is skipped and
|
467
|
+
* the stored value is used as the application address (\p mcontext.pc).
|
468
|
+
*
|
469
|
+
* DR then calls the fault state restoration event to allow the client
|
470
|
+
* to restore the registers and application memory to their proper
|
471
|
+
* values as they would have appeared if the original application code
|
472
|
+
* had been executed up to the \p mcontext.pc instruction. Memory
|
473
|
+
* should only be restored if the \p restore_memory parameter is true;
|
474
|
+
* if it is false, DR may only be querying for the address (\p
|
475
|
+
* mcontext.pc) or register state and may not relocate this thread.
|
476
|
+
*
|
477
|
+
* The \p app_code_consistent parameter indicates whether the original
|
478
|
+
* application code containing the instruction being translated is
|
479
|
+
* guaranteed to still be in the same state it was when the code was
|
480
|
+
* placed in the code cache. This guarantee varies depending on the
|
481
|
+
* type of cache consistency being used by DR.
|
482
|
+
*
|
483
|
+
* The client can update \p mcontext.pc in this callback.
|
484
|
+
*
|
485
|
+
* \note The passed-in \p drcontext may correspond to a different thread
|
486
|
+
* than the thread executing the callback. Do not assume that the
|
487
|
+
* executing thread is the target thread.
|
488
|
+
*/
|
489
|
+
void
|
490
|
+
dr_register_restore_state_event(void (*func)
|
491
|
+
(void *drcontext, void *tag, dr_mcontext_t *mcontext,
|
492
|
+
bool restore_memory, bool app_code_consistent));
|
493
|
+
|
494
|
+
/**
|
495
|
+
* Unregister a callback function for the machine state restoration event.
|
496
|
+
* \return true if unregistration is successful and false if it is not
|
497
|
+
* (e.g., \p func was not registered).
|
498
|
+
*/
|
499
|
+
bool
|
500
|
+
dr_unregister_restore_state_event(void (*func)
|
501
|
+
(void *drcontext, void *tag, dr_mcontext_t *mcontext,
|
502
|
+
bool restore_memory, bool app_code_consistent));
|
503
|
+
/**
|
504
|
+
* Data structure passed within dr_exception_t, dr_siginfo_t, and
|
505
|
+
* dr_restore_state_info_t.
|
506
|
+
* Contains information about the code fragment inside the code cache
|
507
|
+
* at the exception/signal/translation interruption point.
|
508
|
+
*/
|
509
|
+
typedef struct _dr_fault_fragment_info_t {
|
510
|
+
/**
|
511
|
+
* The tag of the code fragment inside the code cache at the
|
512
|
+
* exception/signal/translation interruption point. NULL for
|
513
|
+
* interruption not in the code cache.
|
514
|
+
*/
|
515
|
+
void *tag;
|
516
|
+
/**
|
517
|
+
* The start address of the code fragment inside the code cache at
|
518
|
+
* the exception/signal/translation interruption point. NULL for interruption
|
519
|
+
* not in the code cache. Clients are cautioned when examining
|
520
|
+
* code cache instructions to not rely on any details of code
|
521
|
+
* inserted other than their own.
|
522
|
+
*/
|
523
|
+
byte *cache_start_pc;
|
524
|
+
/** Indicates whether the interrupted code fragment is a trace */
|
525
|
+
bool is_trace;
|
526
|
+
/**
|
527
|
+
* Indicates whether the original application code containing the
|
528
|
+
* code corresponding to the exception/signal/translation interruption point
|
529
|
+
* is guaranteed to still be in the same state it was when the
|
530
|
+
* code was placed in the code cache. This guarantee varies
|
531
|
+
* depending on the type of cache consistency being used by DR.
|
532
|
+
*/
|
533
|
+
bool app_code_consistent;
|
534
|
+
} dr_fault_fragment_info_t;
|
535
|
+
|
536
|
+
/**
|
537
|
+
* Data structure passed to a restore_state_ex event handler (see
|
538
|
+
* dr_register_restore_state_ex_event()). Contains the machine
|
539
|
+
* context at the translation point and other translation
|
540
|
+
* information.
|
541
|
+
*/
|
542
|
+
typedef struct _dr_restore_state_info_t {
|
543
|
+
/** The application machine state at the translation point. */
|
544
|
+
dr_mcontext_t *mcontext;
|
545
|
+
/** Whether raw_mcontext is valid. */
|
546
|
+
bool raw_mcontext_valid;
|
547
|
+
/**
|
548
|
+
* The raw pre-translated machine state at the translation
|
549
|
+
* interruption point inside the code cache. Clients are
|
550
|
+
* cautioned when examining code cache instructions to not rely on
|
551
|
+
* any details of code inserted other than their own.
|
552
|
+
*/
|
553
|
+
dr_mcontext_t raw_mcontext;
|
554
|
+
/**
|
555
|
+
* Information about the code fragment inside the code cache
|
556
|
+
* at the translation interruption point.
|
557
|
+
*/
|
558
|
+
dr_fault_fragment_info_t fragment_info;
|
559
|
+
} dr_restore_state_info_t;
|
560
|
+
|
561
|
+
|
562
|
+
/**
|
563
|
+
* Registers a callback function for the machine state restoration
|
564
|
+
* event with extended information.
|
565
|
+
*
|
566
|
+
* This event is identical to that for dr_register_restore_state_event()
|
567
|
+
* with the following exceptions:
|
568
|
+
*
|
569
|
+
* - Additional information is provided in the
|
570
|
+
* dr_restore_state_info_t structure, including the pre-translation
|
571
|
+
* context (containing the address inside the code cache of the
|
572
|
+
* translation point) and the starting address of the containing
|
573
|
+
* fragment in the code cache. Certain registers may not contain
|
574
|
+
* proper application values in \p info->raw_mcontext. Clients are
|
575
|
+
* cautioned against relying on any details of code cache layout or
|
576
|
+
* register usage beyond instrumentation inserted by the client
|
577
|
+
* itself when examining \p info->raw_mcontext.
|
578
|
+
*
|
579
|
+
* - The callback function returns a boolean indicating the success of
|
580
|
+
* the translation. When DR is translating not for a fault but for
|
581
|
+
* thread relocation, the \p restore_memory parameter will be false.
|
582
|
+
* Such translation can target a meta-instruction that can fault
|
583
|
+
* (see instr_set_meta_may_fault()). For that scenario, a client
|
584
|
+
* can choose not to translate. Such instructions do not always
|
585
|
+
* require full translation for faults, and allowing translation
|
586
|
+
* failure removes the requirement that a client must translate at
|
587
|
+
* all such instructions. Note, however, that returning false can
|
588
|
+
* cause performance degradation as DR must then resume the thread
|
589
|
+
* and attempt to re-suspend it at a safer spot. Clients must
|
590
|
+
* return true for translation points in application code in order
|
591
|
+
* to avoid catastropic failure to suspend, and should thus identify
|
592
|
+
* whether translation points are inside their own instrumentation
|
593
|
+
* before returning false. Translation for relocation will never
|
594
|
+
* occur in meta instructions, so clients only need to look for
|
595
|
+
* meta-may-fault instructions. Clients should never return false
|
596
|
+
* when \p restore_memory is true.
|
597
|
+
*/
|
598
|
+
void
|
599
|
+
dr_register_restore_state_ex_event(bool (*func) (void *drcontext, bool restore_memory,
|
600
|
+
dr_restore_state_info_t *info));
|
601
|
+
|
602
|
+
/**
|
603
|
+
* Unregister a callback function for the machine state restoration
|
604
|
+
* event with extended ifnormation. \return true if unregistration is
|
605
|
+
* successful and false if it is not (e.g., \p func was not
|
606
|
+
* registered).
|
607
|
+
*/
|
608
|
+
bool
|
609
|
+
dr_unregister_restore_state_ex_event(bool (*func) (void *drcontext, bool restore_memory,
|
610
|
+
dr_restore_state_info_t *info));
|
611
|
+
|
612
|
+
/**
|
613
|
+
* Registers a callback function for the thread initialization event.
|
614
|
+
* DR calls \p func whenever the application creates a new thread.
|
615
|
+
*/
|
616
|
+
void
|
617
|
+
dr_register_thread_init_event(void (*func)(void *drcontext));
|
618
|
+
|
619
|
+
/**
|
620
|
+
* Unregister a callback function for the thread initialization event.
|
621
|
+
* \return true if unregistration is successful and false if it is not
|
622
|
+
* (e.g., \p func was not registered).
|
623
|
+
*/
|
624
|
+
bool
|
625
|
+
dr_unregister_thread_init_event(void (*func)(void *drcontext));
|
626
|
+
|
627
|
+
/**
|
628
|
+
* Registers a callback function for the thread exit event. DR calls
|
629
|
+
* \p func whenever an application thread exits.
|
630
|
+
*/
|
631
|
+
void
|
632
|
+
dr_register_thread_exit_event(void (*func)(void *drcontext));
|
633
|
+
|
634
|
+
/**
|
635
|
+
* Unregister a callback function for the thread exit event.
|
636
|
+
* \return true if unregistration is successful and false if it is not
|
637
|
+
* (e.g., \p func was not registered).
|
638
|
+
*/
|
639
|
+
bool
|
640
|
+
dr_unregister_thread_exit_event(void (*func)(void *drcontext));
|
641
|
+
|
642
|
+
/**
|
643
|
+
* Registers a callback function for the fork event. DR calls \p func
|
644
|
+
* whenever the application forks a new process.
|
645
|
+
* \note Valid on Linux only.
|
646
|
+
*/
|
647
|
+
void
|
648
|
+
dr_register_fork_init_event(void (*func)(void *drcontext));
|
649
|
+
|
650
|
+
/**
|
651
|
+
* Unregister a callback function for the fork event.
|
652
|
+
* \return true if unregistration is successful and false if it is not
|
653
|
+
* (e.g., \p func was not registered).
|
654
|
+
*/
|
655
|
+
bool
|
656
|
+
dr_unregister_fork_init_event(void (*func)(void *drcontext));
|
657
|
+
|
658
|
+
/**
|
659
|
+
* Registers a callback function for the module load event. DR calls
|
660
|
+
* \p func whenever the application loads a module. The \p loaded
|
661
|
+
* parameter indicates whether the module is about to be loaded (the
|
662
|
+
* normal case) or is already loaded (if the module was already there
|
663
|
+
* at the time DR initialized). \note The client should be aware that
|
664
|
+
* if the module is being loaded it may not be fully processed by the
|
665
|
+
* loader (relocating, rebinding and on Linux segment remapping may
|
666
|
+
* have not yet occured). \note The module_data_t \p *info passed
|
667
|
+
* to the callback routine is valid only for the duration of the
|
668
|
+
* callback and should not be freed; a persistent copy can be made with
|
669
|
+
* dr_copy_module_data().
|
670
|
+
*/
|
671
|
+
void
|
672
|
+
dr_register_module_load_event(void (*func)(void *drcontext, const module_data_t *info,
|
673
|
+
bool loaded));
|
674
|
+
|
675
|
+
/**
|
676
|
+
* Unregister a callback for the module load event.
|
677
|
+
* \return true if unregistration is successful and false if it is not
|
678
|
+
* (e.g., \p func was not registered).
|
679
|
+
*/
|
680
|
+
bool
|
681
|
+
dr_unregister_module_load_event(void (*func)(void *drcontext, const module_data_t *info,
|
682
|
+
bool loaded));
|
683
|
+
|
684
|
+
/**
|
685
|
+
* Registers a callback function for the module unload event. DR
|
686
|
+
* calls \p func whenever the application unloads a module.
|
687
|
+
* \note The module_data_t \p *info passed to
|
688
|
+
* the callback routine is valid only for the duration of the callback
|
689
|
+
* and should not be freed; a persistent copy can be made with
|
690
|
+
* dr_copy_module_data().
|
691
|
+
*/
|
692
|
+
void
|
693
|
+
dr_register_module_unload_event(void (*func)(void *drcontext,
|
694
|
+
const module_data_t *info));
|
695
|
+
|
696
|
+
/**
|
697
|
+
* Unregister a callback function for the module unload event.
|
698
|
+
* \return true if unregistration is successful and false if it is not
|
699
|
+
* (e.g., \p func was not registered).
|
700
|
+
*/
|
701
|
+
bool
|
702
|
+
dr_unregister_module_unload_event(void (*func)(void *drcontext,
|
703
|
+
const module_data_t *info));
|
704
|
+
#ifdef WINDOWS
|
705
|
+
|
706
|
+
/**
|
707
|
+
* Data structure passed with an exception event. Contains the
|
708
|
+
* machine context and the Win32 exception record.
|
709
|
+
*/
|
710
|
+
typedef struct _dr_exception_t {
|
711
|
+
dr_mcontext_t mcontext; /**< Machine context at exception point. */
|
712
|
+
EXCEPTION_RECORD *record; /**< Win32 exception record. */
|
713
|
+
/**
|
714
|
+
* The raw pre-translated machine state at the exception interruption
|
715
|
+
* point inside the code cache. Clients are cautioned when examining
|
716
|
+
* code cache instructions to not rely on any details of code inserted
|
717
|
+
* other than their own.
|
718
|
+
*/
|
719
|
+
ALIGN_VAR(8)/*avoid differences in padding*/
|
720
|
+
dr_mcontext_t raw_mcontext;
|
721
|
+
/**
|
722
|
+
* Information about the code fragment inside the code cache at
|
723
|
+
* the exception interruption point.
|
724
|
+
*/
|
725
|
+
dr_fault_fragment_info_t fault_fragment_info;
|
726
|
+
} dr_exception_t;
|
727
|
+
|
728
|
+
|
729
|
+
/**
|
730
|
+
* Registers a callback function for the exception event. DR calls \p func
|
731
|
+
* whenever the application throws an exception. If \p func returns true,
|
732
|
+
* the exception is delivered to the application's handler along with any
|
733
|
+
* changes made to \p excpt->mcontext. If \p func returns false, the
|
734
|
+
* faulting instruction in the code cache is re-executed using \p
|
735
|
+
* excpt->raw_mcontext, including any changes made to that structure.
|
736
|
+
* Clients are expected to use \p excpt->raw_mcontext when using faults as
|
737
|
+
* a mechanism to push rare cases out of an instrumentation fastpath that
|
738
|
+
* need to examine instrumentation instructions rather than the translated
|
739
|
+
* application state and should normally not examine it for application
|
740
|
+
* instruction faults. Certain registers may not contain proper
|
741
|
+
* application values in \p excpt->raw_mcontext for exceptions in
|
742
|
+
* application instructions. Clients are cautioned against relying on any
|
743
|
+
* details of code cache layout or register usage beyond instrumentation
|
744
|
+
* inserted by the client itself when examining \p excpt->raw_mcontext.
|
745
|
+
*
|
746
|
+
* DR raises this event for exceptions outside the code cache that
|
747
|
+
* could come from code generated by a client. For such exceptions,
|
748
|
+
* mcontext is not translated and is identical to raw_mcontext.
|
749
|
+
*
|
750
|
+
* To skip the passing of the exception to the application's exception
|
751
|
+
* handlers and to send control elsewhere instead, a client can call
|
752
|
+
* dr_redirect_execution() from \p func.
|
753
|
+
*
|
754
|
+
* \note \p excpt->fault_fragment_info data is provided with
|
755
|
+
* \p excpt->raw_mcontext. It is valid only if
|
756
|
+
* \p excpt->fault_fragment_info.cache_start_pc is not \p NULL.
|
757
|
+
* It provides clients information about the code fragment being
|
758
|
+
* executed at the exception interruption point. Clients are cautioned
|
759
|
+
* against relying on any details of code cache layout or register
|
760
|
+
* usage beyond instrumentation inserted by the client itself.
|
761
|
+
* \note Only valid on Windows.
|
762
|
+
* \note The function is not called for RaiseException.
|
763
|
+
*/
|
764
|
+
void
|
765
|
+
dr_register_exception_event(bool (*func)(void *drcontext, dr_exception_t *excpt));
|
766
|
+
|
767
|
+
/**
|
768
|
+
* Unregister a callback function for the exception event.
|
769
|
+
* \return true if unregistration is successful and false if it is not
|
770
|
+
* (e.g., \p func was not registered).
|
771
|
+
*/
|
772
|
+
bool
|
773
|
+
dr_unregister_exception_event(bool (*func)(void *drcontext, dr_exception_t *excpt));
|
774
|
+
#endif /* WINDOWS */
|
775
|
+
|
776
|
+
|
777
|
+
/**
|
778
|
+
* Registers a callback function for the syscall filter event. DR
|
779
|
+
* calls \p func to decide whether to invoke the syscall events for
|
780
|
+
* each system call site encountered with a statically-determinable
|
781
|
+
* system call number. If \p func returns true, the pre-syscall
|
782
|
+
* (dr_register_pre_syscall_event()) and post-syscall
|
783
|
+
* (dr_register_post_syscall_event()) events will be invoked.
|
784
|
+
* Otherwise, the events may or may not occur, depending on whether DR
|
785
|
+
* itself needs to intercept them and whether the system call number
|
786
|
+
* is statically determinable. System call number determination can
|
787
|
+
* depend on whether the -opt_speed option is enabled. If a system
|
788
|
+
* call number is not determinable, the filter event will not be
|
789
|
+
* called, but the pre and post events will be called.
|
790
|
+
*
|
791
|
+
* Intercepting every system call can be detrimental to performance
|
792
|
+
* for certain types of applications. Filtering provides for greater
|
793
|
+
* performance by letting uninteresting system calls execute without
|
794
|
+
* interception overhead.
|
795
|
+
*/
|
796
|
+
void
|
797
|
+
dr_register_filter_syscall_event(bool (*func)(void *drcontext, int sysnum));
|
798
|
+
|
799
|
+
/**
|
800
|
+
* Unregister a callback function for the syscall filter event.
|
801
|
+
* \return true if unregistration is successful and false if it is not
|
802
|
+
* (e.g., \p func was not registered).
|
803
|
+
*/
|
804
|
+
bool
|
805
|
+
dr_unregister_filter_syscall_event(bool (*func)(void *drcontext, int sysnum));
|
806
|
+
|
807
|
+
/**
|
808
|
+
* Registers a callback function for the pre-syscall event. DR calls
|
809
|
+
* \p func whenever the application is about to invoke a system call,
|
810
|
+
* if any client asked for that system call number to be intercepted
|
811
|
+
* via the filter event (dr_register_filter_syscall_event()).
|
812
|
+
*
|
813
|
+
* The application parameters to the system call can be viewed with
|
814
|
+
* dr_syscall_get_param() and set with dr_syscall_set_param(). The
|
815
|
+
* system call number can also be changed with
|
816
|
+
* dr_syscall_set_sysnum().
|
817
|
+
*
|
818
|
+
* The application's machine state can be accessed and set with
|
819
|
+
* dr_get_mcontext() and dr_set_mcontext(). Changing registers in
|
820
|
+
* this way overlaps with system call parameter changes on some
|
821
|
+
* platforms. On Linux, for SYS_clone, client changes to the ebp/rbp
|
822
|
+
* register will be ignored by the clone child.
|
823
|
+
*
|
824
|
+
* If \p func returns true, the application's system call is invoked
|
825
|
+
* normally; if \p func returns false, the system call is skipped. If
|
826
|
+
* it is skipped, the return value can be set with
|
827
|
+
* dr_syscall_set_result(). If the system call is skipped, there will
|
828
|
+
* not be a post-syscall event.
|
829
|
+
*/
|
830
|
+
void
|
831
|
+
dr_register_pre_syscall_event(bool (*func)(void *drcontext, int sysnum));
|
832
|
+
|
833
|
+
/**
|
834
|
+
* Unregister a callback function for the pre-syscall event.
|
835
|
+
* \return true if unregistration is successful and false if it is not
|
836
|
+
* (e.g., \p func was not registered).
|
837
|
+
*/
|
838
|
+
bool
|
839
|
+
dr_unregister_pre_syscall_event(bool (*func)(void *drcontext, int sysnum));
|
840
|
+
|
841
|
+
/**
|
842
|
+
* Registers a callback function for the post-syscall event. DR calls
|
843
|
+
* \p func whenever the application just finished invoking a system
|
844
|
+
* call, if any client asked for that system call number to be
|
845
|
+
* intercepted via the filter event
|
846
|
+
* (dr_register_filter_syscall_event()) or if DR itself needs to
|
847
|
+
* intercept the system call. The result of the system call can be
|
848
|
+
* modified with dr_syscall_set_result().
|
849
|
+
*
|
850
|
+
* System calls that change control flow or terminate the current
|
851
|
+
* thread or process typically do not have a post-syscall event.
|
852
|
+
* These include SYS_exit, SYS_exit_group, SYS_execve, SYS_sigreturn,
|
853
|
+
* and SYS_rt_sigreturn on Linux, and NtTerminateThread,
|
854
|
+
* NtTerminateProcess (depending on the parameters), NtCallbackReturn,
|
855
|
+
* and NtContinue on Windows.
|
856
|
+
*
|
857
|
+
* The application's machine state can be accessed and set with
|
858
|
+
* dr_get_mcontext() and dr_set_mcontext().
|
859
|
+
*
|
860
|
+
* Additional system calls may be invoked by calling
|
861
|
+
* dr_syscall_invoke_another() prior to returning from the
|
862
|
+
* post-syscall event callback. The system call to be invoked should
|
863
|
+
* be specified with dr_syscall_set_sysnum(), and its parameters can
|
864
|
+
* be set with dr_syscall_set_param().
|
865
|
+
*/
|
866
|
+
void
|
867
|
+
dr_register_post_syscall_event(void (*func)(void *drcontext, int sysnum));
|
868
|
+
|
869
|
+
/**
|
870
|
+
* Unregister a callback function for the post-syscall event.
|
871
|
+
* \return true if unregistration is successful and false if it is not
|
872
|
+
* (e.g., \p func was not registered).
|
873
|
+
*/
|
874
|
+
bool
|
875
|
+
dr_unregister_post_syscall_event(void (*func)(void *drcontext, int sysnum));
|
876
|
+
|
877
|
+
#ifdef LINUX
|
878
|
+
|
879
|
+
/**
|
880
|
+
* Data structure passed with a signal event. Contains the machine
|
881
|
+
* context at the signal interruption point and other signal
|
882
|
+
* information.
|
883
|
+
*/
|
884
|
+
typedef struct _dr_siginfo_t {
|
885
|
+
/** The signal number. */
|
886
|
+
int sig;
|
887
|
+
/** The context of the thread receiving the signal. */
|
888
|
+
void *drcontext;
|
889
|
+
/** The application machine state at the signal interruption point. */
|
890
|
+
dr_mcontext_t mcontext;
|
891
|
+
/**
|
892
|
+
* The raw pre-translated machine state at the signal interruption
|
893
|
+
* point inside the code cache. NULL for delayable signals. Clients
|
894
|
+
* are cautioned when examining code cache instructions to not rely on
|
895
|
+
* any details of code inserted other than their own.
|
896
|
+
*/
|
897
|
+
dr_mcontext_t raw_mcontext;
|
898
|
+
/** Whether raw_mcontext is valid. */
|
899
|
+
bool raw_mcontext_valid;
|
900
|
+
/**
|
901
|
+
* For SIGBUS and SIGSEGV, the address whose access caused the signal
|
902
|
+
* to be raised (as calculated by DR).
|
903
|
+
*/
|
904
|
+
byte *access_address;
|
905
|
+
/**
|
906
|
+
* Indicates this signal is blocked. DR_SIGNAL_BYPASS is not allowed,
|
907
|
+
* and a second event will be sent if the signal is later delivered to
|
908
|
+
* the application. Events are only sent for blocked non-delayable signals,
|
909
|
+
* not for delayable signals.
|
910
|
+
*/
|
911
|
+
bool blocked;
|
912
|
+
/**
|
913
|
+
* Information about the code fragment inside the code cache
|
914
|
+
* at the signal interruption point.
|
915
|
+
*/
|
916
|
+
dr_fault_fragment_info_t fault_fragment_info;
|
917
|
+
} dr_siginfo_t;
|
918
|
+
|
919
|
+
/**
|
920
|
+
* Return value of client signal event callback, determining how DR will
|
921
|
+
* proceed with the signal.
|
922
|
+
*/
|
923
|
+
typedef enum {
|
924
|
+
/** Deliver signal to the application as normal. */
|
925
|
+
DR_SIGNAL_DELIVER,
|
926
|
+
/** Suppress signal as though it never happened. */
|
927
|
+
DR_SIGNAL_SUPPRESS,
|
928
|
+
/**
|
929
|
+
* Deliver signal according to the default SIG_DFL action, as would
|
930
|
+
* happen if the application had no handler.
|
931
|
+
*/
|
932
|
+
DR_SIGNAL_BYPASS,
|
933
|
+
/**
|
934
|
+
* Do not deliver the signal. Instead, redirect control to the
|
935
|
+
* application state specified in dr_siginfo_t.mcontext.
|
936
|
+
*/
|
937
|
+
DR_SIGNAL_REDIRECT,
|
938
|
+
} dr_signal_action_t;
|
939
|
+
|
940
|
+
|
941
|
+
/**
|
942
|
+
* Requests that DR call the provided callback function \p func whenever a
|
943
|
+
* signal is received by any application thread. The return value of \p
|
944
|
+
* func determines whether DR delivers the signal to the application.
|
945
|
+
* To redirect execution return DR_SIGNAL_REDIRECT (do not call
|
946
|
+
* dr_redirect_execution() from a signal callback). The callback function
|
947
|
+
* will be called even if the application has no handler or has registered
|
948
|
+
* a SIG_IGN or SIG_DFL handler.
|
949
|
+
*
|
950
|
+
* Modifications to the fields of \p siginfo->mcontext will be propagated
|
951
|
+
* to the application if it has a handler for the signal, if
|
952
|
+
* DR_SIGNAL_DELIVER is returned.
|
953
|
+
*
|
954
|
+
* The \p siginfo->raw_mcontext data is only provided for non-delayable
|
955
|
+
* signals (e.g., SIGSEGV) that must be delivered immediately. Whether it
|
956
|
+
* is supplied is specified in \p siginfo->raw_mcontext_valid. It is
|
957
|
+
* intended for clients using faults as a mechanism to push rare cases out
|
958
|
+
* of an instrumentation fastpath that need to examine instrumentation
|
959
|
+
* instructions rather than the translated application state. Certain
|
960
|
+
* registers may not contain proper application values in \p
|
961
|
+
* excpt->raw_mcontext for exceptions in application instructions. Clients
|
962
|
+
* are cautioned against relying on any details of code cache layout or
|
963
|
+
* register usage beyond instrumentation inserted by the client itself. If
|
964
|
+
* DR_SIGNAL_SUPPRESS is returned, \p siginfo->mcontext is ignored and \p
|
965
|
+
* siginfo->raw_mcontext is used as the resumption context. The client's
|
966
|
+
* changes to \p siginfo->raw_mcontext will take effect.
|
967
|
+
*
|
968
|
+
* For a delayable signal, DR raises a signal event only when about to
|
969
|
+
* deliver the signal to the application. Thus, if the application has
|
970
|
+
* blocked a delayable signal, the corresponding signal event will not
|
971
|
+
* occur until the application unblocks the signal, even if such a signal
|
972
|
+
* is delivered by the kernel. For non-delayable signals, DR will raise a
|
973
|
+
* signal event on initial receipt of the signal, with the \p
|
974
|
+
* siginfo->blocked field set. Such a blocked signal will have a second
|
975
|
+
* event raised when it is delivered to the application (if it is not
|
976
|
+
* suppressed by the client, and if there is not already a pending blocked
|
977
|
+
* signal, for non-real-time signals).
|
978
|
+
*
|
979
|
+
* DR raises this event for faults outside the code cache that
|
980
|
+
* could come from code generated by a client. For such cases,
|
981
|
+
* mcontext is not translated and is identical to raw_mcontext.
|
982
|
+
*
|
983
|
+
* DR will not raise a signal event for a SIGSEGV or SIGBUS
|
984
|
+
* raised by a client code fault rather than the application. Use
|
985
|
+
* dr_safe_read() or dr_safe_write() to prevent such faults.
|
986
|
+
*
|
987
|
+
* \note \p siginfo->fault_fragment_info data is provided
|
988
|
+
* with \p siginfo->raw_mcontext. It is valid only if
|
989
|
+
* \p siginfo->fault_fragment_info.cache_start_pc is not
|
990
|
+
* \p NULL. It provides clients information about the code fragment
|
991
|
+
* being executed at the signal interruption point. Clients are
|
992
|
+
* cautioned against relying on any details of code cache layout or
|
993
|
+
* register usage beyond instrumentation inserted by the client
|
994
|
+
* itself.
|
995
|
+
*
|
996
|
+
* \note Only valid on Linux.
|
997
|
+
*
|
998
|
+
* \note DR always requests SA_SIGINFO for all signals.
|
999
|
+
*
|
1000
|
+
* \note This version of DR does not intercept the signals SIGCONT,
|
1001
|
+
* SIGSTOP, SIGTSTP, SIGTTIN, or SIGTTOU. Future versions should add
|
1002
|
+
* support for these signals.
|
1003
|
+
*
|
1004
|
+
* \note If the client uses signals for its own communication it should set
|
1005
|
+
* a flag to distinguish its own uses of signals from the application's
|
1006
|
+
* use. Races where the two are re-ordered should not be problematic.
|
1007
|
+
*/
|
1008
|
+
void
|
1009
|
+
dr_register_signal_event(dr_signal_action_t (*func)
|
1010
|
+
(void *drcontext, dr_siginfo_t *siginfo));
|
1011
|
+
|
1012
|
+
/**
|
1013
|
+
* Unregister a callback function for the signal event.
|
1014
|
+
* \return true if unregistration is successful and false if it is not
|
1015
|
+
* (e.g., \p func was not registered).
|
1016
|
+
*/
|
1017
|
+
bool
|
1018
|
+
dr_unregister_signal_event(dr_signal_action_t (*func)
|
1019
|
+
(void *drcontext, dr_siginfo_t *siginfo));
|
1020
|
+
#endif /* LINUX */
|
1021
|
+
|
1022
|
+
|
1023
|
+
/**
|
1024
|
+
* Registers a callback function for nudge events. External entities
|
1025
|
+
* can nudge a process through the dr_nudge_process() API routine on
|
1026
|
+
* Windows or using the \p nudgeunix tool on Linux. DR then calls \p
|
1027
|
+
* func whenever the current process receives the nudge. On Windows,
|
1028
|
+
* the nudge event is delivered in a new non-application thread.
|
1029
|
+
* Callers must specify the target client by passing the client ID
|
1030
|
+
* that was provided in dr_init().
|
1031
|
+
*/
|
1032
|
+
void
|
1033
|
+
dr_register_nudge_event(void (*func)(void *drcontext, uint64 argument), client_id_t id);
|
1034
|
+
|
1035
|
+
/**
|
1036
|
+
* Unregister a callback function for the nudge event.
|
1037
|
+
* \return true if unregistration is successful and false if it is not
|
1038
|
+
* (e.g., \p func was not registered).
|
1039
|
+
*/
|
1040
|
+
bool
|
1041
|
+
dr_unregister_nudge_event(void (*func)(void *drcontext, uint64 argument), client_id_t id);
|
1042
|
+
|
1043
|
+
/**
|
1044
|
+
* Triggers an asynchronous nudge event in the current process. The callback
|
1045
|
+
* function registered with dr_register_nudge_event() will be called with the
|
1046
|
+
* supplied \p argument (in a new non-application thread on Windows).
|
1047
|
+
*
|
1048
|
+
* \note On Linux, the nudge will not be delivered until this thread exits
|
1049
|
+
* the code cache. Thus, if this routine is called from a clean call,
|
1050
|
+
* dr_redirect_execution() should be used to ensure cache exit.
|
1051
|
+
*
|
1052
|
+
* \note Not yet supported for 32-bit processes running on 64-bit Windows (WOW64).
|
1053
|
+
*/
|
1054
|
+
bool
|
1055
|
+
dr_nudge_client(client_id_t id, uint64 argument);
|
1056
|
+
|
1057
|
+
#endif /* _DR_EVENTS_H_ */
|