Data Structures | |
struct | _dr_mem_info_t |
union | _version_number_t |
struct | _module_names_t |
struct | _module_data_t |
struct | _dr_export_info_t |
struct | _tracedump_file_header_t |
struct | _tracedump_trace_header_t |
struct | _tracedump_stub_data |
Defines | |
#define | DR_MEMPROT_NONE 0x00 |
#define | DR_MEMPROT_READ 0x01 |
#define | DR_MEMPROT_WRITE 0x02 |
#define | DR_MEMPROT_EXEC 0x04 |
#define | DR_ASSERT_MSG(x, msg) |
#define | DR_ASSERT(x) DR_ASSERT_MSG(x, "") |
#define | DR_FILE_READ 0x1 |
#define | DR_FILE_WRITE_REQUIRE_NEW 0x2 |
#define | DR_FILE_WRITE_APPEND 0x4 |
#define | DR_FILE_WRITE_OVERWRITE 0x8 |
#define | DR_FILE_ALLOW_LARGE 0x10 |
#define | DR_SEEK_SET 0 |
#define | DR_SEEK_CUR 1 |
#define | DR_SEEK_END 2 |
#define | LOG_NONE 0x00000000 |
#define | LOG_STATS 0x00000001 |
#define | LOG_TOP 0x00000002 |
#define | LOG_THREADS 0x00000004 |
#define | LOG_SYSCALLS 0x00000008 |
#define | LOG_ASYNCH 0x00000010 |
#define | LOG_INTERP 0x00000020 |
#define | LOG_EMIT 0x00000040 |
#define | LOG_LINKS 0x00000080 |
#define | LOG_CACHE 0x00000100 |
#define | LOG_FRAGMENT 0x00000200 |
#define | LOG_DISPATCH 0x00000400 |
#define | LOG_MONITOR 0x00000800 |
#define | LOG_HEAP 0x00001000 |
#define | LOG_VMAREAS 0x00002000 |
#define | LOG_SYNCH 0x00004000 |
#define | LOG_MEMSTATS 0x00008000 |
#define | LOG_OPTS 0x00010000 |
#define | LOG_SIDELINE 0x00020000 |
#define | LOG_SYMBOLS 0x00040000 |
#define | LOG_RCT 0x00080000 |
#define | LOG_NT 0x00100000 |
#define | LOG_HOT_PATCHING 0x00200000 |
#define | LOG_HTABLE 0x00400000 |
#define | LOG_MODULEDB 0x00800000 |
#define | LOG_ALL 0x00ffffff |
#define | BB_ORIGIN_HEADER_SIZE (sizeof(app_pc)+sizeof(int)) |
#define | STUB_DATA_FIXED_SIZE (offsetof(tracedump_stub_data_t, count)) |
Typedefs | |
typedef struct _dr_mem_info_t | dr_mem_info_t |
typedef void * | module_handle_t |
typedef union _version_number_t | version_number_t |
typedef struct _module_names_t | module_names_t |
typedef void * | dr_module_iterator_t |
typedef struct _dr_export_info_t | dr_export_info_t |
typedef struct _tracedump_file_header_t | tracedump_file_header_t |
typedef struct _tracedump_trace_header_t | tracedump_trace_header_t |
typedef struct _tracedump_stub_data | tracedump_stub_data_t |
Enumerations | |
enum | dr_mem_type_t { DR_MEMTYPE_FREE, DR_MEMTYPE_IMAGE, DR_MEMTYPE_DATA } |
Functions | |
void * | dr_standalone_init (void) |
bool | dr_using_all_private_caches (void) |
void | dr_request_synchronized_exit (void) |
const char * | dr_get_options (client_id_t client_id) |
const char * | dr_get_client_path (client_id_t client_id) |
const char * | dr_get_application_name (void) |
process_id_t | dr_get_process_id (void) |
process_id_t | dr_get_parent_id (void) |
bool | dr_is_wow64 (void) |
void | dr_get_time (dr_time_t *time) |
uint64 | dr_get_milliseconds (void) |
void | dr_abort (void) |
void * | dr_thread_alloc (void *drcontext, size_t size) |
void | dr_thread_free (void *drcontext, void *mem, size_t size) |
void * | dr_global_alloc (size_t size) |
void | dr_global_free (void *mem, size_t size) |
void * | dr_nonheap_alloc (size_t size, uint prot) |
void | dr_nonheap_free (void *mem, size_t size) |
void * | __wrap_malloc (size_t size) |
void * | __wrap_realloc (void *mem, size_t size) |
void | __wrap_free (void *mem) |
bool | dr_memory_is_readable (const byte *pc, size_t size) |
bool | dr_query_memory (const byte *pc, byte **base_pc, size_t *size, uint *prot) |
bool | dr_query_memory_ex (const byte *pc, OUT dr_mem_info_t *info) |
size_t | dr_virtual_query (const byte *pc, MEMORY_BASIC_INFORMATION *mbi, size_t mbi_size) |
bool | dr_safe_read (const void *base, size_t size, void *out_buf, size_t *bytes_read) |
bool | dr_safe_write (void *base, size_t size, const void *in_buf, size_t *bytes_written) |
bool | dr_memory_protect (void *base, size_t size, uint new_prot) |
bool | dr_memory_is_dr_internal (const byte *pc) |
bool | dr_memory_is_in_client (const byte *pc) |
void * | dr_mutex_create (void) |
void | dr_mutex_destroy (void *mutex) |
void | dr_mutex_lock (void *mutex) |
void | dr_mutex_unlock (void *mutex) |
bool | dr_mutex_trylock (void *mutex) |
module_data_t * | dr_lookup_module (byte *pc) |
module_data_t * | dr_lookup_module_by_name (const char *name) |
dr_module_iterator_t * | dr_module_iterator_start (void) |
bool | dr_module_iterator_hasnext (dr_module_iterator_t *mi) |
module_data_t * | dr_module_iterator_next (dr_module_iterator_t *mi) |
void | dr_module_iterator_stop (dr_module_iterator_t *mi) |
module_data_t * | dr_copy_module_data (const module_data_t *data) |
void | dr_free_module_data (module_data_t *data) |
const char * | dr_module_preferred_name (const module_data_t *data) |
bool | dr_lookup_module_section (module_handle_t lib, byte *pc, IMAGE_SECTION_HEADER *section_out) |
generic_func_t | dr_get_proc_address (module_handle_t lib, const char *name) |
bool | dr_get_proc_address_ex (module_handle_t lib, const char *name, dr_export_info_t *info OUT, size_t info_len) |
reg_t | dr_syscall_get_param (void *drcontext, int param_num) |
void | dr_syscall_set_param (void *drcontext, int param_num, reg_t new_value) |
reg_t | dr_syscall_get_result (void *drcontext) |
void | dr_syscall_set_result (void *drcontext, reg_t value) |
void | dr_syscall_set_sysnum (void *drcontext, int new_num) |
void | dr_syscall_invoke_another (void *drcontext) |
bool | dr_create_dir (const char *fname) |
bool | dr_directory_exists (const char *fname) |
bool | dr_file_exists (const char *fname) |
file_t | dr_open_file (const char *fname, uint mode_flags) |
void | dr_close_file (file_t f) |
void | dr_flush_file (file_t f) |
ssize_t | dr_write_file (file_t f, const void *buf, size_t count) |
ssize_t | dr_read_file (file_t f, void *buf, size_t count) |
bool | dr_file_seek (file_t f, int64 offset, int origin) |
int64 | dr_file_tell (file_t f) |
file_t | dr_dup_file_handle (file_t f) |
void | dr_log (void *drcontext, uint mask, uint level, const char *fmt,...) |
file_t | dr_get_logfile (void *drcontext) |
bool | dr_is_notify_on (void) |
file_t | dr_get_stdout_file (void) |
file_t | dr_get_stderr_file (void) |
file_t | dr_get_stdin_file (void) |
void | dr_messagebox (const char *fmt,...) |
void | dr_printf (const char *fmt,...) |
void | dr_fprintf (file_t f, const char *fmt,...) |
int | dr_snprintf (char *buf, size_t max, const char *fmt,...) |
void | dr_print_instr (void *drcontext, file_t f, instr_t *instr, const char *msg) |
void | dr_print_opnd (void *drcontext, file_t f, opnd_t opnd, const char *msg) |
void * | dr_get_current_drcontext (void) |
thread_id_t | dr_get_thread_id (void *drcontext) |
void * | dr_get_tls_field (void *drcontext) |
void | dr_set_tls_field (void *drcontext, void *value) |
bool | dr_raw_tls_calloc (OUT reg_id_t *segment_register, OUT uint *offset, IN uint num_slots, IN uint alignment) |
bool | dr_raw_tls_cfree (uint offset, uint num_slots) |
bool | dr_create_client_thread (void(*func)(void *param), void *arg) |
void | dr_sleep (int time_ms) |
void | dr_thread_yield (void) |
bool | dr_suspend_all_other_threads (OUT void ***drcontexts, OUT uint *num_suspended, OUT uint *num_unsuspended) |
bool | dr_resume_all_other_threads (IN void **drcontexts, IN uint num_suspended) |
bool | dr_set_itimer (int which, uint millisec, void(*func)(void *drcontext, dr_mcontext_t *mcontext)) |
uint | dr_get_itimer (int which) |
bool | dr_replace_fragment (void *drcontext, void *tag, instrlist_t *ilist) |
bool | dr_delete_fragment (void *drcontext, void *tag) |
bool | dr_flush_region (app_pc start, size_t size) |
bool | dr_unlink_flush_region (app_pc start, size_t size) |
bool | dr_delay_flush_region (app_pc start, size_t size, uint flush_id, void(*flush_completion_callback)(int flush_id)) |
bool | dr_fragment_exists_at (void *drcontext, void *tag) |
bool | dr_bb_exists_at (void *drcontext, void *tag) |
uint | dr_fragment_size (void *drcontext, void *tag) |
app_pc | dr_fragment_app_pc (void *tag) |
app_pc | dr_app_pc_for_decoding (app_pc pc) |
bool | dr_mark_trace_head (void *drcontext, void *tag) |
bool | dr_trace_head_at (void *drcontext, void *tag) |
bool | dr_trace_exists_at (void *drcontext, void *tag) |
#define BB_ORIGIN_HEADER_SIZE (sizeof(app_pc)+sizeof(int)) |
Size of tag + bb_code_size fields for each bb. tracedump_stub_data_t.stub_size will not exceed this value.
#define DR_ASSERT | ( | x | ) | DR_ASSERT_MSG(x, "") |
If x
is false, displays a message about an assertion failure and then calls dr_abort()
#define DR_ASSERT_MSG | ( | x, | |||
msg | ) |
Value:
((void)((!(x)) ? \ (dr_messagebox("ASSERT FAILURE: %s:%d: %s (%s)", __FILE__, __LINE__, #x, msg),\ dr_abort(), 0) : 0))
x
is false, displays a message about an assertion failure (appending msg
to the message) and then calls dr_abort()
#define DR_FILE_ALLOW_LARGE 0x10 |
Open with large (>2GB) file support. Only applicable on 32-bit Linux.
#define DR_FILE_READ 0x1 |
Open with read access.
#define DR_FILE_WRITE_APPEND 0x4 |
Open with write access. If the file already exists, set the file position to the end of the file.
#define DR_FILE_WRITE_OVERWRITE 0x8 |
Open with write access. If the file already exists, truncate the file to zero length.
#define DR_FILE_WRITE_REQUIRE_NEW 0x2 |
Open with write access, but do not open if the file already exists.
#define DR_MEMPROT_EXEC 0x04 |
Execute privileges.
#define DR_MEMPROT_NONE 0x00 |
No read, write, or execute privileges.
#define DR_MEMPROT_READ 0x01 |
Read privileges.
#define DR_MEMPROT_WRITE 0x02 |
Write privileges.
#define DR_SEEK_CUR 1 |
current file position
#define DR_SEEK_END 2 |
end of file
#define DR_SEEK_SET 0 |
start of file
#define LOG_ALL 0x00ffffff |
Log all data.
#define LOG_ASYNCH 0x00000010 |
Log data related to signals/callbacks/etc.
#define LOG_CACHE 0x00000100 |
Log data related to code cache management.
#define LOG_DISPATCH 0x00000400 |
Log data on every context switch dispatch.
#define LOG_EMIT 0x00000040 |
Log data related to emitting code.
#define LOG_FRAGMENT 0x00000200 |
Log data related to app code fragments.
#define LOG_HEAP 0x00001000 |
Log data related to memory management.
#define LOG_HOT_PATCHING 0x00200000 |
Log data related to hot patching.
#define LOG_HTABLE 0x00400000 |
Log data related to hash tables.
#define LOG_INTERP 0x00000020 |
Log data related to app interpretation.
#define LOG_LINKS 0x00000080 |
Log data related to linking code.
#define LOG_MEMSTATS 0x00008000 |
Log data related to memory statistics.
#define LOG_MODULEDB 0x00800000 |
Log data related to the module database.
#define LOG_MONITOR 0x00000800 |
Log data related to trace building.
#define LOG_NONE 0x00000000 |
Log no data.
#define LOG_NT 0x00100000 |
Log data related to Windows Native API.
#define LOG_OPTS 0x00010000 |
Log data related to optimizations.
#define LOG_RCT 0x00080000 |
Log data related to indirect transfers.
#define LOG_SIDELINE 0x00020000 |
Log data related to sideline threads.
#define LOG_STATS 0x00000001 |
Log per-thread and global statistics.
#define LOG_SYMBOLS 0x00040000 |
Log data related to app symbols.
#define LOG_SYNCH 0x00004000 |
Log data related to synchronization.
#define LOG_SYSCALLS 0x00000008 |
Log data related to system calls.
#define LOG_THREADS 0x00000004 |
Log data related to threads.
#define LOG_TOP 0x00000002 |
Log top-level information.
#define LOG_VMAREAS 0x00002000 |
Log data related to address space regions.
#define STUB_DATA_FIXED_SIZE (offsetof(tracedump_stub_data_t, count)) |
The last offset into tracedump_stub_data_t of always-present fields.
typedef struct _dr_export_info_t dr_export_info_t |
Data structure used by dr_get_proc_address_ex() to retrieve information about an exported symbol.
typedef struct _dr_mem_info_t dr_mem_info_t |
Describes a memory region. Used by dr_query_memory_ex().
typedef void* dr_module_iterator_t |
For dr_module_iterator_* interface
typedef void* module_handle_t |
Type used for dr_get_proc_address(). This can be obtained from the _module_data_t structure. It is equivalent to the base address of the module on both Windows and Linux.
typedef struct _module_names_t module_names_t |
Holds the names of a module. This structure contains multiple fields corresponding to different sources of a module name. Note that some of these names may not exist for certain modules. It is highly likely, however, that at least one name is available. Use dr_module_preferred_name() on the parent _module_data_t to get the preferred name of the module.
typedef struct _tracedump_file_header_t tracedump_file_header_t |
Binary trace dump format: the file starts with a tracedump_file_header_t then, for each trace: struct _tracedump_trace_header if num_bbs > 0 # tracedump_origins foreach bb: app_pc tag; int bb_code_size; byte code[bb_code_size]; endif foreach exit: struct _tracedump_stub_data if linkcount_size > 0 linkcount_type_t count; # sizeof == linkcount_size endif if separate from body (i.e., exit_stub < cache_start_pc || exit_stub >= cache_start_pc+code_size): byte stub_code[15]; # all separate stubs are 15 endif endfor byte code[code_size]; if the -tracedump_threshold option (deprecated) was specified: int num_below_treshold linkcount_type_t count_below_threshold endif
typedef struct _tracedump_stub_data tracedump_stub_data_t |
The format of a stub in a trace dump file.
typedef struct _tracedump_trace_header_t tracedump_trace_header_t |
Header for an individual trace in a binary trace dump file.
typedef union _version_number_t version_number_t |
Used to hold .rsrc section version number information. This number is usually presented as p1.p2.p3.p4 by PE parsing tools.
enum dr_mem_type_t |
Flags describing memory used by dr_query_memory_ex().
void __wrap_free | ( | void * | mem | ) |
Frees memory from DR's global memory pool. Memory must have been allocated with __wrap_malloc(). The __wrap routines are intended to be used with ld's -wrap option; see __wrap_malloc() for more information.
void* __wrap_malloc | ( | size_t | size | ) |
Allocates memory from DR's global memory pool, but mimics the behavior of malloc. Memory must be freed with __wrap_free(). The __wrap routines are intended to be used with ld's -wrap option to replace a client's use of malloc, realloc, and free with internal versions that allocate memory from DR's private pool. With -wrap, clients can link to libraries that allocate heap memory without interfering with application allocations.
void* __wrap_realloc | ( | void * | mem, | |
size_t | size | |||
) |
Reallocates memory from DR's global memory pool, but mimics the behavior of realloc. Memory must be freed with __wrap_free(). The __wrap routines are intended to be used with ld's -wrap option; see __wrap_malloc() for more information.
void dr_abort | ( | void | ) |
Aborts the process immediately.
app_pc dr_app_pc_for_decoding | ( | app_pc | pc | ) |
Given an application PC, returns a PC that contains the application code corresponding to the original PC. In some circumstances on Windows DR inserts a jump on top of the original code, which the client will not see in the bb and trace hooks due to DR replacing it there with the displaced original application code in order to present the client with an unmodified view of the application code. A client should use this routine when attempting to decode the original application instruction that caused a fault from the translated fault address, as the translated address may actually point in the middle of DR's jump.
bool dr_bb_exists_at | ( | void * | drcontext, | |
void * | tag | |||
) |
Returns true if a basic block with tag tag
exists in the code cache.
void dr_close_file | ( | file_t | f | ) |
Closes file f
.
module_data_t* dr_copy_module_data | ( | const module_data_t * | data | ) |
Makes a copy of data
. Copy must be freed with dr_free_module_data(). Useful for making persistent copies of module_data_t's received as part of image load and unload event callbacks.
bool dr_create_client_thread | ( | void(*)(void *param) | func, | |
void * | arg | |||
) |
Creates a new thread that is marked as a non-application thread (i.e., DR will let it run natively and not execute its code from the code cache). The thread will terminate automatically simply by returning from func
; if running when the application terminates its last thread, the client thread will also terminate when DR shuts the process down.
Init and exit events will not be raised for this thread (instead simply place init and exit code in func
).
The new client thread has a drcontext that can be used for thread-private heap allocations. It has a stack of the same size as the DR stack used by application threads.
On Linux, this thread is guaranteed to have its own private itimer if dr_set_itimer() is called from it. However this does mean it will have its own process id.
A client thread should refrain from spending most of its time in calls to other libraries or making blocking or long-running system calls as such actions may incur performance or correctness problems with DR's synchronization engine, which needs to be able to suspend client threads at safe points and cannot determine whether the aforementioned actions are safe for suspension. Calling dr_sleep(), dr_thread_yield(), dr_messagebox(), or using DR's locks are safe.
bool dr_create_dir | ( | const char * | fname | ) |
Creates a new directory. Fails if the directory already exists or if it can't be created.
bool dr_delay_flush_region | ( | app_pc | start, | |
size_t | size, | |||
uint | flush_id, | |||
void(*)(int flush_id) | flush_completion_callback | |||
) |
Request a flush of all fragments containing code from the region [start
, start
+ size
). The flush will be performed at the next safe point in time (usually before any new code is added to the cache after this routine is called). If flush_completion_callback
is non-NULL, it will be called with the flush_id
provided to this routine when the flush completes, after which no execution will occur out of the fragments flushed. Returns true if the flush was successfully queued.
Use size
== 1 to flush fragments containing the instruction at address start
. A flush of size
== 0 is not allowed.
As currently implemented there may be a performance penalty for requesting a flush_completion_callback
; for most performant usage set flush_completion_callback
to NULL.
bool dr_delete_fragment | ( | void * | drcontext, | |
void * | tag | |||
) |
Deletes the fragment with tag tag
. This routine is only valid with the -thread_private option; it deletes the fragment in the current thread only. After deletion, the existing fragment is allowed to complete execution. For example, a clean call deleting the currently executing fragment will safely return to the existing code. Subsequent executions will cause DynamoRIO to reconstruct the fragment, and therefore call the appropriate fragment-creation event hook, if registered.
drcontext
must be from the current thread and must be the drcontext used to create the instruction list.bool dr_directory_exists | ( | const char * | fname | ) |
Checks for the existence of a directory.
file_t dr_dup_file_handle | ( | file_t | f | ) |
Returns a new copy of the file handle f
. Returns INVALID_FILE on error.
bool dr_file_exists | ( | const char * | fname | ) |
Checks the existence of a file.
bool dr_file_seek | ( | file_t | f, | |
int64 | offset, | |||
int | origin | |||
) |
Sets the current file position for file f
to offset
bytes from the specified origin, where origin
is one of the DR_SEEK_* values. Returns true if successful.
int64 dr_file_tell | ( | file_t | f | ) |
Returns the current position for the file f
in bytes from the start of the file. Returns -1 on an error.
void dr_flush_file | ( | file_t | f | ) |
Flushes any buffers for file f
.
bool dr_flush_region | ( | app_pc | start, | |
size_t | size | |||
) |
Flush all fragments containing any code from the region [start
, start
+ size
). Once this routine returns no execution will occur out of the fragments flushed. This routine may only be called during a clean call from the cache or from a nudge event handler. It may not be called from any other event callback. No locks can held when calling this routine. If called from a clean call, caller can NOT return to the cache (the fragment that was called out of may have been flushed even if it doesn't apparently overlap the flushed region). Instead the caller must call dr_redirect_execution() after this routine to continue execution. Returns true if successful.
If called from a clean call, caller must continue execution by calling dr_redirect_execution() after this routine, as the fragment containing the callout may have been flushed. The context and app_errno to use can be obtained via dr_get_mcontext() with the exception of the pc to continue at which must be passed as an argument to the callout (see instr_get_app_pc()) or otherwise determined.
This routine may not be called while any locks are held that could block a thread processing a registered event callback or cache callout.
dr_delay_flush_region() has fewer restrictions on use, but is less synchronous.
Use size
== 1 to flush fragments containing the instruction at address start
. A flush of size
== 0 is not allowed.
As currently implemented, dr_delay_flush_region() with no completion callback routine specified can be substantially more performant.
void dr_fprintf | ( | file_t | f, | |
const char * | fmt, | |||
... | ||||
) |
Printing to a file that won't interfere with the application's own printing. Currently non-buffered.
On Windows, this routine does not support printing floating point values. Use dr_snprintf() instead.
If the data to be printed is large it will be truncated to an internal buffer size. Use dr_write_file() to print large buffers.
On Linux this routine does not check for errors like EINTR. Use dr_write_file() if that is a concern.
app_pc dr_fragment_app_pc | ( | void * | tag | ) |
Retrieves the application PC of a fragment with tag tag
.
bool dr_fragment_exists_at | ( | void * | drcontext, | |
void * | tag | |||
) |
Returns whether or not there is a fragment in code cache with tag tag
.
uint dr_fragment_size | ( | void * | drcontext, | |
void * | tag | |||
) |
Looks up the fragment with tag tag
. If not found, returns 0. If found, returns the total size occupied in the cache by the fragment.
void dr_free_module_data | ( | module_data_t * | data | ) |
Frees a module_data_t returned by dr_module_iterator_next(), dr_lookup_module(), dr_lookup_module_by_name(), or dr_copy_module_data().
const char* dr_get_application_name | ( | void | ) |
Returns the image name (without path) of the current application.
const char* dr_get_client_path | ( | client_id_t | client_id | ) |
Returns the client library name and path that were originally specified to load the library. If the resulting string is longer than MAXIMUM_PATH it will be truncated. client_id
is the client ID passed to a client's dr_init() function.
void* dr_get_current_drcontext | ( | void | ) |
Returns the DR context of the current thread.
uint dr_get_itimer | ( | int | which | ) |
If an interval timer is already installed in the itimer sharing group that contains the calling thread, returns its frequency. Else returns 0.
[in] | which | Must be one of ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF |
file_t dr_get_logfile | ( | void * | drcontext | ) |
Returns the log file for the thread with drcontext drcontext
. If drcontext
is NULL, returns the main log file.
uint64 dr_get_milliseconds | ( | void | ) |
On Linux, returns the number of milliseconds since the Epoch (Jan 1, 1970). On Windows, returns the number of milliseconds since Jan 1, 1600 (this is the current UTC time).
const char* dr_get_options | ( | client_id_t | client_id | ) |
Returns the client-specific option string specified at client registration. client_id
is the client ID passed to dr_init().
process_id_t dr_get_parent_id | ( | void | ) |
Returns the process id of the parent of the current process.
generic_func_t dr_get_proc_address | ( | module_handle_t | lib, | |
const char * | name | |||
) |
Returns the entry point of the exported function with the given name in the module with the given base. Returns NULL on failure.
On Linux, in order to handle indirect code objects, use dr_get_proc_address_ex().
bool dr_get_proc_address_ex | ( | module_handle_t | lib, | |
const char * | name, | |||
dr_export_info_t *info | OUT, | |||
size_t | info_len | |||
) |
Returns information in info
about the symbol name
exported by the module lib
. Returns false if the symbol is not found.
process_id_t dr_get_process_id | ( | void | ) |
Returns the process id of the current process.
file_t dr_get_stderr_file | ( | void | ) |
Returns a handle to stderr.
file_t dr_get_stdin_file | ( | void | ) |
Returns a handle to stdin.
file_t dr_get_stdout_file | ( | void | ) |
Returns a handle to stdout.
thread_id_t dr_get_thread_id | ( | void * | drcontext | ) |
Returns the thread id of the thread with drcontext drcontext
.
void dr_get_time | ( | dr_time_t * | time | ) |
Retrieves the current time.
void* dr_get_tls_field | ( | void * | drcontext | ) |
Returns the user-controlled thread-local-storage field. To generate an instruction sequence that reads the drcontext field inline in the code cache, use dr_insert_read_tls_field().
void* dr_global_alloc | ( | size_t | size | ) |
Allocates size
bytes of memory from DR's global memory pool.
void dr_global_free | ( | void * | mem, | |
size_t | size | |||
) |
Frees memory allocated by dr_global_alloc(). size
must be the same as that passed to dr_global_alloc().
bool dr_is_notify_on | ( | void | ) |
Returns true iff the -stderr_mask runtime option is non-zero, indicating that the user wants notification messages printed to stderr.
bool dr_is_wow64 | ( | void | ) |
Returns true if this process is a 32-bit process operating on a 64-bit Windows kernel, known as Windows-On-Windows-64, or WOW64. Returns false otherwise.
void dr_log | ( | void * | drcontext, | |
uint | mask, | |||
uint | level, | |||
const char * | fmt, | |||
... | ||||
) |
Writes to DR's log file for the thread with drcontext drcontext
if the current loglevel is >= level
and the current logmask
& mask
!= 0. The mask constants are below. Logging is disabled for the release build. If drcontext
is NULL, writes to the main log file.
module_data_t* dr_lookup_module | ( | byte * | pc | ) |
Looks up the module containing pc
. If a module containing pc
is found returns a module_data_t describing that module else returns NULL. Can be used to obtain a module_handle_t for dr_lookup_module_section().
module_data_t* dr_lookup_module_by_name | ( | const char * | name | ) |
Looks up the module with name name
ignoring case. If an exact name match is found returns a module_data_t describing that module else returns NULL. User must call dr_free_module_data() on the returned module_data_t once finished. Can be used to obtain a module_handle_t for dr_get_proc_address().
bool dr_lookup_module_section | ( | module_handle_t | lib, | |
byte * | pc, | |||
IMAGE_SECTION_HEADER * | section_out | |||
) |
Returns whether pc
is within a section within the module in section_found
and information about that section in section_out
.
bool dr_mark_trace_head | ( | void * | drcontext, | |
void * | tag | |||
) |
Marks the fragment associated with tag tag
as a trace head. The fragment need not exist yet -- once it is created it will be marked as a trace head.
DR associates a counter with a trace head and once it passes the -hot_threshold parameter, DR begins building a trace. Before each fragment is added to the trace, DR calls the client's end_trace callback to determine whether to end the trace. (The callback will be called both for standard DR traces and for client-defined traces.)
Some fragments' notion of trace heads is dependent on which previous block targets them. For these fragments, calling this routine will only mark as a trace head for targets from the same memory region.
bool dr_memory_is_dr_internal | ( | const byte * | pc | ) |
Returns true iff pc is memory allocated by DR for its own purposes, and would not exist if the application were run natively.
bool dr_memory_is_in_client | ( | const byte * | pc | ) |
Returns true iff pc is located inside a client library.
bool dr_memory_is_readable | ( | const byte * | pc, | |
size_t | size | |||
) |
Checks to see that all bytes with addresses in the range [pc
, pc
+ size
- 1] are readable and that reading from that range won't generate an exception (see also dr_safe_read()).
On Linux, especially if the app is in the middle of loading a library and has not properly set up the .bss yet, a page that seems readable can still generate SIGBUS if beyond the end of an mmapped file. Use dr_safe_read() to avoid such problems.
bool dr_memory_protect | ( | void * | base, | |
size_t | size, | |||
uint | new_prot | |||
) |
Modifies the memory protections of the region from start
through start
+ size
. Modification of memory allocated by DR or of the DR or client libraries themselves is allowed under the assumption that the client knows what it is doing. Modification of the ntdll.dll library on Windows is not allowed. Returns true if successful.
void dr_messagebox | ( | const char * | fmt, | |
... | ||||
) |
Displays a message in a pop-up window.
On Windows Vista most Windows services are unable to display message boxes.
bool dr_module_iterator_hasnext | ( | dr_module_iterator_t * | mi | ) |
Returns true if there is another loaded module in the iterator.
module_data_t* dr_module_iterator_next | ( | dr_module_iterator_t * | mi | ) |
Retrieves the module_data_t for the next loaded module in the iterator. User must call dr_free_module_data() on the returned module_data_t once finished.
dr_module_iterator_t* dr_module_iterator_start | ( | void | ) |
Initialize a new module iterator. The returned module iterator contains a snapshot of the modules loaded at the time it was created. Use dr_module_iterator_hasnext() and dr_module_iterator_next() to walk the loaded modules. Call dr_module_iterator_stop() when finished to release the iterator.
void dr_module_iterator_stop | ( | dr_module_iterator_t * | mi | ) |
User should call this routine to free the module iterator.
const char* dr_module_preferred_name | ( | const module_data_t * | data | ) |
Returns the preferred name for the module described by data
from data->module_names
.
void* dr_mutex_create | ( | void | ) |
Initializes a mutex.
Warning: there are restrictions on when DR-provided mutexes, and locks in general, can be held by a client: no lock should be held while application code is executing in the code cache. Locks can be used while inside client code reached from clean calls out of the code cache, but they must be released before returning to the cache. Failing to follow these restrictions can lead to deadlocks.
void dr_mutex_destroy | ( | void * | mutex | ) |
Deletes mutex
.
void dr_mutex_lock | ( | void * | mutex | ) |
Locks mutex
. Waits until the mutex is successfully held.
bool dr_mutex_trylock | ( | void * | mutex | ) |
Tries once to lock mutex
, returns whether or not successful.
void dr_mutex_unlock | ( | void * | mutex | ) |
Unlocks mutex
. Asserts that mutex is currently locked.
void* dr_nonheap_alloc | ( | size_t | size, | |
uint | prot | |||
) |
Allocates size
bytes of memory as a separate allocation from DR's heap, allowing for separate protection. The prot
protection should use the DR_MEMPROT_READ, DR_MEMPROT_WRITE, and DR_MEMPROT_EXEC bits. When creating a region to hold dynamically generated code, use this routine in order to create executable memory.
void dr_nonheap_free | ( | void * | mem, | |
size_t | size | |||
) |
Frees memory allocated by dr_nonheap_alloc(). size
must be the same as that passed to dr_nonheap_alloc().
file_t dr_open_file | ( | const char * | fname, | |
uint | mode_flags | |||
) |
Opens the file fname
. On Windows, fname
must be an absolute path. If no such file exists then one is created. The file access mode is set by the mode_flags
argument which is drawn from the DR_FILE_* defines ORed together. Returns INVALID_FILE if unsuccessful.
DR does not hide files opened by clients from the application, to allow clients to open application files and other forms of interaction. Some applications close all file descriptors, and clients may want to watch for the close system call and turn it into a nop (e.g., return -EBADF and not execute it on Linux) if targeting a client-owned filed.
void dr_print_instr | ( | void * | drcontext, | |
file_t | f, | |||
instr_t * | instr, | |||
const char * | msg | |||
) |
Prints msg
followed by the instruction instr
to file f
.
void dr_print_opnd | ( | void * | drcontext, | |
file_t | f, | |||
opnd_t | opnd, | |||
const char * | msg | |||
) |
Prints msg
followed by the operand opnd
to file f
.
void dr_printf | ( | const char * | fmt, | |
... | ||||
) |
Stdout printing that won't interfere with the application's own printing. Currently non-buffered.
On Windows, this routine does not support printing floating point values. Use dr_snprintf() instead.
If the data to be printed is large it will be truncated to an internal buffer size.
bool dr_query_memory | ( | const byte * | pc, | |
byte ** | base_pc, | |||
size_t * | size, | |||
uint * | prot | |||
) |
An os neutral method for querying a memory address. Returns true iff a memory region containing pc
is found. If found additional information about the memory region is returned in the optional out arguments base_pc
, size
, and prot
where base_pc
is the start address of the memory region continaing pc
, size
is the size of said memory region and prot
is an ORed combination of DR_MEMPROT_* flags describing its current protection.
bool dr_query_memory_ex | ( | const byte * | pc, | |
OUT dr_mem_info_t * | info | |||
) |
Provides additional information beyond dr_query_memory(). Returns true if it was able to obtain information (including about free regions) and sets the fields of info
. This routine can be used to iterate over the entire address space. Returns false on failure.
bool dr_raw_tls_calloc | ( | OUT reg_id_t * | segment_register, | |
OUT uint * | offset, | |||
IN uint | num_slots, | |||
IN uint | alignment | |||
) |
Allocates num_slots
contiguous thread-local storage slots that can be directly accessed via an offset from segment_register
. These slots will be initialized to 0 for each new thread. The slot offsets are [offset
.. offset
+ (num_slots - 1)]. These slots are disjoint from the dr_spill_slot_t register spill slots and the client tls field (dr_get_tls_field()). Returns whether or not the slots were successfully obtained.
These slots are a limited resource. On Windows the slots are shared with the application and reserving even one slot can result in failure to initialize for certain applications. On Linux they are more plentiful and transparent but currently DR limits clients to no more than 64 slots.
bool dr_raw_tls_cfree | ( | uint | offset, | |
uint | num_slots | |||
) |
Frees num_slots
raw thread-local storage slots starting at offset offset
that were allocated with dr_raw_tls_calloc(). Returns whether or not the slots were successfully freed.
ssize_t dr_read_file | ( | file_t | f, | |
void * | buf, | |||
size_t | count | |||
) |
Reads up to count
bytes from file f
into buf
. Returns the actual number read.
bool dr_replace_fragment | ( | void * | drcontext, | |
void * | tag, | |||
instrlist_t * | ilist | |||
) |
Replaces the fragment with tag tag
with the instructions in ilist
. This routine is only valid with the -thread_private option; it replaces the fragment for the current thread only. After replacement, the existing fragment is allowed to complete if currently executing. For example, a clean call replacing the currently executing fragment will safely return to the existing code. Subsequent executions will use the new instructions.
ilist
and all responsibility for deleting it. The client should not keep, use, or reference, the instrlist or any of the instrs it contains after passing.
This routine supports replacement for the current thread only. drcontext
must be from the current thread and must be the drcontext used to create the instruction list.
void dr_request_synchronized_exit | ( | void | ) |
Enables the -synch_at_exit runtime option, which guarantees that no thread will executed beyond its own thread exit event at process exit time. When the -synch_at_exit option is off, which is the default setting, in release builds there is no such guarantee.
bool dr_resume_all_other_threads | ( | IN void ** | drcontexts, | |
IN uint | num_suspended | |||
) |
May only be used after invoking dr_suspend_all_other_threads(). This routine resumes the threads that were suspended by dr_suspend_all_other_threads() and must be passed the same array and count of suspended threads that were returned by dr_suspend_all_other_threads(). It also frees the drcontexts
array and releases the locks acquired by dr_suspend_all_other_threads(). The return value indicates whether all resumption attempts were successful.
bool dr_safe_read | ( | const void * | base, | |
size_t | size, | |||
void * | out_buf, | |||
size_t * | bytes_read | |||
) |
Safely reads size
bytes from address base
into buffer out_buf
. Reading is done without the possibility of an exception occurring. Optionally returns the actual number of bytes copied into bytes_read
. Returns true if successful.
bool dr_safe_write | ( | void * | base, | |
size_t | size, | |||
const void * | in_buf, | |||
size_t * | bytes_written | |||
) |
Safely writes size
bytes from buffer in_buf
to address base
. Writing is done without the possibility of an exception occurring. Optionally returns the actual number of bytes copied into bytes_written
. Returns true if successful.
bool dr_set_itimer | ( | int | which, | |
uint | millisec, | |||
void(*)(void *drcontext, dr_mcontext_t *mcontext) | func | |||
) |
Installs an interval timer in the itimer sharing group that contains the calling thread.
[in] | which | Must be one of ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF |
[in] | millisec | The frequency of the timer, in milliseconds. Passing 0 disables the timer. |
[in] | func | The function that will be called each time the timer fires. It will be passed the context of the thread that received the itimer signal and its machine context, which has not been translated and so may contain raw code cache values. The function will be called from a signal handler that may have interrupted lock holder or other critical code, so it must be careful in its operations. If a general timer that does not interrupt client code is required, the client should create a separate thread via dr_create_client_thread() (which is guaranteed to have a private itimer) and set the itimer there, where the callback function can perform more operations safely if that new thread never acquires locks in its normal operation. |
The itimer will operate successfully in the presence of an application itimer of the same type.
The return value indicates whether the timer was successfully installed (or uninstalled if 0 was passed for millisec
).
void dr_set_tls_field | ( | void * | drcontext, | |
void * | value | |||
) |
Sets the user-controlled thread-local-storage field. To generate an instruction sequence that reads the drcontext field inline in the code cache, use dr_insert_write_tls_field().
void dr_sleep | ( | int | time_ms | ) |
Current thread sleeps for time_ms
milliseconds.
int dr_snprintf | ( | char * | buf, | |
size_t | max, | |||
const char * | fmt, | |||
... | ||||
) |
Utility routine to print a formatted message to a string. Will not print more than max characters. If successful, returns the number of characters printed, not including the terminating null character. If the number of characters to write equals max, then the caller is responsible for supplying a terminating null character. If the number of characters to write exceeds max, then max characters are written and -1 is returned. If an error occurs, a negative value is returned.
If the data to be printed is large it will be truncated to an internal buffer size.
void* dr_standalone_init | ( | void | ) |
Creates a DR context that can be used in a standalone program.
bool dr_suspend_all_other_threads | ( | OUT void *** | drcontexts, | |
OUT uint * | num_suspended, | |||
OUT uint * | num_unsuspended | |||
) |
Suspends all other threads in the process and returns an array of contexts in drcontexts
with one context per successfully suspended threads. The contexts can be passed to routines like dr_get_thread_id() or dr_get_mcontext(). However, the contexts may not be modified: dr_set_mcontext() is not supported. dr_get_mcontext() can be called on the caller of this routine, unless in a Windows nudge callback.
The number of successfully suspended threads, which is also the length of the drcontexts
array, is returned in num_suspended
, which is a required parameter. The number of un-successfully suspended threads, if any, is returned in the optional parameter num_unsuspended
. The calling thread is not considered in either count. DR can fail to suspend a thread for privilege reasons (e.g., on Windows in a low-privilege process where another process injected a thread). This function returns true iff all threads were suspended, in which case num_unsuspended
will be 0.
The caller must invoke dr_resume_all_other_threads() in order to resume the suspended threads, free the drcontexts
array, and release coarse-grain locks that prevent new threads from being created.
This routine may not be called from any registered event callback other than the nudge event. It may be called from clean calls out of the cache. This routine may not be called while any locks are held that could block a thread processing a registered event callback or cache callout.
reg_t dr_syscall_get_param | ( | void * | drcontext, | |
int | param_num | |||
) |
Usable only from a pre-syscall (dr_register_pre_syscall_event()) event. Returns the value of system call parameter number param_num
.
reg_t dr_syscall_get_result | ( | void * | drcontext | ) |
Usable only from a post-syscall (dr_register_post_syscall_event()) event. Returns the return value of the system call that will be presented to the application.
void dr_syscall_invoke_another | ( | void * | drcontext | ) |
Usable only from a post-syscall (dr_register_post_syscall_event()) event. An additional system call will be invoked immediately, using the current values of the parameters, which can be set with dr_syscall_set_param(). The system call to be invoked should be specified with dr_syscall_set_sysnum().
Use this routine with caution. Especially on Windows, care must be taken if the application is expected to continue afterward. When system call parameters are stored on the stack, modifying them can result in incorrect application behavior, particularly when setting more parameters than were present in the original system call, which will result in corruption of the application stack.
On Windows, when the first system call is interruptible (alertable), the additional system call may be delayed.
DR will set key registers such as r10 for 64-bit or xdx for sysenter or WOW64 system calls. However, DR will not set ecx for WOW64; that is up to the client.
void dr_syscall_set_param | ( | void * | drcontext, | |
int | param_num, | |||
reg_t | new_value | |||
) |
Usable only from a pre-syscall (dr_register_pre_syscall_event()) event, or from a post-syscall (dr_register_post_syscall_event()) event when also using dr_syscall_invoke_another(). Sets the value of system call parameter number param_num
to new_value
.
void dr_syscall_set_result | ( | void * | drcontext, | |
reg_t | value | |||
) |
Usable only from a pre-syscall (dr_register_pre_syscall_event()) or post-syscall (dr_register_post_syscall_event()) event. For pre-syscall, should only be used when skipping the system call. This sets the return value of the system call that the application sees to value
.
void dr_syscall_set_sysnum | ( | void * | drcontext, | |
int | new_num | |||
) |
Usable only from a pre-syscall (dr_register_pre_syscall_event()) event, or from a post-syscall (dr_register_post_syscall_event()) event when also using dr_syscall_invoke_another(). Sets the system call number of the system call about to be invoked to new_num
.
void* dr_thread_alloc | ( | void * | drcontext, | |
size_t | size | |||
) |
Allocates size
bytes of memory from DR's memory pool specific to the thread associated with drcontext
.
void dr_thread_free | ( | void * | drcontext, | |
void * | mem, | |||
size_t | size | |||
) |
Frees thread-specific memory allocated by dr_thread_alloc(). size
must be the same as that passed to dr_thread_alloc().
void dr_thread_yield | ( | void | ) |
Current thread gives up its time quantum.
bool dr_trace_exists_at | ( | void * | drcontext, | |
void * | tag | |||
) |
Checks to see that if there is a trace in the code cache at tag tag
.
bool dr_trace_head_at | ( | void * | drcontext, | |
void * | tag | |||
) |
Checks to see if the fragment (or future fragment) with tag tag
is marked as a trace head.
bool dr_unlink_flush_region | ( | app_pc | start, | |
size_t | size | |||
) |
Flush all fragments containing any code from the region [start
, start
+ size
). Control will not enter a fragment containing code from the region after this returns, but a thread already in such a fragment will finish out the fragment. This includes the current thread if this is called from a clean call that returns to the cache. This routine may only be called during a clean call from the cache or from a nudge event handler. It may not be called from any other event callback. No locks can be held when calling this routine. Returns true if successful.
This routine may not be called while any locks are held that could block a thread processing a registered event callback or cache callout.
dr_delay_flush_region() has fewer restrictions on use, but is less synchronous.
Use size
== 1 to flush fragments containing the instruction at address start
. A flush of size
== 0 is not allowed.
This routine is only available with either the -thread_private or -enable_full_api options. It is not available when -opt_memory is specified.
bool dr_using_all_private_caches | ( | void | ) |
Returns true if all DynamoRIO caches are thread private.
size_t dr_virtual_query | ( | const byte * | pc, | |
MEMORY_BASIC_INFORMATION * | mbi, | |||
size_t | mbi_size | |||
) |
Equivalent to the win32 API function VirtualQuery(). See that routine for a description of arguments and return values.
ssize_t dr_write_file | ( | file_t | f, | |
const void * | buf, | |||
size_t | count | |||
) |
Writes count
bytes from buf
to file f
. Returns the actual number written.