Defines | |
| #define | DRMGR_PRIORITY_NAME_DRWRAP "drwrap" |
Enumerations | |
| enum | { DRMGR_PRIORITY_APP2APP_DRWRAP = -500, DRMGR_PRIORITY_INSERT_DRWRAP = 500 } |
| enum | drwrap_wrap_flags_t { DRWRAP_UNWIND_ON_EXCEPTION = 0x01 } |
| enum | drwrap_global_flags_t { DRWRAP_SAFE_READ_RETADDR = 0x01, DRWRAP_SAFE_READ_ARGS = 0x02, DRWRAP_NO_FRILLS = 0x04, DRWRAP_FAST_CLEANCALLS = 0x08 } |
Functions | |
| DR_EXPORT bool | drwrap_init (void) |
| DR_EXPORT void | drwrap_exit (void) |
| DR_EXPORT bool | drwrap_replace (app_pc original, app_pc replacement, bool override) |
| DR_EXPORT bool | drwrap_wrap (app_pc func, void(*pre_func_cb)(void *wrapcxt, OUT void **user_data), void(*post_func_cb)(void *wrapcxt, void *user_data)) |
| DR_EXPORT bool | drwrap_wrap_ex (app_pc func, void(*pre_func_cb)(void *wrapcxt, INOUT void **user_data), void(*post_func_cb)(void *wrapcxt, void *user_data), void *user_data, drwrap_wrap_flags_t flags) |
| DR_EXPORT bool | drwrap_unwrap (app_pc func, void(*pre_func_cb)(void *wrapcxt, OUT void **user_data), void(*post_func_cb)(void *wrapcxt, void *user_data)) |
| DR_EXPORT app_pc | drwrap_get_drcontext (void *wrapcxt) |
| DR_EXPORT app_pc | drwrap_get_func (void *wrapcxt) |
| DR_EXPORT dr_mcontext_t * | drwrap_get_mcontext (void *wrapcxt) |
| DR_EXPORT dr_mcontext_t * | drwrap_get_mcontext_ex (void *wrapcxt, dr_mcontext_flags_t flags) |
| DR_EXPORT bool | drwrap_set_mcontext (void *wrapcxt) |
| DR_EXPORT app_pc | drwrap_get_retaddr (void *wrapcxt) |
| DR_EXPORT void * | drwrap_get_arg (void *wrapcxt, int arg) |
| DR_EXPORT bool | drwrap_set_arg (void *wrapcxt, int arg, void *val) |
| DR_EXPORT void * | drwrap_get_retval (void *wrapcxt) |
| DR_EXPORT bool | drwrap_set_retval (void *wrapcxt, void *val) |
| DR_EXPORT bool | drwrap_skip_call (void *wrapcxt, void *retval, size_t stdcall_args_size) |
| DR_EXPORT bool | drwrap_register_post_call_notify (void(*cb)(app_pc pc)) |
| DR_EXPORT bool | drwrap_unregister_post_call_notify (void(*cb)(app_pc pc)) |
| DR_EXPORT bool | drwrap_mark_as_post_call (app_pc pc) |
| DR_EXPORT bool | drwrap_set_global_flags (drwrap_global_flags_t flags) |
| DR_EXPORT bool | drwrap_is_wrapped (app_pc func, void(*pre_func_cb)(void *wrapcxt, OUT void **user_data), void(*post_func_cb)(void *wrapcxt, void *user_data)) |
| DR_EXPORT bool | drwrap_is_post_wrap (app_pc pc) |
| #define DRMGR_PRIORITY_NAME_DRWRAP "drwrap" |
Name of drmgr instrumentation pass priorities for both app2app and insert
| anonymous enum |
Priorities of drmgr instrumentation passes used by drwrap. Users of drwrap can use the name DRMGR_PRIORITY_NAME_DRWRAP 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.
| DRMGR_PRIORITY_APP2APP_DRWRAP |
Priority of drwap_replace() |
| DRMGR_PRIORITY_INSERT_DRWRAP |
Priority of drwrap_wrap() |
Values for the flags parameter to drwrap_set_global_flags()
| DRWRAP_SAFE_READ_RETADDR |
By default the return address is read directly. A more conservative and safe approach would use a safe read to avoid crashing when the stack is unsafe to access. This flag will cause the return address to be read safely. If any call to drwrap_set_global_flags() sets this flag, no later call can remove it. |
| DRWRAP_SAFE_READ_ARGS |
By default function arguments stored in memory are read and written directly. A more conservative and safe approach would use a safe read or write to avoid crashing when the stack is unsafe to access. This flag will cause all arguments in memory to be read and written safely. If any call to drwrap_set_global_flags() sets this flag, no later call can remove it. |
| DRWRAP_NO_FRILLS |
If this flag is set, then a leaner wrapping mechanism is used with lower overhead. However, several features are not supported with this flag:
|
| DRWRAP_FAST_CLEANCALLS |
If this flag is set, then a leaner clean call is used to invoke wrap pre callbacks. This clean call assumes that all wrap requests are for function entrance points and that standard ABI calling conventions are used for those functions. This means that caller-saved registers may not be saved and thus will have invalid values in drwrap_get_mcontext(). When using this setting and skipping a function via drwrap_skip_call() (or calling dr_redirect_execution() directly), setting xmm registers (in particular those used as return values) will work correctly (of course, be sure to retrieve the existing xmm values via drwrap_get_mcontext() or drwrap_get_mcontext_ex(DR_MC_ALL) first). Only set this flag if you are certain that all uses of wrapping in your client and all libraries it uses can abide the above restrictions. Once set, this flag cannot be unset. |
| enum drwrap_wrap_flags_t |
Values for the flags parameter to drwrap_wrap_ex()
| DR_EXPORT void drwrap_exit | ( | void | ) |
Cleans up the drwrap extension.
| DR_EXPORT void* drwrap_get_arg | ( | void * | wrapcxt, | |
| int | arg | |||
| ) |
Returns the value of the arg-th argument (0-based) to the wrapped function represented by wrapcxt. Assumes the regular C calling convention (i.e., no fastcall). May only be called from a drwrap_wrap pre-function callback. To access argument values in a post-function callback, store them in the user_data parameter passed between the pre and post functions.
This routine may de-reference application memory directly, so the caller should wrap in DR_TRY_EXCEPT if crashes must be avoided.
| DR_EXPORT app_pc drwrap_get_drcontext | ( | void * | wrapcxt | ) |
Returns the DynamoRIO context. This routine can be faster than dr_get_current_drcontext() but should return the same result.
| DR_EXPORT app_pc drwrap_get_func | ( | void * | wrapcxt | ) |
Returns the address of the wrapped function represented by wrapcxt.
| DR_EXPORT dr_mcontext_t* drwrap_get_mcontext | ( | void * | wrapcxt | ) |
Returns the machine context of the wrapped function represented by wrapcxt corresponding to the application state at the time of the pre-function or post-function wrap callback. In order for any changes to the returned context to take effect, drwrap_set_mcontext() must be called.
| DR_EXPORT dr_mcontext_t* drwrap_get_mcontext_ex | ( | void * | wrapcxt, | |
| dr_mcontext_flags_t | flags | |||
| ) |
Identical to drwrap_get_mcontext() but only fills in the state indicated by flags.
| DR_EXPORT app_pc drwrap_get_retaddr | ( | void * | wrapcxt | ) |
Returns the return address of the wrapped function represented by wrapcxt.
This routine may de-reference application memory directly, so the caller should wrap in DR_TRY_EXCEPT if crashes must be avoided.
| DR_EXPORT void* drwrap_get_retval | ( | void * | wrapcxt | ) |
Returns the return value of the wrapped function represented by wrapcxt. Assumes a pointer-sized return value. May only be called from a drwrap_wrap post-function callback.
| DR_EXPORT bool drwrap_init | ( | void | ) |
Initializes the drwrap extension. Must be called prior to any of the other routines, and should only be called once.
| DR_EXPORT bool drwrap_is_post_wrap | ( | app_pc | pc | ) |
pc is currently considered a post-wrap point, for any wrap request. | DR_EXPORT bool drwrap_is_wrapped | ( | app_pc | func, | |
| void(*)(void *wrapcxt, OUT void **user_data) | pre_func_cb, | |||
| void(*)(void *wrapcxt, void *user_data) | post_func_cb | |||
| ) |
func is currently wrapped with pre_func_cb and post_func_cb. | DR_EXPORT bool drwrap_mark_as_post_call | ( | app_pc | pc | ) |
Records the address pc as a post-call address for instrumentation for post-call function wrapping purposes.
pc is legitimate, as that code will be stored for consistency purposes and the post-call entry will be invalidated if it changes. This means that when using this routine for the performance purposes described in the drwrap_register_post_call_notify() documentation, the tool should wait for a newly loaded module to be relocated before calling this routine. A good approach is to wait for the first execution of code from the new module.| DR_EXPORT bool drwrap_register_post_call_notify | ( | void(*)(app_pc pc) | cb | ) |
Registers a callback cb to be called every time a new post-call address is encountered. The intended use is for tools that want faster start-up time by avoiding flushes for inserting wrap instrumentation at post-call sites. A tool can use this callback to record all of the post-call addresses to disk, and use drwrap_mark_as_post_call() during module load of the next execution. It is up to the tool to verify that the module has not changed since its addresses were recorded.
| DR_EXPORT bool drwrap_replace | ( | app_pc | original, | |
| app_pc | replacement, | |||
| bool | override | |||
| ) |
Replaces the application function that starts at the address original with the code at the address replacement.
Only one replacement is supported per target address. If a replacement already exists for original, this function fails unless override is true, in which case it replaces the prior replacement. To remove a replacement, pass NULL for replacement and true for override. When removing or replacing a prior replacement, existing replaced code in the code cache will be flushed lazily: i.e., there may be some execution in other threads after this call is made.
When replacing a function, it is up to the user to ensure that the replacement mirrors the calling convention and other semantics of the original function. The replacement code will be executed as application code, NOT as client code.
| DR_EXPORT bool drwrap_set_arg | ( | void * | wrapcxt, | |
| int | arg, | |||
| void * | val | |||
| ) |
Sets the the arg-th argument (0-based) to the wrapped function represented by wrapcxt to val. Assumes the regular C calling convention (i.e., no fastcall). May only be called from a drwrap_wrap pre-function callback. To access argument values in a post-function callback, store them in the user_data parameter passed between the pre and post functions.
This routine may write to application memory directly, so the caller should wrap in DR_TRY_EXCEPT if crashes must be avoided.
| DR_EXPORT bool drwrap_set_global_flags | ( | drwrap_global_flags_t | flags | ) |
Sets flags that affect the global behavior of the drwrap module. This can be called at any time and it will affect future behavior.
| DR_EXPORT bool drwrap_set_mcontext | ( | void * | wrapcxt | ) |
Propagates any changes made to the dr_mcontext_t pointed by drwrap_get_mcontext() back to the application.
| DR_EXPORT bool drwrap_set_retval | ( | void * | wrapcxt, | |
| void * | val | |||
| ) |
Sets the return value of the wrapped function represented by wrapcxt to val. Assumes a pointer-sized return value. May only be called from a drwrap_wrap post-function callback.
| DR_EXPORT bool drwrap_skip_call | ( | void * | wrapcxt, | |
| void * | retval, | |||
| size_t | stdcall_args_size | |||
| ) |
May only be called from a drwrap_wrap pre-function callback. Skips execution of the original function and returns to the function's caller with a return value of retval. The post-function callback will not be invoked; nor will any pre-function callbacks (if multiple were registered) that have not yet been called. If the original function uses the stdcall calling convention, the total size of its arguments must be supplied. The return value is set regardless of whether the original function officially returns a value or not. Further state changes may be made with drwrap_get_mcontext() and drwrap_set_mcontext() prior to calling this function.
| DR_EXPORT bool drwrap_unregister_post_call_notify | ( | void(*)(app_pc pc) | cb | ) |
Unregisters a callback registered with drwrap_register_post_call_notify().
| DR_EXPORT bool drwrap_unwrap | ( | app_pc | func, | |
| void(*)(void *wrapcxt, OUT void **user_data) | pre_func_cb, | |||
| void(*)(void *wrapcxt, void *user_data) | post_func_cb | |||
| ) |
Removes a previously-requested wrap for the function func and the callback pair pre_func_cb and post_func_cb. This must be the same pair that was passed to dr_wrap.
This routine can be called from pre_func_cb or post_func_cb.
| DR_EXPORT bool drwrap_wrap | ( | app_pc | func, | |
| void(*)(void *wrapcxt, OUT void **user_data) | pre_func_cb, | |||
| void(*)(void *wrapcxt, void *user_data) | post_func_cb | |||
| ) |
Wraps the application function that starts at the address original by calling pre_func_cb prior to every invocation of original and calling post_func_cb after every invocation of original. One of the callbacks can be NULL, but not both.
Multiple wrap requests are allowed for one original function (unless DRWRAP_NO_FRILLS is set). Their callbacks are called sequentially in the reverse order of registration.
The pre_func_cb can examine (drwrap_get_arg()) and set (drwrap_set_arg()) the arguments to original and can skip the call to original (drwrap_skip_call()). The post_func_cb can examine (drwrap_get_retval()) and set (drwrap_set_retval()) original's return value. The opaque pointer wrapcxt passed to each callback should be passed to these routines.
When an abnormal stack unwind, such as longjmp or a Windows exception, occurs, drwrap does its best to detect it. All post-calls that would be missed will still be invoked, but with wrapcxt set to NULL. Since there is no post-call environment, it does not make sense to query the return value or arguments. The call is invoked to allow for cleanup of state allocated in pre_func_cb. However, detection of a stack unwind is not guaranteed. When wrapping a series of functions that do not themselves contain exception handlers, pass the DRWRAP_UNWIND_ON_EXCEPTION flag to drwrap_wrap_ex() to ensure that all post-call callbacks will be called on an exception.
| DR_EXPORT bool drwrap_wrap_ex | ( | app_pc | func, | |
| void(*)(void *wrapcxt, INOUT void **user_data) | pre_func_cb, | |||
| void(*)(void *wrapcxt, void *user_data) | post_func_cb, | |||
| void * | user_data, | |||
| drwrap_wrap_flags_t | flags | |||
| ) |
Identical to drwrap_wrap() except for two additional parameters: user_data, which is passed as the initial value of *user_data to pre_func_cb, and flags.