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,708 @@
|
|
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_IR_UTILS_H_
|
34
|
+
#define _DR_IR_UTILS_H_ 1
|
35
|
+
|
36
|
+
#ifdef X64
|
37
|
+
|
38
|
+
|
39
|
+
/**
|
40
|
+
* The decode and encode routines use a per-thread persistent flag that
|
41
|
+
* indicates whether to treat code as 32-bit (x86) or 64-bit (x64). This
|
42
|
+
* routine sets that flag to the indicated value and returns the old value. Be
|
43
|
+
* sure to restore the old value prior to any further application execution to
|
44
|
+
* avoid problems in mis-interpreting application code.
|
45
|
+
*
|
46
|
+
* \note For 64-bit DR builds only.
|
47
|
+
*/
|
48
|
+
bool
|
49
|
+
set_x86_mode(void *drcontext, bool x86);
|
50
|
+
|
51
|
+
/**
|
52
|
+
* The decode and encode routines use a per-thread persistent flag that
|
53
|
+
* indicates whether to treat code as 32-bit (x86) or 64-bit (x64). This
|
54
|
+
* routine returns the value of that flag.
|
55
|
+
*
|
56
|
+
* \note For 64-bit DR builds only.
|
57
|
+
*/
|
58
|
+
bool
|
59
|
+
get_x86_mode(void *drcontext);
|
60
|
+
#endif
|
61
|
+
|
62
|
+
|
63
|
+
/**************************************************
|
64
|
+
* CODE TRANSFORMATION UTILITIES
|
65
|
+
*/
|
66
|
+
/**
|
67
|
+
* @file dr_ir_utils.h
|
68
|
+
* @brief Code transformation utilities.
|
69
|
+
*/
|
70
|
+
|
71
|
+
/**
|
72
|
+
* An enum of spill slots to use with dr_save_reg(), dr_restore_reg(),
|
73
|
+
* dr_save_arith_flags(), dr_restore_arith_flags() and
|
74
|
+
* dr_insert_mbr_instrumentation(). Values stored in spill slots remain
|
75
|
+
* valid only until the next non-meta (i.e. application) instruction. Spill slots
|
76
|
+
* can be accessed/modifed during clean calls and restore_state_events (see
|
77
|
+
* dr_register_restore_state_event()) with dr_read_saved_reg() and
|
78
|
+
* dr_write_saved_reg().
|
79
|
+
*
|
80
|
+
* Spill slots <= dr_max_opnd_accessible_spill_slot() can be directly accessed
|
81
|
+
* from client inserted instructions with dr_reg_spill_slot_opnd().
|
82
|
+
*
|
83
|
+
* \note Some spill slots may be faster to access than others. Currently spill
|
84
|
+
* slots 1-3 are significantly faster to access than the others when running
|
85
|
+
* without -thread_private. When running with -thread_private all spill slots
|
86
|
+
* are expected to have similar performance. This is subject to change in future
|
87
|
+
* releases, but clients may assume that smaller numbered spill slots are faster
|
88
|
+
* or the same cost to access as larger numbered spill slots.
|
89
|
+
*
|
90
|
+
* \note The number of spill slots may change in future releases.
|
91
|
+
*/
|
92
|
+
typedef enum {
|
93
|
+
SPILL_SLOT_1 = 0, /** spill slot for register save/restore routines */
|
94
|
+
SPILL_SLOT_2 = 1, /** spill slot for register save/restore routines */
|
95
|
+
SPILL_SLOT_3 = 2, /** spill slot for register save/restore routines */
|
96
|
+
SPILL_SLOT_4 = 3, /** spill slot for register save/restore routines */
|
97
|
+
SPILL_SLOT_5 = 4, /** spill slot for register save/restore routines */
|
98
|
+
SPILL_SLOT_6 = 5, /** spill slot for register save/restore routines */
|
99
|
+
SPILL_SLOT_7 = 6, /** spill slot for register save/restore routines */
|
100
|
+
SPILL_SLOT_8 = 7, /** spill slot for register save/restore routines */
|
101
|
+
SPILL_SLOT_9 = 8, /** spill slot for register save/restore routines */
|
102
|
+
#ifdef X64
|
103
|
+
SPILL_SLOT_10 = 9, /** spill slot for register save/restore routines
|
104
|
+
* \note x64 only */
|
105
|
+
SPILL_SLOT_11 = 10, /** spill slot for register save/restore routines
|
106
|
+
* \note x64 only */
|
107
|
+
SPILL_SLOT_12 = 11, /** spill slot for register save/restore routines
|
108
|
+
* \note x64 only */
|
109
|
+
SPILL_SLOT_13 = 12, /** spill slot for register save/restore routines
|
110
|
+
* \note x64 only */
|
111
|
+
SPILL_SLOT_14 = 13, /** spill slot for register save/restore routines
|
112
|
+
* \note x64 only */
|
113
|
+
SPILL_SLOT_15 = 14, /** spill slot for register save/restore routines
|
114
|
+
* \note x64 only */
|
115
|
+
SPILL_SLOT_16 = 15, /** spill slot for register save/restore routines
|
116
|
+
* \note x64 only */
|
117
|
+
SPILL_SLOT_17 = 16, /** spill slot for register save/restore routines
|
118
|
+
* \note x64 only */
|
119
|
+
SPILL_SLOT_MAX = SPILL_SLOT_17 /** Enum value of the last register save/restore
|
120
|
+
* spill slot. */
|
121
|
+
#else
|
122
|
+
SPILL_SLOT_MAX = SPILL_SLOT_9 /** Enum value of the last register save/restore
|
123
|
+
* spill slot. */
|
124
|
+
#endif
|
125
|
+
} dr_spill_slot_t;
|
126
|
+
|
127
|
+
|
128
|
+
/**
|
129
|
+
* Inserts into \p ilist prior to \p where meta-instruction(s) to save the
|
130
|
+
* register \p reg in the spill slot \p slot. See dr_restore_reg(). Use
|
131
|
+
* dr_read_saved_reg() and dr_write_saved_reg() to access spill slots from clean
|
132
|
+
* calls and restore_state_events (see dr_register_restore_state_event()).
|
133
|
+
* \note The stored value remains available only until the next non-meta (i.e.
|
134
|
+
* application) instruction. Use dr_insert_write_tls_field() and
|
135
|
+
* dr_insert_read_tls_field() for a persistent (but more costly to access)
|
136
|
+
* thread-local-storage location. See also dr_raw_tls_calloc().
|
137
|
+
*/
|
138
|
+
void
|
139
|
+
dr_save_reg(void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg,
|
140
|
+
dr_spill_slot_t slot);
|
141
|
+
|
142
|
+
/**
|
143
|
+
* Inserts into \p ilist prior to \p where meta-instruction(s) to restore the
|
144
|
+
* register \p reg from the spill slot \p slot. See dr_save_reg() for notes on
|
145
|
+
* lifetime and alternative access to spill slots.
|
146
|
+
*/
|
147
|
+
void
|
148
|
+
dr_restore_reg(void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg,
|
149
|
+
dr_spill_slot_t slot);
|
150
|
+
|
151
|
+
/**
|
152
|
+
* Returns the largest dr_spill_slot_t that can be accessed with an opnd_t from
|
153
|
+
* dr_reg_spill_slot_opnd().
|
154
|
+
*/
|
155
|
+
dr_spill_slot_t
|
156
|
+
dr_max_opnd_accessible_spill_slot(void);
|
157
|
+
|
158
|
+
/**
|
159
|
+
* Returns an opnd_t that directly accesses the spill slot \p slot. Only slots
|
160
|
+
* <= dr_max_opnd_accessible_spill_slot() can be used with this routine.
|
161
|
+
* \note \p slot must be <= dr_max_opnd_accessible_spill_slot()
|
162
|
+
*/
|
163
|
+
opnd_t
|
164
|
+
dr_reg_spill_slot_opnd(void *drcontext, dr_spill_slot_t slot);
|
165
|
+
|
166
|
+
/**
|
167
|
+
* Can be used from a clean call or a restore_state_event (see
|
168
|
+
* dr_register_restore_state_event()) to see the value saved in spill slot
|
169
|
+
* \p slot by dr_save_reg().
|
170
|
+
*/
|
171
|
+
reg_t
|
172
|
+
dr_read_saved_reg(void *drcontext, dr_spill_slot_t slot);
|
173
|
+
|
174
|
+
/**
|
175
|
+
* Can be used from a clean call to modify the value saved in the spill slot
|
176
|
+
* \p slot by dr_save_reg() such that a later dr_restore_reg() will see the
|
177
|
+
* new value.
|
178
|
+
*
|
179
|
+
* \note This routine should only be used during a clean call out of the
|
180
|
+
* cache. Use at any other time could corrupt application or \DynamoRIO
|
181
|
+
* state.
|
182
|
+
*/
|
183
|
+
void
|
184
|
+
dr_write_saved_reg(void *drcontext, dr_spill_slot_t slot, reg_t value);
|
185
|
+
|
186
|
+
/**
|
187
|
+
* Inserts into \p ilist prior to \p where meta-instruction(s) to save the 6
|
188
|
+
* arithmetic flags into xax after first saving xax to the spill slot \p slot.
|
189
|
+
* This is equivalent to dr_save_reg() of xax to \p slot followed by lahf and
|
190
|
+
* seto al instructions. See dr_restore_arith_flags().
|
191
|
+
*
|
192
|
+
* \note At completion of the inserted instructions the saved flags are in the
|
193
|
+
* xax register. The xax register should not be modified after using this
|
194
|
+
* routine unless it is first saved (and later restored prior to
|
195
|
+
* using dr_restore_arith_flags()).
|
196
|
+
*/
|
197
|
+
void
|
198
|
+
dr_save_arith_flags(void *drcontext, instrlist_t *ilist, instr_t *where,
|
199
|
+
dr_spill_slot_t slot);
|
200
|
+
|
201
|
+
/**
|
202
|
+
* Inserts into \p ilist prior to \p where meta-instruction(s) to restore the 6
|
203
|
+
* arithmetic flags, assuming they were saved using dr_save_arith_flags() with
|
204
|
+
* slot \p slot and that xax holds the same value it did after the save.
|
205
|
+
*/
|
206
|
+
void
|
207
|
+
dr_restore_arith_flags(void *drcontext, instrlist_t *ilist, instr_t *where,
|
208
|
+
dr_spill_slot_t slot);
|
209
|
+
|
210
|
+
/**
|
211
|
+
* Inserts into \p ilist prior to \p where meta-instruction(s) to read into the
|
212
|
+
* general-purpose full-size register \p reg from the user-controlled drcontext
|
213
|
+
* field for this thread. Reads from the same field as dr_get_tls_field().
|
214
|
+
*/
|
215
|
+
void
|
216
|
+
dr_insert_read_tls_field(void *drcontext, instrlist_t *ilist, instr_t *where,
|
217
|
+
reg_id_t reg);
|
218
|
+
|
219
|
+
/**
|
220
|
+
* Inserts into \p ilist prior to \p where meta-instruction(s) to write the
|
221
|
+
* general-purpose full-size register \p reg to the user-controlled drcontext field
|
222
|
+
* for this thread. Writes to the same field as dr_set_tls_field().
|
223
|
+
*/
|
224
|
+
void
|
225
|
+
dr_insert_write_tls_field(void *drcontext, instrlist_t *ilist, instr_t *where,
|
226
|
+
reg_id_t reg);
|
227
|
+
|
228
|
+
/** Inserts \p instr as a non-application instruction into \p ilist prior to \p where. */
|
229
|
+
void
|
230
|
+
instrlist_meta_preinsert(instrlist_t *ilist, instr_t *where, instr_t *instr);
|
231
|
+
|
232
|
+
/** Inserts \p instr as a non-application instruction into \p ilist after \p where. */
|
233
|
+
void
|
234
|
+
instrlist_meta_postinsert(instrlist_t *ilist, instr_t *where, instr_t *instr);
|
235
|
+
|
236
|
+
/** Inserts \p instr as a non-application instruction onto the end of \p ilist */
|
237
|
+
void
|
238
|
+
instrlist_meta_append(instrlist_t *ilist, instr_t *instr);
|
239
|
+
|
240
|
+
/**
|
241
|
+
* Inserts \p instr as a non-application instruction that can fault (see
|
242
|
+
* instr_set_meta_may_fault()) into \p ilist prior to \p where.
|
243
|
+
*/
|
244
|
+
void
|
245
|
+
instrlist_meta_fault_preinsert(instrlist_t *ilist, instr_t *where, instr_t *instr);
|
246
|
+
|
247
|
+
/**
|
248
|
+
* Inserts \p instr as a non-application instruction that can fault (see
|
249
|
+
* instr_set_meta_may_fault()) into \p ilist after \p where.
|
250
|
+
*/
|
251
|
+
void
|
252
|
+
instrlist_meta_fault_postinsert(instrlist_t *ilist, instr_t *where, instr_t *instr);
|
253
|
+
|
254
|
+
/**
|
255
|
+
* Inserts \p instr as a non-application instruction that can fault (see
|
256
|
+
* instr_set_meta_may_fault()) onto the end of \p ilist.
|
257
|
+
*/
|
258
|
+
void
|
259
|
+
instrlist_meta_fault_append(instrlist_t *ilist, instr_t *instr);
|
260
|
+
|
261
|
+
/**
|
262
|
+
* Inserts into \p ilist prior to \p where meta-instruction(s) to save state
|
263
|
+
* for a call, switch to this thread's DR stack, set up the passed-in
|
264
|
+
* parameters, make a call to \p callee, clean up the parameters, and
|
265
|
+
* then restore the saved state.
|
266
|
+
*
|
267
|
+
* The callee must use the standard C calling convention that matches the
|
268
|
+
* underlying 32-bit or 64-bit binary interface convention ("cdecl"). Other
|
269
|
+
* calling conventions, such as "fastcall" and "stdcall", are not supported.
|
270
|
+
*
|
271
|
+
* Stores the application state information on the DR stack, where it can
|
272
|
+
* be accessed from \c callee using dr_get_mcontext() and modified using
|
273
|
+
* dr_set_mcontext().
|
274
|
+
*
|
275
|
+
* If \p save_fpstate is true, preserves the fp/mmx/sse state on the DR stack.
|
276
|
+
* Note that it is relatively expensive to save this state (on the
|
277
|
+
* order of 200 cycles) and that it typically takes 512 bytes to store
|
278
|
+
* it (see proc_fpstate_save_size()).
|
279
|
+
*
|
280
|
+
* DR does support translating a fault in an argument (e.g., an
|
281
|
+
* argument that references application memory); such a fault will be
|
282
|
+
* treated as an application exception.
|
283
|
+
*
|
284
|
+
* \note The stack used to save state and call \p callee is limited to
|
285
|
+
* 20KB by default; this can be changed with the -stack_size DR runtime
|
286
|
+
* parameter. This stack cannot be used to store state that persists
|
287
|
+
* beyond \c callee's return point.
|
288
|
+
*
|
289
|
+
* \note This routine only supports passing arguments that are
|
290
|
+
* integers or pointers of a size equal to the register size: i.e., no
|
291
|
+
* floating-point, multimedia, or aggregate data types.
|
292
|
+
* The routine also supports immediate integers that are smaller than
|
293
|
+
* the register size, and for 64-bit mode registers or memory references that
|
294
|
+
* are OPSZ_4.
|
295
|
+
*
|
296
|
+
* \note For 64-bit mode, passing arguments that use calling
|
297
|
+
* convention registers (for Windows, RCX, RDX, R8, R9; for Linux,
|
298
|
+
* RDI, RSI, RDX, RCX, R8 and R9) are supported but may incur
|
299
|
+
* additional stack usage.
|
300
|
+
*
|
301
|
+
* \note For 64-bit mode, if a 32-bit immediate integer is specified as an
|
302
|
+
* argument and it has its top bit set, we assume it is intended to be
|
303
|
+
* sign-extended to 64-bits; otherwise we zero-extend it.
|
304
|
+
*
|
305
|
+
* \note For 64-bit mode, variable-sized argument operands may not work
|
306
|
+
* properly.
|
307
|
+
*
|
308
|
+
* \note Arguments that reference sub-register portions of REG_XSP are
|
309
|
+
* not supported (full REG_XSP is supported).
|
310
|
+
*/
|
311
|
+
void
|
312
|
+
dr_insert_clean_call(void *drcontext, instrlist_t *ilist, instr_t *where,
|
313
|
+
void *callee, bool save_fpstate, uint num_args, ...);
|
314
|
+
|
315
|
+
/**
|
316
|
+
* Inserts into \p ilist prior to \p where meta-instruction(s) to set
|
317
|
+
* up the passed-in parameters, make a call to \p callee, and clean up
|
318
|
+
* the parameters.
|
319
|
+
*
|
320
|
+
* The callee must use the standard C calling convention that matches the
|
321
|
+
* underlying 32-bit or 64-bit binary interface convention ("cdecl"). Other
|
322
|
+
* calling conventions, such as "fastcall" and "stdcall", are not supported.
|
323
|
+
*
|
324
|
+
* This routine uses the existing stack. In 64-bit mode, this routine assumes
|
325
|
+
* that the stack pointer is currently 16-byte aligned.
|
326
|
+
*
|
327
|
+
* The application state is NOT saved or restored (use dr_prepare_for_call()
|
328
|
+
* and dr_cleanup_after_call(), or replace this routine with dr_insert_clean_call()).
|
329
|
+
* The parameter set-up may write to registers if the calling convention so
|
330
|
+
* dictates. The registers are NOT saved beforehand (to do so, use
|
331
|
+
* dr_insert_clean_call()).
|
332
|
+
*
|
333
|
+
* It is up to the caller of this routine to preserve caller-saved registers.
|
334
|
+
*
|
335
|
+
* DR does not support translating a fault in an argument. For fault
|
336
|
+
* transparency, the client must perform the translation (see
|
337
|
+
* #dr_register_restore_state_event()), or use
|
338
|
+
* #dr_insert_clean_call().
|
339
|
+
*
|
340
|
+
* \note This routine only supports passing arguments that are
|
341
|
+
* integers or pointers of a size equal to the register size: i.e., no
|
342
|
+
* floating-point, multimedia, or aggregate data types.
|
343
|
+
* The routine also supports immediate integers that are smaller than
|
344
|
+
* the register size, and for 64-bit mode registers or memory references that
|
345
|
+
* are OPSZ_4.
|
346
|
+
*
|
347
|
+
* \note For 64-bit mode, passing arguments that use calling
|
348
|
+
* convention registers (for Windows, RCX, RDX, R8, R9; for Linux,
|
349
|
+
* RDI, RSI, RDX, RCX, R8 and R9) are supported but may incur
|
350
|
+
* additional stack usage.
|
351
|
+
*
|
352
|
+
* \note For 64-bit mode, if a 32-bit immediate integer is specified as an
|
353
|
+
* argument and it has its top bit set, we assume it is intended to be
|
354
|
+
* sign-extended to 64-bits; otherwise we zero-extend it.
|
355
|
+
*
|
356
|
+
* \note For 64-bit mode, variable-sized argument operands may not work
|
357
|
+
* properly.
|
358
|
+
*
|
359
|
+
* \note Arguments that reference REG_XSP are not supported in 64-bit mode.
|
360
|
+
*/
|
361
|
+
void
|
362
|
+
dr_insert_call(void *drcontext, instrlist_t *ilist, instr_t *where,
|
363
|
+
void *callee, uint num_args, ...);
|
364
|
+
|
365
|
+
/**
|
366
|
+
* Inserts into \p ilist prior to \p where meta-instruction(s) to save state for a call.
|
367
|
+
* Stores the application state information on the DR stack.
|
368
|
+
* Returns the size of the data stored on the DR stack (in case the caller
|
369
|
+
* needs to align the stack pointer).
|
370
|
+
*
|
371
|
+
* \warning This routine does NOT save the fp/mmx/sse state: to do that the
|
372
|
+
* instrumentation routine should call proc_save_fpstate() to save and
|
373
|
+
* then proc_restore_fpstate() to restore (or use dr_insert_clean_call()).
|
374
|
+
*
|
375
|
+
* \note The preparation modifies the REG_XSP and REG_XAX registers
|
376
|
+
* (after saving them). Use dr_insert_clean_call() instead if an
|
377
|
+
* argument to the subsequent call that references REG_XAX is
|
378
|
+
* desired.
|
379
|
+
*
|
380
|
+
* \note The stack used to save the state is limited to
|
381
|
+
* 20KB by default; this can be changed with the -stack_size DR runtime
|
382
|
+
* parameter. This stack cannot be used to store state that persists
|
383
|
+
* beyond a single clean call, code cache execution, or probe callback
|
384
|
+
* function execution.
|
385
|
+
*/
|
386
|
+
uint
|
387
|
+
dr_prepare_for_call(void *drcontext, instrlist_t *ilist, instr_t *instr);
|
388
|
+
|
389
|
+
/**
|
390
|
+
* Inserts into \p ilist prior to \p where meta-instruction(s) to restore state
|
391
|
+
* after a call.
|
392
|
+
*/
|
393
|
+
void
|
394
|
+
dr_cleanup_after_call(void *drcontext, instrlist_t *ilist, instr_t *where,
|
395
|
+
uint sizeof_param_area);
|
396
|
+
|
397
|
+
/**
|
398
|
+
* Inserts into \p ilist prior to \p where meta-instruction(s) to save the current
|
399
|
+
* esp and switch to this thread's DR stack.
|
400
|
+
* \note The DR stack is limited to 20KB by default; this can be changed with
|
401
|
+
* the -stack_size DR runtime parameter. This stack cannot be used to store
|
402
|
+
* state that persists beyond a single clean call, code cache execution,
|
403
|
+
* or probe callback function execution.
|
404
|
+
*/
|
405
|
+
void
|
406
|
+
dr_swap_to_clean_stack(void *drcontext, instrlist_t *ilist, instr_t *where);
|
407
|
+
|
408
|
+
/**
|
409
|
+
* Inserts into \p ilist prior to \p where meta-instruction(s) to restore into
|
410
|
+
* esp the value saved by dr_swap_to_dr_stack().
|
411
|
+
*/
|
412
|
+
void
|
413
|
+
dr_restore_app_stack(void *drcontext, instrlist_t *ilist, instr_t *where);
|
414
|
+
|
415
|
+
/**
|
416
|
+
* Assumes that \p instr is a near call.
|
417
|
+
* Inserts into \p ilist prior to \p instr instruction(s) to call callee passing
|
418
|
+
* two arguments:
|
419
|
+
* -# address of call instruction (caller)
|
420
|
+
* -# target address of call (callee)
|
421
|
+
*/
|
422
|
+
void
|
423
|
+
dr_insert_call_instrumentation(void *drcontext, instrlist_t *ilist,
|
424
|
+
instr_t *instr, void *callee);
|
425
|
+
|
426
|
+
/**
|
427
|
+
* Assumes that \p instr is an indirect branch.
|
428
|
+
* Inserts into \p ilist prior to \p instr instruction(s) to call callee passing
|
429
|
+
* two arguments:
|
430
|
+
* -# address of branch instruction
|
431
|
+
* -# target address of branch
|
432
|
+
* \note Only the address portion of a far indirect branch is considered.
|
433
|
+
* \note \p scratch_slot must be <= dr_max_opnd_accessible_spill_slot(). \p scratch_slot
|
434
|
+
* is used internally to this routine and will be clobbered.
|
435
|
+
*/
|
436
|
+
void
|
437
|
+
dr_insert_mbr_instrumentation(void *drcontext, instrlist_t *ilist,
|
438
|
+
instr_t *instr, void *callee, dr_spill_slot_t scratch_slot);
|
439
|
+
|
440
|
+
/**
|
441
|
+
* Assumes that \p instr is a conditional branch
|
442
|
+
* Inserts into \p ilist prior to \p instr instruction(s) to call callee passing
|
443
|
+
* three arguments:
|
444
|
+
* -# address of branch instruction
|
445
|
+
* -# target address of branch
|
446
|
+
* -# 0 if the branch is not taken, 1 if it is taken
|
447
|
+
*/
|
448
|
+
void
|
449
|
+
dr_insert_cbr_instrumentation(void *drcontext, instrlist_t *ilist,
|
450
|
+
instr_t *instr, void *callee);
|
451
|
+
|
452
|
+
/**
|
453
|
+
* Assumes that \p instr is a direct, near, unconditional branch.
|
454
|
+
* Inserts into \p ilist prior to \p instr instruction(s) to call callee passing
|
455
|
+
* two arguments:
|
456
|
+
* -# address of branch instruction
|
457
|
+
* -# target address of branch
|
458
|
+
*
|
459
|
+
* \warning Basic block eliding is controlled by -max_elide_jmp. If that
|
460
|
+
* option is set to non-zero, ubrs may never be seen.
|
461
|
+
*/
|
462
|
+
void
|
463
|
+
dr_insert_ubr_instrumentation(void *drcontext, instrlist_t *ilist,
|
464
|
+
instr_t *instr, void *callee);
|
465
|
+
|
466
|
+
/**
|
467
|
+
* Returns true if the xmm0 through xmm5 for Windows, or xmm0 through
|
468
|
+
* xmm15 for Linux, fields in dr_mcontext_t are valid for this process
|
469
|
+
* (i.e., whether this process is 64-bit or WOW64, and the processor
|
470
|
+
* supports SSE).
|
471
|
+
*/
|
472
|
+
bool
|
473
|
+
dr_mcontext_xmm_fields_valid(void);
|
474
|
+
|
475
|
+
/**
|
476
|
+
* Copies the current application machine context to \p context.
|
477
|
+
* This routine may only be called from:
|
478
|
+
* - A clean call invoked by dr_insert_clean_call() or dr_prepare_for_call()
|
479
|
+
* - A pre- or post-syscall event (dr_register_pre_syscall_event(),
|
480
|
+
* dr_register_post_syscall_event())
|
481
|
+
* - Basic block or trace creation events (dr_register_bb_event(),
|
482
|
+
* dr_register_trace_event()), but for basic block creation only when the
|
483
|
+
* basic block callback parameters \p for_trace and \p translating are
|
484
|
+
* false, and for trace creation only when \p translating is false.
|
485
|
+
* - A nudge callback (dr_register_nudge_event()) on Linux.
|
486
|
+
* (On Windows nudges happen in separate dedicated threads.)
|
487
|
+
*
|
488
|
+
* Does NOT copy the pc field. If \p app_errno is non-NULL copies the
|
489
|
+
* saved application error code (value of GetLastError() on Windows; ignored
|
490
|
+
* on Linux) to \p app_errno.
|
491
|
+
*
|
492
|
+
* \note NUM_XMM_SLOTS in the dr_mcontext_t.xmm array are filled in, but
|
493
|
+
* only if dr_mcontext_fields_valid() returns true.
|
494
|
+
* \note The context is the context saved at the dr_insert_clean_call() or
|
495
|
+
* dr_prepare_for_call() points. It does not correct for any registers saved
|
496
|
+
* with dr_save_reg(). To access registers saved with dr_save_reg() from a
|
497
|
+
* clean call use dr_read_saved_reg().
|
498
|
+
*/
|
499
|
+
void
|
500
|
+
dr_get_mcontext(void *drcontext, dr_mcontext_t *context, int *app_errno);
|
501
|
+
|
502
|
+
/**
|
503
|
+
* Sets the application machine context to \p context.
|
504
|
+
* This routine may only be called from:
|
505
|
+
* - A clean call invoked by dr_insert_clean_call() or dr_prepare_for_call()
|
506
|
+
* - A pre- or post-syscall event (dr_register_pre_syscall_event(),
|
507
|
+
* dr_register_post_syscall_event())
|
508
|
+
* dr_register_thread_exit_event())
|
509
|
+
* - Basic block or trace creation events (dr_register_bb_event(),
|
510
|
+
* dr_register_trace_event()), but for basic block creation only when the
|
511
|
+
* basic block callback parameters \p for_trace and \p translating are
|
512
|
+
* false, and for trace creation only when \p translating is false.
|
513
|
+
*
|
514
|
+
* Ignores the pc field. If \p app_errno is non-NULL sets the
|
515
|
+
* application error code (value of GetLastError() on Windows; ignored
|
516
|
+
* on Linux) to be restored as well.
|
517
|
+
*
|
518
|
+
* \note The xmm0 through xmm5 fields are only set for 64-bit or WOW64
|
519
|
+
* processes where the underlying processor supports SSE. For
|
520
|
+
* dr_insert_clean_call() that requested \p save_fpstate, the xmm0
|
521
|
+
* through xmm5 values set here override that saved state.
|
522
|
+
* Use dr_mcontext_xmm_fields_valid() to determine whether the fields are valid.
|
523
|
+
*/
|
524
|
+
void
|
525
|
+
dr_set_mcontext(void *drcontext, dr_mcontext_t *context, const int *app_errno);
|
526
|
+
|
527
|
+
/**
|
528
|
+
* Immediately resumes application execution from a clean call out of the cache (see
|
529
|
+
* dr_insert_clean_call() or dr_prepare_for_call()) or an exception event with the
|
530
|
+
* state specified in \p mcontext (including pc, and including the xmm0 through xmm5
|
531
|
+
* values if dr_mcontext_xmm_fields_valid() returns true) and the application error
|
532
|
+
* code (value of GetLastError() on Windows; ignored on Linux) specified by \p app_errno.
|
533
|
+
*
|
534
|
+
* \note dr_get_mcontext() can be used to get the register state (except pc) and the
|
535
|
+
* \p app_errno value saved in dr_insert_clean_call() or dr_prepare_for_call()
|
536
|
+
* \note If floating point state was saved by dr_prepare_for_call() or
|
537
|
+
* dr_insert_clean_call() it is not restored (other than xmm0 through xmm5, if
|
538
|
+
* dr_mcontext_xmm_fields_valid()). The caller should instead manually save and
|
539
|
+
* restore the floating point state with proc_save_fpstate() and proc_restore_fpstate()
|
540
|
+
* if necessary.
|
541
|
+
* \note If the caller wishes to set any other state (such as xmm registers that are
|
542
|
+
* not part of the mcontext) they may do so by just setting that state in the current
|
543
|
+
* thread before making this call.
|
544
|
+
* \note This routine may only be called from a clean call from the cache. It can not be
|
545
|
+
* called from any registered event callback.
|
546
|
+
* \note This routine doesn't return.
|
547
|
+
*/
|
548
|
+
void
|
549
|
+
dr_redirect_execution(dr_mcontext_t *mcontext, int app_errno);
|
550
|
+
|
551
|
+
/***************************************************************************
|
552
|
+
* DECODE / DISASSEMBLY ROUTINES
|
553
|
+
*/
|
554
|
+
|
555
|
+
|
556
|
+
/**
|
557
|
+
* Calculates the size, in bytes, of the memory read or write of
|
558
|
+
* the instr at \p pc. If the instruction is a repeating string instruction,
|
559
|
+
* considers only one iteration.
|
560
|
+
* Returns the pc of the following instruction.
|
561
|
+
* If the instruction at \p pc does not reference memory, or is invalid,
|
562
|
+
* returns NULL.
|
563
|
+
*/
|
564
|
+
app_pc
|
565
|
+
decode_memory_reference_size(void *drcontext, app_pc pc, uint *size_in_bytes);
|
566
|
+
|
567
|
+
/**
|
568
|
+
* Decodes only enough of the instruction at address \p pc to determine
|
569
|
+
* its eflags usage, which is returned in \p usage as EFLAGS_ constants
|
570
|
+
* or'ed together.
|
571
|
+
* Returns the address of the next byte after the decoded instruction.
|
572
|
+
* Returns NULL on decoding an invalid instruction.
|
573
|
+
*/
|
574
|
+
byte *
|
575
|
+
decode_eflags_usage(void *drcontext, byte *pc, uint *usage);
|
576
|
+
|
577
|
+
/**
|
578
|
+
* Decodes the instruction at address \p pc into \p instr, filling in the
|
579
|
+
* instruction's opcode, eflags usage, prefixes, and operands.
|
580
|
+
* The instruction's raw bits are set to valid and pointed at \p pc
|
581
|
+
* (xref instr_get_raw_bits()).
|
582
|
+
* Assumes that \p instr is already initialized, but uses the x86/x64 mode
|
583
|
+
* for the thread \p dcontext rather than that set in instr.
|
584
|
+
* If caller is re-using same instr_t struct over multiple decodings,
|
585
|
+
* caller should call instr_reset() or instr_reuse().
|
586
|
+
* Returns the address of the next byte after the decoded instruction.
|
587
|
+
* Returns NULL on decoding an invalid instr and sets opcode to OP_INVALID.
|
588
|
+
*/
|
589
|
+
byte *
|
590
|
+
decode(void *drcontext, byte *pc, instr_t *instr);
|
591
|
+
|
592
|
+
/**
|
593
|
+
* Decodes the instruction at address \p copy_pc into \p instr as though
|
594
|
+
* it were located at address \p orig_pc. Any pc-relative operands have
|
595
|
+
* their values calculated as though the instruction were actually at
|
596
|
+
* \p orig_pc, though that address is never de-referenced.
|
597
|
+
* The instruction's raw bits are not valid, but its translation field
|
598
|
+
* (see instr_get_translation()) is set to \p orig_pc.
|
599
|
+
* The instruction's opcode, eflags usage, prefixes, and operands are
|
600
|
+
* all filled in.
|
601
|
+
* Assumes that \p instr is already initialized, but uses the x86/x64 mode
|
602
|
+
* for the thread \p dcontext rather than that set in instr.
|
603
|
+
* If caller is re-using same instr_t struct over multiple decodings,
|
604
|
+
* caller should call instr_reset() or instr_reuse().
|
605
|
+
* Returns the address of the next byte after the decoded instruction
|
606
|
+
* copy at \p copy_pc.
|
607
|
+
* Returns NULL on decoding an invalid instr and sets opcode to OP_INVALID.
|
608
|
+
*/
|
609
|
+
byte *
|
610
|
+
decode_from_copy(void *drcontext, byte *copy_pc, byte *orig_pc, instr_t *instr);
|
611
|
+
|
612
|
+
/**
|
613
|
+
* Client routine to decode instructions at an arbitrary app address,
|
614
|
+
* following all the rules that DynamoRIO follows internally for
|
615
|
+
* terminating basic blocks. Note that DynamoRIO does not validate
|
616
|
+
* that \p start_pc is actually the first instruction of a basic block.
|
617
|
+
* \note Caller is reponsible for freeing the list and its instrs!
|
618
|
+
*/
|
619
|
+
instrlist_t *
|
620
|
+
decode_as_bb(void *drcontext, byte *start_pc);
|
621
|
+
|
622
|
+
/**
|
623
|
+
* Decodes the trace with tag \p tag, and returns an instrlist_t of
|
624
|
+
* the instructions comprising that fragment. If \p tag is not a
|
625
|
+
* valid tag for an existing trace, the routine returns NULL. Clients
|
626
|
+
* can use dr_trace_exists_at() to determine whether the trace exists.
|
627
|
+
* \note Unlike the instruction list presented by the trace event, the
|
628
|
+
* list here does not include any existing client modifications. If
|
629
|
+
* client-modified instructions are needed, it is the responsibility
|
630
|
+
* of the client to record or recreate that list itself.
|
631
|
+
* \note This routine does not support decoding thread-private traces
|
632
|
+
* created by other than the calling thread.
|
633
|
+
*/
|
634
|
+
instrlist_t *
|
635
|
+
decode_trace(void *drcontext, void *tag);
|
636
|
+
|
637
|
+
/**
|
638
|
+
* Given an OP_ constant, returns the first byte of its opcode when
|
639
|
+
* encoded as an IA-32 instruction.
|
640
|
+
*/
|
641
|
+
byte
|
642
|
+
decode_first_opcode_byte(int opcode);
|
643
|
+
|
644
|
+
/** Given an OP_ constant, returns the string name of its opcode. */
|
645
|
+
const char *
|
646
|
+
decode_opcode_name(int opcode);
|
647
|
+
|
648
|
+
/**
|
649
|
+
* Decodes only enough of the instruction at address \p pc to determine its size.
|
650
|
+
* Returns that size.
|
651
|
+
* If \p num_prefixes is non-NULL, returns the number of prefix bytes.
|
652
|
+
* If \p rip_rel_pos is non-NULL, returns the offset into the instruction
|
653
|
+
* of a rip-relative addressing displacement (for data only: ignores
|
654
|
+
* control-transfer relative addressing), or 0 if none.
|
655
|
+
* May return 0 size for certain invalid instructions.
|
656
|
+
*/
|
657
|
+
int
|
658
|
+
decode_sizeof(void *drcontext, byte *pc, int *num_prefixes
|
659
|
+
_IF_X64(uint *rip_rel_pos));
|
660
|
+
|
661
|
+
/**
|
662
|
+
* Decodes only enough of the instruction at address \p pc to determine its size.
|
663
|
+
* Returns the address of the byte following the instruction.
|
664
|
+
* Returns NULL on decoding an invalid instruction.
|
665
|
+
*/
|
666
|
+
byte *
|
667
|
+
decode_next_pc(void *drcontext, byte *pc);
|
668
|
+
|
669
|
+
|
670
|
+
/**
|
671
|
+
* Decodes and then prints the instruction at address \p pc to file \p outfile.
|
672
|
+
* The default is to use AT&T-style syntax, unless the \ref op_syntax_intel
|
673
|
+
* "-syntax_intel" runtime option is specified.
|
674
|
+
* Returns the address of the subsequent instruction, or NULL if the instruction
|
675
|
+
* at \p pc is invalid.
|
676
|
+
*/
|
677
|
+
byte *
|
678
|
+
disassemble(void *drcontext, byte *pc, file_t outfile);
|
679
|
+
|
680
|
+
/**
|
681
|
+
* Decodes and then prints the instruction at address \p pc to file \p outfile.
|
682
|
+
* Prior to the instruction the address is printed if \p show_pc and the raw
|
683
|
+
* bytes are printed if \p show_bytes.
|
684
|
+
* The default is to use AT&T-style syntax, unless the \ref op_syntax_intel
|
685
|
+
* "-syntax_intel" runtime option is specified.
|
686
|
+
* Returns the address of the subsequent instruction, or NULL if the instruction
|
687
|
+
* at \p pc is invalid.
|
688
|
+
*/
|
689
|
+
byte *
|
690
|
+
disassemble_with_info(void *drcontext, byte *pc, file_t outfile,
|
691
|
+
bool show_pc, bool show_bytes);
|
692
|
+
|
693
|
+
/**
|
694
|
+
* Decodes the instruction at address \p copy_pc as though
|
695
|
+
* it were located at address \p orig_pc, and then prints the
|
696
|
+
* instruction to file \p outfile.
|
697
|
+
* Prior to the instruction the address \p orig_pc is printed if \p show_pc and the raw
|
698
|
+
* bytes are printed if \p show_bytes.
|
699
|
+
* The default is to use AT&T-style syntax, unless the \ref op_syntax_intel
|
700
|
+
* "-syntax_intel" runtime option is specified.
|
701
|
+
* Returns the address of the subsequent instruction after the copy at
|
702
|
+
* \p copy_pc, or NULL if the instruction at \p copy_pc is invalid.
|
703
|
+
*/
|
704
|
+
byte *
|
705
|
+
disassemble_from_copy(void *drcontext, byte *copy_pc, byte *orig_pc,
|
706
|
+
file_t outfile, bool show_pc, bool show_bytes);
|
707
|
+
|
708
|
+
#endif /* _DR_IR_UTILS_H_ */
|