dr_ir_utils.h File Reference

Code transformation utilities. More...

Macros

#define SPILL_SLOT_REDIRECT_NATIVE_TGT   SPILL_SLOT_1
 

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

DR_API void dr_save_reg (void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg, dr_spill_slot_t slot)
 
DR_API void dr_restore_reg (void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg, dr_spill_slot_t slot)
 
DR_API dr_spill_slot_t dr_max_opnd_accessible_spill_slot (void)
 
DR_API opnd_t dr_reg_spill_slot_opnd (void *drcontext, dr_spill_slot_t slot)
 
DR_API reg_t dr_read_saved_reg (void *drcontext, dr_spill_slot_t slot)
 
DR_API void dr_write_saved_reg (void *drcontext, dr_spill_slot_t slot, reg_t value)
 
DR_API void dr_save_arith_flags (void *drcontext, instrlist_t *ilist, instr_t *where, dr_spill_slot_t slot)
 
DR_API void dr_restore_arith_flags (void *drcontext, instrlist_t *ilist, instr_t *where, dr_spill_slot_t slot)
 
DR_API void dr_save_arith_flags_to_xax (void *drcontext, instrlist_t *ilist, instr_t *where)
 
DR_API void dr_restore_arith_flags_from_xax (void *drcontext, instrlist_t *ilist, instr_t *where)
 
DR_API void dr_save_arith_flags_to_reg (void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg)
 
DR_API void dr_restore_arith_flags_from_reg (void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg)
 
DR_API reg_t dr_merge_arith_flags (reg_t cur_xflags, reg_t saved_xflag)
 
DR_API void dr_insert_read_tls_field (void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg)
 
DR_API void dr_insert_write_tls_field (void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg)
 
DR_API void instrlist_meta_preinsert (instrlist_t *ilist, instr_t *where, instr_t *instr)
 
DR_API void instrlist_meta_postinsert (instrlist_t *ilist, instr_t *where, instr_t *instr)
 
DR_API void instrlist_meta_append (instrlist_t *ilist, instr_t *instr)
 
DR_API void instrlist_meta_fault_preinsert (instrlist_t *ilist, instr_t *where, instr_t *instr)
 
DR_API void instrlist_meta_fault_postinsert (instrlist_t *ilist, instr_t *where, instr_t *instr)
 
DR_API void instrlist_meta_fault_append (instrlist_t *ilist, instr_t *instr)
 
DR_API void dr_insert_clean_call (void *drcontext, instrlist_t *ilist, instr_t *where, void *callee, bool save_fpstate, uint num_args,...)
 
DR_API void dr_insert_clean_call_ex (void *drcontext, instrlist_t *ilist, instr_t *where, void *callee, dr_cleancall_save_t save_flags, uint num_args,...)
 
DR_API void dr_insert_call (void *drcontext, instrlist_t *ilist, instr_t *where, void *callee, uint num_args,...)
 
DR_API bool dr_insert_call_ex (void *drcontext, instrlist_t *ilist, instr_t *where, byte *encode_pc, void *callee, uint num_args,...)
 
DR_API uint dr_prepare_for_call (void *drcontext, instrlist_t *ilist, instr_t *instr)
 
DR_API void dr_cleanup_after_call (void *drcontext, instrlist_t *ilist, instr_t *where, uint sizeof_param_area)
 
DR_API void dr_swap_to_clean_stack (void *drcontext, instrlist_t *ilist, instr_t *where)
 
DR_API void dr_restore_app_stack (void *drcontext, instrlist_t *ilist, instr_t *where)
 
DR_API void * dr_call_on_clean_stack (void *drcontext, void *(*func)(void), void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8)
 
DR_API void dr_insert_call_instrumentation (void *drcontext, instrlist_t *ilist, instr_t *instr, void *callee)
 
DR_API void dr_insert_mbr_instrumentation (void *drcontext, instrlist_t *ilist, instr_t *instr, void *callee, dr_spill_slot_t scratch_slot)
 
DR_API void dr_insert_cbr_instrumentation (void *drcontext, instrlist_t *ilist, instr_t *instr, void *callee)
 
DR_API void dr_insert_cbr_instrumentation_ex (void *drcontext, instrlist_t *ilist, instr_t *instr, void *callee, opnd_t user_data)
 
DR_API void dr_insert_ubr_instrumentation (void *drcontext, instrlist_t *ilist, instr_t *instr, void *callee)
 
DR_API bool dr_clobber_retaddr_after_read (void *drcontext, instrlist_t *ilist, instr_t *instr, ptr_uint_t value)
 
DR_API bool dr_mcontext_xmm_fields_valid (void)
 
DR_API bool dr_mcontext_zmm_fields_valid (void)
 
DR_API bool dr_get_mcontext (void *drcontext, dr_mcontext_t *context)
 
DR_API bool dr_set_mcontext (void *drcontext, dr_mcontext_t *context)
 
DR_API bool dr_redirect_execution (dr_mcontext_t *context)
 
DR_API byte * dr_redirect_native_target (void *drcontext)
 
DR_API bool dr_mcontext_to_context (CONTEXT *dst, dr_mcontext_t *src)
 
DR_API void instrlist_insert_mov_immed_ptrsz (void *drcontext, ptr_int_t val, opnd_t dst, instrlist_t *ilist, instr_t *where, instr_t **first DR_PARAM_OUT, instr_t **last DR_PARAM_OUT)
 
DR_API void instrlist_insert_push_immed_ptrsz (void *drcontext, ptr_int_t val, instrlist_t *ilist, instr_t *where, instr_t **first DR_PARAM_OUT, instr_t **last DR_PARAM_OUT)
 
DR_API void instrlist_insert_mov_instr_addr (void *drcontext, instr_t *src_inst, byte *encode_estimate, opnd_t dst, instrlist_t *ilist, instr_t *where, instr_t **first DR_PARAM_OUT, instr_t **last DR_PARAM_OUT)
 
DR_API void instrlist_insert_push_instr_addr (void *drcontext, instr_t *src_inst, byte *encode_estimate, instrlist_t *ilist, instr_t *where, instr_t **first DR_PARAM_OUT, instr_t **last DR_PARAM_OUT)
 
DR_API reg_id_t dr_get_stolen_reg (void)
 
DR_API bool dr_insert_get_stolen_reg_value (void *drcontext, instrlist_t *ilist, instr_t *instr, reg_id_t reg)
 
DR_API bool dr_insert_set_stolen_reg_value (void *drcontext, instrlist_t *ilist, instr_t *instr, reg_id_t reg)
 
DR_API int dr_remove_it_instrs (void *drcontext, instrlist_t *ilist)
 
DR_API int dr_insert_it_instrs (void *drcontext, instrlist_t *ilist)
 
DR_API bool dr_insert_get_app_tls (void *drcontext, instrlist_t *ilist, instr_t *instr, reg_id_t tls_reg, reg_id_t reg)
 
DR_API void dr_insert_save_fpstate (void *drcontext, instrlist_t *ilist, instr_t *where, opnd_t buf)
 
DR_API void dr_insert_restore_fpstate (void *drcontext, instrlist_t *ilist, instr_t *where, opnd_t buf)
 
DR_API bool dr_insert_get_seg_base (void *drcontext, instrlist_t *ilist, instr_t *instr, reg_id_t seg, reg_id_t reg)
 

Detailed Description

Code transformation utilities.

Macro Definition Documentation

◆ SPILL_SLOT_REDIRECT_NATIVE_TGT

#define SPILL_SLOT_REDIRECT_NATIVE_TGT   SPILL_SLOT_1

Flags to request non-default preservation of state in a clean call

Enumeration Type Documentation

◆ 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().

Note
Some spill slots may be faster to access than others. Currently spill slots 1-3 are significantly faster to access than the others when running without -thread_private. When running with -thread_private all spill slots are expected to have similar performance. This is subject to change in future releases, but clients may assume that smaller numbered spill slots are faster or the same cost to access as larger numbered spill slots.
The number of spill slots may change in future releases.
Enumerator
SPILL_SLOT_2 

spill slot for register save/restore routines

SPILL_SLOT_3 

spill slot for register save/restore routines

SPILL_SLOT_4 

spill slot for register save/restore routines

SPILL_SLOT_5 

spill slot for register save/restore routines

SPILL_SLOT_6 

spill slot for register save/restore routines

SPILL_SLOT_7 

spill slot for register save/restore routines

SPILL_SLOT_8 

spill slot for register save/restore routines

SPILL_SLOT_9 

spill slot for register save/restore routines

SPILL_SLOT_10 

spill slot for register save/restore routines

SPILL_SLOT_11 

spill slot for register save/restore routines

Note
x64 only
SPILL_SLOT_12 

spill slot for register save/restore routines

Note
x64 only
SPILL_SLOT_13 

spill slot for register save/restore routines

Note
x64 only
SPILL_SLOT_14 

spill slot for register save/restore routines

Note
x64 only
SPILL_SLOT_15 

spill slot for register save/restore routines

Note
x64 only
SPILL_SLOT_16 

spill slot for register save/restore routines

Note
x64 only
SPILL_SLOT_17 

spill slot for register save/restore routines

Note
x64 only
SPILL_SLOT_MAX 

spill slot for register save/restore routines

Note
x64 only

Function Documentation

◆ dr_call_on_clean_stack()

DR_API void* dr_call_on_clean_stack ( void *  drcontext,
void *(*)(void)  func,
void *  arg1,
void *  arg2,
void *  arg3,
void *  arg4,
void *  arg5,
void *  arg6,
void *  arg7,
void *  arg8 
)

Calls the specified function func after switching to the DR stack for the thread corresponding to drcontext. Passes in 8 arguments. Uses the C calling convention, so func will work just fine even if if takes fewer than 8 args. Swaps the stack back upon return and returns the value returned by func.

On Windows, this routine does swap the TEB stack fields, avoiding issues with fault handling on Windows 8.1. This means there is no need for the callee to use dr_switch_to_dr_state_ex() with DR_STATE_STACK_BOUNDS.

◆ dr_cleanup_after_call()

DR_API 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.

◆ dr_clobber_retaddr_after_read()

DR_API bool dr_clobber_retaddr_after_read ( void *  drcontext,
instrlist_t ilist,
instr_t instr,
ptr_uint_t  value 
)

Causes DynamoRIO to insert code that stores value into the return address slot on the stack immediately after the original value is read by the return instruction instr. instr must be a return instruction or this routine will fail.

On ARM, value is ignored and instead a value that is guaranteed to not look like a return address is used. This is for efficiency reasons, as on ARM it would require an extra register spill in order to write an arbitrary value.

Note
This is meant to make it easier to obtain efficient callstacks by eliminating stale return addresses from prior stack frames. However, it is possible that writing to the application stack could result in incorrect application behavior, so use this at your own risk.
Returns
whether successful.

◆ dr_get_mcontext()

DR_API bool dr_get_mcontext ( void *  drcontext,
dr_mcontext_t context 
)

Copies the fields of the current application machine context selected by the flags field of context into context.

This routine may only be called from:

Even when DR_MC_CONTROL is specified, does NOT copy the pc field, except for system call events, when it will point at the post-syscall address, and kernel transfer events, when it will point to the target pc.

Returns false if called from the init event or the initial thread's init event; returns true otherwise (cannot distinguish whether the caller is in a clean call so it is up to the caller to ensure it is used properly).

The size field of context must be set to the size of the structure as known at compile time. If the size field is invalid, this routine will return false.

The flags field of context must be set to the desired amount of information using the dr_mcontext_flags_t values. Asking for multimedia registers incurs a higher performance cost. An invalid flags value will return false.

Note
NUM_SIMD_SLOTS in the dr_mcontext_t.xmm array are filled in, but only if dr_mcontext_xmm_fields_valid() returns true and DR_MC_MULTIMEDIA is set in the flags field.
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().
System data structures are swapped to private versions prior to invoking clean calls or client events. Use dr_switch_to_app_state() to examine the application version of system state.

◆ dr_get_stolen_reg()

DR_API reg_id_t dr_get_stolen_reg ( void  )

Returns the register that is stolen and used by DynamoRIO. Reference Register Stolen by DynamoRIO for more information.

◆ dr_insert_call()

DR_API 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 any caller-saved registers that the callee might modify.

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, for purposes of reachability, this call is assumed to be destined for encoding into DR's code cache-reachable memory region. This includes the code cache as well as memory allocated with dr_thread_alloc(), dr_global_alloc(), dr_nonheap_alloc(), or dr_custom_alloc() with DR_ALLOC_CACHE_REACHABLE. The call used here will be direct if it is reachable from those locations; if it is not reachable, an indirect call through r11 will be used (with r11's contents being clobbered). Use dr_insert_call_ex() when encoding to a location other than DR's regular code region.

Note
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 DR_REG_XSP are not supported in 64-bit mode.

◆ dr_insert_call_ex()

DR_API bool dr_insert_call_ex ( void *  drcontext,
instrlist_t ilist,
instr_t where,
byte *  encode_pc,
void *  callee,
uint  num_args,
  ... 
)

Identical to dr_insert_call() except it takes in encode_pc indicating roughly where the call sequence will be encoded. If callee is not reachable from encode_pc plus or minus one page, an indirect call will be used instead of the direct call used by dr_insert_call(). The indirect call overwrites the r11 register.

Returns
true if the inserted call is direct and false if indirect.

◆ dr_insert_call_instrumentation()

DR_API 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:

  1. address of call instruction (caller)
  2. target address of call (callee)
    Note
    Sets DR_CLEANCALL_READS_APP_CONTEXT and DR_CLEANCALL_WRITES_APP_CONTEXT. Conditionally skipping the instrumentation inserted by this routine is not supported (i.e., DR_CLEANCALL_MULTIPATH is not supported here).

◆ dr_insert_cbr_instrumentation()

DR_API 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:

  1. address of branch instruction
  2. target address of branch
  3. 0 if the branch is not taken, 1 if it is taken
    Note
    Sets DR_CLEANCALL_READS_APP_CONTEXT and DR_CLEANCALL_WRITES_APP_CONTEXT. Conditionally skipping the instrumentation inserted by this routine is not supported (i.e., DR_CLEANCALL_MULTIPATH is not supported here).

◆ dr_insert_cbr_instrumentation_ex()

DR_API void dr_insert_cbr_instrumentation_ex ( void *  drcontext,
instrlist_t ilist,
instr_t instr,
void *  callee,
opnd_t  user_data 
)

Assumes that instr is a conditional branch Inserts into ilist prior to instr instruction(s) to call callee passing four arguments:

  1. address of branch instruction
  2. target address of branch
  3. fall-through address of branch
  4. 0 if the branch is not taken, 1 if it is taken
  5. user defined operand (e.g., TLS slot, immed value, register, etc.)
    Note
    The user defined operand cannot use register ebx!
    Sets DR_CLEANCALL_READS_APP_CONTEXT and DR_CLEANCALL_WRITES_APP_CONTEXT. Conditionally skipping the instrumentation inserted by this routine is not supported (i.e., DR_CLEANCALL_MULTIPATH is not supported here).

◆ dr_insert_clean_call()

DR_API 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.

This routine expects to be passed a number of arguments beyond num_args equal to the value of num_args. Each of those arguments is a parameter to pass to the clean call, in the order passed to this routine. Each argument should be of type opnd_t and will be copied into the proper location for that argument slot as specified by the calling convention.

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(). However, if register reservation code is in use (e.g., via the drreg extension library: Register Management), dr_insert_clean_call_ex() must be called with its flags argument including DR_CLEANCALL_READS_APP_CONTEXT (for dr_get_mcontext() use) and/or DR_CLEANCALL_WRITES_APP_CONTEXT (for dr_set_mcontext() use) (and possibly DR_CLEANCALL_MULTIPATH) to ensure proper interaction with register reservations.

On x86, if save_fpstate is true, preserves the x87 floating-point and MMX 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()). The last floating-point instruction address in the saved state is left in an untranslated state (i.e., it may point into the code cache). This optional floating-point state preservation is specific to x87; floating-point values in XMM, YMM, or ZMM registers, or any SIMD register on any non-x86 architecture, are always preserved. Thus, on ARM/AArch64, save_fpstate is ignored.

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.

The clean call sequence will be optimized based on the runtime option -opt_cleancall.

For 64-bit, for purposes of reachability, this call is assumed to be destined for encoding into DR's code cache-reachable memory region. This includes the code cache as well as memory allocated with dr_thread_alloc(), dr_global_alloc(), dr_nonheap_alloc(), or dr_custom_alloc() with DR_ALLOC_CACHE_REACHABLE. The call used here will be direct if it is reachable from those locations; if it is not reachable, an indirect call through r11 will be used (with r11's contents being clobbered). Use dr_insert_clean_call_ex() with DR_CLEANCALL_INDIRECT to ensure reachability when encoding to a location other than DR's regular code region. See also dr_insert_call_ex().

Note
The stack used to save state and call 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 DR_REG_XSP are not supported (full DR_REG_XSP is supported).

◆ dr_insert_clean_call_ex()

DR_API void dr_insert_clean_call_ex ( void *  drcontext,
instrlist_t ilist,
instr_t where,
void *  callee,
dr_cleancall_save_t  save_flags,
uint  num_args,
  ... 
)

Identical to dr_insert_clean_call() except it takes in save_flags which allows requests to not save certain state. This is intended for use at application call entry points or other contexts where a client is comfortable making assumptions. Keep in mind that any register that is not saved will not be present in a context obtained from dr_get_mcontext().

◆ dr_insert_get_app_tls()

DR_API bool dr_insert_get_app_tls ( void *  drcontext,
instrlist_t ilist,
instr_t instr,
reg_id_t  tls_reg,
reg_id_t  reg 
)

Insert code to get the application value of the thread pointer register into register reg.

Returns
whether successful.
Note
RISCV-only

◆ dr_insert_get_seg_base()

DR_API bool dr_insert_get_seg_base ( void *  drcontext,
instrlist_t ilist,
instr_t instr,
reg_id_t  seg,
reg_id_t  reg 
)

Insert code to get the segment base address pointed to by seg into register reg. In Linux, it is only supported with -mangle_app_seg option. In Windows, it only supports getting base address of the TLS segment.

Returns
whether successful.

◆ dr_insert_get_stolen_reg_value()

DR_API bool dr_insert_get_stolen_reg_value ( void *  drcontext,
instrlist_t ilist,
instr_t instr,
reg_id_t  reg 
)

Insert code to get the application value of the register stolen by DynamoRIO into register reg. Reference Register Stolen by DynamoRIO for more information.

Returns
whether successful.
Note
ARM-only

◆ dr_insert_it_instrs()

DR_API int dr_insert_it_instrs ( void *  drcontext,
instrlist_t ilist 
)

Inserts enough OP_it instructions with proper parameters into ilist to make all predicated instructions in ilist legal in Thumb mode (DR_ISA_ARM_THUMB). Treats predicated app and tool instructions identically, but marks inserted OP_it instructions as app instructions (see instr_set_app()).

Returns
the number of OP_it instructions inserted; -1 on error.
Note
ARM-only

◆ dr_insert_mbr_instrumentation()

DR_API 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:

  1. address of branch instruction
  2. target address of branch
    Note
    Only the address portion of a far indirect branch is considered.
    scratch_slot must be <= dr_max_opnd_accessible_spill_slot(). scratch_slot is used internally to this routine and will be clobbered.
    Sets DR_CLEANCALL_READS_APP_CONTEXT and DR_CLEANCALL_WRITES_APP_CONTEXT. Conditionally skipping the instrumentation inserted by this routine is not supported (i.e., DR_CLEANCALL_MULTIPATH is not supported here).

◆ dr_insert_read_tls_field()

DR_API 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().

◆ dr_insert_restore_fpstate()

DR_API void dr_insert_restore_fpstate ( void *  drcontext,
instrlist_t ilist,
instr_t where,
opnd_t  buf 
)

Inserts into ilist prior to where meta-instruction(s) to restore the x87 floating point state from the 16-byte-aligned buffer referred to by buf, which must be 512 bytes for processors with the FXSR feature, and 108 bytes for those without (where this routine does not support 16-bit operand sizing). buf should have size of OPSZ_512; this routine will automatically adjust it to OPSZ_108 if necessary.

Note
proc_fpstate_save_size() can be used to determine the particular size needed.

When the FXSR feature is present, the fxsave format matches the bitwidth of the ISA mode of the current thread (see dr_get_isa_mode()).

◆ dr_insert_save_fpstate()

DR_API void dr_insert_save_fpstate ( void *  drcontext,
instrlist_t ilist,
instr_t where,
opnd_t  buf 
)

Inserts into ilist prior to where meta-instruction(s) to save the x87 floating point state into the 16-byte-aligned buffer referred to by buf, which must be 512 bytes for processors with the FXSR feature, and 108 bytes for those without (where this routine does not support 16-bit operand sizing). buf should have size of OPSZ_512; this routine will automatically adjust it to OPSZ_108 if necessary.

Note
proc_fpstate_save_size() can be used to determine the particular size needed.

When the FXSR feature is present, the fxsave format matches the bitwidth of the ISA mode of the current thread (see dr_get_isa_mode()).

The last floating-point instruction address is left in an untranslated state (i.e., it may point into the code cache).

◆ dr_insert_set_stolen_reg_value()

DR_API bool dr_insert_set_stolen_reg_value ( void *  drcontext,
instrlist_t ilist,
instr_t instr,
reg_id_t  reg 
)

Insert code to set the value of register reg as the application value of the register stolen by DynamoRIO Reference Register Stolen by DynamoRIO for more information.

Returns
whether successful.
Note
ARM-only

◆ dr_insert_ubr_instrumentation()

DR_API 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:

  1. address of branch instruction
  2. target address of branch
Warning
Basic block eliding is controlled by -max_elide_jmp. If that option is set to non-zero, ubrs may never be seen.
Note
Sets DR_CLEANCALL_READS_APP_CONTEXT and DR_CLEANCALL_WRITES_APP_CONTEXT. Conditionally skipping the instrumentation inserted by this routine is not supported (i.e., DR_CLEANCALL_MULTIPATH is not supported here).

◆ dr_insert_write_tls_field()

DR_API 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_max_opnd_accessible_spill_slot()

DR_API 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().

◆ dr_mcontext_to_context()

DR_API bool dr_mcontext_to_context ( CONTEXT *  dst,
dr_mcontext_t src 
)

Copies the machine state in src into dst. Sets the ContextFlags field of dst to reflect the flags field of src. However, CONTEXT_CONTROL includes Ebp/Rbp, while that's under DR_MC_INTEGER, so we recommend always setting both DR_MC_INTEGER and DR_MC_CONTROL when calling this routine.

It is up to the caller to ensure that dst is allocated and initialized properly in order to contain multimedia processor state, if DR_MC_MULTIMEDIA is set in the flags field of src.

The current segment register values are filled in under the assumption that this context is for the calling thread.

Note
floating-point values are not filled in for dst.
Windows only.
Returns
false if unsuccessful; if successful, does not return.

◆ dr_mcontext_xmm_fields_valid()

DR_API bool dr_mcontext_xmm_fields_valid ( void  )

Returns true if the simd fields in dr_mcontext_t are valid xmm, ymm, or zmm values (i.e., whether the underlying processor supports SSE).

Note
If DR_MC_MULTIMEDIA is not specified when calling dr_get_mcontext(), the simd fields will not be filled in regardless of the return value of this routine.

◆ dr_mcontext_zmm_fields_valid()

DR_API bool dr_mcontext_zmm_fields_valid ( void  )

Returns true if the simd fields in dr_mcontext_t are valid zmm values (i.e., whether the underlying processor and OS support AVX-512 and AVX-512 code is present).

Note
If DR_MC_MULTIMEDIA is not specified when calling dr_get_mcontext(), the simd fields will not be filled in regardless of the return value of this routine.

◆ dr_merge_arith_flags()

DR_API reg_t dr_merge_arith_flags ( reg_t  cur_xflags,
reg_t  saved_xflag 
)

A convenience routine to aid restoring the arith flags done by outlined code, such as when handling restore state events. The routine takes the current value of the flags register cur_xflags, as well as the saved value saved_xflag, in order to return the original app value.

◆ dr_prepare_for_call()

DR_API 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).

Warning
On x86, this routine does NOT save the x87 floating-point or MMX state: to do that the instrumentation routine should call proc_save_fpstate() to save and then proc_restore_fpstate() to restore (or use dr_insert_clean_call()).
Note
The preparation modifies the DR_REG_XSP and DR_REG_XAX registers (after saving them). Use dr_insert_clean_call() instead if an argument to the subsequent call that references DR_REG_XAX is desired.
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.

◆ dr_read_saved_reg()

DR_API 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().

◆ dr_redirect_execution()

DR_API bool dr_redirect_execution ( dr_mcontext_t context)

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 xmm fields that are valid according to dr_mcontext_xmm_fields_valid()). The flags field of context must contain DR_MC_ALL; using a partial set of fields is not suported.

For 32-bit ARM, be sure to use dr_app_pc_as_jump_target() to properly set the ISA mode for the continuation pc if it was obtained from instr_get_app_pc() or a similar source rather than from dr_get_proc_address(). This will set the least significant bit of the mcontext pc field to 1 when in Thumb mode (DR_ISA_ARM_THUMB), Thumb Mode Addresses for more information.

Note
dr_get_mcontext() can be used to get the register state (except pc) saved in dr_insert_clean_call() or dr_prepare_for_call().
If x87 floating point state was saved by dr_prepare_for_call() or dr_insert_clean_call() it is not restored (other than the valid xmm fields according to dr_mcontext_xmm_fields_valid(), if DR_MC_MULTIMEDIA is specified in the flags field). 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. To set system data structures, use dr_switch_to_app_state(), make the changes, and then switch back with dr_switch_to_dr_state() before calling this routine.
This routine may only be called from a clean call from the cache. It can not be called from any registered event callback except the exception event (dr_register_exception_event()). From a signal event callback, use the DR_SIGNAL_REDIRECT return value rather than calling this routine.
If control is being redirected to a new pc (determined using drsyms, dr_get_proc_address, or any other way) ensure that the app state (such as the register values) are set as expected by the transfer point.
Returns
false if unsuccessful; if successful, does not return.

◆ dr_redirect_native_target()

DR_API byte* dr_redirect_native_target ( void *  drcontext)

Returns the target to use for a native context transfer to a target application address.

Normally, redirection is performed from a client context in a clean call or event callback by invoking dr_redirect_execution(). In some circumstances, redirection from an application (or "native") context is desirable without creating an application control transfer in a basic block.

To accomplish such a redirection, store the target application address in SPILL_SLOT_REDIRECT_NATIVE_TGT by calling dr_write_saved_reg(). Set up any other application state as desired directly in the current machine context. Then jump to the target returned by this routine. By default, the target is global and can be cached globally. However, if traces are thread-private, or if traces are disabled and basic blocks are thread-private, there will be a separate target per drcontext.

If a basic block is exited via such a redirection, the block should be emitted with the flag DR_EMIT_MUST_END_TRACE in order to avoid trace building errors.

For ARM, the address returned by this routine has its least significant bit set to 1 if the target is Thumb.

Returns null on error.

◆ dr_reg_spill_slot_opnd()

DR_API 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.

Note
slot must be <= dr_max_opnd_accessible_spill_slot()

◆ dr_remove_it_instrs()

DR_API int dr_remove_it_instrs ( void *  drcontext,
instrlist_t ilist 
)

Removes all OP_it instructions from ilist without changing the instructions that were inside each IT block. This is intended to be paired with dr_insert_it_instrs(), where a client's examination of the application instruction list and insertion of instrumentation occurs in between the two calls and thus does not have to worry about groups of instructions that cannot be separated or changed. The resulting predicated instructions are not encodable in Thumb mode (DR_ISA_ARM_THUMB): dr_insert_it_instrs() must be called before encoding.

Returns
the number of OP_it instructions removed; -1 on error.
Note
ARM-only

◆ dr_restore_app_stack()

DR_API 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_clean_stack().

◆ dr_restore_arith_flags()

DR_API 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.

Note
X86-only
Deprecated:
This routine is equivalent to dr_restore_arith_flags_from_xax() followed by dr_restore_reg().

◆ dr_restore_arith_flags_from_reg()

DR_API void dr_restore_arith_flags_from_reg ( void *  drcontext,
instrlist_t ilist,
instr_t where,
reg_id_t  reg 
)

Inserts into ilist prior to where meta-instruction(s) to restore the arithmetic flags (6 arithmetic flags on X86 or APSR on ARM) from reg. The caller must ensure that reg contains the program status flags, most likely from dr_save_arith_flags_to_reg().

Note
On X86, only DR_REG_XAX should be passed in.

◆ dr_restore_arith_flags_from_xax()

DR_API void dr_restore_arith_flags_from_xax ( void *  drcontext,
instrlist_t ilist,
instr_t where 
)

Inserts into ilist prior to where meta-instruction(s) to restore the 6 arithmetic flags from xax. This currently uses DynamoRIO's "add $0x7f %al ; sahf" code sequence, which is faster and easier than popf. The caller must ensure that xax contains the arithmetic flags, most likely from dr_save_arith_flags_to_xax().

Note
X86-only

◆ dr_restore_reg()

DR_API 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.

◆ dr_save_arith_flags()

DR_API 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().

Warning
At completion of the inserted instructions the saved flags are in the xax register. The xax register should not be modified after using this routine unless it is first saved (and later restored prior to using dr_restore_arith_flags()).
Note
X86-only
Deprecated:
This routine is equivalent to dr_save_reg() followed by dr_save_arith_flags_to_xax().

◆ dr_save_arith_flags_to_reg()

DR_API void dr_save_arith_flags_to_reg ( void *  drcontext,
instrlist_t ilist,
instr_t where,
reg_id_t  reg 
)

Inserts into ilist prior to where meta-instruction(s) to save the arithmetic flags (6 arithmetic flags on X86 or APSR on ARM) into reg. If the caller wishes to use reg between saving and restoring these flags, they must save and restore reg, potentially using dr_save_reg()/dr_restore_reg(). If the caller needs to save both the current value of reg and the flags stored to reg by this routine, they must use separate spill slots, or they will overwrite the original reg value in memory.

Note
On X86, only DR_REG_XAX should be passed in.
Warning
Clobbers reg; the caller must ensure reg is dead or saved at where.

◆ dr_save_arith_flags_to_xax()

DR_API void dr_save_arith_flags_to_xax ( void *  drcontext,
instrlist_t ilist,
instr_t where 
)

Inserts into ilist prior to where meta-instruction(s) to save the 6 arithmetic flags into xax. This currently uses DynamoRIO's "lahf ; seto al" code sequence, which is faster and easier than pushf. If the caller wishes to use xax between saving and restoring these flags, they must save and restore xax, potentially using dr_save_reg()/dr_restore_reg(). If the caller needs to save both the current value of xax and the flags stored to xax by this routine, they must use separate spill slots, or they will overwrite the original xax value in memory.

Note
X86-only
Warning
Clobbers xax; the caller must ensure xax is dead or saved at where.

◆ dr_save_reg()

DR_API 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()).

Note
The stored value remains available only until the next non-meta (i.e. application) instruction. Use dr_insert_write_tls_field() and dr_insert_read_tls_field() for a persistent (but more costly to access) thread-local-storage location. See also dr_raw_tls_calloc().

Generally, using the Register Management Extension Library instead is recommended. When using custom spills and restores, be sure to look for the labels DR_NOTE_ANNOTATION and DR_NOTE_REG_BARRIER at which all application values should be restored to registers.

◆ dr_set_mcontext()

DR_API bool dr_set_mcontext ( void *  drcontext,
dr_mcontext_t context 
)

Sets the fields of the application machine context selected by the flags field of context to the values in context.

This routine may only be called from:

Ignores the pc field, except for kernel transfer events.

If the size field of context is invalid, this routine will return false. A dr_mcontext_t obtained from DR will have the size field set.

The flags field of context must be set to select the desired fields for copying, using the dr_mcontext_flags_t values. Asking to copy multimedia registers incurs a higher performance cost. An invalid flags value will return false.

Returns
whether successful.
Note
The xmm fields are only set for processes where the underlying processor supports them (and when DR_MC_MULTIMEDIA is set in the flags field). For dr_insert_clean_call() that requested save_fpstate, the xmm values set here override that saved state. Use dr_mcontext_xmm_fields_valid() to determine whether the xmm fields are valid.

◆ dr_swap_to_clean_stack()

DR_API 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.

Note
The DR stack 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.

◆ dr_write_saved_reg()

DR_API 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.

Note
This routine should only be used during a clean call out of the cache. Use at any other time could corrupt application or DynamoRIO state.

◆ instrlist_insert_mov_immed_ptrsz()

DR_API void instrlist_insert_mov_immed_ptrsz ( void *  drcontext,
ptr_int_t  val,
opnd_t  dst,
instrlist_t ilist,
instr_t where,
instr_t **first  DR_PARAM_OUT,
instr_t **last  DR_PARAM_OUT 
)

Create meta instructions for storing pointer-size integer val to dst, and then insert them into ilist prior to where. Pointers to the first and last created meta instructions are returned in first and last, unless only one meta instruction is created, in which case NULL is returned in last. If the instruction is a no-op (when dst is the zero register on AArch64) then no instructions are created and NULL is returned in first and last.

◆ instrlist_insert_mov_instr_addr()

DR_API void instrlist_insert_mov_instr_addr ( void *  drcontext,
instr_t src_inst,
byte *  encode_estimate,
opnd_t  dst,
instrlist_t ilist,
instr_t where,
instr_t **first  DR_PARAM_OUT,
instr_t **last  DR_PARAM_OUT 
)

Create meta instructions for storing the address of src_inst to dst, and then insert them into ilist prior to where. The encode_estimate parameter, used only for 64-bit mode, indicates whether the final address of src_inst, when it is encoded later, will fit in 32 bits or needs 64 bits. If the encoding will be in DynamoRIO's code cache, pass NULL. If the final encoding location is unknown, pass a high address to be on the safe side. Pointers to the first and last created meta instructions are returned in first and last, unless only one meta instruction is created, in which case NULL is returned in last. If the instruction is a no-op (when dst is the zero register on AArch64) then no instructions are created and NULL is returned in first and last.

◆ instrlist_insert_push_immed_ptrsz()

DR_API void instrlist_insert_push_immed_ptrsz ( void *  drcontext,
ptr_int_t  val,
instrlist_t ilist,
instr_t where,
instr_t **first  DR_PARAM_OUT,
instr_t **last  DR_PARAM_OUT 
)

Create meta instructions for pushing pointer-size integer val on the stack, and then insert them into ilist prior to where. Pointers to the first and last created meta instructions are returned in first and last, unless only one meta instruction is created, in which case NULL is returned in last.

◆ instrlist_insert_push_instr_addr()

DR_API void instrlist_insert_push_instr_addr ( void *  drcontext,
instr_t src_inst,
byte *  encode_estimate,
instrlist_t ilist,
instr_t where,
instr_t **first  DR_PARAM_OUT,
instr_t **last  DR_PARAM_OUT 
)

Create meta instructions for pushing the address of src_inst on the stack, and then insert them into ilist prior to where. The encode_estimate parameter, used only for 64-bit mode, indicates whether the final address of src_inst, when it is encoded later, will fit in 32 bits or needs 64 bits. If the encoding will be in DynamoRIO's code cache, pass NULL. If the final encoding location is unknown, pass a high address to be on the safe side. Pointers to the first and last created meta instructions are returned in first and last, unless only one meta instruction is created, in which case NULL is returned in last.

◆ instrlist_meta_append()

DR_API void instrlist_meta_append ( instrlist_t ilist,
instr_t instr 
)

Inserts instr as a non-application instruction onto the end of ilist

◆ instrlist_meta_fault_append()

DR_API 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.

Deprecated:
Essentially equivalent to instrlist_meta_append()

◆ instrlist_meta_fault_postinsert()

DR_API void instrlist_meta_fault_postinsert ( instrlist_t ilist,
instr_t where,
instr_t instr 
)

Inserts instr as a non-application instruction that can fault (see instr_set_meta_may_fault()) into ilist after where.

Deprecated:
Essentially equivalent to instrlist_meta_postinsert()

◆ instrlist_meta_fault_preinsert()

DR_API void instrlist_meta_fault_preinsert ( instrlist_t ilist,
instr_t where,
instr_t instr 
)

Inserts instr as a non-application instruction that can fault (see instr_set_meta_may_fault()) into ilist prior to where.

Deprecated:
Essentially equivalent to instrlist_meta_preinsert()

◆ instrlist_meta_postinsert()

DR_API void instrlist_meta_postinsert ( instrlist_t ilist,
instr_t where,
instr_t instr 
)

Inserts instr as a non-application instruction into ilist after where.

◆ instrlist_meta_preinsert()

DR_API void instrlist_meta_preinsert ( instrlist_t ilist,
instr_t where,
instr_t instr 
)

Inserts instr as a non-application instruction into ilist prior to where.