DynamoRIO API
Register Usage Coordinator

Data Structures

struct  _drreg_options_t
 
struct  _drreg_reserve_info_t
 

Macros

#define DRMGR_PRIORITY_NAME_DRREG_HIGH   "drreg_high"
 
#define DRMGR_PRIORITY_NAME_DRREG_LOW   "drreg_low"
 
#define DRMGR_PRIORITY_NAME_DRREG_FAULT   "drreg_fault"
 

Typedefs

typedef struct _drreg_options_t drreg_options_t
 
typedef struct _drreg_reserve_info_t drreg_reserve_info_t
 

Enumerations

enum  drreg_status_t {
  DRREG_SUCCESS,
  DRREG_ERROR,
  DRREG_ERROR_INVALID_PARAMETER,
  DRREG_ERROR_FEATURE_NOT_AVAILABLE,
  DRREG_ERROR_REG_CONFLICT,
  DRREG_ERROR_IN_USE,
  DRREG_ERROR_OUT_OF_SLOTS,
  DRREG_ERROR_NO_APP_VALUE
}
 
enum  {
  DRMGR_PRIORITY_INSERT_DRREG_HIGH = -7500,
  DRMGR_PRIORITY_INSERT_DRREG_LOW = 7500,
  DRMGR_PRIORITY_FAULT_DRREG = -7500
}
 
enum  drreg_bb_properties_t {
  DRREG_CONTAINS_SPANNING_CONTROL_FLOW = 0x001,
  DRREG_IGNORE_CONTROL_FLOW = 0x002
}
 

Functions

DR_EXPORT drreg_status_t drreg_init (drreg_options_t *ops)
 
DR_EXPORT drreg_status_t drreg_exit (void)
 
DR_EXPORT drreg_status_t drreg_max_slots_used (OUT uint *max)
 
DR_EXPORT drreg_status_t drreg_reserve_aflags (void *drcontext, instrlist_t *ilist, instr_t *where)
 
DR_EXPORT drreg_status_t drreg_unreserve_aflags (void *drcontext, instrlist_t *ilist, instr_t *where)
 
DR_EXPORT drreg_status_t drreg_aflags_liveness (void *drcontext, instr_t *inst, OUT uint *value)
 
DR_EXPORT drreg_status_t drreg_are_aflags_dead (void *drcontext, instr_t *inst, bool *dead)
 
DR_EXPORT drreg_status_t drreg_restore_app_aflags (void *drcontext, instrlist_t *ilist, instr_t *where)
 
DR_EXPORT drreg_status_t drreg_reserve_register (void *drcontext, instrlist_t *ilist, instr_t *where, drvector_t *reg_allowed, OUT reg_id_t *reg)
 
DR_EXPORT drreg_status_t drreg_reserve_dead_register (void *drcontext, instrlist_t *ilist, instr_t *where, drvector_t *reg_allowed, OUT reg_id_t *reg)
 
DR_EXPORT drreg_status_t drreg_init_and_fill_vector (drvector_t *vec, bool allowed)
 
DR_EXPORT drreg_status_t drreg_set_vector_entry (drvector_t *vec, reg_id_t reg, bool allowed)
 
DR_EXPORT drreg_status_t drreg_get_app_value (void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t app_reg, reg_id_t dst_reg)
 
DR_EXPORT drreg_status_t drreg_restore_app_values (void *drcontext, instrlist_t *ilist, instr_t *where, opnd_t opnd, INOUT reg_id_t *swap)
 
DR_EXPORT drreg_status_t drreg_statelessly_restore_app_value (void *drcontext, instrlist_t *ilist, reg_id_t reg, instr_t *where_restore, instr_t *where_respill, bool *restore_needed OUT, bool *respill_needed OUT)
 
DR_EXPORT drreg_status_t drreg_reservation_info (void *drcontext, reg_id_t reg, opnd_t *opnd OUT, bool *is_dr_slot OUT, uint *tls_offs OUT)
 
DR_EXPORT drreg_status_t drreg_reservation_info_ex (void *drcontext, reg_id_t reg, drreg_reserve_info_t *info OUT)
 
DR_EXPORT drreg_status_t drreg_unreserve_register (void *drcontext, instrlist_t *ilist, instr_t *where, reg_id_t reg)
 
DR_EXPORT drreg_status_t drreg_is_register_dead (void *drcontext, reg_id_t reg, instr_t *inst, bool *dead)
 
DR_EXPORT drreg_status_t drreg_set_bb_properties (void *drcontext, drreg_bb_properties_t flags)
 
DR_EXPORT drreg_status_t drreg_is_instr_spill_or_restore (void *drcontext, instr_t *instr, bool *spill OUT, bool *restore OUT, reg_id_t *reg_spilled OUT)
 

Detailed Description

Macro Definition Documentation

◆ DRMGR_PRIORITY_NAME_DRREG_FAULT

#define DRMGR_PRIORITY_NAME_DRREG_FAULT   "drreg_fault"

Name of drreg fault handling event.

◆ DRMGR_PRIORITY_NAME_DRREG_HIGH

#define DRMGR_PRIORITY_NAME_DRREG_HIGH   "drreg_high"

Name of drreg instrumentation pass priorities for analysis and insert steps that are meant to take place before any tool actions.

◆ DRMGR_PRIORITY_NAME_DRREG_LOW

#define DRMGR_PRIORITY_NAME_DRREG_LOW   "drreg_low"

Name of drreg instrumentation pass priorities for analysis and insert steps that are meant to take place after any tool actions.

Typedef Documentation

◆ drreg_options_t

Specifies the options when initializing drreg.

◆ drreg_reserve_info_t

Contains information about a register's reservation and restoration status.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Priorities of drmgr instrumentation passes used by drreg. Users of drreg can use the name DRMGR_PRIORITY_NAME_DRREG in the drmgr_priority_t.before field or can use these numeric priorities in the drmgr_priority_t.priority field to ensure proper instrumentation pass ordering.

Enumerator
DRMGR_PRIORITY_INSERT_DRREG_HIGH 

Priority of drreg analysis and pre-insert

DRMGR_PRIORITY_INSERT_DRREG_LOW 

Priority of drreg post-insert

DRMGR_PRIORITY_FAULT_DRREG 

Priority of drreg fault handling event

◆ drreg_bb_properties_t

Flags passed to drreg_set_bb_properties().

Enumerator
DRREG_CONTAINS_SPANNING_CONTROL_FLOW 

drreg was designed for linear control flow and assumes that it can safely wait to restore an unreserved scratch register across application instructions. If a client inserts internal control flow that crosses application instructions (hence "spanning"), and the client is not explicitly ensuring that each forward jump contains the same set of saved scratch registers at its source and target (typically done by saving all scratch registers needed inside control flow prior to any forward branches), the client should set this property either prior to the drmgr insertion phase or as early as possible in the insertion phase. Setting this property causes application instructions to become barriers to spilled scratch registers that have been unreserved but have not yet been lazily restored. drreg will still collapse adjacent spill+restore pairs for the same app instr.

DRREG_IGNORE_CONTROL_FLOW 

drreg was designed for linear control flow. Normally, drreg disables optimizations if it sees any kind of internal control flow (viz., a branch with an instr_t target) that was added during drmgr's app2app phase, which includes flow added by drutil_expand_rep_string(). The primary consequence of disabling optimizations means that application instructions become barriers to spilled scratch registers that have been unreserved but have not yet been lazily restored, which are restored prior to each application instruction. If this flag is set, drreg assumes that internal control flow either does not cross application instructions or that the client is ensuring that each forward jump contains the same set of saved scratch registers at its source and target (typically done by saving all scratch registers needed inside control flow prior to any forward branches). Such scratch registers are then restored prior to each application instruction.

◆ drreg_status_t

Success code for each drreg operation

Enumerator
DRREG_SUCCESS 

Operation succeeded.

DRREG_ERROR 

Operation failed.

DRREG_ERROR_INVALID_PARAMETER 

Operation failed: invalid parameter

DRREG_ERROR_FEATURE_NOT_AVAILABLE 

Operation failed: not available

DRREG_ERROR_REG_CONFLICT 

Operation failed: register conflict

DRREG_ERROR_IN_USE 

Operation failed: resource already in use

DRREG_ERROR_OUT_OF_SLOTS 

Operation failed: no more TLS slots

DRREG_ERROR_NO_APP_VALUE 

Operation failed: app value not available. Set conservative in drreg_options_t to avoid this error.

Function Documentation

◆ drreg_aflags_liveness()

DR_EXPORT drreg_status_t drreg_aflags_liveness ( void *  drcontext,
instr_t inst,
OUT uint *  value 
)

Returns in value EFLAGS_READ_6 bits telling which arithmetic flags are live at the point of inst. If called during drmgr's insertion phase, inst must be the current application instruction.

Returns
whether successful or an error code on failure.

◆ drreg_are_aflags_dead()

DR_EXPORT drreg_status_t drreg_are_aflags_dead ( void *  drcontext,
instr_t inst,
bool *  dead 
)

Returns in dead whether the arithmetic flags are all dead at the point of inst. If called during drmgr's insertion phase, inst must be the current application instruction.

Returns
whether successful or an error code on failure.

◆ drreg_exit()

DR_EXPORT drreg_status_t drreg_exit ( void  )

Cleans up the drreg extension.

Returns
whether successful or an error code on failure.

◆ drreg_get_app_value()

DR_EXPORT drreg_status_t drreg_get_app_value ( void *  drcontext,
instrlist_t *  ilist,
instr_t where,
reg_id_t  app_reg,
reg_id_t  dst_reg 
)

Inserts instructions at where in ilist to retrieve the application value for app_reg into dst_reg. This will automatically be done for reserved registers prior to an application instruction that reads app_reg, but sometimes instrumentation needs to read the application value of a register that has been reserved. If app_reg is a dead register, DRREG_ERROR_NO_APP_VALUE may be returned. Set conservative in drreg_options_t to avoid this error.

If called during drmgr's insertion phase, where must be the current application instruction.

On ARM, asking to place the application value of the register returned by dr_get_stolen_reg() into itself is not supported. Instead the caller should use dr_insert_get_stolen_reg_value() and opnd_replace_reg() to swap the use of the stolen register within a tool instruction with a scratch register.

Returns
whether successful or an error code on failure.

◆ drreg_init()

DR_EXPORT drreg_status_t drreg_init ( drreg_options_t ops)

Initializes the drreg extension. Must be called prior to any of the other routines. Can be called multiple times (by separate components, normally) but each call must be paired with a corresponding call to drreg_exit(). The fields of ops are combined from multiple calls as described in the documentation for each field. Typically the end-user tool itself specifies these options, with most other library components not directly interacting with drreg (libraries often take in scratch registers from the caller for most of their operations).

Parameters
[in]opsSpecifies the optional parameters that control how drreg operates.
Returns
whether successful or an error code on failure.

◆ drreg_init_and_fill_vector()

DR_EXPORT drreg_status_t drreg_init_and_fill_vector ( drvector_t vec,
bool  allowed 
)

Initializes vec to hold DR_NUM_GPR_REGS entries, each either set to NULL if allowed is false or a non-NULL value if allowed is true. This is intendend as a convenience routine for setting up the reg_allowed parameter to drreg_reserve_register().

Returns
whether successful or an error code on failure.

◆ drreg_is_instr_spill_or_restore()

DR_EXPORT drreg_status_t drreg_is_instr_spill_or_restore ( void *  drcontext,
instr_t instr,
bool *spill  OUT,
bool *restore  OUT,
reg_id_t *reg_spilled  OUT 
)

Analyzes instr and returns whether it is a drreg register spill in spill, a drreg register restore in restore, and which register is being spilled or restored in reg_spilled. Each output parameter is optional and may be NULL. If DR's spill slots are being used (see drreg_options_t.num_spill_slots), this routine may not be able to distinguish a drreg spill or restore from some other spill or restore.

Returns
whether successful or an error code on failure.

◆ drreg_is_register_dead()

DR_EXPORT drreg_status_t drreg_is_register_dead ( void *  drcontext,
reg_id_t  reg,
instr_t inst,
bool *  dead 
)

Returns in dead whether the register reg is dead at the point of inst. If called during drmgr's insertion phase, inst must be the current application instruction.

Returns
whether successful or an error code on failure.

◆ drreg_max_slots_used()

DR_EXPORT drreg_status_t drreg_max_slots_used ( OUT uint *  max)

In debug build, drreg tracks the maximum simultaneous number of spill slots in use. This can help a user to tune drreg_options_t.num_spill_slots.

Parameters
[out]maxThe maximum number of spill slots used is written here.
Returns
whether successful or an error code on failure. In release build, this routine always fails.

◆ drreg_reservation_info()

DR_EXPORT drreg_status_t drreg_reservation_info ( void *  drcontext,
reg_id_t  reg,
opnd_t *opnd  OUT,
bool *is_dr_slot  OUT,
uint *tls_offs  OUT 
)

Returns information about the TLS slot assigned to reg, which must be a currently-reserved register.

If opnd is non-NULL, returns an opnd_t in opnd that references the TLS slot assigned to reg. If too many slots are in use and reg is stored in a non-directly-addressable slot, returns a null opnd_t in opnd.

If is_dr_slot is non-NULL, returns true if the slot is a DR slot (and can thus be accessed by dr_read_saved_reg()) and false if the slot is inside the dr_raw_tls_calloc() allocation used by drreg.

If tls_offs is non-NULL, if the slot is a DR slot, returns the DR slot index; otherwise, returns the offset from the TLS base of the slot assigned to reg.

Returns
whether successful or an error code on failure.

◆ drreg_reservation_info_ex()

DR_EXPORT drreg_status_t drreg_reservation_info_ex ( void *  drcontext,
reg_id_t  reg,
drreg_reserve_info_t *info  OUT 
)

Returns information about the reservation and restoration status of reg. The size field of info must be set before calling. To query information about the arithmetic flags, pass DR_REG_NULL for reg.

Returns
whether successful or an error code on failure.

◆ drreg_reserve_aflags()

DR_EXPORT drreg_status_t drreg_reserve_aflags ( void *  drcontext,
instrlist_t *  ilist,
instr_t where 
)

Requests exclusive use of the arithmetic flags register. Spills the application value at where in ilist, if necessary. When used during drmgr's insertion phase, optimizations such as keeping the application flags value in a register and eliding duplicate spills and restores will be automatically applied. If called during drmgr's insertion phase, where must be the current application instruction.

Returns
whether successful or an error code on failure.

◆ drreg_reserve_dead_register()

DR_EXPORT drreg_status_t drreg_reserve_dead_register ( void *  drcontext,
instrlist_t *  ilist,
instr_t where,
drvector_t reg_allowed,
OUT reg_id_t reg 
)

Identical to drreg_reserve_register() except returns failure if no register is available that does not require a spill.

Returns
whether successful or an error code on failure.

◆ drreg_reserve_register()

DR_EXPORT drreg_status_t drreg_reserve_register ( void *  drcontext,
instrlist_t *  ilist,
instr_t where,
drvector_t reg_allowed,
OUT reg_id_t reg 
)

Requests exclusive use of an application register, spilling the application value at where in ilist if necessary. The register chosen is returned in reg.

When used during drmgr's insertion phase, optimizations such as keeping the application flags value in a register and eliding duplicate spills and restores will be automatically applied. If called during drmgr's insertion phase, where must be the current application instruction.

If reg_allowed is non-NULL, only registers from the specified set will be considered, where reg_allowed must be a vector with one entry for each general-purpose register in [DR_REG_START_GPR..DR_REG_STOP_GPR] where a NULL entry indicates not allowed and any non-NULL entry indicates allowed. The drreg_init_and_fill_vector() routine can be used to set up reg_allowed.

Returns
whether successful or an error code on failure.

◆ drreg_restore_app_aflags()

DR_EXPORT drreg_status_t drreg_restore_app_aflags ( void *  drcontext,
instrlist_t *  ilist,
instr_t where 
)

This routine ensures that the application's value for the arithmetic flags is in place prior to where. This is automatically done when the flags are reserved prior to an application instruction, but sometimes instrumentation needs to read the value of the flags. This is intended as a convenience barrier for lazy restores performed by drreg.

If called during drmgr's insertion phase, where must be the current application instruction.

Returns
whether successful or an error code on failure.

◆ drreg_restore_app_values()

DR_EXPORT drreg_status_t drreg_restore_app_values ( void *  drcontext,
instrlist_t *  ilist,
instr_t where,
opnd_t  opnd,
INOUT reg_id_t swap 
)

This is a convenience routine that calls drreg_get_app_value() for every register used by opnd, with that register passed as the application and destination registers. This routine will write to reserved as well as unreserved registers. This is intended as a convenience barrier for lazy restores performed by drreg.

If called during drmgr's insertion phase, where must be the current application instruction.

On ARM, asking to place the application value of the register returned by dr_get_stolen_reg() into itself is not supported. If opnd uses the stolen register, this routine will swap it for a scratch register. This scratch register will be *swap if *swap is not DR_REG_NULL; otherwise, drreg_reserve_register() with NULL for reg_allowed will be called, and the result returned in *swap. It is up to the caller to un-reserve the register in that case.

Returns
whether successful or an error code on failure. On failure, any values that were already restored are not undone.

◆ drreg_set_bb_properties()

DR_EXPORT drreg_status_t drreg_set_bb_properties ( void *  drcontext,
drreg_bb_properties_t  flags 
)

May only be called during drmgr's app2app, analysis, or insertion phase. Sets the given properties for the current basic block being instrumented.

Returns
whether successful or an error code on failure.

◆ drreg_set_vector_entry()

DR_EXPORT drreg_status_t drreg_set_vector_entry ( drvector_t vec,
reg_id_t  reg,
bool  allowed 
)

Sets the entry in vec at index reg minus DR_REG_START_GPR to NULL if allowed is false or a non-NULL value if allowed is true. This is intendend as a convenience routine for setting up the reg_allowed parameter to drreg_reserve_register().

Returns
whether successful or an error code on failure.

◆ drreg_statelessly_restore_app_value()

DR_EXPORT drreg_status_t drreg_statelessly_restore_app_value ( void *  drcontext,
instrlist_t *  ilist,
reg_id_t  reg,
instr_t where_restore,
instr_t where_respill,
bool *restore_needed  OUT,
bool *respill_needed  OUT 
)

This routine is meant for use with instrumentation that uses separate control flow paths, such as a fastpath and a slowpath, where the slowpath needs access to the full application state yet must retain scratch register parity with the fastpath. The application value for reg is restored into reg at where_restore, but internal drreg state is not updated to reflect this. Furthermore, if doing so affects subsequent behavior, such as when reg is being used to hold the preserved application value for another register or flags, instructions are inserted at where_respill to restore the state, such that where_respill will operate correctly whether where_restore was executed or not. The optional output parameters restore_needed and respill_needed are set to indicate whether instructions were inserted at where_restore and where_respill, respectively.

The results from drreg_reservation_info_ex() can be used to predict the behavior of this routine. A restore is needed if !drreg_reserve_info_t.holds_app_value. and drreg_reserve_info_t.app_value_retained. A respill is needed if a restore is needed and drreg_reserve_info_t.opnd is a register.

If app_reg is a dead register, DRREG_ERROR_NO_APP_VALUE may be returned. Set conservative in drreg_options_t to avoid this error.

If called during drmgr's insertion phase, where must be the current application instruction.

To restore the arithmetic flags, pass DR_REG_NULL for reg.

On ARM, passing reg equal to dr_get_stolen_reg() is not supported.

Returns
whether successful or an error code on failure.

◆ drreg_unreserve_aflags()

DR_EXPORT drreg_status_t drreg_unreserve_aflags ( void *  drcontext,
instrlist_t *  ilist,
instr_t where 
)

Terminates exclusive use of the arithmetic flags register. Restores the application value at where in ilist, if necessary. If called during drmgr's insertion phase, where must be the current application instruction.

Returns
whether successful or an error code on failure.

◆ drreg_unreserve_register()

DR_EXPORT drreg_status_t drreg_unreserve_register ( void *  drcontext,
instrlist_t *  ilist,
instr_t where,
reg_id_t  reg 
)

Terminates exclusive use of the register reg. Restores the application value at where in ilist, if necessary. If called during drmgr's insertion phase, where must be the current application instruction.

Returns
whether successful or an error code on failure.