Data Structures | |
struct | _dr_fault_fragment_info_t |
struct | _dr_restore_state_info_t |
struct | _dr_exception_t |
struct | _dr_siginfo_t |
Typedefs | |
typedef struct _dr_fault_fragment_info_t | dr_fault_fragment_info_t |
typedef struct _dr_restore_state_info_t | dr_restore_state_info_t |
typedef struct _dr_exception_t | dr_exception_t |
typedef struct _dr_siginfo_t | dr_siginfo_t |
Enumerations | |
enum | dr_emit_flags_t { DR_EMIT_DEFAULT = 0, DR_EMIT_STORE_TRANSLATIONS = 0x01 } |
enum | dr_custom_trace_action_t |
enum | dr_signal_action_t { DR_SIGNAL_DELIVER, DR_SIGNAL_SUPPRESS, DR_SIGNAL_BYPASS, DR_SIGNAL_REDIRECT } |
Functions | |
void | dr_register_exit_event (void(*func)(void)) |
bool | dr_unregister_exit_event (void(*func)(void)) |
void | dr_register_bb_event (dr_emit_flags_t(*func)(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating)) |
bool | dr_unregister_bb_event (dr_emit_flags_t(*func)(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating)) |
void | dr_register_trace_event (dr_emit_flags_t(*func)(void *drcontext, void *tag, instrlist_t *trace, bool translating)) |
bool | dr_unregister_trace_event (dr_emit_flags_t(*func)(void *drcontext, void *tag, instrlist_t *trace, bool translating)) |
void | dr_register_end_trace_event (dr_custom_trace_action_t(*func)(void *drcontext, void *tag, void *next_tag)) |
bool | dr_unregister_end_trace_event (dr_custom_trace_action_t(*func)(void *drcontext, void *tag, void *next_tag)) |
void | dr_register_delete_event (void(*func)(void *drcontext, void *tag)) |
bool | dr_unregister_delete_event (void(*func)(void *drcontext, void *tag)) |
void | dr_register_restore_state_event (void(*func)(void *drcontext, void *tag, dr_mcontext_t *mcontext, bool restore_memory, bool app_code_consistent)) |
bool | dr_unregister_restore_state_event (void(*func)(void *drcontext, void *tag, dr_mcontext_t *mcontext, bool restore_memory, bool app_code_consistent)) |
void | dr_register_restore_state_ex_event (bool(*func)(void *drcontext, bool restore_memory, dr_restore_state_info_t *info)) |
bool | dr_unregister_restore_state_ex_event (bool(*func)(void *drcontext, bool restore_memory, dr_restore_state_info_t *info)) |
void | dr_register_thread_init_event (void(*func)(void *drcontext)) |
bool | dr_unregister_thread_init_event (void(*func)(void *drcontext)) |
void | dr_register_thread_exit_event (void(*func)(void *drcontext)) |
bool | dr_unregister_thread_exit_event (void(*func)(void *drcontext)) |
void | dr_register_fork_init_event (void(*func)(void *drcontext)) |
bool | dr_unregister_fork_init_event (void(*func)(void *drcontext)) |
void | dr_register_module_load_event (void(*func)(void *drcontext, const module_data_t *info, bool loaded)) |
bool | dr_unregister_module_load_event (void(*func)(void *drcontext, const module_data_t *info, bool loaded)) |
void | dr_register_module_unload_event (void(*func)(void *drcontext, const module_data_t *info)) |
bool | dr_unregister_module_unload_event (void(*func)(void *drcontext, const module_data_t *info)) |
void | dr_register_exception_event (bool(*func)(void *drcontext, dr_exception_t *excpt)) |
bool | dr_unregister_exception_event (bool(*func)(void *drcontext, dr_exception_t *excpt)) |
void | dr_register_filter_syscall_event (bool(*func)(void *drcontext, int sysnum)) |
bool | dr_unregister_filter_syscall_event (bool(*func)(void *drcontext, int sysnum)) |
void | dr_register_pre_syscall_event (bool(*func)(void *drcontext, int sysnum)) |
bool | dr_unregister_pre_syscall_event (bool(*func)(void *drcontext, int sysnum)) |
void | dr_register_post_syscall_event (void(*func)(void *drcontext, int sysnum)) |
bool | dr_unregister_post_syscall_event (void(*func)(void *drcontext, int sysnum)) |
void | dr_register_signal_event (dr_signal_action_t(*func)(void *drcontext, dr_siginfo_t *siginfo)) |
bool | dr_unregister_signal_event (dr_signal_action_t(*func)(void *drcontext, dr_siginfo_t *siginfo)) |
void | dr_register_nudge_event (void(*func)(void *drcontext, uint64 argument), client_id_t id) |
bool | dr_unregister_nudge_event (void(*func)(void *drcontext, uint64 argument), client_id_t id) |
bool | dr_nudge_client (client_id_t id, uint64 argument) |
typedef struct _dr_exception_t dr_exception_t |
Data structure passed with an exception event. Contains the machine context and the Win32 exception record.
typedef struct _dr_fault_fragment_info_t dr_fault_fragment_info_t |
Data structure passed within dr_exception_t, dr_siginfo_t, and dr_restore_state_info_t. Contains information about the code fragment inside the code cache at the exception/signal/translation interruption point.
typedef struct _dr_restore_state_info_t dr_restore_state_info_t |
Data structure passed to a restore_state_ex event handler (see dr_register_restore_state_ex_event()). Contains the machine context at the translation point and other translation information.
typedef struct _dr_siginfo_t dr_siginfo_t |
Data structure passed with a signal event. Contains the machine context at the signal interruption point and other signal information.
DR will call the end trace event if it is registered prior to adding each basic block to a trace being generated. The return value of the event callback should be from the dr_custom_trace_action_t enum.
enum dr_emit_flags_t |
Flags controlling the behavior of basic blocks and traces when emitted into the code cache. For multiple clients, the flags returned by each client are or-ed together.
DR_EMIT_DEFAULT | Emit as normal. |
DR_EMIT_STORE_TRANSLATIONS |
Store translation information at emit time rather than calling the basic block or trace event later to recreate the information. Note that even if a standalone basic block has stored translations, if when it is added to a trace it does not request storage (and the trace callback also does not request storage) then the basic block callback may still be called to translate for the trace.
|
enum dr_signal_action_t |
Return value of client signal event callback, determining how DR will proceed with the signal.
DR_SIGNAL_DELIVER | Deliver signal to the application as normal. |
DR_SIGNAL_SUPPRESS | Suppress signal as though it never happened. |
DR_SIGNAL_BYPASS | Deliver signal according to the default SIG_DFL action, as would happen if the application had no handler. |
DR_SIGNAL_REDIRECT | Do not deliver the signal. Instead, redirect control to the application state specified in dr_siginfo_t.mcontext. |
bool dr_nudge_client | ( | client_id_t | id, | |
uint64 | argument | |||
) |
Triggers an asynchronous nudge event in the current process. The callback function registered with dr_register_nudge_event() will be called with the supplied argument
(in a new non-application thread on Windows).
Not yet supported for 32-bit processes running on 64-bit Windows (WOW64).
void dr_register_bb_event | ( | dr_emit_flags_t(*)(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) | func | ) |
Registers a callback function for the basic block event. DR calls func
before inserting a new basic block into the code cache. When adding a basic block to a new trace, DR calls func
again with for_trace
set to true, giving the client the opportunity to keep its same instrumentation in the trace, or to change it. The original basic block's instrumentation is unchanged by whatever action is taken in the for_trace
call.
DR may call func
again if it needs to translate from code cache addresses back to application addresses, which happens on faulting instructions as well as in certain situations involving suspended threads or forcibly relocated threads. The translating
parameter distinguishes the two types of calls and is further explained below.
drcontext
is a pointer to the input program's machine context. Clients should not inspect or modify the context; it is provided as an opaque pointer (i.e., void *
) to be passed to API routines that require access to this internal data. drcontext is specific to the current thread, but in normal configurations the basic block being created is thread-shared: thus, when allocating data structures with the same lifetime as the basic block, usually global heap (dr_global_alloc()) is a better choice than heap tied to the thread that happened to first create the basic block (dr_thread_alloc()). Thread-private heap is fine for temporary structures such as instr_t and instrlist_t.
tag
is a unique identifier for the basic block fragment. Use dr_fragment_app_pc() to translate it to an application address.bb
is a pointer to the list of instructions that comprise the basic block. Clients can examine, manipulate, or completely replace the instructions in the list.
translating
indicates whether this callback is for basic block creation (false) or is for address translation (true). This is further explained below.
To support transparent fault handling, DR must translate a fault in the code cache into a fault at the corresponding application address. DR must also be able to translate when a suspended thread is examined by the application or by DR itself for internal synchronization purposes. If the client is only adding observational instrumentation (i.e., meta instructions: see instr_set_ok_to_mangle()) (which should not fault) and is not modifying, reordering, or removing application instructions, these details can be ignored. In that case the client should return DR_EMIT_DEFAULT and set up its basic block callback to be deterministic and idempotent. If the client is performing modifications, then in order for DR to properly translate a code cache address the client must use instr_set_translation() in the basic block creation callback to set the corresponding application address (the address that should be presented to the application as the faulting address, or the address that should be restarted after a suspend) for each modified instruction and each added non-meta instruction (see instr_set_ok_to_mangle()).
There are two methods for using the translated addresses:
tag
will not be called with translating
set to true. Note that unless DR_EMIT_STORE_TRANSLATIONS is also returned for for_trace
calls (or DR_EMIT_STORE_TRANSLATIONS is returned in the trace callback), each constituent block comprising the trace will need to be re-created with both for_trace
and translating
set to true. Storing translations uses additional memory that can be significant: up to 20% in some cases, as it prevents DR from using its simple data structures and forces it to fall back to its complex, corner-case design. This is why DR does not store all translations by default.translating
set to true. All modifications to bb
that were performed on the creation callback must be repeated on the translating callback. This option is only possible when basic block modifications are deterministic and idempotent, but it saves memory. Naturally, global state changes triggered by block creation should be wrapped in checks for translating
being false. Even in this case, instr_set_translation() should be called for non-meta instructions even when translating
is false, as DR may decide to store the translations at creation time for reasons of its own.Furthermore, if the client's modifications change any part of the machine state besides the program counter, the client should use dr_register_restore_state_event() or dr_register_restore_state_ex_event() to restore the registers and application memory to their original application values.
For meta instructions that do not reference application memory (i.e., they should not fault), leave the translation field as NULL. A NULL value instructs DR to use the subsequent non-meta instruction's translation as the application address, and to fail when translating the full state. Since the full state will only be needed when relocating a thread (as stated, there will not be a fault here), failure indicates that this is not a valid relocation point, and DR's thread synchronization scheme will use another spot. If the translation field is set to a non-NULL value, the client should be willing to also restore the rest of the machine state at that point (restore spilled registers, etc.) via dr_register_restore_state_event() or dr_register_restore_state_ex_event(). This is necessary for meta instructions that reference application memory. DR takes care of such potentially-faulting instructions added by its own API routines (dr_insert_clean_call() arguments that reference application data, dr_insert_mbr_instrumentation()'s read of application indirect branch data, etc.)
If multiple clients are present, the instruction list for a basic block passed to earlier-registered clients will contain the instrumentation and modifications put in place by later-registered clients.
Basic blocks can be deleted due to hitting capacity limits or cache consistency events (when the source application code of a basic block is modified). In that case, the client will see a new basic block callback if the block is then executed again after deletion. The deletion event (dr_register_delete_event()) will be raised at deletion time.
If the -thread_private runtime option is specified, clients should expect to see duplicate tags for separate threads, albeit with different dcrcontext values. Additionally, DR employs a cache-sizing algorithm for thread private operation that proactively deletes fragments. Even with thread-shared caches enabled, however, certain situations cause DR to emit thread-private basic blocks (e.g., self-modifying code). In this case, clients should be prepared to see duplicate tags without an intermediate deletion.
void dr_register_delete_event | ( | void(*)(void *drcontext, void *tag) | func | ) |
Registers a callback function for the fragment deletion event. DR calls func
whenever it removes a fragment from the code cache. Due to DR's high-performance non-precise flushing, a fragment can be made inaccessible but not actually freed for some time. A new fragment can thus be created before the deletion event for the old fragment is raised. We recommended using a counter to ignore subsequent deletion events when using per-fragment data structures and duplicate fragments are seen.
void dr_register_end_trace_event | ( | dr_custom_trace_action_t(*)(void *drcontext, void *tag, void *next_tag) | func | ) |
Registers a callback function for the end-trace event. DR calls func
before extending a trace with a new basic block. The func
should return one of the dr_custom_trace_action_t enum values.
void dr_register_exception_event | ( | bool(*)(void *drcontext, dr_exception_t *excpt) | func | ) |
Registers a callback function for the exception event. DR calls func
whenever the application throws an exception. If func
returns true, the exception is delivered to the application's handler along with any changes made to excpt->mcontext
. If func
returns false, the faulting instruction in the code cache is re-executed using excpt->raw_mcontext
, including any changes made to that structure. Clients are expected to use excpt->raw_mcontext
when using faults as a mechanism to push rare cases out of an instrumentation fastpath that need to examine instrumentation instructions rather than the translated application state and should normally not examine it for application instruction faults. Certain registers may not contain proper application values in excpt->raw_mcontext
for exceptions in application instructions. Clients are cautioned against relying on any details of code cache layout or register usage beyond instrumentation inserted by the client itself when examining excpt->raw_mcontext
.
DR raises this event for exceptions outside the code cache that could come from code generated by a client. For such exceptions, mcontext is not translated and is identical to raw_mcontext.
To skip the passing of the exception to the application's exception handlers and to send control elsewhere instead, a client can call dr_redirect_execution() from func
.
excpt->fault_fragment_info
data is provided with excpt->raw_mcontext
. It is valid only if excpt->fault_fragment_info.cache_start_pc
is not NULL
. It provides clients information about the code fragment being executed at the exception interruption point. Clients are cautioned against relying on any details of code cache layout or register usage beyond instrumentation inserted by the client itself. Only valid on Windows.
The function is not called for RaiseException.
void dr_register_exit_event | ( | void(*)(void) | func | ) |
Registers a callback function for the process exit event. DR calls func
when the process exits. Note that in release build it is possible for other threads to still be executing, so synchronization should be used for global variables; alternatively, the -synch_at_exit option can be set, or the dr_request_synchronized_exit() routine invoked, to guarantee that only one thread is active at exit time (at a potential performance cost).
On Linux, SYS_execve does NOT result in an exit event, but it WILL result in the client library being reloaded and its dr_init() routine being called.
void dr_register_filter_syscall_event | ( | bool(*)(void *drcontext, int sysnum) | func | ) |
Registers a callback function for the syscall filter event. DR calls func
to decide whether to invoke the syscall events for each system call site encountered with a statically-determinable system call number. If func
returns true, the pre-syscall (dr_register_pre_syscall_event()) and post-syscall (dr_register_post_syscall_event()) events will be invoked. Otherwise, the events may or may not occur, depending on whether DR itself needs to intercept them and whether the system call number is statically determinable. System call number determination can depend on whether the -opt_speed option is enabled. If a system call number is not determinable, the filter event will not be called, but the pre and post events will be called.
Intercepting every system call can be detrimental to performance for certain types of applications. Filtering provides for greater performance by letting uninteresting system calls execute without interception overhead.
void dr_register_fork_init_event | ( | void(*)(void *drcontext) | func | ) |
Registers a callback function for the fork event. DR calls func
whenever the application forks a new process.
void dr_register_module_load_event | ( | void(*)(void *drcontext, const module_data_t *info, bool loaded) | func | ) |
Registers a callback function for the module load event. DR calls func
whenever the application loads a module. The loaded
parameter indicates whether the module is about to be loaded (the normal case) or is already loaded (if the module was already there at the time DR initialized).
The module_data_t *info
passed to the callback routine is valid only for the duration of the callback and should not be freed; a persistent copy can be made with dr_copy_module_data().
void dr_register_module_unload_event | ( | void(*)(void *drcontext, const module_data_t *info) | func | ) |
Registers a callback function for the module unload event. DR calls func
whenever the application unloads a module.
*info
passed to the callback routine is valid only for the duration of the callback and should not be freed; a persistent copy can be made with dr_copy_module_data(). void dr_register_nudge_event | ( | void(*)(void *drcontext, uint64 argument) | func, | |
client_id_t | id | |||
) |
Registers a callback function for nudge events. External entities can nudge a process through the dr_nudge_process() API routine on Windows or using the nudgeunix
tool on Linux. DR then calls func
whenever the current process receives the nudge. On Windows, the nudge event is delivered in a new non-application thread. Callers must specify the target client by passing the client ID that was provided in dr_init().
void dr_register_post_syscall_event | ( | void(*)(void *drcontext, int sysnum) | func | ) |
Registers a callback function for the post-syscall event. DR calls func
whenever the application just finished invoking a system call, if any client asked for that system call number to be intercepted via the filter event (dr_register_filter_syscall_event()) or if DR itself needs to intercept the system call. The result of the system call can be modified with dr_syscall_set_result().
System calls that change control flow or terminate the current thread or process typically do not have a post-syscall event. These include SYS_exit, SYS_exit_group, SYS_execve, SYS_sigreturn, and SYS_rt_sigreturn on Linux, and NtTerminateThread, NtTerminateProcess (depending on the parameters), NtCallbackReturn, and NtContinue on Windows.
The application's machine state can be accessed and set with dr_get_mcontext() and dr_set_mcontext().
Additional system calls may be invoked by calling dr_syscall_invoke_another() prior to returning from the post-syscall event callback. The system call to be invoked should be specified with dr_syscall_set_sysnum(), and its parameters can be set with dr_syscall_set_param().
void dr_register_pre_syscall_event | ( | bool(*)(void *drcontext, int sysnum) | func | ) |
Registers a callback function for the pre-syscall event. DR calls func
whenever the application is about to invoke a system call, if any client asked for that system call number to be intercepted via the filter event (dr_register_filter_syscall_event()).
The application parameters to the system call can be viewed with dr_syscall_get_param() and set with dr_syscall_set_param(). The system call number can also be changed with dr_syscall_set_sysnum().
The application's machine state can be accessed and set with dr_get_mcontext() and dr_set_mcontext(). Changing registers in this way overlaps with system call parameter changes on some platforms. On Linux, for SYS_clone, client changes to the ebp/rbp register will be ignored by the clone child.
If func
returns true, the application's system call is invoked normally; if func
returns false, the system call is skipped. If it is skipped, the return value can be set with dr_syscall_set_result(). If the system call is skipped, there will not be a post-syscall event.
void dr_register_restore_state_event | ( | void(*)(void *drcontext, void *tag, dr_mcontext_t *mcontext, bool restore_memory, bool app_code_consistent) | func | ) |
Registers a callback function for the machine state restoration event. DR calls func
whenever it needs to translate a code cache machine context from the code cache to its corresponding original application context. DR needs to translate when instructions fault in the cache as well as when a suspended thread is examined or relocated for internal purposes.
If a client is only adding instrumentation (meta-code: see instr_ok_to_mangle()) that does not reference application memory, and is not reordering or removing application instructions, then it need not register for this event. If, however, a client is modifying application code or is adding code that can fault, the client must be capable of restoring the original context.
When DR needs to translate a code cache context, DR recreates the faulting instruction's containing fragment, storing translation information along the way, by calling the basic block and/or trace event callbacks with the translating
parameter set to true. DR uses the recreated code to identify the application instruction (mcontext.pc
) corresponding to the faulting code cache instruction. If the client asked to store translation information by returning DR_EMIT_STORE_TRANSLATIONS from the basic block or trace event callback, then this step of re-calling the event callback is skipped and the stored value is used as the application address (mcontext.pc
).
DR then calls the fault state restoration event to allow the client to restore the registers and application memory to their proper values as they would have appeared if the original application code had been executed up to the mcontext.pc
instruction. Memory should only be restored if the restore_memory
parameter is true; if it is false, DR may only be querying for the address (mcontext.pc
) or register state and may not relocate this thread.
The app_code_consistent
parameter indicates whether the original application code containing the instruction being translated is guaranteed to still be in the same state it was when the code was placed in the code cache. This guarantee varies depending on the type of cache consistency being used by DR.
The client can update mcontext.pc
in this callback.
drcontext
may correspond to a different thread than the thread executing the callback. Do not assume that the executing thread is the target thread. void dr_register_restore_state_ex_event | ( | bool(*)(void *drcontext, bool restore_memory, dr_restore_state_info_t *info) | func | ) |
Registers a callback function for the machine state restoration event with extended information.
This event is identical to that for dr_register_restore_state_event() with the following exceptions:
info->raw_mcontext
. Clients are cautioned against relying on any details of code cache layout or register usage beyond instrumentation inserted by the client itself when examining info->raw_mcontext
.
restore_memory
parameter will be false. Such translation can target a meta-instruction that can fault (see instr_set_meta_may_fault()). For that scenario, a client can choose not to translate. Such instructions do not always require full translation for faults, and allowing translation failure removes the requirement that a client must translate at all such instructions. Note, however, that returning false can cause performance degradation as DR must then resume the thread and attempt to re-suspend it at a safer spot. Clients must return true for translation points in application code in order to avoid catastropic failure to suspend, and should thus identify whether translation points are inside their own instrumentation before returning false. Translation for relocation will never occur in meta instructions, so clients only need to look for meta-may-fault instructions. Clients should never return false when restore_memory
is true. void dr_register_signal_event | ( | dr_signal_action_t(*)(void *drcontext, dr_siginfo_t *siginfo) | func | ) |
Requests that DR call the provided callback function func
whenever a signal is received by any application thread. The return value of func
determines whether DR delivers the signal to the application. To redirect execution return DR_SIGNAL_REDIRECT (do not call dr_redirect_execution() from a signal callback). The callback function will be called even if the application has no handler or has registered a SIG_IGN or SIG_DFL handler.
Modifications to the fields of siginfo->mcontext
will be propagated to the application if it has a handler for the signal, if DR_SIGNAL_DELIVER is returned.
The siginfo->raw_mcontext
data is only provided for non-delayable signals (e.g., SIGSEGV) that must be delivered immediately. Whether it is supplied is specified in siginfo->raw_mcontext_valid
. It is intended for clients using faults as a mechanism to push rare cases out of an instrumentation fastpath that need to examine instrumentation instructions rather than the translated application state. Certain registers may not contain proper application values in excpt->raw_mcontext
for exceptions in application instructions. Clients are cautioned against relying on any details of code cache layout or register usage beyond instrumentation inserted by the client itself. If DR_SIGNAL_SUPPRESS is returned, siginfo->mcontext
is ignored and siginfo->raw_mcontext
is used as the resumption context. The client's changes to siginfo->raw_mcontext
will take effect.
For a delayable signal, DR raises a signal event only when about to deliver the signal to the application. Thus, if the application has blocked a delayable signal, the corresponding signal event will not occur until the application unblocks the signal, even if such a signal is delivered by the kernel. For non-delayable signals, DR will raise a signal event on initial receipt of the signal, with the siginfo->blocked
field set. Such a blocked signal will have a second event raised when it is delivered to the application (if it is not suppressed by the client, and if there is not already a pending blocked signal, for non-real-time signals).
DR raises this event for faults outside the code cache that could come from code generated by a client. For such cases, mcontext is not translated and is identical to raw_mcontext.
DR will not raise a signal event for a SIGSEGV or SIGBUS raised by a client code fault rather than the application. Use dr_safe_read() or dr_safe_write() to prevent such faults.
siginfo->fault_fragment_info
data is provided with siginfo->raw_mcontext
. It is valid only if siginfo->fault_fragment_info.cache_start_pc
is not NULL
. It provides clients information about the code fragment being executed at the signal interruption point. Clients are cautioned against relying on any details of code cache layout or register usage beyond instrumentation inserted by the client itself.Only valid on Linux.
DR always requests SA_SIGINFO for all signals.
This version of DR does not intercept the signals SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, or SIGTTOU. Future versions should add support for these signals.
If the client uses signals for its own communication it should set a flag to distinguish its own uses of signals from the application's use. Races where the two are re-ordered should not be problematic.
void dr_register_thread_exit_event | ( | void(*)(void *drcontext) | func | ) |
Registers a callback function for the thread exit event. DR calls func
whenever an application thread exits.
There are some potential races at process exit time with the thread exit event for all remaining threads. In debug builds, DynamoRIO synchronizes with all remaining threads at process exit time, guaranteeing that no other threads are executing when the thread exit events are raised. In release build, however, for performance reasons, while DynamoRIO attempts to prevent other threads from executing (and thus running instrumentation code or raising events) beyond when their own thread exit events are raised, no guarantee is provided. The -synch_at_exit
option can be turned on in order to provide such a guarantee, at a potential performance hit.
void dr_register_thread_init_event | ( | void(*)(void *drcontext) | func | ) |
Registers a callback function for the thread initialization event. DR calls func
whenever the application creates a new thread.
void dr_register_trace_event | ( | dr_emit_flags_t(*)(void *drcontext, void *tag, instrlist_t *trace, bool translating) | func | ) |
Registers a callback function for the trace event. DR calls func
before inserting a new trace into the code cache. DR may call func
again if it needs to translate from code cache addresses back to application addresses, which happens on faulting instructions as well as in certain situations involving suspended threads or forcibly relocated threads. The translating
parameter distinguishes the two types of calls and behaves identically to the same parameter in the basic block callback: see dr_register_bb_event() for further details.
Traces are not built if the -disable_traces runtime option is specified.
drcontext
is a pointer to the input program's machine context. Clients should not inspect or modify the context; it is provided as an opaque pointer (i.e., void *
) to be passed to API routines that require access to this internal data.tag
is a unique identifier for the trace fragment.trace
is a pointer to the list of instructions that comprise the trace.translating
indicates whether this callback is for trace creation (false) or is for fault address recreation (true). This is further explained below.
If hitting a size limit due to extensive instrumentation, reduce the -max_trace_bbs option to start with a smaller trace.
The basic block restrictions on modifying application source code apply to traces as well. If the user wishes to change which basic blocks comprise the trace, either the dr_register_end_trace_event() should be used or the for_trace
basic block callbacks should modify their continuation addresses via direct jumps.
All of the comments for dr_register_bb_event() regarding transparent fault handling and state translation apply to the trace callback as well. Please read those comments carefully.
for_trace
parameter set to true. In order to preserve basic block instrumentation inside of traces, a client need only act identically with respect to the for_trace
parameter; it can ignore the trace event if its goal is to place instrumentation on all code.Certain control flow modifications applied to a basic block can prevent it from becoming part of a trace: e.g., adding additional non-meta control transfers.
If multiple clients are present, the instruction list for a trace passed to earlier-registered clients will contain the instrumentation and modifications put in place by later-registered clients; similarly for each constituent basic block.
Traces can be deleted due to hitting capacity limits or cache consistency events (when the source application code of a trace is modified). In that case, the client will see a new trace callback if a new trace containing that code is created again after deletion. The deletion event (dr_register_delete_event()) will be raised at deletion time.
bool dr_unregister_bb_event | ( | dr_emit_flags_t(*)(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) | func | ) |
Unregister a callback function for the basic block event.
func
was not registered).for_trace
is true, or if the client has a trace creation callback that returns DR_EMIT_STORE_TRANSLATIONS). Unregistering can prevent proper state translation on a later fault or other translation event for this basic block or for a trace that includes this basic block. Instead of unregistering, turn the event callback into a nop. bool dr_unregister_delete_event | ( | void(*)(void *drcontext, void *tag) | func | ) |
Unregister a callback function for the fragment deletion event.
func
was not registered). bool dr_unregister_end_trace_event | ( | dr_custom_trace_action_t(*)(void *drcontext, void *tag, void *next_tag) | func | ) |
Unregister a callback function for the end-trace event.
func
was not registered). bool dr_unregister_exception_event | ( | bool(*)(void *drcontext, dr_exception_t *excpt) | func | ) |
Unregister a callback function for the exception event.
func
was not registered). bool dr_unregister_exit_event | ( | void(*)(void) | func | ) |
Unregister a callback function for the process exit event.
func
was not registered). bool dr_unregister_filter_syscall_event | ( | bool(*)(void *drcontext, int sysnum) | func | ) |
Unregister a callback function for the syscall filter event.
func
was not registered). bool dr_unregister_fork_init_event | ( | void(*)(void *drcontext) | func | ) |
Unregister a callback function for the fork event.
func
was not registered). bool dr_unregister_module_load_event | ( | void(*)(void *drcontext, const module_data_t *info, bool loaded) | func | ) |
Unregister a callback for the module load event.
func
was not registered). bool dr_unregister_module_unload_event | ( | void(*)(void *drcontext, const module_data_t *info) | func | ) |
Unregister a callback function for the module unload event.
func
was not registered). bool dr_unregister_nudge_event | ( | void(*)(void *drcontext, uint64 argument) | func, | |
client_id_t | id | |||
) |
Unregister a callback function for the nudge event.
func
was not registered). bool dr_unregister_post_syscall_event | ( | void(*)(void *drcontext, int sysnum) | func | ) |
Unregister a callback function for the post-syscall event.
func
was not registered). bool dr_unregister_pre_syscall_event | ( | bool(*)(void *drcontext, int sysnum) | func | ) |
Unregister a callback function for the pre-syscall event.
func
was not registered). bool dr_unregister_restore_state_event | ( | void(*)(void *drcontext, void *tag, dr_mcontext_t *mcontext, bool restore_memory, bool app_code_consistent) | func | ) |
Unregister a callback function for the machine state restoration event.
func
was not registered). bool dr_unregister_restore_state_ex_event | ( | bool(*)(void *drcontext, bool restore_memory, dr_restore_state_info_t *info) | func | ) |
Unregister a callback function for the machine state restoration event with extended ifnormation.
func
was not registered). bool dr_unregister_signal_event | ( | dr_signal_action_t(*)(void *drcontext, dr_siginfo_t *siginfo) | func | ) |
Unregister a callback function for the signal event.
func
was not registered). bool dr_unregister_thread_exit_event | ( | void(*)(void *drcontext) | func | ) |
Unregister a callback function for the thread exit event.
func
was not registered). bool dr_unregister_thread_init_event | ( | void(*)(void *drcontext) | func | ) |
Unregister a callback function for the thread initialization event.
func
was not registered). bool dr_unregister_trace_event | ( | dr_emit_flags_t(*)(void *drcontext, void *tag, instrlist_t *trace, bool translating) | func | ) |
Unregister a callback function for the trace event.
func
was not registered).