Enumerations | |
enum | dr_spill_slot_t { , SPILL_SLOT_2 = 1, SPILL_SLOT_3 = 2, SPILL_SLOT_4 = 3, SPILL_SLOT_5 = 4, SPILL_SLOT_6 = 5, SPILL_SLOT_7 = 6, SPILL_SLOT_8 = 7, SPILL_SLOT_9 = 8, SPILL_SLOT_10 = 9, SPILL_SLOT_11 = 10, SPILL_SLOT_12 = 11, SPILL_SLOT_13 = 12, SPILL_SLOT_14 = 13, SPILL_SLOT_15 = 14, SPILL_SLOT_16 = 15, SPILL_SLOT_17 = 16, SPILL_SLOT_MAX = SPILL_SLOT_17 } |
Functions | |
bool | set_x86_mode (void *drcontext, bool x86) |
bool | get_x86_mode (void *drcontext) |
void | dr_save_reg (void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg, dr_spill_slot_t slot) |
void | dr_restore_reg (void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg, dr_spill_slot_t slot) |
dr_spill_slot_t | dr_max_opnd_accessible_spill_slot (void) |
opnd_t | dr_reg_spill_slot_opnd (void *drcontext, dr_spill_slot_t slot) |
reg_t | dr_read_saved_reg (void *drcontext, dr_spill_slot_t slot) |
void | dr_write_saved_reg (void *drcontext, dr_spill_slot_t slot, reg_t value) |
void | dr_save_arith_flags (void *drcontext, instrlist_t *ilist, instr_t *where, dr_spill_slot_t slot) |
void | dr_restore_arith_flags (void *drcontext, instrlist_t *ilist, instr_t *where, dr_spill_slot_t slot) |
void | dr_insert_read_tls_field (void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg) |
void | dr_insert_write_tls_field (void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg) |
void | instrlist_meta_preinsert (instrlist_t *ilist, instr_t *where, instr_t *instr) |
void | instrlist_meta_postinsert (instrlist_t *ilist, instr_t *where, instr_t *instr) |
void | instrlist_meta_append (instrlist_t *ilist, instr_t *instr) |
void | instrlist_meta_fault_preinsert (instrlist_t *ilist, instr_t *where, instr_t *instr) |
void | instrlist_meta_fault_postinsert (instrlist_t *ilist, instr_t *where, instr_t *instr) |
void | instrlist_meta_fault_append (instrlist_t *ilist, instr_t *instr) |
void | dr_insert_clean_call (void *drcontext, instrlist_t *ilist, instr_t *where, void *callee, bool save_fpstate, uint num_args,...) |
void | dr_insert_call (void *drcontext, instrlist_t *ilist, instr_t *where, void *callee, uint num_args,...) |
uint | dr_prepare_for_call (void *drcontext, instrlist_t *ilist, instr_t *instr) |
void | dr_cleanup_after_call (void *drcontext, instrlist_t *ilist, instr_t *where, uint sizeof_param_area) |
void | dr_swap_to_clean_stack (void *drcontext, instrlist_t *ilist, instr_t *where) |
void | dr_restore_app_stack (void *drcontext, instrlist_t *ilist, instr_t *where) |
void | dr_insert_call_instrumentation (void *drcontext, instrlist_t *ilist, instr_t *instr, void *callee) |
void | dr_insert_mbr_instrumentation (void *drcontext, instrlist_t *ilist, instr_t *instr, void *callee, dr_spill_slot_t scratch_slot) |
void | dr_insert_cbr_instrumentation (void *drcontext, instrlist_t *ilist, instr_t *instr, void *callee) |
void | dr_insert_ubr_instrumentation (void *drcontext, instrlist_t *ilist, instr_t *instr, void *callee) |
bool | dr_mcontext_xmm_fields_valid (void) |
void | dr_get_mcontext (void *drcontext, dr_mcontext_t *context, int *app_errno) |
void | dr_set_mcontext (void *drcontext, dr_mcontext_t *context, const int *app_errno) |
void | dr_redirect_execution (dr_mcontext_t *mcontext, int app_errno) |
app_pc | decode_memory_reference_size (void *drcontext, app_pc pc, uint *size_in_bytes) |
byte * | decode_eflags_usage (void *drcontext, byte *pc, uint *usage) |
byte * | decode (void *drcontext, byte *pc, instr_t *instr) |
byte * | decode_from_copy (void *drcontext, byte *copy_pc, byte *orig_pc, instr_t *instr) |
instrlist_t * | decode_as_bb (void *drcontext, byte *start_pc) |
instrlist_t * | decode_trace (void *drcontext, void *tag) |
byte | decode_first_opcode_byte (int opcode) |
const char * | decode_opcode_name (int opcode) |
int | decode_sizeof (void *drcontext, byte *pc, int *num_prefixes _IF_X64(uint *rip_rel_pos)) |
byte * | decode_next_pc (void *drcontext, byte *pc) |
byte * | disassemble (void *drcontext, byte *pc, file_t outfile) |
byte * | disassemble_with_info (void *drcontext, byte *pc, file_t outfile, bool show_pc, bool show_bytes) |
byte * | disassemble_from_copy (void *drcontext, byte *copy_pc, byte *orig_pc, file_t outfile, bool show_pc, bool show_bytes) |
enum dr_spill_slot_t |
An enum of spill slots to use with dr_save_reg(), dr_restore_reg(), dr_save_arith_flags(), dr_restore_arith_flags() and dr_insert_mbr_instrumentation(). Values stored in spill slots remain valid only until the next non-meta (i.e. application) instruction. Spill slots can be accessed/modifed during clean calls and restore_state_events (see dr_register_restore_state_event()) with dr_read_saved_reg() and dr_write_saved_reg().
Spill slots <= dr_max_opnd_accessible_spill_slot() can be directly accessed from client inserted instructions with dr_reg_spill_slot_opnd().
The number of spill slots may change in future releases.
byte* decode | ( | void * | drcontext, | |
byte * | pc, | |||
instr_t * | instr | |||
) |
Decodes the instruction at address pc
into instr
, filling in the instruction's opcode, eflags usage, prefixes, and operands. The instruction's raw bits are set to valid and pointed at pc
(xref instr_get_raw_bits()). Assumes that instr
is already initialized, but uses the x86/x64 mode for the thread dcontext
rather than that set in instr. If caller is re-using same instr_t struct over multiple decodings, caller should call instr_reset() or instr_reuse(). Returns the address of the next byte after the decoded instruction. Returns NULL on decoding an invalid instr and sets opcode to OP_INVALID.
instrlist_t* decode_as_bb | ( | void * | drcontext, | |
byte * | start_pc | |||
) |
Client routine to decode instructions at an arbitrary app address, following all the rules that DynamoRIO follows internally for terminating basic blocks. Note that DynamoRIO does not validate that start_pc
is actually the first instruction of a basic block.
byte* decode_eflags_usage | ( | void * | drcontext, | |
byte * | pc, | |||
uint * | usage | |||
) |
Decodes only enough of the instruction at address pc
to determine its eflags usage, which is returned in usage
as EFLAGS_ constants or'ed together. Returns the address of the next byte after the decoded instruction. Returns NULL on decoding an invalid instruction.
byte decode_first_opcode_byte | ( | int | opcode | ) |
Given an OP_ constant, returns the first byte of its opcode when encoded as an IA-32 instruction.
byte* decode_from_copy | ( | void * | drcontext, | |
byte * | copy_pc, | |||
byte * | orig_pc, | |||
instr_t * | instr | |||
) |
Decodes the instruction at address copy_pc
into instr
as though it were located at address orig_pc
. Any pc-relative operands have their values calculated as though the instruction were actually at orig_pc
, though that address is never de-referenced. The instruction's raw bits are not valid, but its translation field (see instr_get_translation()) is set to orig_pc
. The instruction's opcode, eflags usage, prefixes, and operands are all filled in. Assumes that instr
is already initialized, but uses the x86/x64 mode for the thread dcontext
rather than that set in instr. If caller is re-using same instr_t struct over multiple decodings, caller should call instr_reset() or instr_reuse(). Returns the address of the next byte after the decoded instruction copy at copy_pc
. Returns NULL on decoding an invalid instr and sets opcode to OP_INVALID.
app_pc decode_memory_reference_size | ( | void * | drcontext, | |
app_pc | pc, | |||
uint * | size_in_bytes | |||
) |
Calculates the size, in bytes, of the memory read or write of the instr at pc
. If the instruction is a repeating string instruction, considers only one iteration. Returns the pc of the following instruction. If the instruction at pc
does not reference memory, or is invalid, returns NULL.
byte* decode_next_pc | ( | void * | drcontext, | |
byte * | pc | |||
) |
Decodes only enough of the instruction at address pc
to determine its size. Returns the address of the byte following the instruction. Returns NULL on decoding an invalid instruction.
const char* decode_opcode_name | ( | int | opcode | ) |
Given an OP_ constant, returns the string name of its opcode.
int decode_sizeof | ( | void * | drcontext, | |
byte * | pc, | |||
int *num_prefixes | _IF_X64uint *rip_rel_pos | |||
) |
Decodes only enough of the instruction at address pc
to determine its size. Returns that size. If num_prefixes
is non-NULL, returns the number of prefix bytes. If rip_rel_pos
is non-NULL, returns the offset into the instruction of a rip-relative addressing displacement (for data only: ignores control-transfer relative addressing), or 0 if none. May return 0 size for certain invalid instructions.
instrlist_t* decode_trace | ( | void * | drcontext, | |
void * | tag | |||
) |
Decodes the trace with tag tag
, and returns an instrlist_t of the instructions comprising that fragment. If tag
is not a valid tag for an existing trace, the routine returns NULL. Clients can use dr_trace_exists_at() to determine whether the trace exists.
This routine does not support decoding thread-private traces created by other than the calling thread.
byte* disassemble | ( | void * | drcontext, | |
byte * | pc, | |||
file_t | outfile | |||
) |
Decodes and then prints the instruction at address pc
to file outfile
. The default is to use AT&T-style syntax, unless the -syntax_intel runtime option is specified. Returns the address of the subsequent instruction, or NULL if the instruction at pc
is invalid.
byte* disassemble_from_copy | ( | void * | drcontext, | |
byte * | copy_pc, | |||
byte * | orig_pc, | |||
file_t | outfile, | |||
bool | show_pc, | |||
bool | show_bytes | |||
) |
Decodes the instruction at address copy_pc
as though it were located at address orig_pc
, and then prints the instruction to file outfile
. Prior to the instruction the address orig_pc
is printed if show_pc
and the raw bytes are printed if show_bytes
. The default is to use AT&T-style syntax, unless the -syntax_intel runtime option is specified. Returns the address of the subsequent instruction after the copy at copy_pc
, or NULL if the instruction at copy_pc
is invalid.
byte* disassemble_with_info | ( | void * | drcontext, | |
byte * | pc, | |||
file_t | outfile, | |||
bool | show_pc, | |||
bool | show_bytes | |||
) |
Decodes and then prints the instruction at address pc
to file outfile
. Prior to the instruction the address is printed if show_pc
and the raw bytes are printed if show_bytes
. The default is to use AT&T-style syntax, unless the -syntax_intel runtime option is specified. Returns the address of the subsequent instruction, or NULL if the instruction at pc
is invalid.
void dr_cleanup_after_call | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | where, | |||
uint | sizeof_param_area | |||
) |
Inserts into ilist
prior to where
meta-instruction(s) to restore state after a call.
void dr_get_mcontext | ( | void * | drcontext, | |
dr_mcontext_t * | context, | |||
int * | app_errno | |||
) |
Copies the current application machine context to context
. This routine may only be called from:
for_trace
and translating
are false, and for trace creation only when translating
is false.
Does NOT copy the pc field. If app_errno
is non-NULL copies the saved application error code (value of GetLastError() on Windows; ignored on Linux) to app_errno
.
The context is the context saved at the dr_insert_clean_call() or dr_prepare_for_call() points. It does not correct for any registers saved with dr_save_reg(). To access registers saved with dr_save_reg() from a clean call use dr_read_saved_reg().
void dr_insert_call | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | where, | |||
void * | callee, | |||
uint | num_args, | |||
... | ||||
) |
Inserts into ilist
prior to where
meta-instruction(s) to set up the passed-in parameters, make a call to callee
, and clean up the parameters.
The callee must use the standard C calling convention that matches the underlying 32-bit or 64-bit binary interface convention ("cdecl"). Other calling conventions, such as "fastcall" and "stdcall", are not supported.
This routine uses the existing stack. In 64-bit mode, this routine assumes that the stack pointer is currently 16-byte aligned.
The application state is NOT saved or restored (use dr_prepare_for_call() and dr_cleanup_after_call(), or replace this routine with dr_insert_clean_call()). The parameter set-up may write to registers if the calling convention so dictates. The registers are NOT saved beforehand (to do so, use dr_insert_clean_call()).
It is up to the caller of this routine to preserve caller-saved registers.
DR does not support translating a fault in an argument. For fault transparency, the client must perform the translation (see dr_register_restore_state_event()), or use dr_insert_clean_call().
For 64-bit mode, passing arguments that use calling convention registers (for Windows, RCX, RDX, R8, R9; for Linux, RDI, RSI, RDX, RCX, R8 and R9) are supported but may incur additional stack usage.
For 64-bit mode, if a 32-bit immediate integer is specified as an argument and it has its top bit set, we assume it is intended to be sign-extended to 64-bits; otherwise we zero-extend it.
For 64-bit mode, variable-sized argument operands may not work properly.
Arguments that reference REG_XSP are not supported in 64-bit mode.
void dr_insert_call_instrumentation | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | instr, | |||
void * | callee | |||
) |
Assumes that instr
is a near call. Inserts into ilist
prior to instr
instruction(s) to call callee passing two arguments:
void dr_insert_cbr_instrumentation | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | instr, | |||
void * | callee | |||
) |
Assumes that instr
is a conditional branch Inserts into ilist
prior to instr
instruction(s) to call callee passing three arguments:
void dr_insert_clean_call | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | where, | |||
void * | callee, | |||
bool | save_fpstate, | |||
uint | num_args, | |||
... | ||||
) |
Inserts into ilist
prior to where
meta-instruction(s) to save state for a call, switch to this thread's DR stack, set up the passed-in parameters, make a call to callee
, clean up the parameters, and then restore the saved state.
The callee must use the standard C calling convention that matches the underlying 32-bit or 64-bit binary interface convention ("cdecl"). Other calling conventions, such as "fastcall" and "stdcall", are not supported.
Stores the application state information on the DR stack, where it can be accessed from callee
using dr_get_mcontext() and modified using dr_set_mcontext().
If save_fpstate
is true, preserves the fp/mmx/sse state on the DR stack. Note that it is relatively expensive to save this state (on the order of 200 cycles) and that it typically takes 512 bytes to store it (see proc_fpstate_save_size()).
DR does support translating a fault in an argument (e.g., an argument that references application memory); such a fault will be treated as an application exception.
callee
is limited to 20KB by default; this can be changed with the -stack_size DR runtime parameter. This stack cannot be used to store state that persists beyond callee's
return point.This routine only supports passing arguments that are integers or pointers of a size equal to the register size: i.e., no floating-point, multimedia, or aggregate data types. The routine also supports immediate integers that are smaller than the register size, and for 64-bit mode registers or memory references that are OPSZ_4.
For 64-bit mode, passing arguments that use calling convention registers (for Windows, RCX, RDX, R8, R9; for Linux, RDI, RSI, RDX, RCX, R8 and R9) are supported but may incur additional stack usage.
For 64-bit mode, if a 32-bit immediate integer is specified as an argument and it has its top bit set, we assume it is intended to be sign-extended to 64-bits; otherwise we zero-extend it.
For 64-bit mode, variable-sized argument operands may not work properly.
Arguments that reference sub-register portions of REG_XSP are not supported (full REG_XSP is supported).
void dr_insert_mbr_instrumentation | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | instr, | |||
void * | callee, | |||
dr_spill_slot_t | scratch_slot | |||
) |
Assumes that instr
is an indirect branch. Inserts into ilist
prior to instr
instruction(s) to call callee passing two arguments:
scratch_slot
must be <= dr_max_opnd_accessible_spill_slot(). scratch_slot
is used internally to this routine and will be clobbered.
void dr_insert_read_tls_field | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | where, | |||
reg_id_t | reg | |||
) |
Inserts into ilist
prior to where
meta-instruction(s) to read into the general-purpose full-size register reg
from the user-controlled drcontext field for this thread. Reads from the same field as dr_get_tls_field().
void dr_insert_ubr_instrumentation | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | instr, | |||
void * | callee | |||
) |
Assumes that instr
is a direct, near, unconditional branch. Inserts into ilist
prior to instr
instruction(s) to call callee passing two arguments:
void dr_insert_write_tls_field | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | where, | |||
reg_id_t | reg | |||
) |
Inserts into ilist
prior to where
meta-instruction(s) to write the general-purpose full-size register reg
to the user-controlled drcontext field for this thread. Writes to the same field as dr_set_tls_field().
dr_spill_slot_t dr_max_opnd_accessible_spill_slot | ( | void | ) |
Returns the largest dr_spill_slot_t that can be accessed with an opnd_t from dr_reg_spill_slot_opnd().
bool dr_mcontext_xmm_fields_valid | ( | void | ) |
Returns true if the xmm0 through xmm5 for Windows, or xmm0 through xmm15 for Linux, fields in dr_mcontext_t are valid for this process (i.e., whether this process is 64-bit or WOW64, and the processor supports SSE).
uint dr_prepare_for_call | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | instr | |||
) |
Inserts into ilist
prior to where
meta-instruction(s) to save state for a call. Stores the application state information on the DR stack. Returns the size of the data stored on the DR stack (in case the caller needs to align the stack pointer).
The stack used to save the state is limited to 20KB by default; this can be changed with the -stack_size DR runtime parameter. This stack cannot be used to store state that persists beyond a single clean call, code cache execution, or probe callback function execution.
reg_t dr_read_saved_reg | ( | void * | drcontext, | |
dr_spill_slot_t | slot | |||
) |
Can be used from a clean call or a restore_state_event (see dr_register_restore_state_event()) to see the value saved in spill slot slot
by dr_save_reg().
void dr_redirect_execution | ( | dr_mcontext_t * | mcontext, | |
int | app_errno | |||
) |
Immediately resumes application execution from a clean call out of the cache (see dr_insert_clean_call() or dr_prepare_for_call()) or an exception event with the state specified in mcontext
(including pc, and including the xmm0 through xmm5 values if dr_mcontext_xmm_fields_valid() returns true) and the application error code (value of GetLastError() on Windows; ignored on Linux) specified by app_errno
.
app_errno
value saved in dr_insert_clean_call() or dr_prepare_for_call() If floating point state was saved by dr_prepare_for_call() or dr_insert_clean_call() it is not restored (other than xmm0 through xmm5, if dr_mcontext_xmm_fields_valid()). The caller should instead manually save and restore the floating point state with proc_save_fpstate() and proc_restore_fpstate() if necessary.
If the caller wishes to set any other state (such as xmm registers that are not part of the mcontext) they may do so by just setting that state in the current thread before making this call.
This routine may only be called from a clean call from the cache. It can not be called from any registered event callback.
This routine doesn't return.
opnd_t dr_reg_spill_slot_opnd | ( | void * | drcontext, | |
dr_spill_slot_t | slot | |||
) |
Returns an opnd_t that directly accesses the spill slot slot
. Only slots <= dr_max_opnd_accessible_spill_slot() can be used with this routine.
slot
must be <= dr_max_opnd_accessible_spill_slot() void dr_restore_app_stack | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | where | |||
) |
Inserts into ilist
prior to where
meta-instruction(s) to restore into esp the value saved by dr_swap_to_dr_stack().
void dr_restore_arith_flags | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | where, | |||
dr_spill_slot_t | slot | |||
) |
Inserts into ilist
prior to where
meta-instruction(s) to restore the 6 arithmetic flags, assuming they were saved using dr_save_arith_flags() with slot slot
and that xax holds the same value it did after the save.
void dr_restore_reg | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | where, | |||
reg_id_t | reg, | |||
dr_spill_slot_t | slot | |||
) |
Inserts into ilist
prior to where
meta-instruction(s) to restore the register reg
from the spill slot slot
. See dr_save_reg() for notes on lifetime and alternative access to spill slots.
void dr_save_arith_flags | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | where, | |||
dr_spill_slot_t | slot | |||
) |
Inserts into ilist
prior to where
meta-instruction(s) to save the 6 arithmetic flags into xax after first saving xax to the spill slot slot
. This is equivalent to dr_save_reg() of xax to slot
followed by lahf and seto al instructions. See dr_restore_arith_flags().
void dr_save_reg | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | where, | |||
reg_id_t | reg, | |||
dr_spill_slot_t | slot | |||
) |
Inserts into ilist
prior to where
meta-instruction(s) to save the register reg
in the spill slot slot
. See dr_restore_reg(). Use dr_read_saved_reg() and dr_write_saved_reg() to access spill slots from clean calls and restore_state_events (see dr_register_restore_state_event()).
void dr_set_mcontext | ( | void * | drcontext, | |
dr_mcontext_t * | context, | |||
const int * | app_errno | |||
) |
Sets the application machine context to context
. This routine may only be called from:
for_trace
and translating
are false, and for trace creation only when translating
is false.
Ignores the pc field. If app_errno
is non-NULL sets the application error code (value of GetLastError() on Windows; ignored on Linux) to be restored as well.
save_fpstate
, the xmm0 through xmm5 values set here override that saved state. Use dr_mcontext_xmm_fields_valid() to determine whether the fields are valid. void dr_swap_to_clean_stack | ( | void * | drcontext, | |
instrlist_t * | ilist, | |||
instr_t * | where | |||
) |
Inserts into ilist
prior to where
meta-instruction(s) to save the current esp and switch to this thread's DR stack.
void dr_write_saved_reg | ( | void * | drcontext, | |
dr_spill_slot_t | slot, | |||
reg_t | value | |||
) |
Can be used from a clean call to modify the value saved in the spill slot slot
by dr_save_reg() such that a later dr_restore_reg() will see the new value.
bool get_x86_mode | ( | void * | drcontext | ) |
The decode and encode routines use a per-thread persistent flag that indicates whether to treat code as 32-bit (x86) or 64-bit (x64). This routine returns the value of that flag.
void instrlist_meta_append | ( | instrlist_t * | ilist, | |
instr_t * | instr | |||
) |
Inserts instr
as a non-application instruction onto the end of ilist
void instrlist_meta_fault_append | ( | instrlist_t * | ilist, | |
instr_t * | instr | |||
) |
Inserts instr
as a non-application instruction that can fault (see instr_set_meta_may_fault()) onto the end of ilist
.
Inserts instr
as a non-application instruction that can fault (see instr_set_meta_may_fault()) into ilist
after where
.
Inserts instr
as a non-application instruction that can fault (see instr_set_meta_may_fault()) into ilist
prior to where
.
Inserts instr
as a non-application instruction into ilist
after where
.
Inserts instr
as a non-application instruction into ilist
prior to where
.
bool set_x86_mode | ( | void * | drcontext, | |
bool | x86 | |||
) |
The decode and encode routines use a per-thread persistent flag that indicates whether to treat code as 32-bit (x86) or 64-bit (x64). This routine sets that flag to the indicated value and returns the old value. Be sure to restore the old value prior to any further application execution to avoid problems in mis-interpreting application code.