| /* ********************************************************** |
| * Copyright (c) 2010-2024, Inc. All rights reserved. |
| * Copyright (c) 2002-2010 VMware, Inc. All rights reserved. |
| * **********************************************************/ |
| |
| /* |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * * Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * * Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * * Neither the name of VMware, Inc. nor the names of its contributors may be |
| * used to endorse or promote products derived from this software without |
| * specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| * DAMAGE. |
| */ |
| |
| #ifndef _DR_TOOLS_H_ |
| #define _DR_TOOLS_H_ 1 |
| |
| /************************************************** |
| * TOP-LEVEL ROUTINES |
| */ |
| /** |
| * @file dr_tools.h |
| * @brief Main API routines, including transparency support. |
| */ |
| |
| DR_API |
| /** |
| * Creates a DR context that can be used in a standalone program. |
| * \warning This context cannot be used as the drcontext for a thread |
| * running under DR control! It is only for standalone programs that |
| * wish to use DR as a library of disassembly, etc. routines. |
| * \warning This context is not fully thread-safe as it stores some state |
| * (such as #dr_isa_mode_t and other fields related to AArch32 encoding |
| * and decoding) that is global and may be prone to data races. |
| * For example, having different threads use dr_set_isa_mode() to set |
| * different ISA modes at the same time can result in a data race. |
| * Furthermore, encoding and decoding of AArch32 instructions in parallel |
| * may also result in a data race. |
| * Code that uses a standalone DR context across multiple threads should |
| * implement its own lock/unlock mechanism to avoid such data races |
| * when using dr_set_isa_mode() or encoding/decoding AArch32 instructions. |
| * \return NULL on failure, such as running on an unsupported operating |
| * system version. |
| */ |
| /* TODO i#6690: Add better multi-thread standalone decoding support. |
| */ |
| void * |
| dr_standalone_init(void); |
| |
| DR_API |
| /** |
| * Restores application state modified by dr_standalone_init(), which can |
| * include some signal handlers. |
| */ |
| void |
| dr_standalone_exit(void); |
| |
| #ifndef GLOBAL_DCONTEXT |
| /** |
| * Use this dcontext for use with the standalone static decoder library. |
| * Pass it whenever a decoding-related API routine asks for a context. |
| * Note that this GLOBAL_DCONTEXT is returned by dr_standalone_init(); |
| * beware of its limitations (especially about thread-safety) described |
| * there. |
| */ |
| # define GLOBAL_DCONTEXT ((void *)-1) |
| #endif |
| |
| /************************************************** |
| * UTILITY ROUTINES |
| */ |
| |
| #ifdef WINDOWS |
| /** |
| * If \p x is false, displays a message about an assertion failure |
| * (appending \p msg to the message) and then calls dr_abort() |
| */ |
| # define DR_ASSERT_MSG(x, msg) \ |
| ((void)((!(x)) ? (dr_messagebox("ASSERT FAILURE: %s:%d: %s (%s)", __FILE__, \ |
| __LINE__, #x, msg), \ |
| dr_abort(), 0) \ |
| : 0)) |
| #else |
| # define DR_ASSERT_MSG(x, msg) \ |
| ((void)((!(x)) ? (dr_fprintf(STDERR, "ASSERT FAILURE: %s:%d: %s (%s)\n", \ |
| __FILE__, __LINE__, #x, msg), \ |
| dr_abort(), 0) \ |
| : 0)) |
| #endif |
| |
| /** |
| * If \p x is false, displays a message about an assertion failure and |
| * then calls dr_abort() |
| */ |
| #define DR_ASSERT(x) DR_ASSERT_MSG(x, "") |
| |
| DR_API |
| /** Returns true if all DynamoRIO caches are thread private. */ |
| bool |
| dr_using_all_private_caches(void); |
| |
| DR_API |
| /** |
| * Returns false if DynamoRIO is being used as a "regular" standalone library |
| * (see dr_standalone_init() and \ref page_standalone). |
| * Returns true if DynamoRIO is controlling the application by running |
| * its code through a software code cache. |
| */ |
| bool |
| dr_running_under_dynamorio(void); |
| |
| DR_API |
| /** \deprecated Replaced by dr_set_process_exit_behavior() */ |
| void |
| dr_request_synchronized_exit(void); |
| |
| DR_API |
| /** |
| * Returns the client-specific option string specified at client |
| * registration. \p client_id is the client ID passed to dr_client_main(). |
| * |
| * \deprecated This routine is replaced by dr_client_main()'s arguments and |
| * by dr_get_option_array(). |
| * The front-end \p drrun and other utilities now re-quote all tokens, |
| * providing simpler option passing without escaping or extra quote layers. |
| * This routine, for compatibility, strips those quotes off and returns |
| * a flat string without any token-delimiting quotes. |
| */ |
| const char * |
| dr_get_options(client_id_t client_id); |
| |
| DR_API |
| /** |
| * Returns the client-specific option string specified at client |
| * registration, parsed into an array of \p argc separate option tokens |
| * stored in \p argv. This is the same array of arguments passed |
| * to the dr_client_main() routine. |
| */ |
| bool |
| dr_get_option_array(client_id_t client_id, int *argc DR_PARAM_OUT, |
| const char ***argv DR_PARAM_OUT); |
| |
| DR_API |
| /** |
| * Read the value of a string DynamoRIO runtime option named \p option_name into |
| * \p buf. Options are listed in \ref sec_options. DynamoRIO has many other |
| * undocumented options which may be queried through this API, but they are not |
| * officially supported. The option value is truncated to \p len bytes and |
| * null-terminated. |
| * \return false if no option named \p option_name exists, and true otherwise. |
| */ |
| bool |
| dr_get_string_option(const char *option_name, char *buf DR_PARAM_OUT, size_t len); |
| |
| DR_API |
| /** |
| * Read the value of an integer DynamoRIO runtime option named \p option_name |
| * into \p val. This includes boolean options. Options are listed in \ref |
| * sec_options. DynamoRIO has many other undocumented options which may be |
| * queried through this API, but they are not officially supported. |
| * \warning Always pass a full uint64 for \p val even if the option is a smaller |
| * integer to avoid overwriting nearby data. |
| * \return false if no option named \p option_name exists, and true otherwise. |
| */ |
| bool |
| dr_get_integer_option(const char *option_name, uint64 *val DR_PARAM_OUT); |
| |
| DR_API |
| /** |
| * 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. \p client_id is the client ID passed to a client's |
| * dr_client_main() function. |
| */ |
| const char * |
| dr_get_client_path(client_id_t client_id); |
| |
| DR_API |
| /** |
| * Returns the base address of the client library. \p client_id is |
| * the client ID passed to a client's dr_client_main() function. |
| */ |
| byte * |
| dr_get_client_base(client_id_t client_id); |
| |
| DR_API |
| /** |
| * Sets information presented to users in diagnostic messages. |
| * Only one name is supported, regardless of how many clients are in use. |
| * If this routine is called a second time, the new values supersede |
| * the original. |
| * The \p report_URL is meant to be a bug tracker location where users |
| * should go to report errors in the client end-user tool. |
| */ |
| bool |
| dr_set_client_name(const char *name, const char *report_URL); |
| |
| DR_API |
| /** |
| * Sets the version string presented to users in diagnostic messages. |
| * This has a maximum length of 96 characters; anything beyond that is |
| * silently truncated. |
| */ |
| bool |
| dr_set_client_version_string(const char *version); |
| |
| DR_API |
| /** |
| * Returns the error code of the last failed API routine. Users should check whether or |
| * not the API routine that they just called has failed prior to calling this function. |
| * |
| * \warning Not all API routines currently support the registering of an error code upon |
| * their failure. Therefore, check the routine's documentation to see whether it supports |
| * setting error codes. |
| */ |
| dr_error_code_t |
| dr_get_error_code(void *drcontext); |
| |
| DR_API |
| /** Retrieves the current time. */ |
| void |
| dr_get_time(dr_time_t *time); |
| |
| DR_API |
| /** |
| * Returns the number of milliseconds since Jan 1, 1601 (this is |
| * the current UTC time). |
| * |
| * \note This is the Windows standard. UNIX time functions typically |
| * count from the Epoch (Jan 1, 1970). The Epoch is 11644473600*1000 |
| * milliseconds after Jan 1, 1601. |
| */ |
| uint64 |
| dr_get_milliseconds(void); |
| |
| DR_API |
| /** |
| * Returns the number of microseconds since Jan 1, 1601 (this is |
| * the current UTC time). |
| * |
| * \note This is the Windows standard. UNIX time functions typically |
| * count from the Epoch (Jan 1, 1970). The Epoch is 11644473600*1000*1000 |
| * microseconds after Jan 1, 1601. |
| */ |
| uint64 |
| dr_get_microseconds(void); |
| |
| DR_API |
| /** |
| * Returns a pseudo-random number in the range [0..max). |
| * The pseudo-random sequence can be repeated by passing the seed |
| * used during a run to the next run via the -prng_seed runtime option. |
| */ |
| uint |
| dr_get_random_value(uint max); |
| |
| DR_API |
| /** |
| * Sets the seed used for dr_get_random_value(). Generally this would |
| * only be called during client initialization. |
| */ |
| void |
| dr_set_random_seed(uint seed); |
| |
| DR_API |
| /** Returns the seed used for dr_get_random_value(). */ |
| uint |
| dr_get_random_seed(void); |
| |
| DR_API |
| /** |
| * Aborts the process immediately without any cleanup (i.e., the exit event |
| * will not be called). |
| */ |
| void |
| dr_abort(void); |
| |
| DR_API |
| /** |
| * Aborts the process immediately without any cleanup (i.e., the exit event |
| * will not be called) with the exit code \p exit_code. |
| * |
| * On Linux, only the bottom 8 bits of \p exit_code will be honored |
| * for a normal exit. If bits 9..16 are not all zero, DR will send an |
| * unhandled signal of that signal number instead of performing a normal |
| * exit. |
| */ |
| void |
| dr_abort_with_code(int exit_code); |
| |
| DR_API |
| /** |
| * Exits the process, first performing a full cleanup that will |
| * trigger the exit event (dr_register_exit_event()). The process |
| * exit code is set to \p exit_code. |
| * |
| * On Linux, only the bottom 8 bits of \p exit_code will be honored |
| * for a normal exit. If bits 9..16 are not all zero, DR will send an |
| * unhandled signal of that signal number instead of performing a normal |
| * exit. |
| * |
| * \note Calling this from \p dr_client_main or from the primary thread's |
| * initialization event is not guaranteed to always work, as DR may |
| * invoke a thread exit event where a thread init event was never |
| * called. We recommend using dr_abort_with_code() or waiting for full |
| * initialization prior to use of this routine. |
| */ |
| void |
| dr_exit_process(int exit_code); |
| |
| /** Indicates the type of memory dump for dr_create_memory_dump(). */ |
| typedef enum { |
| /** |
| * A "livedump", or "ldmp", DynamoRIO's own custom memory dump format. |
| * The ldmp format does not currently support specifying a context |
| * for the calling thread, so it will always include the call frames |
| * to dr_create_memory_dump(). The \p ldmp.exe tool can be used to |
| * create a dummy process (using the \p dummy.exe executable) which |
| * can then be attached to by the debugger (use a non-invasive attach) |
| * in order to view the memory dump contents. |
| * |
| * \note Windows only. |
| */ |
| DR_MEMORY_DUMP_LDMP = 0x0001, |
| } dr_memory_dump_flags_t; |
| |
| /** Indicates the type of memory dump for dr_create_memory_dump(). */ |
| typedef struct _dr_memory_dump_spec_t { |
| /** The size of this structure. Set this to sizeof(dr_memory_dump_spec_t). */ |
| size_t size; |
| /** The type of memory dump requested. */ |
| dr_memory_dump_flags_t flags; |
| /** |
| * This field only applies to DR_MEMORY_DUMP_LDMP. This string is |
| * stored inside the ldmp as the reason for the dump. |
| */ |
| const char *label; |
| /** |
| * This field only applies to DR_MEMORY_DUMP_LDMP. This is an optional output |
| * field that, if non-NULL, will be written with the path to the created file. |
| */ |
| char *ldmp_path; |
| /** |
| * This field only applies to DR_MEMORY_DUMP_LDMP. This is the maximum size, |
| * in bytes, of ldmp_path. |
| */ |
| size_t ldmp_path_size; |
| } dr_memory_dump_spec_t; |
| |
| DR_API |
| /** |
| * Requests that DR create a memory dump file of the current process. |
| * The type of dump is specified by \p spec. |
| * |
| * \return whether successful. |
| * |
| * \note this function is only supported on Windows for now. |
| */ |
| bool |
| dr_create_memory_dump(dr_memory_dump_spec_t *spec); |
| |
| /************************************************** |
| * APPLICATION-INDEPENDENT MEMORY ALLOCATION |
| */ |
| |
| /** Flags used with dr_custom_alloc() */ |
| typedef enum { |
| /** |
| * If this flag is not specified, dr_custom_alloc() uses a managed |
| * heap to allocate the memory, just like dr_thread_alloc() or |
| * dr_global_alloc(). In that case, it ignores any requested |
| * protection bits (\p prot parameter), and the location (\p addr |
| * parameter) must be NULL. If this flag is specified, a |
| * page-aligned, separate block of memory is allocated, in a |
| * similar fashion to dr_nonheap_alloc(). |
| */ |
| DR_ALLOC_NON_HEAP = 0x0001, |
| /** |
| * This flag only applies to heap memory (i.e., when |
| * #DR_ALLOC_NON_HEAP is not specified). If this flag is not |
| * specified, global heap is used (just like dr_global_alloc()) |
| * and the \p drcontext parameter is ignored. If it is specified, |
| * thread-private heap specific to \p drcontext is used, just like |
| * dr_thread_alloc(). |
| */ |
| DR_ALLOC_THREAD_PRIVATE = 0x0002, |
| /** |
| * Allocate memory that is 32-bit-displacement reachable from the |
| * code caches and from the client library. Memory allocated |
| * through dr_thread_alloc(), dr_global_alloc(), and |
| * dr_nonheap_alloc() is also reachable, but for |
| * dr_custom_alloc(), the resulting memory is not reachable unless |
| * this flag is specified. If this flag is passed, the requested |
| * location (\p addr parameter) must be NULL. This flag is not |
| * compatible with #DR_ALLOC_LOW_2GB, #DR_ALLOC_FIXED_LOCATION, or |
| * #DR_ALLOC_NON_DR. |
| */ |
| DR_ALLOC_CACHE_REACHABLE = 0x0004, |
| /** |
| * This flag only applies to non-heap memory (i.e., when |
| * #DR_ALLOC_NON_HEAP is specified). The flag requests that |
| * memory be allocated at a specific address, given in the \p addr |
| * parameter. Without this flag, the \p addr parameter is not |
| * honored. This flag is not compatible with #DR_ALLOC_LOW_2GB or |
| * #DR_ALLOC_CACHE_REACHABLE. |
| */ |
| DR_ALLOC_FIXED_LOCATION = 0x0008, |
| /** |
| * This flag only applies to non-heap memory (i.e., when |
| * #DR_ALLOC_NON_HEAP is specified) in 64-bit mode. The flag |
| * requests that memory be allocated in the low 2GB of the address |
| * space. If this flag is passed, the requested location (\p addr |
| * parameter) must be NULL. This flag is not compatible with |
| * #DR_ALLOC_FIXED_LOCATION. |
| */ |
| DR_ALLOC_LOW_2GB = 0x0010, |
| /** |
| * This flag only applies to non-heap memory (i.e., when |
| * #DR_ALLOC_NON_HEAP is specified). When this flag is specified, |
| * the allocated memory is not considered to be DynamoRIO or tool |
| * memory and thus is not kept separate from the application. |
| * This is similar to dr_raw_mem_alloc(). Use of this memory is |
| * at the client's own risk. This flag is not compatible with |
| * #DR_ALLOC_CACHE_REACHABLE. |
| */ |
| DR_ALLOC_NON_DR = 0x0020, |
| #ifdef WINDOWS |
| /** |
| * This flag only applies to non-heap, non-DR memory (i.e., when |
| * both #DR_ALLOC_NON_HEAP and #DR_ALLOC_NON_DR are specified) on |
| * Windows. When this flag is specified, the allocated memory is |
| * reserved but not committed, just like the MEM_RESERVE Windows API |
| * flag (the default is MEM_RESERVE|MEM_COMMIT). |
| */ |
| DR_ALLOC_RESERVE_ONLY = 0x0040, |
| /** |
| * This flag only applies to non-heap, non-DR memory (i.e., when both |
| * #DR_ALLOC_NON_HEAP and #DR_ALLOC_NON_DR are specified) on Windows. |
| * This flag must be combined with DR_ALLOC_FIXED_LOCATION. When this |
| * flag is specified, previously allocated memory is committed, just |
| * like the MEM_COMMIT Windows API flag (when this flag is not passed, |
| * the effect is MEM_RESERVE|MEM_COMMIT). When passed to |
| * dr_custom_free(), this flag causes a de-commit, just like the |
| * MEM_DECOMMIT Windows API flag. This flag cannot be combined with |
| * #DR_ALLOC_LOW_2GB and must include a non-NULL requested location (\p |
| * addr parameter). |
| */ |
| DR_ALLOC_COMMIT_ONLY = 0x0080, |
| #endif |
| } dr_alloc_flags_t; |
| |
| DR_API |
| /** |
| * Allocates \p size bytes of memory from DR's memory pool specific to the |
| * thread associated with \p drcontext. |
| * This memory is only guaranteed to be aligned to the pointer size: |
| * 8 byte alignment for 64-bit; 4-byte alignment for 32-bit. |
| * (The wrapped malloc() guarantees the more standard double-pointer-size.) |
| */ |
| void * |
| dr_thread_alloc(void *drcontext, size_t size); |
| |
| DR_API |
| /** |
| * Frees thread-specific memory allocated by dr_thread_alloc(). |
| * \p size must be the same as that passed to dr_thread_alloc(). |
| */ |
| void |
| dr_thread_free(void *drcontext, void *mem, size_t size); |
| |
| DR_API |
| /** |
| * Allocates \p size bytes of memory from DR's global memory pool. |
| * This memory is only guaranteed to be aligned to the pointer size: |
| * 8 byte alignment for 64-bit; 4-byte alignment for 32-bit. |
| * (The wrapped malloc() guarantees the more standard double-pointer-size.) |
| */ |
| void * |
| dr_global_alloc(size_t size); |
| |
| DR_API |
| /** |
| * Frees memory allocated by dr_global_alloc(). |
| * \p size must be the same as that passed to dr_global_alloc(). |
| */ |
| void |
| dr_global_free(void *mem, size_t size); |
| |
| DR_API |
| /** |
| * Allocates memory with the properties requested by \p flags. |
| * |
| * If \p addr is non-NULL (only allowed with certain flags), it must |
| * be page-aligned. |
| * |
| * To make more space available for the code caches when running |
| * larger applications, or for clients that use a lot of heap memory |
| * that is not directly referenced from the cache, we recommend that |
| * dr_custom_alloc() be called to obtain memory that is not guaranteed |
| * to be reachable from the code cache (by not passing |
| * #DR_ALLOC_CACHE_REACHABLE). This frees up space in the reachable |
| * region. |
| * |
| * Returns NULL on failure. |
| */ |
| void * |
| dr_custom_alloc(void *drcontext, dr_alloc_flags_t flags, size_t size, uint prot, |
| void *addr); |
| |
| DR_API |
| /** |
| * Frees memory allocated by dr_custom_alloc(). The same \p flags |
| * and \p size must be passed here as were passed to dr_custom_alloc(). |
| */ |
| bool |
| dr_custom_free(void *drcontext, dr_alloc_flags_t flags, void *addr, size_t size); |
| |
| DR_API |
| /** |
| * Allocates \p size bytes of memory as a separate allocation from DR's |
| * heap, allowing for separate protection. |
| * The \p 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_alloc(size_t size, uint prot); |
| |
| DR_API |
| /** |
| * Frees memory allocated by dr_nonheap_alloc(). |
| * \p size must be the same as that passed to dr_nonheap_alloc(). |
| */ |
| void |
| dr_nonheap_free(void *mem, size_t size); |
| |
| DR_API |
| /** |
| * \warning This raw memory allocation interface is in flux and is subject to |
| * change in the next release. Consider it experimental in this release. |
| * |
| * Allocates \p size bytes (page size aligned) of memory as a separate |
| * allocation at preferred base \p addr that must be page size aligned, |
| * allowing for separate protection. |
| * If \p addr is NULL, an arbitrary address is picked. |
| * |
| * The \p prot protection should use the DR_MEMPROT_READ, |
| * DR_MEMPROT_WRITE, and DR_MEMPROT_EXEC bits. |
| * The allocated memory is not considered to be DynamoRIO or tool memory and |
| * thus is not kept separate from the application. Use of this memory is at the |
| * client's own risk. |
| * |
| * The resulting memory is guaranteed to be initialized to all zeroes. |
| * |
| * Returns the actual address allocated or NULL if memory allocation at |
| * preferred base fails. |
| */ |
| void * |
| dr_raw_mem_alloc(size_t size, uint prot, void *addr); |
| |
| DR_API |
| /** |
| * Frees memory allocated by dr_raw_mem_alloc(). |
| * \p addr and \p size must be the same as that passed to dr_raw_mem_alloc() |
| * on Windows. |
| */ |
| bool |
| dr_raw_mem_free(void *addr, size_t size); |
| |
| #ifdef LINUX |
| DR_API |
| /** |
| * Calls mremap with the specified parameters and returns the result. |
| * The old memory must be non-DR memory, and the new memory is also |
| * considered to be non-DR memory (see #DR_ALLOC_NON_DR). |
| * \note Linux-only. |
| */ |
| void * |
| dr_raw_mremap(void *old_address, size_t old_size, size_t new_size, int flags, |
| void *new_address); |
| |
| DR_API |
| /** |
| * Sets the program break to the specified value. Invokes the SYS_brk |
| * system call and returns the result. This is the application's |
| * program break, so use this system call only when deliberately |
| * changing the application's behavior. |
| * \note Linux-only. |
| */ |
| void * |
| dr_raw_brk(void *new_address); |
| #endif |
| |
| DR_API |
| /** |
| * 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. |
| * The returned address is guaranteed to be double-pointer-aligned: |
| * aligned to 16 bytes for 64-bit; aligned to 8 bytes for 32-bit. |
| */ |
| void * |
| __wrap_malloc(size_t size); |
| |
| DR_API |
| /** |
| * 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. |
| * The returned address is guaranteed to be double-pointer-aligned: |
| * aligned to 16 bytes for 64-bit; aligned to 8 bytes for 32-bit. |
| */ |
| void * |
| __wrap_realloc(void *mem, size_t size); |
| |
| DR_API |
| /** |
| * Allocates memory from DR's global memory pool, but mimics the |
| * behavior of calloc. 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. |
| * The returned address is guaranteed to be double-pointer-aligned: |
| * aligned to 16 bytes for 64-bit; aligned to 8 bytes for 32-bit. |
| */ |
| void * |
| __wrap_calloc(size_t nmemb, size_t size); |
| |
| DR_API |
| /** |
| * 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_free(void *mem); |
| |
| DR_API |
| /** |
| * Allocates memory for a new string identical to 'str' and copies the |
| * contents of 'str' into the new string, including a terminating |
| * null. 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. |
| * The returned address is guaranteed to be double-pointer-aligned: |
| * aligned to 16 bytes for 64-bit; aligned to 8 bytes for 32-bit. |
| */ |
| char * |
| __wrap_strdup(const char *str); |
| |
| /************************************************** |
| * LOCK SUPPORT |
| */ |
| |
| DR_API |
| /** |
| * 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. A lock must also be released by the same thread that acquired |
| * it. Failing to follow these restrictions can lead to deadlocks. |
| */ |
| void * |
| dr_mutex_create(void); |
| |
| DR_API |
| /** Deletes \p mutex. */ |
| void |
| dr_mutex_destroy(void *mutex); |
| |
| DR_API |
| /** Locks \p mutex. Waits until the mutex is successfully held. */ |
| void |
| dr_mutex_lock(void *mutex); |
| |
| DR_API |
| /** |
| * Unlocks \p mutex. Asserts that mutex is currently locked by the |
| * current thread. |
| */ |
| void |
| dr_mutex_unlock(void *mutex); |
| |
| DR_API |
| /** Tries once to lock \p mutex and returns whether or not successful. */ |
| bool |
| dr_mutex_trylock(void *mutex); |
| |
| DR_API |
| /** |
| * Returns true iff \p mutex is owned by the calling thread. |
| * This routine is only available in debug builds. |
| * In release builds it always returns true. |
| */ |
| bool |
| dr_mutex_self_owns(void *mutex); |
| |
| DR_API |
| /** |
| * Instructs DR to treat this lock as an application lock. Primarily |
| * this avoids debug-build checks that no DR locks are held in situations |
| * where locks are disallowed. |
| * |
| * \warning Any one lock should either be a DR lock or an application lock. |
| * Use this routine with caution and do not call it on a DR lock that is |
| * used in DR contexts, as it disables debug checks. |
| * |
| * \warning This routine is not sufficient on its own to prevent deadlocks |
| * during scenarios where DR wants to suspend all threads such as detach or |
| * relocation. See dr_app_recurlock_lock() and dr_mark_safe_to_suspend(). |
| * |
| * \return whether successful. |
| */ |
| bool |
| dr_mutex_mark_as_app(void *mutex); |
| |
| DR_API |
| /** |
| * Creates and initializes a read-write lock. A read-write lock allows |
| * multiple readers or alternatively a single writer. The lock |
| * restrictions for mutexes apply (see dr_mutex_create()). |
| */ |
| void * |
| dr_rwlock_create(void); |
| |
| DR_API |
| /** Deletes \p rwlock. */ |
| void |
| dr_rwlock_destroy(void *rwlock); |
| |
| DR_API |
| /** Acquires a read lock on \p rwlock. */ |
| void |
| dr_rwlock_read_lock(void *rwlock); |
| |
| DR_API |
| /** Releases a read lock on \p rwlock. */ |
| void |
| dr_rwlock_read_unlock(void *rwlock); |
| |
| DR_API |
| /** Acquires a write lock on \p rwlock. */ |
| void |
| dr_rwlock_write_lock(void *rwlock); |
| |
| DR_API |
| /** Releases a write lock on \p rwlock. */ |
| void |
| dr_rwlock_write_unlock(void *rwlock); |
| |
| DR_API |
| /** Tries once to acquire a write lock on \p rwlock and returns whether successful. */ |
| bool |
| dr_rwlock_write_trylock(void *rwlock); |
| |
| DR_API |
| /** Returns whether the calling thread owns the write lock on \p rwlock. */ |
| bool |
| dr_rwlock_self_owns_write_lock(void *rwlock); |
| |
| DR_API |
| /** |
| * Instructs DR to treat this lock as an application lock. Primarily |
| * this avoids debug-build checks that no DR locks are held in situations |
| * where locks are disallowed. |
| * |
| * \warning Any one lock should either be a DR lock or an application lock. |
| * Use this routine with caution and do not call it on a DR lock that is |
| * used in DR contexts, as it disables debug checks. |
| * |
| * \return whether successful. |
| */ |
| bool |
| dr_rwlock_mark_as_app(void *rwlock); |
| |
| DR_API |
| /** |
| * Creates and initializes a recursive lock. A recursive lock allows |
| * the same thread to acquire it multiple times. The lock |
| * restrictions for mutexes apply (see dr_mutex_create()). |
| */ |
| void * |
| dr_recurlock_create(void); |
| |
| DR_API |
| /** Deletes \p reclock. */ |
| void |
| dr_recurlock_destroy(void *reclock); |
| |
| DR_API |
| /** Acquires \p reclock, or increments the ownership count if already owned. */ |
| void |
| dr_recurlock_lock(void *reclock); |
| |
| DR_API |
| /** |
| * Acquires \p reclock, or increments the ownership count if already owned. |
| * Calls to this method which block (i.e. when the lock is already held) are |
| * marked safe to suspend AND transfer; in that case the provided mcontext \p mc |
| * will overwrite the current thread's mcontext. \p mc must have a valid PC |
| * and its flags must be DR_MC_ALL. |
| * |
| * This routine must be used in clients holding application locks to prevent |
| * deadlocks in a way similar to dr_mark_safe_to_suspend(), but this routine |
| * is intended to be called by a clean call and may return execution to the |
| * provided mcontext rather than returning normally. |
| * |
| * If this routine is called from a clean call, callers should not return |
| * normally. Instead, dr_redirect_execution() or dr_redirect_native_target() |
| * should be called to to prevent a return into a flushed code page. |
| */ |
| void |
| dr_app_recurlock_lock(void *reclock, dr_mcontext_t *mc); |
| |
| DR_API |
| /** Decrements the ownership count of \p reclock and releases if zero. */ |
| void |
| dr_recurlock_unlock(void *reclock); |
| |
| DR_API |
| /** Tries once to acquire \p reclock and returns whether successful. */ |
| bool |
| dr_recurlock_trylock(void *reclock); |
| |
| DR_API |
| /** Returns whether the calling thread owns \p reclock. */ |
| bool |
| dr_recurlock_self_owns(void *reclock); |
| |
| DR_API |
| /** |
| * Instructs DR to treat this lock as an application lock. Primarily |
| * this avoids debug-build checks that no DR locks are held in situations |
| * where locks are disallowed. |
| * |
| * \warning Any one lock should either be a DR lock or an application lock. |
| * Use this routine with caution and do not call it on a DR lock that is |
| * used in DR contexts, as it disables debug checks. |
| * |
| * \return whether successful. |
| */ |
| bool |
| dr_recurlock_mark_as_app(void *reclock); |
| |
| DR_API |
| /** Creates an event object on which threads can wait and be signaled. */ |
| void * |
| dr_event_create(void); |
| |
| DR_API |
| /** Destroys an event object. */ |
| bool |
| dr_event_destroy(void *event); |
| |
| DR_API |
| /** Suspends the current thread until \p event is signaled. */ |
| bool |
| dr_event_wait(void *event); |
| |
| DR_API |
| /** Wakes up at most one thread waiting on \p event. */ |
| bool |
| dr_event_signal(void *event); |
| |
| DR_API |
| /** Resets \p event to no longer be in a signaled state. */ |
| bool |
| dr_event_reset(void *event); |
| |
| DR_API |
| /** |
| * Use this function to mark a region of code as safe for DR to suspend |
| * the client while inside the region. DR will not relocate the client |
| * from the region and will resume it at precisely the suspend point. |
| * |
| * This function must be used in client code that acquires application locks. |
| * Use this feature with care! Do not mark code as safe to suspend that has |
| * a code cache return point. I.e., do not call this routine from a clean |
| * call. For acquiring application locks from a clean call, see |
| * dr_app_recurlock_lock(). |
| * |
| * No DR locks can be held while in a safe region. Consequently, do |
| * not call this routine from any DR event callback. It may only be used |
| * from natively executing code. |
| * |
| * Always invoke this routine in pairs, with the first passing true |
| * for \p enter and the second passing false, thus delimiting the |
| * region. |
| */ |
| bool |
| dr_mark_safe_to_suspend(void *drcontext, bool enter); |
| |
| DR_API |
| /** |
| * Atomically adds \p val to \p *dest and returns the sum. |
| * \p dest must not straddle two cache lines. |
| */ |
| int |
| dr_atomic_add32_return_sum(volatile int *dest, int val); |
| |
| #ifdef X64 |
| DR_API |
| /** |
| * Atomically adds \p val to \p *dest and returns the sum. |
| * \p dest must not straddle two cache lines. |
| * Currently 64-bit-build only. |
| */ |
| int64 |
| dr_atomic_add64_return_sum(volatile int64 *dest, int64 val); |
| #endif |
| |
| DR_API |
| /** Atomically and visibly loads the value at \p src and returns it. */ |
| int |
| dr_atomic_load32(volatile int *src); |
| |
| DR_API |
| /** Atomically and visibly stores \p val to \p dest. */ |
| void |
| dr_atomic_store32(volatile int *dest, int val); |
| |
| #ifdef X64 |
| DR_API |
| /** |
| * Atomically and visibly loads the value at \p src and returns it. |
| * Currently 64-bit-build only. |
| */ |
| int64 |
| dr_atomic_load64(volatile int64 *src); |
| |
| DR_API |
| /** |
| * Atomically and visibly stores \p val to \p dest. |
| * Currently 64-bit-build only. |
| */ |
| void |
| dr_atomic_store64(volatile int64 *dest, int64 val); |
| #endif |
| |
| /** Flags for use with dr_map_executable_file(). */ |
| typedef enum { |
| /** |
| * Requests that writable segments are not mapped, to save address space. |
| * This may be ignored on some platforms and may only be honored for |
| * a writable segment that is at the very end of the loaded module. |
| */ |
| DR_MAPEXE_SKIP_WRITABLE = 0x0002, |
| } dr_map_executable_flags_t; |
| |
| DR_API |
| /** |
| * Loads \p filename as an executable file for examination, rather |
| * than for execution. No entry point, initialization, or constructor |
| * code is executed, nor is any thread-local storage or other |
| * resources set up. Returns the size (which may include unmappped |
| * gaps) in \p size. The return value of the function is the base |
| * address at which the file is mapped. |
| * |
| * \note Not currently supported on Mac OSX. |
| */ |
| byte * |
| dr_map_executable_file(const char *filename, dr_map_executable_flags_t flags, |
| size_t *size DR_PARAM_OUT); |
| |
| DR_API |
| /** |
| * Unmaps a file loaded by dr_map_executable_file(). |
| */ |
| bool |
| dr_unmap_executable_file(byte *base, size_t size); |
| |
| /************************************************** |
| * SYSTEM CALL PROCESSING ROUTINES |
| */ |
| |
| /** |
| * Data structure used to obtain or modify the result of an application |
| * system call by dr_syscall_get_result_ex() and dr_syscall_set_result_ex(). |
| */ |
| typedef struct _dr_syscall_result_info_t { |
| /** The caller should set this to the size of the structure. */ |
| size_t size; |
| /** |
| * Indicates whether the system call succeeded or failed. For |
| * dr_syscall_set_result_ex(), this requests that DR set any |
| * additional machine state, if any, used by the particular |
| * plaform that is not part of \p value to indicate success or |
| * failure (e.g., on MacOS the carry flag is used to indicate |
| * success). |
| * |
| * For Windows, the success result from dr_syscall_get_result_ex() |
| * should only be relied upon for ntoskrnl system calls. For |
| * other Windows system calls (such as win32k.sys graphical |
| * (NtGdi) or user (NtUser) system calls), computing success |
| * depends on each particular call semantics and is beyond the |
| * scope of this routine (consider using the "drsyscall" Extension |
| * instead). |
| * |
| * For Mach syscalls on MacOS, the success result from |
| * dr_syscall_get_result_ex() should not be relied upon. |
| * Computing success depends on each particular call semantics and |
| * is beyond the scope of this routine (consider using the |
| * "drsyscall" Extension instead). |
| */ |
| bool succeeded; |
| /** |
| * The raw main value returned by the system call. |
| * See also the \p high field. |
| */ |
| reg_t value; |
| /** |
| * On some platforms (such as MacOS), a 32-bit application's |
| * system call can return a 64-bit value. For such calls, |
| * this field will hold the top 32 bit bits, if requested |
| * by \p use_high. It is up to the caller to know which |
| * system calls have 64-bit return values. System calls that |
| * return only 32-bit values do not clear the upper bits. |
| * Consider using the "drsyscall" Extension in order to obtain |
| * per-system-call semantic information, including return type. |
| */ |
| reg_t high; |
| /** |
| * This should be set by the caller, and only applies to 32-bit |
| * system calls. For dr_syscall_get_result_ex(), this requests |
| * that DR fill in the \p high field. For |
| * dr_syscall_set_result_ex(), this requests that DR set the high |
| * 32 bits of the application-facing result to the value in the \p |
| * high field. |
| */ |
| bool use_high; |
| /** |
| * This should be set by the caller. For dr_syscall_get_result_ex(), |
| * this requests that DR fill in the \p errno_value field. |
| * For dr_syscall_set_result_ex(), this requests that DR set the |
| * \p value to indicate the particular error code in \p errno_value. |
| */ |
| bool use_errno; |
| /** |
| * If requested by \p use_errno, if a system call fails (i.e., \p |
| * succeeded is false) dr_syscall_get_result_ex() will set this |
| * field to the absolute value of the error code returned (i.e., |
| * on Linux, it will be inverted from what the kernel directly |
| * returns, in order to facilitate cross-platform clients that |
| * operate on both Linux and MacOS). For Linux and Macos, when |
| * \p succeeded is true, \p errno_value is set to 0. |
| * |
| * If \p use_errno is set for dr_syscall_set_result_ex(), then |
| * this value will be stored as the system call's return value, |
| * negated if necessary for the underlying platform. In that |
| * case, \p value will be ignored. |
| */ |
| uint errno_value; |
| } dr_syscall_result_info_t; |
| |
| DR_API |
| /** |
| * Usable only from a pre-syscall (dr_register_pre_syscall_event()) |
| * event. Returns the value of system call parameter number \p param_num. |
| * |
| * It is up to the caller to ensure that reading this parameter is |
| * safe: this routine does not know the number of parameters for each |
| * system call, nor does it check whether this might read off the base |
| * of the stack. |
| * |
| * \note On some platforms, notably MacOS, a 32-bit application's |
| * system call can still take a 64-bit parameter (typically on the |
| * stack). In that situation, this routine will consider the 64-bit |
| * parameter to be split into high and low parts, each with its own |
| * parameter number. |
| */ |
| reg_t |
| dr_syscall_get_param(void *drcontext, int param_num); |
| |
| DR_API |
| /** |
| * 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 \p param_num to \p new_value. |
| * |
| * It is up to the caller to ensure that writing this parameter is |
| * safe: this routine does not know the number of parameters for each |
| * system call, nor does it check whether this might write beyond the |
| * base of the stack. |
| * |
| * \note On some platforms, notably MacOS, a 32-bit application's |
| * system call can still take a 64-bit parameter (typically on the |
| * stack). In that situation, this routine will consider the 64-bit |
| * parameter to be split into high and low parts, each with its own |
| * parameter number. |
| */ |
| void |
| dr_syscall_set_param(void *drcontext, int param_num, reg_t new_value); |
| |
| DR_API |
| /** |
| * 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. |
| * |
| * \note On some platforms (such as MacOS), a 32-bit application's |
| * system call can return a 64-bit value. Use dr_syscall_get_result_ex() |
| * to obtain the upper bits in that case. |
| * |
| * \note On some platforms (such as MacOS), whether a system call |
| * succeeded or failed cannot be determined from the main result |
| * value. Use dr_syscall_get_result_ex() to obtain the success result |
| * in such cases. |
| */ |
| reg_t |
| dr_syscall_get_result(void *drcontext); |
| |
| DR_API |
| /** |
| * Usable only from a post-syscall (dr_register_post_syscall_event()) |
| * event. Returns whether it successfully retrieved the results |
| * of the system call into \p info. |
| * |
| * The caller should set the \p size, \p use_high, and \p use_errno fields |
| * of \p info prior to calling this routine. |
| * See the fields of #dr_syscall_result_info_t for details. |
| */ |
| bool |
| dr_syscall_get_result_ex(void *drcontext, dr_syscall_result_info_t *info DR_PARAM_OUT); |
| |
| DR_API |
| /** |
| * 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 \p value. |
| * |
| * \note On MacOS, do not use this function as it fails to set the |
| * carry flag and thus fails to properly indicate whether the system |
| * call succeeded or failed: use dr_syscall_set_result_ex() instead. |
| */ |
| void |
| dr_syscall_set_result(void *drcontext, reg_t value); |
| |
| DR_API |
| /** |
| * 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 returned results of the system call as specified in |
| * \p info. Returns whether it successfully did so. |
| * See the fields of #dr_syscall_result_info_t for details. |
| */ |
| bool |
| dr_syscall_set_result_ex(void *drcontext, dr_syscall_result_info_t *info); |
| |
| DR_API |
| /** |
| * 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 \p new_num. |
| */ |
| void |
| dr_syscall_set_sysnum(void *drcontext, int new_num); |
| |
| DR_API |
| /** |
| * 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_invoke_another(void *drcontext); |
| |
| #ifdef WINDOWS |
| DR_API |
| /** |
| * Must be invoked from dr_client_main(). Requests that the named ntoskrnl |
| * system call be intercepted even when threads are native (e.g., due |
| * to #DR_EMIT_GO_NATIVE). Only a limited number of system calls |
| * being intercepted while native are supported. This routine will |
| * fail once that limit is reached. |
| * |
| * @param[in] name The system call name. The name must match an exported |
| * system call wrapper in \p ntdll.dll. |
| * @param[in] sysnum The system call number (the value placed in the eax register). |
| * @param[in] num_args The number of arguments to the system call. |
| * @param[in] wow64_index The value placed in the ecx register when this system |
| * call is executed in a WOW64 process. This value should be obtainable |
| * by examining the system call wrapper. |
| * |
| * \note Windows only. |
| */ |
| bool |
| dr_syscall_intercept_natively(const char *name, int sysnum, int num_args, |
| int wow64_index); |
| #endif |
| |
| /************************************************** |
| * PLATFORM-INDEPENDENT FILE SUPPORT |
| * |
| * Since a FILE cannot be used outside of the DLL it was created in, |
| * we have to use HANDLE on Windows. |
| * We hide the distinction behind the file_t type |
| */ |
| |
| DR_API |
| /** |
| * Creates a new directory. Fails if the directory already exists |
| * or if it can't be created. |
| * Relative path support on Windows is identical to that described in dr_open_file(). |
| */ |
| bool |
| dr_create_dir(const char *fname); |
| |
| DR_API |
| /** |
| * Deletes the given directory. Fails if the directory is not empty. |
| * Relative path support on Windows is identical to that described in dr_open_file(). |
| */ |
| bool |
| dr_delete_dir(const char *fname); |
| |
| DR_API |
| /** |
| * Returns the current directory for this process in \p buf. |
| * On Windows, reading the current directory is considered unsafe |
| * except during initialization, as it is stored in user memory and |
| * access is not controlled via any standard synchronization. |
| */ |
| bool |
| dr_get_current_directory(char *buf, size_t bufsz); |
| |
| DR_API |
| /** |
| * Checks for the existence of a directory. |
| * Relative path support on Windows is identical to that described in dr_open_file(). |
| */ |
| bool |
| dr_directory_exists(const char *fname); |
| |
| DR_API |
| /** |
| * Checks the existence of a file. |
| * Relative path support on Windows is identical to that described in dr_open_file(). |
| */ |
| bool |
| dr_file_exists(const char *fname); |
| |
| /* flags for use with dr_open_file() */ |
| /** Open with read access. */ |
| #define DR_FILE_READ 0x1 |
| /** Open with write access, but do not open if the file already exists. */ |
| #define DR_FILE_WRITE_REQUIRE_NEW 0x2 |
| /** |
| * Open with write access. If the file already exists, set the file position to the |
| * end of the file. |
| */ |
| #define DR_FILE_WRITE_APPEND 0x4 |
| /** |
| * Open with write access. If the file already exists, truncate the |
| * file to zero length. |
| */ |
| #define DR_FILE_WRITE_OVERWRITE 0x8 |
| /** |
| * Open with large (>2GB) file support. Only applicable on 32-bit Linux. |
| * \note DR's log files and tracedump files are all created with this flag. |
| */ |
| #define DR_FILE_ALLOW_LARGE 0x10 |
| /** Linux-only. This file will be closed in the child of a fork. */ |
| #define DR_FILE_CLOSE_ON_FORK 0x20 |
| /** |
| * Open with write-only access. Meant for use with pipes. Linux-only. |
| * Mutually exclusive with DR_FILE_WRITE_REQUIRE_NEW, DR_FILE_WRITE_APPEND, and |
| * DR_FILE_WRITE_OVERWRITE. |
| */ |
| #define DR_FILE_WRITE_ONLY 0x40 |
| |
| DR_API |
| /** |
| * Opens the file \p fname. If no such file exists then one is created. |
| * The file access mode is set by the \p mode_flags argument which is drawn from |
| * the DR_FILE_* defines ORed together. Returns INVALID_FILE if unsuccessful. |
| * |
| * On Windows, \p fname is safest as an absolute path (when using Windows system |
| * calls directly there is no such thing as a relative path). A relative path |
| * passed to this routine will be converted to absolute on a best-effort basis |
| * using the current directory that was set at process initialization time. |
| * (The most recently set current directory can be retrieved (albeit with no |
| * safety guarantees) with dr_get_current_directory().) Drive-implied-absolute |
| * paths ("\foo.txt") and other-drive-relative paths ("c:foo.txt") are not |
| * supported. |
| * |
| * On Linux, the file descriptor will be marked as close-on-exec. The |
| * DR_FILE_CLOSE_ON_FORK flag can be used to automatically close a |
| * file on a fork. |
| * |
| * \note No more then one write mode flag can be specified. |
| * |
| * \note On Linux, DR hides files opened by clients from the |
| * application by using file descriptors that are separate from the |
| * application's and preventing the application from closing |
| * client-opened files. |
| */ |
| file_t |
| dr_open_file(const char *fname, uint mode_flags); |
| |
| DR_API |
| /** Closes file \p f. */ |
| void |
| dr_close_file(file_t f); |
| |
| DR_API |
| /** |
| * Renames the file \p src to \p dst, replacing an existing file named \p dst if |
| * \p replace is true. |
| * Atomic if \p src and \p dst are on the same filesystem. |
| * Returns true if successful. |
| */ |
| bool |
| dr_rename_file(const char *src, const char *dst, bool replace); |
| |
| DR_API |
| /** |
| * Deletes the file referred to by \p filename. |
| * Returns true if successful. |
| * On both Linux and Windows, if filename refers to a symlink, the symlink will |
| * be deleted and not the target of the symlink. |
| * On Windows, this will fail to delete any file that was not opened with |
| * FILE_SHARE_DELETE and is still open. |
| * Relative path support on Windows is identical to that described in dr_open_file(). |
| */ |
| bool |
| dr_delete_file(const char *filename); |
| |
| DR_API |
| /** Flushes any buffers for file \p f. */ |
| void |
| dr_flush_file(file_t f); |
| |
| DR_API |
| /** |
| * Writes \p count bytes from \p buf to file \p f. |
| * Returns the actual number written. |
| */ |
| ssize_t |
| dr_write_file(file_t f, const void *buf, size_t count); |
| |
| DR_API |
| /** |
| * Reads up to \p count bytes from file \p f into \p buf. |
| * Returns the actual number read. |
| */ |
| ssize_t |
| dr_read_file(file_t f, void *buf, size_t count); |
| |
| /* NOTE - keep in synch with OS_SEEK_* in os_shared.h and SEEK_* from Linux headers. |
| * The extra BEGIN END is to get spacing nice. Once we have more control over the |
| * layout of the API header files share with os_shared.h. */ |
| /* For use with dr_file_seek(), specifies the origin at which to apply the offset. */ |
| #define DR_SEEK_SET 0 /**< start of file */ |
| #define DR_SEEK_CUR 1 /**< current file position */ |
| #define DR_SEEK_END 2 /**< end of file */ |
| |
| DR_API |
| /** |
| * Sets the current file position for file \p f to \p offset bytes |
| * from the specified origin, where \p origin is one of the DR_SEEK_* |
| * values. Returns true if successful. |
| */ |
| bool |
| dr_file_seek(file_t f, int64 offset, int origin); |
| |
| DR_API |
| /** |
| * Returns the current position for the file \p f in bytes from the start of the file. |
| * Returns -1 on an error. |
| */ |
| int64 |
| dr_file_tell(file_t f); |
| |
| DR_API |
| /** |
| * Returns a new copy of the file handle \p f. |
| * Returns INVALID_FILE on error. |
| */ |
| file_t |
| dr_dup_file_handle(file_t f); |
| |
| DR_API |
| /** |
| * Determines the size of the file \p fd. |
| * On success, returns the size in \p size. |
| * \return whether successful. |
| */ |
| bool |
| dr_file_size(file_t fd, DR_PARAM_OUT uint64 *size); |
| |
| /** Flags for use with dr_map_file(). */ |
| enum { |
| /** |
| * If set, changes to mapped memory are private to the mapping process and |
| * are not reflected in the underlying file. If not set, changes are visible |
| * to other processes that map the same file, and will be propagated |
| * to the file itself. |
| */ |
| DR_MAP_PRIVATE = 0x0001, |
| #ifdef UNIX |
| /** |
| * If set, indicates that the passed-in start address is required rather than a |
| * hint. On Linux, this has the same semantics as mmap with MAP_FIXED: i.e., |
| * any existing mapping in [addr,addr+size) will be unmapped. This flag is not |
| * supported on Windows. |
| */ |
| DR_MAP_FIXED = 0x0002, |
| #endif |
| #ifdef WINDOWS |
| /** |
| * If set, loads the specified file as an executable image, rather than a data |
| * file. This flag is not supported on Linux. |
| */ |
| DR_MAP_IMAGE = 0x0004, |
| #endif |
| /** |
| * If set, loads the specified file at a location that is reachable from |
| * the code cache and client libraries by a 32-bit displacement. If not |
| * set, the mapped file is not guaranteed to be reachable from the cache. |
| */ |
| DR_MAP_CACHE_REACHABLE = 0x0008, |
| }; |
| |
| DR_API |
| /** |
| * Memory-maps \p size bytes starting at offset \p offs from the file \p f |
| * at address \p addr with privileges \p prot. |
| * |
| * @param[in] f The file to map. |
| * @param[in,out] size The requested size to map. Upon successful return, |
| * contains the actual mapped size. |
| * @param[in] offs The offset within the file at which to start the map. |
| * @param[in] addr The requested start address of the map. Unless \p fixed |
| * is true, this is just a hint and may not be honored. |
| * @param[in] prot The access privileges of the mapping, composed of |
| * the DR_MEMPROT_READ, DR_MEMPROT_WRITE, and DR_MEMPROT_EXEC bits. |
| * @param[in] flags Optional DR_MAP_* flags. |
| * |
| * \note Mapping image files for execution is not supported. |
| * |
| * \return the start address of the mapping, or NULL if unsuccessful. |
| */ |
| void * |
| dr_map_file(file_t f, DR_PARAM_INOUT size_t *size, uint64 offs, app_pc addr, uint prot, |
| uint flags); |
| |
| DR_API |
| /** |
| * Unmaps a portion of a file mapping previously created by dr_map_file(). |
| * \return whether successful. |
| * |
| * @param[in] map The base address to be unmapped. Must be page size aligned. |
| * @param[in] size The size to be unmapped. |
| * All pages overlapping with the range are unmapped. |
| * |
| * \note On Windows, the whole file will be unmapped instead. |
| * |
| */ |
| bool |
| dr_unmap_file(void *map, size_t size); |
| |
| /* TODO add copy_file, truncate_file etc. |
| * All should be easy though at some point should perhaps tell people to just use the raw |
| * systemcalls, esp for linux where they're documented and let them provide their own |
| * wrappers. */ |
| |
| /************************************************** |
| * PRINTING |
| */ |
| |
| DR_API |
| /** |
| * Writes to DR's log file for the thread with drcontext \p drcontext if the current |
| * loglevel is >= \p level and the current \p logmask & \p mask != 0. |
| * The mask constants are the DR_LOG_* defines below. |
| * Logging is disabled for the release build. |
| * If \p drcontext is NULL, writes to the main log file. |
| */ |
| void |
| dr_log(void *drcontext, uint mask, uint level, const char *fmt, ...); |
| |
| /* hack to get these constants in the right place in dr_ir_api.h */ |
| |
| /* The log mask constants */ |
| #define DR_LOG_NONE 0x00000000 /**< Log no data. */ |
| #define DR_LOG_STATS 0x00000001 /**< Log per-thread and global statistics. */ |
| #define DR_LOG_TOP 0x00000002 /**< Log top-level information. */ |
| #define DR_LOG_THREADS 0x00000004 /**< Log data related to threads. */ |
| #define DR_LOG_SYSCALLS 0x00000008 /**< Log data related to system calls. */ |
| #define DR_LOG_ASYNCH 0x00000010 /**< Log data related to signals/callbacks/etc. */ |
| #define DR_LOG_INTERP 0x00000020 /**< Log data related to app interpretation. */ |
| #define DR_LOG_EMIT 0x00000040 /**< Log data related to emitting code. */ |
| #define DR_LOG_LINKS 0x00000080 /**< Log data related to linking code. */ |
| #define DR_LOG_CACHE \ |
| 0x00000100 /**< Log data related to code cache management. \ |
| */ |
| #define DR_LOG_FRAGMENT \ |
| 0x00000200 /**< Log data related to app code fragments. \ |
| */ |
| #define DR_LOG_DISPATCH \ |
| 0x00000400 /**< Log data on every context switch dispatch. \ |
| */ |
| #define DR_LOG_MONITOR 0x00000800 /**< Log data related to trace building. */ |
| #define DR_LOG_HEAP 0x00001000 /**< Log data related to memory management. */ |
| #define DR_LOG_VMAREAS 0x00002000 /**< Log data related to address space regions. */ |
| #define DR_LOG_SYNCH 0x00004000 /**< Log data related to synchronization. */ |
| #define DR_LOG_MEMSTATS \ |
| 0x00008000 /**< Log data related to memory statistics. \ |
| */ |
| #define DR_LOG_OPTS 0x00010000 /**< Log data related to optimizations. */ |
| #define DR_LOG_SIDELINE 0x00020000 /**< Log data related to sideline threads. */ |
| #define DR_LOG_SYMBOLS 0x00040000 /**< Log data related to app symbols. */ |
| #define DR_LOG_RCT 0x00080000 /**< Log data related to indirect transfers. */ |
| #define DR_LOG_NT 0x00100000 /**< Log data related to Windows Native API. */ |
| #define DR_LOG_HOT_PATCHING 0x00200000 /**< Log data related to hot patching. */ |
| #define DR_LOG_HTABLE 0x00400000 /**< Log data related to hash tables. */ |
| #define DR_LOG_MODULEDB 0x00800000 /**< Log data related to the module database. */ |
| #define DR_LOG_ALL 0x00ffffff /**< Log all data. */ |
| #ifdef DR_LOG_DEFINE_COMPATIBILITY |
| # define LOG_NONE DR_LOG_NONE /**< Identical to #DR_LOG_NONE. */ |
| # define LOG_STATS DR_LOG_STATS /**< Identical to #DR_LOG_STATS. */ |
| # define LOG_TOP DR_LOG_TOP /**< Identical to #DR_LOG_TOP. */ |
| # define LOG_THREADS DR_LOG_THREADS /**< Identical to #DR_LOG_THREADS. */ |
| # define LOG_SYSCALLS DR_LOG_SYSCALLS /**< Identical to #DR_LOG_SYSCALLS. */ |
| # define LOG_ASYNCH DR_LOG_ASYNCH /**< Identical to #DR_LOG_ASYNCH. */ |
| # define LOG_INTERP DR_LOG_INTERP /**< Identical to #DR_LOG_INTERP. */ |
| # define LOG_EMIT DR_LOG_EMIT /**< Identical to #DR_LOG_EMIT. */ |
| # define LOG_LINKS DR_LOG_LINKS /**< Identical to #DR_LOG_LINKS. */ |
| # define LOG_CACHE DR_LOG_CACHE /**< Identical to #DR_LOG_CACHE. */ |
| # define LOG_FRAGMENT DR_LOG_FRAGMENT /**< Identical to #DR_LOG_FRAGMENT. */ |
| # define LOG_DISPATCH DR_LOG_DISPATCH /**< Identical to #DR_LOG_DISPATCH. */ |
| # define LOG_MONITOR DR_LOG_MONITOR /**< Identical to #DR_LOG_MONITOR. */ |
| # define LOG_HEAP DR_LOG_HEAP /**< Identical to #DR_LOG_HEAP. */ |
| # define LOG_VMAREAS DR_LOG_VMAREAS /**< Identical to #DR_LOG_VMAREAS. */ |
| # define LOG_SYNCH DR_LOG_SYNCH /**< Identical to #DR_LOG_SYNCH. */ |
| # define LOG_MEMSTATS DR_LOG_MEMSTATS /**< Identical to #DR_LOG_MEMSTATS. */ |
| # define LOG_OPTS DR_LOG_OPTS /**< Identical to #DR_LOG_OPTS. */ |
| # define LOG_SIDELINE DR_LOG_SIDELINE /**< Identical to #DR_LOG_SIDELINE. */ |
| # define LOG_SYMBOLS DR_LOG_SYMBOLS /**< Identical to #DR_LOG_SYMBOLS. */ |
| # define LOG_RCT DR_LOG_RCT /**< Identical to #DR_LOG_RCT. */ |
| # define LOG_NT DR_LOG_NT /**< Identical to #DR_LOG_NT. */ |
| # define LOG_HOT_PATCHING \ |
| DR_LOG_HOT_PATCHING /**< Identical to #DR_LOG_HOT_PATCHING. */ |
| # define LOG_HTABLE DR_LOG_HTABLE /**< Identical to #DR_LOG_HTABLE. */ |
| # define LOG_MODULEDB DR_LOG_MODULEDB /**< Identical to #DR_LOG_MODULEDB. */ |
| # define LOG_ALL DR_LOG_ALL /**< Identical to #DR_LOG_ALL. */ |
| #endif |
| |
| DR_API |
| /** |
| * Returns the log file for the thread with drcontext \p drcontext. |
| * If \p drcontext is NULL, returns the main log file. |
| */ |
| file_t |
| dr_get_logfile(void *drcontext); |
| |
| DR_API |
| /** |
| * Returns true iff the -stderr_mask runtime option is non-zero, indicating |
| * that the user wants notification messages printed to stderr. |
| */ |
| bool |
| dr_is_notify_on(void); |
| |
| DR_API |
| /** Returns a handle to stdout. */ |
| file_t |
| dr_get_stdout_file(void); |
| |
| DR_API |
| /** Returns a handle to stderr. */ |
| file_t |
| dr_get_stderr_file(void); |
| |
| DR_API |
| /** Returns a handle to stdin. */ |
| file_t |
| dr_get_stdin_file(void); |
| |
| #ifdef PROGRAM_SHEPHERDING |
| DR_API |
| /** Writes a security violation forensics report to the supplied file. The forensics |
| * report will include detailed information about the source and target addresses of the |
| * violation as well as information on the current thread, process, and machine. The |
| * forensics report is generated in an xml block described by dr_forensics-1.0.dtd. |
| * The encoding used is iso-8859-1. |
| * |
| * The dcontext, violation, and action arguments are supplied by the security violation |
| * event callback. The file argument is the file to write the forensics report to and |
| * the violation_name argument is a supplied name for the violation. |
| */ |
| void |
| dr_write_forensics_report(void *dcontext, file_t file, |
| dr_security_violation_type_t violation, |
| dr_security_violation_action_t action, |
| const char *violation_name); |
| #endif /* PROGRAM_SHEPHERDING */ |
| |
| #ifdef WINDOWS |
| DR_API |
| /** |
| * Displays a message in a pop-up window. \note Windows only. \note On Windows Vista |
| * most Windows services are unable to display message boxes. |
| */ |
| void |
| dr_messagebox(const char *fmt, ...); |
| #endif |
| |
| DR_API |
| /** |
| * Stdout printing that won't interfere with the |
| * application's own printing. |
| * It is not buffered, which means that it should not be used for |
| * very frequent, small print amounts: for that the client should either |
| * do its own buffering or it should use printf from the C library |
| * via DR's private loader. |
| * \note On Windows 7 and earlier, this routine is not able to print |
| * to the \p cmd window |
| * unless dr_enable_console_printing() is called ahead of time, and |
| * even then there are limitations: see dr_enable_console_printing(). |
| * \note This routine supports printing wide characters via the ls |
| * or S format specifiers. On Windows, they are assumed to be UTF-16, |
| * and are converted to UTF-8. On Linux, they are converted by simply |
| * dropping the high-order bytes. |
| * \note If the data to be printed is large it will be truncated to |
| * an internal buffer size. Use dr_snprintf() and dr_write_file() for |
| * large output. |
| * \note When printing floating-point values on x86, the caller's code should |
| * use proc_save_fpstate() or be inside a clean call that |
| * has requested to preserve the floating-point state, unless it can prove |
| * that its compiler will not use x87 operations. |
| */ |
| void |
| dr_printf(const char *fmt, ...); |
| |
| DR_API |
| /** |
| * Printing to a file that won't interfere with the |
| * application's own printing. |
| * It is not buffered, which means that it should not be used for |
| * very frequent, small print amounts: for that the client should either |
| * do its own buffering or it should use printf from the C library |
| * via DR's private loader. |
| * \note On Windows 7 and earlier, this routine is not able to print to STDOUT or |
| * STDERR in the \p cmd window unless dr_enable_console_printing() is |
| * called ahead of time, and even then there are limitations: see |
| * dr_enable_console_printing(). |
| * \note This routine supports printing wide characters via the ls |
| * or S format specifiers. On Windows, they are assumed to be UTF-16, |
| * and are converted to UTF-8. On Linux, they are converted by simply |
| * dropping the high-order bytes. |
| * \note If the data to be printed is large it will be truncated to |
| * an internal buffer size. Use dr_snprintf() and dr_write_file() for |
| * large output. |
| * \note On Linux this routine does not check for errors like EINTR. Use |
| * dr_write_file() if that is a concern. |
| * \note When printing floating-point values, the caller's code should |
| * use proc_save_fpstate() or be inside a clean call that |
| * has requested to preserve the floating-point state, unless it can prove |
| * that its compiler will not use x87 operations. |
| * On success, the number of bytes written is returned. |
| * On error, -1 is returned. |
| */ |
| ssize_t |
| dr_fprintf(file_t f, const char *fmt, ...); |
| |
| DR_API |
| /** |
| * Identical to dr_fprintf() but exposes va_list. |
| */ |
| ssize_t |
| dr_vfprintf(file_t f, const char *fmt, va_list ap); |
| |
| #ifdef WINDOWS |
| DR_API |
| /** |
| * Enables dr_printf() and dr_fprintf() to work with a legacy console |
| * window (viz., \p cmd on Windows 7 or earlier). Loads a private |
| * copy of kernel32.dll (if not |
| * already loaded) in order to accomplish this. To keep the default |
| * DR lean and mean, loading kernel32.dll is not performed by default. |
| * |
| * This routine must be called during client initialization (\p dr_client_main()). |
| * If called later, it will fail. |
| * |
| * Without calling this routine, dr_printf() and dr_fprintf() will not |
| * print anything in a console window on Windows 7 or earlier, nor will they |
| * print anything when running a graphical application. |
| * |
| * Even after calling this routine, there are significant limitations |
| * to console printing support in DR: |
| * |
| * - On Windows versions prior to Vista, and for WOW64 applications |
| * on Vista, it does not work from the exit event. Once the |
| * application terminates its state with csrss (toward the very end |
| * of ExitProcess), no output will show up on the console. We have |
| * no good solution here yet as exiting early is not ideal. |
| * - In the future, with earliest injection (Issue 234), writing to the |
| * console may not work from the client init event on Windows 7 and |
| * earlier (it will work on Windows 8). |
| * |
| * These limitations stem from the complex arrangement of the console |
| * window in Windows (prior to Windows 8), where printing to it |
| * involves sending a message |
| * in an undocumented format to the \p csrss process, rather than a |
| * simple write to a file handle. We recommend using a terminal |
| * window such as cygwin's \p rxvt rather than the \p cmd window, or |
| * alternatively redirecting all output to a file, which will solve |
| * all of the above limitations. |
| * |
| * Returns whether successful. |
| * \note Windows only. |
| */ |
| bool |
| dr_enable_console_printing(void); |
| |
| DR_API |
| /** |
| * Returns true if the current standard error handle belongs to a |
| * legacy console window (viz., \p cmd on Windows 7 or earlier). DR's |
| * dr_printf() and dr_fprintf() |
| * do not work with such console windows unless |
| * dr_enable_console_printing() is called ahead of time, and even then |
| * there are limitations detailed in dr_enable_console_printing(). |
| * This routine may result in loading a private copy of kernel32.dll. |
| * \note Windows only. |
| */ |
| bool |
| dr_using_console(void); |
| #endif |
| |
| DR_API |
| /** |
| * 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. |
| * \note This routine supports printing wide characters via the ls |
| * or S format specifiers. On Windows, they are assumed to be UTF-16, |
| * and are converted to UTF-8. On Linux, they are converted by simply |
| * dropping the high-order bytes. |
| * \note When printing floating-point values, the caller's code should |
| * use proc_save_fpstate() or be inside a clean call that |
| * has requested to preserve the floating-point state, unless it can prove |
| * that its compiler will not use x87 operations.. |
| */ |
| int |
| dr_snprintf(char *buf, size_t max, const char *fmt, ...); |
| |
| DR_API |
| /** |
| * Wide character version of dr_snprintf(). All of the comments for |
| * dr_snprintf() apply, except for the hs or S format specifiers. |
| * On Windows, these will assume that the input is UTF-8, and will |
| * convert to UTF-16. On Linux, they will widen a single-byte |
| * character string into a wchar_t character string with zero as the |
| * high-order bytes. |
| */ |
| int |
| dr_snwprintf(wchar_t *buf, size_t max, const wchar_t *fmt, ...); |
| |
| DR_API |
| /** |
| * Identical to dr_snprintf() but exposes va_list. |
| */ |
| int |
| dr_vsnprintf(char *buf, size_t max, const char *fmt, va_list ap); |
| |
| DR_API |
| /** |
| * Identical to dr_snwprintf() but exposes va_list. |
| */ |
| int |
| dr_vsnwprintf(wchar_t *buf, size_t max, const wchar_t *fmt, va_list ap); |
| |
| DR_API |
| /** |
| * Utility routine to parse strings that match a pre-defined format string, |
| * similar to the sscanf() C routine. |
| * |
| * @param[in] str String to parse. |
| * @param[in] fmt Format string controlling parsing. |
| * @param[out] ... All remaining parameters interpreted as output parameter |
| * pointers. The type of each parameter must match the type |
| * implied by the corresponding format specifier in \p fmt. |
| * \return The number of specifiers matched. |
| * |
| * The benefit of using dr_sscanf() over native sscanf() is that DR's |
| * implementation is standalone, signal-safe, and cross-platform. On Linux, |
| * sscanf() has been observed to call malloc(). On Windows, sscanf() will call |
| * strlen(), which can break when using mapped files. |
| * |
| * The behavior of dr_sscanf() is mostly identical to that of the sscanf() C |
| * routine. |
| * |
| * Supported format specifiers: |
| * - \%s: Matches a sequence of non-whitespace characters. The string is copied |
| * into the provided output buffer. To avoid buffer overflow, the caller |
| * should use a width specifier. |
| * - \%c: Matches any single character. |
| * - \%d: Matches a signed decimal integer. |
| * - \%u: Matches an unsigned decimal integer. |
| * - \%x: Matches an unsigned hexadecimal integer, with or without a leading 0x. |
| * - \%p: Matches a pointer-sized hexadecimal integer as %x does. |
| * - \%%: Matches a literal % character. Does not store output. |
| * |
| * Supported format modifiers: |
| * - *: The * modifier causes the scan to match the specifier, but not store any |
| * output. No output parameter is consumed for this specifier, and one should |
| * not be passed. |
| * - 0-9: A decimal integer preceding the specifier gives the width to match. |
| * For strings, this indicates the maximum number of characters to copy. For |
| * integers, this indicates the maximum number of digits to parse. |
| * - h: Marks an integer specifier as short. |
| * - l: Marks an integer specifier as long. |
| * - ll: Marks an integer specifier as long long. Use this for 64-bit integers. |
| * |
| * \warning dr_sscanf() does \em not support parsing floating point numbers yet. |
| */ |
| int |
| dr_sscanf(const char *str, const char *fmt, ...); |
| |
| DR_API |
| /** |
| * Utility function that aids in tokenizing a string, such as a client |
| * options string from dr_get_options(). The function scans \p str |
| * until a non-whitespace character is found. It then starts copying |
| * into \p buf until a whitespace character is found denoting the end |
| * of the token. If the token begins with a quote, the token |
| * continues (including across whitespace) until the matching end |
| * quote is found. Characters considered whitespace are ' ', '\\t', |
| * '\\r', and '\\n'; characters considered quotes are '\\'', '\\"', and |
| * '`'. |
| * |
| * @param[in] str The start of the string containing the next token. |
| * @param[out] buf A buffer to store a null-terminated copy of the next token. |
| * @param[in] buflen The capacity of the buffer, in characters. If the token |
| * is too large to fit, it will be truncated and null-terminated. |
| * |
| * \return a pointer to the end of the token in \p str. Thus, to retrieve |
| * the subsequent token, call this routine again with the prior return value |
| * as the new value of \p str. Returns NULL when the end of \p str is reached. |
| */ |
| const char * |
| dr_get_token(const char *str, char *buf, size_t buflen); |
| |
| DR_API |
| /** Prints \p msg followed by the instruction \p instr to file \p f. */ |
| void |
| dr_print_instr(void *drcontext, file_t f, instr_t *instr, const char *msg); |
| |
| DR_API |
| /** Prints \p msg followed by the operand \p opnd to file \p f. */ |
| void |
| dr_print_opnd(void *drcontext, file_t f, opnd_t opnd, const char *msg); |
| |
| /************************************************** |
| * THREAD SUPPORT |
| */ |
| |
| DR_API |
| /** |
| * Returns the DR context of the current thread. |
| */ |
| void * |
| dr_get_current_drcontext(void); |
| |
| DR_API |
| /** Returns the thread id of the thread with drcontext \p drcontext. */ |
| thread_id_t |
| dr_get_thread_id(void *drcontext); |
| |
| #ifdef WINDOWS |
| DR_API |
| /** |
| * Returns a Windows handle to the thread with drcontext \p drcontext. |
| * This handle is DR's handle to this thread (it is not a separate |
| * copy) and as such it should not be closed by the caller; nor should |
| * it be used beyond the thread's exit, as DR's handle will be closed |
| * at that point. |
| * |
| * The handle should have THREAD_ALL_ACCESS privileges. |
| * \note Windows only. |
| */ |
| HANDLE |
| dr_get_dr_thread_handle(void *drcontext); |
| #endif |
| |
| DR_API |
| /** |
| * 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_get_tls_field(void *drcontext); |
| |
| DR_API |
| /** |
| * 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_set_tls_field(void *drcontext, void *value); |
| |
| DR_API |
| /** |
| * Get DR's thread local storage segment base pointed at by \p tls_register. |
| * It can be used to get the base of the thread-local storage segment |
| * used by #dr_raw_tls_calloc. |
| * |
| * \note It should not be called on thread exit event, |
| * as the thread exit event may be invoked from other threads. |
| * See #dr_register_thread_exit_event for details. |
| */ |
| void * |
| dr_get_dr_segment_base(DR_PARAM_IN reg_id_t tls_register); |
| |
| DR_API |
| /** |
| * Allocates \p num_slots contiguous thread-local storage (TLS) slots that |
| * can be directly accessed via an offset from \p tls_register. |
| * If \p alignment is non-zero, the slots will be aligned to \p alignment. |
| * These slots will be initialized to 0 for each new thread. |
| * The slot offsets are [\p offset .. \p 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. |
| * The linear address of the TLS base pointed at by \p tls_register can be obtained |
| * using #dr_get_dr_segment_base. |
| * Raw TLs slots can be read directly using dr_insert_read_raw_tls() and written |
| * using dr_insert_write_raw_tls(). |
| * |
| * Supports passing 0 for \p num_slots, in which case \p tls_register will be |
| * written but no other action taken. |
| * |
| * \note These slots are useful for thread-shared code caches. With |
| * thread-private caches, DR's memory pools are guaranteed to be |
| * reachable via absolute or rip-relative accesses from the code cache |
| * and client libraries. |
| * |
| * \note 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. |
| * |
| * \note On Mac OS, TLS slots may not be initialized to zero. |
| */ |
| bool |
| dr_raw_tls_calloc(DR_PARAM_OUT reg_id_t *tls_register, DR_PARAM_OUT uint *offset, |
| DR_PARAM_IN uint num_slots, DR_PARAM_IN uint alignment); |
| |
| DR_API |
| /** |
| * Frees \p num_slots raw thread-local storage slots starting at |
| * offset \p offset that were allocated with dr_raw_tls_calloc(). |
| * Returns whether or not the slots were successfully freed. |
| */ |
| bool |
| dr_raw_tls_cfree(uint offset, uint num_slots); |
| |
| DR_API |
| /** |
| * Returns an operand that refers to the raw TLS slot with offset \p |
| * tls_offs from the TLS base \p tls_register. |
| */ |
| opnd_t |
| dr_raw_tls_opnd(void *drcontext, reg_id_t tls_register, uint tls_offs); |
| |
| DR_API |
| /** |
| * Inserts into ilist prior to "where" instruction(s) to read into the |
| * general-purpose full-size register \p reg from the raw TLS slot with offset |
| * \p tls_offs from the TLS base \p tls_register. |
| */ |
| void |
| dr_insert_read_raw_tls(void *drcontext, instrlist_t *ilist, instr_t *where, |
| reg_id_t tls_register, uint tls_offs, reg_id_t reg); |
| |
| DR_API |
| /** |
| * Inserts into ilist prior to "where" instruction(s) to store the value in the |
| * general-purpose full-size register \p reg into the raw TLS slot with offset |
| * \p tls_offs from the TLS base \p tls_register. |
| */ |
| void |
| dr_insert_write_raw_tls(void *drcontext, instrlist_t *ilist, instr_t *where, |
| reg_id_t tls_register, uint tls_offs, reg_id_t reg); |
| |
| /* PR 222812: due to issues in supporting client thread synchronization |
| * and other complexities we are using nudges for simple push-i/o and |
| * saving thread creation for sideline usage scenarios. |
| * These are implemented in <os>/os.c. |
| */ |
| /* PR 231301: for synch with client threads we can't distinguish between |
| * client_lib->ntdll/gencode/other_lib (which is safe) from |
| * client_lib->dr->ntdll/gencode/other_lib (which isn't) so we consider both |
| * unsafe. If the client thread spends a lot of time in ntdll or worse directly |
| * makes blocking/long running system calls (note dr_thread_yield, dr_sleep, |
| * dr_mutex_lock, and dr_messagebox are ok) then it may have performance or |
| * correctness (if the synch times out) impacts. |
| */ |
| DR_API |
| /** |
| * 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 \p 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 \p 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. If a client thread spends a lot of time holding locks, |
| * consider marking it as un-suspendable by calling |
| * dr_client_thread_set_suspendable() for better performance. |
| * |
| * Client threads, whether suspendable or not, must never execute from |
| * the code cache as the underlying fragments might be removed by another |
| * thread. |
| * |
| * Client threads are suspended while DR is not executing the application. |
| * This includes initialization time: the client thread's \p func code will not |
| * execute until DR starts executing the application. |
| * |
| * \note Thread creation via this routine is not yet fully |
| * transparent: on Windows, the thread will show up in the list of |
| * application threads if the operating system is queried about |
| * threads. The thread will not trigger a DLL_THREAD_ATTACH message. |
| * On Linux, the thread will not receive signals meant for the application, |
| * and is guaranteed to have a private itimer. |
| */ |
| bool |
| dr_create_client_thread(void (*func)(void *param), void *arg); |
| |
| DR_API |
| /** |
| * Can only be called from a client thread: returns false if called |
| * from a non-client thread. |
| * |
| * Controls whether a client thread created with dr_create_client_thread() |
| * will be suspended by DR for synchronization operations such as |
| * flushing or client requests like dr_suspend_all_other_threads(). |
| * A client thread that spends a lot of time holding locks can gain |
| * greater performance by not being suspended. |
| * |
| * A client thread \b will be suspended for a thread termination |
| * operation, including at process exit, regardless of its suspendable |
| * requests. |
| */ |
| bool |
| dr_client_thread_set_suspendable(bool suspendable); |
| |
| DR_API |
| /** Current thread sleeps for \p time_ms milliseconds. */ |
| void |
| dr_sleep(int time_ms); |
| |
| DR_API |
| /** Current thread gives up its time quantum. */ |
| void |
| dr_thread_yield(void); |
| |
| /** Flags controlling the behavior of dr_suspend_all_other_threads_ex(). */ |
| typedef enum { |
| /** |
| * By default, native threads are not suspended by |
| * dr_suspend_all_other_threads_ex(). This flag requests that native |
| * threads (including those temporarily-native due to actions such as |
| * #DR_EMIT_GO_NATIVE) be suspended as well. |
| */ |
| DR_SUSPEND_NATIVE = 0x0001, |
| } dr_suspend_flags_t; |
| |
| /* FIXME - xref PR 227619 - some other event handler are safe (image_load/unload for* |
| * example) which we could note here. */ |
| DR_API |
| /** |
| * Suspends all other threads in the process and returns an array of |
| * contexts in \p drcontexts with one context per successfully suspended |
| * thread. 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 \p flags argument controls which threads are suspended and may |
| * add further options in the future. |
| * |
| * The number of successfully suspended threads, which is also the length |
| * of the \p drcontexts array, is returned in \p num_suspended, which is a |
| * required parameter. The number of un-successfully suspended threads, if |
| * any, is returned in the optional parameter \p 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 \p |
| * num_unsuspended will be 0. |
| * |
| * The caller must invoke dr_resume_all_other_threads() in order to resume |
| * the suspended threads, free the \p 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 or the pre- or post-system call 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. |
| * |
| * \note A client wishing to invoke this routine from an event callback can |
| * queue up a nudge via dr_nudge_client() and invoke this routine from the |
| * nudge callback. |
| */ |
| bool |
| dr_suspend_all_other_threads_ex(DR_PARAM_OUT void ***drcontexts, |
| DR_PARAM_OUT uint *num_suspended, |
| DR_PARAM_OUT uint *num_unsuspended, |
| dr_suspend_flags_t flags); |
| |
| DR_API |
| /** Identical to dr_suspend_all_other_threads_ex() with \p flags set to 0. */ |
| bool |
| dr_suspend_all_other_threads(DR_PARAM_OUT void ***drcontexts, |
| DR_PARAM_OUT uint *num_suspended, |
| DR_PARAM_OUT uint *num_unsuspended); |
| |
| DR_API |
| /** |
| * 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 \p 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_resume_all_other_threads(DR_PARAM_IN void **drcontexts, |
| DR_PARAM_IN uint num_suspended); |
| |
| DR_API |
| /** |
| * Returns whether the thread represented by \p drcontext is currently |
| * executing natively (typically due to an earlier #DR_EMIT_GO_NATIVE |
| * return value). |
| */ |
| bool |
| dr_is_thread_native(void *drcontext); |
| |
| DR_API |
| /** |
| * Causes the thread owning \p drcontext to begin executing in the |
| * code cache again once it is resumed. The thread must currently be |
| * suspended (typically by dr_suspend_all_other_threads_ex() with |
| * #DR_SUSPEND_NATIVE) and must be currently native (typically from |
| * #DR_EMIT_GO_NATIVE). \return whether successful. |
| */ |
| bool |
| dr_retakeover_suspended_native_thread(void *drcontext); |
| |
| /* We do not translate the context to avoid lock issues (PR 205795). |
| * We do not delay until a safe point (via regular delayable signal path) |
| * since some clients may want the interrupted context: for a general |
| * timer clients should create a separate thread. |
| */ |
| #ifdef UNIX |
| DR_API |
| /** |
| * Installs an interval timer in the itimer sharing group that |
| * contains the calling thread. |
| * |
| * @param[in] which Must be one of ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF |
| * @param[in] millisec The frequency of the timer, in milliseconds. Passing |
| * 0 disables the timer. |
| * @param[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 a |
| * lock holder or other critical code, so it must be careful in its |
| * operations: keep it as simple as possible, and avoid any non-reentrant actions |
| * such as lock usage. 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. |
| * |
| * Itimer sharing varies by kernel. Prior to 2.6.12 itimers were |
| * thread-private; after 2.6.12 they are shared across a thread group, |
| * though there could be multiple thread groups in one address space. |
| * The dr_get_itimer() function can be used to see whether a thread |
| * already has an itimer in its group to avoid re-setting an itimer |
| * set by an earlier thread. A client thread created by |
| * dr_create_client_thread() is guaranteed to not share its itimers |
| * with application threads. |
| * |
| * The itimer will operate successfully in the presence of an |
| * application itimer of the same type. |
| * |
| * Additional itimer signals are blocked while in our signal handler. |
| * |
| * The return value indicates whether the timer was successfully |
| * installed (or uninstalled if 0 was passed for \p millisec). |
| * |
| * \note Linux-only. |
| */ |
| bool |
| dr_set_itimer(int which, uint millisec, |
| void (*func)(void *drcontext, dr_mcontext_t *mcontext)); |
| |
| DR_API |
| /** |
| * If an interval timer is already installed in the itimer sharing group that |
| * contains the calling thread, returns its frequency. Else returns 0. |
| * |
| * @param[in] which Must be one of ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF |
| * |
| * \note Linux-only. |
| */ |
| uint |
| dr_get_itimer(int which); |
| #endif /* UNIX */ |
| |
| DR_API |
| /** |
| * Should be called during process initialization. Requests more accurate |
| * tracking of the #dr_where_am_i_t value for use with dr_where_am_i(). By |
| * default, if this routine is not called, DR avoids some updates to the value |
| * that incur extra overhead, such as identifying clean callees. |
| */ |
| void |
| dr_track_where_am_i(void); |
| |
| DR_API |
| /** |
| * Returns whether DR is using accurate tracking of the #dr_where_am_i value. |
| * Typically this is enabled by calling dr_track_where_am_i(). |
| */ |
| bool |
| dr_is_tracking_where_am_i(void); |
| |
| DR_API |
| /** |
| * Returns the #dr_where_am_i_t value indicating in which area of code \p pc |
| * resides. This is meant for use with dr_set_itimer() for PC sampling for |
| * profiling purposes. If the optional \p tag is non-NULL and \p pc is inside a |
| * fragment in the code cache, the fragment's tag is returned in \p tag. It is |
| * recommended that the user of this routine also call dr_track_where_am_i() |
| * during process initialization for more accurate results. |
| */ |
| dr_where_am_i_t |
| dr_where_am_i(void *drcontext, app_pc pc, DR_PARAM_OUT void **tag); |
| |
| /**************************************************************************** |
| * ADAPTIVE OPTIMIZATION SUPPORT |
| */ |
| |
| /* xref PR 199115 and PR 237461: We decided to make the replace and |
| * delete routines valid for -thread_private only. Both routines |
| * replace for the current thread and leave the other threads |
| * unmodified. The rationale is that we expect these routines will be |
| * primarily useful for optimization, where a client wants to modify a |
| * fragment specific to one thread. |
| */ |
| DR_API |
| /** |
| * Replaces the fragment with tag \p tag with the instructions in \p |
| * 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. |
| * |
| * \note The routine takes control of \p 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. |
| * |
| * \note This routine supports replacement for the current thread |
| * only. \p drcontext must be from the current thread and must |
| * be the drcontext used to create the instruction list. |
| * This routine may not be called from the thread exit event. |
| * |
| * \return false if the fragment does not exist and true otherwise. |
| */ |
| bool |
| dr_replace_fragment(void *drcontext, void *tag, instrlist_t *ilist); |
| |
| DR_API |
| /** |
| * Deletes the fragment with tag \p 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. |
| * |
| * \note This routine supports deletion for the current thread |
| * only. \p drcontext must be from the current thread and must |
| * be the drcontext used to create the instruction list. |
| * This routine may not be called from the thread exit event. |
| * |
| * \note Other options of removing the code fragments from code cache include |
| * dr_flush_region(), dr_unlink_flush_region(), and dr_delay_flush_region(). |
| * |
| * \return false if the fragment does not exist and true otherwise. |
| */ |
| bool |
| dr_delete_fragment(void *drcontext, void *tag); |
| |
| /* FIXME - xref PR 227619 - some other event handler are safe (image_load/unload for* |
| * example) which we could note here. */ |
| DR_API |
| /** |
| * Flush all fragments containing any code from the region [\p start, \p start + \p 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, from a nudge |
| * event handler, or from a pre- or post-system call 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 redirect |
| * execution via dr_redirect_execution() (or DR_SIGNAL_REDIRECT from a signal callback) |
| * after this routine to continue execution. Returns true if successful. |
| * |
| * \note This routine may not be called from any registered event callback other than |
| * the nudge event, the pre- or post-system call events, the exception event, or |
| * the signal event; clean calls |
| * out of the cache may call this routine. |
| * |
| * \note 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 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. |
| * |
| * \note This routine may not be called while any locks are held that could block a thread |
| * processing a registered event callback or cache callout. |
| * |
| * \note dr_delay_flush_region() has fewer restrictions on use, but is less synchronous. |
| * |
| * \note Use \p size == 1 to flush fragments containing the instruction at address |
| * \p start. A flush of \p size == 0 is not allowed. |
| * |
| * \note Use flush_completion_callback to specify logic to be executed after the flush |
| * and before the threads are resumed. Use NULL if not needed. |
| * |
| * \note As currently implemented, dr_delay_flush_region() with no completion callback |
| * routine specified can be substantially more performant. |
| */ |
| bool |
| dr_flush_region_ex(app_pc start, size_t size, |
| void (*flush_completion_callback)(void *user_data), void *user_data); |
| |
| DR_API |
| /** Equivalent to dr_flush_region_ex(start, size, NULL). */ |
| bool |
| dr_flush_region(app_pc start, size_t size); |
| |
| /* FIXME - get rid of the no locks requirement by making event callbacks !couldbelinking |
| * and no dr locks (see PR 227619) so that client locks owned by this thread can't block |
| * any couldbelinking thread. FIXME - would be nice to make this available for |
| * windows since there's less of a performance hit than using synch_all flushing, but |
| * with coarse_units can't tell if we need a synch all flush or not and that confuses |
| * the interface a lot. FIXME - xref PR 227619 - some other event handler are safe |
| * (image_load/unload for example) which we could note here. */ |
| /* FIXME - add a completion callback (see vm_area_check_shared_pending()). */ |
| /* FIXME - could enable on windows when -thread_private since no coarse then. */ |
| DR_API |
| /** |
| * Flush all fragments containing any code from the region [\p start, \p start + \p 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, from a nudge |
| * event handler, or from a pre- or post-system call 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. |
| * |
| * \note This routine may not be called from any registered event callback other than |
| * the nudge event, the pre- or post-system call events, the exception event, or |
| * the signal event; clean calls |
| * out of the cache may call this routine. |
| * \note This routine may not be called while any locks are held that could block a thread |
| * processing a registered event callback or cache callout. |
| * \note dr_delay_flush_region() has fewer restrictions on use, but is less synchronous. |
| * \note Use \p size == 1 to flush fragments containing the instruction at address |
| * \p start. A flush of \p size == 0 is not allowed. |
| * \note 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_unlink_flush_region(app_pc start, size_t size); |
| |
| /* FIXME - can we better bound when the flush will happen? Maybe unlink shared syscalls |
| * or similar or check the queue in more locations? Should always hit the flush before |
| * executing new code in the cache, and I think we'll always hit it before a nudge is |
| * processed too. Could trigger a nudge, or do this in a nudge, but that's rather |
| * expensive. */ |
| DR_API |
| /** |
| * Request a flush of all fragments containing code from the region |
| * [\p start, \p start + \p 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 \p flush_completion_callback is non-NULL, it will be |
| * called with the \p 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. |
| * |
| * \note dr_flush_region() and dr_unlink_flush_region() can give stronger guarantees on |
| * when the flush will occur, but have more restrictions on use. |
| * \note Use \p size == 1 to flush fragments containing the instruction at address |
| * \p start. A flush of \p size == 0 is not allowed. |
| * \note As currently implemented there may be a performance penalty for requesting a |
| * \p flush_completion_callback; for most performant usage set |
| * \p flush_completion_callback to NULL. |
| */ |
| bool |
| dr_delay_flush_region(app_pc start, size_t size, uint flush_id, |
| void (*flush_completion_callback)(int flush_id)); |
| |
| DR_API |
| /** Returns whether or not there is a fragment in code cache with tag \p tag. */ |
| bool |
| dr_fragment_exists_at(void *drcontext, void *tag); |
| |
| DR_API |
| /** |
| * Returns true if a basic block with tag \p tag exists in the code cache. |
| */ |
| bool |
| dr_bb_exists_at(void *drcontext, void *tag); |
| |
| DR_API |
| /** |
| * Looks up the fragment with tag \p tag. |
| * If not found, returns 0. |
| * If found, returns the total size occupied in the cache by the fragment. |
| */ |
| uint |
| dr_fragment_size(void *drcontext, void *tag); |
| |
| DR_API |
| /** Retrieves the application PC of a fragment with tag \p tag. */ |
| app_pc |
| dr_fragment_app_pc(void *tag); |
| |
| DR_API |
| /** |
| * 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. |
| * |
| * \note Other applications on the system sometimes insert their own hooks, |
| * which will not be hidden by DR and will appear to the client as jumps |
| * and subsequent displaced code. |
| */ |
| app_pc |
| dr_app_pc_for_decoding(app_pc pc); |
| |
| DR_API |
| /** |
| * Given a code cache pc, returns the corresponding application pc. |
| * This involves translating the state and thus may incur calls to |
| * the basic block and trace events (see dr_register_bb_event()). |
| * If translation fails, returns NULL. |
| * This routine may not be called from a thread exit event. |
| */ |
| app_pc |
| dr_app_pc_from_cache_pc(byte *cache_pc); |
| |
| DR_API |
| /** |
| * Intended to be called between dr_app_setup() and dr_app_start() to |
| * pre-create code cache fragments for each basic block address in the |
| * \p tags array. This speeds up the subsequent attach when |
| * dr_app_start() is called. |
| * If any code in the passed-in tags array is not readable, it is up to the |
| * caller to handle any fault, as DR's own signal handlers are not enabled |
| * at this point. |
| * Returns whether successful. |
| */ |
| bool |
| dr_prepopulate_cache(app_pc *tags, size_t tags_count); |
| |
| /** |
| * Specifies the type of indirect branch for use with dr_prepopulate_indirect_targets(). |
| */ |
| typedef enum { |
| DR_INDIRECT_RETURN, /**< Return instruction type. */ |
| DR_INDIRECT_CALL, /**< Indirect call instruction type. */ |
| DR_INDIRECT_JUMP, /**< Indirect jump instruction type. */ |
| } dr_indirect_branch_type_t; |
| |
| DR_API |
| /** |
| * Intended to augment dr_prepopulate_cache() by populating DR's indirect branch |
| * tables, avoiding trips back to the dispatcher during initial execution. This is only |
| * effective when one of the the runtime options -shared_trace_ibt_tables and |
| * -shared_bb_ibt_tables (depending on whether traces are enabled) is turned on, as |
| * this routine does not try to populate tables belonging to threads other than the |
| * calling thread. |
| * |
| * This is meant to be called between dr_app_setup() and dr_app_start(), immediately |
| * after calling dr_prepopulate_cache(). It adds entries for each target address in |
| * the \p tags array to the indirect branch table for the branch type \p branch_type. |
| * |
| * Returns whether successful. |
| */ |
| bool |
| dr_prepopulate_indirect_targets(dr_indirect_branch_type_t branch_type, app_pc *tags, |
| size_t tags_count); |
| |
| DR_API |
| /** |
| * Retrieves various statistics exported by DR as global, process-wide values. |
| * The API is not thread-safe. |
| * The caller is expected to pass a pointer to a valid, initialized #dr_stats_t |
| * value, with the size field set (see #dr_stats_t). |
| * Returns false if stats are not enabled. |
| */ |
| bool |
| dr_get_stats(dr_stats_t *drstats); |
| |
| /**************************************************************************** |
| * CUSTOM TRACE SUPPORT |
| */ |
| |
| DR_API |
| /** |
| * Marks the fragment associated with tag \p 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.) |
| * |
| * \note Some fragments are unsuitable for trace heads. DR will |
| * ignore attempts to mark such fragments as trace heads and will return |
| * false. If the client marks a fragment that doesn't exist yet as a trace |
| * head and DR later determines that the fragment is unsuitable for |
| * a trace head it will unmark the fragment as a trace head without |
| * notifying the client. |
| * |
| * \note 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. |
| * |
| * Returns true if the target fragment is marked as a trace head. |
| */ |
| bool |
| dr_mark_trace_head(void *drcontext, void *tag); |
| |
| DR_API |
| /** |
| * Checks to see if the fragment (or future fragment) with tag \p tag |
| * is marked as a trace head. |
| */ |
| bool |
| dr_trace_head_at(void *drcontext, void *tag); |
| |
| DR_API |
| /** Checks to see that if there is a trace in the code cache at tag \p tag. */ |
| bool |
| dr_trace_exists_at(void *drcontext, void *tag); |
| |
| /************************************************** |
| * OPEN-ADDRESS HASHTABLE |
| */ |
| |
| DR_API |
| /** |
| * Allocates and initializes an open-address library-independent hashtable: |
| * |
| * @param[in] drcontext This context controls whether thread-private or global |
| * heap is used for the table. |
| * @param[in] bits The base-2 log of the initial capacity of the table. |
| * @param[in] load_factor_percent The threshold of the table's occupancy at which |
| * it will be resized (so smaller values keep the table sparser |
| * and generally more performant but at the cost of more memory). |
| * This is a percentage and so must be between 0 and 100. |
| * Values are typically in the 20-80 range and for performance |
| * critical tables would usually be below 50. |
| * @param[in] synch Whether to use a lock around all operations. |
| * @param[in] free_payload_func An optional function to call when removing an entry. |
| * |
| * @return a pointer to the heap-allocated table. |
| */ |
| void * |
| dr_hashtable_create(void *drcontext, uint bits, uint load_factor_percent, bool synch, |
| void (*free_payload_func)(void * /*drcontext*/, void *)); |
| |
| DR_API |
| /** |
| * Destroys a hashtable created by dr_hashtable_create(). |
| * |
| * @param[in] drcontext Must be the same context passed to dr_hashtable_create(). |
| * @param[in] htable A pointer to the table itself, returned by dr_hashtable_create(). |
| */ |
| void |
| dr_hashtable_destroy(void *drcontext, void *htable); |
| |
| DR_API |
| /** |
| * Removes all entries in a hashtable created by dr_hashtable_create(). |
| * |
| * @param[in] drcontext Must be the same context passed to dr_hashtable_create(). |
| * @param[in] htable A pointer to the table itself, returned by dr_hashtable_create(). |
| */ |
| void |
| dr_hashtable_clear(void *drcontext, void *htable); |
| |
| DR_API |
| /** |
| * Queries whether an entry for the given key exists. |
| * |
| * @param[in] drcontext Must be the same context passed to dr_hashtable_create(). |
| * @param[in] htable A pointer to the table itself, returned by dr_hashtable_create(). |
| * @param[in] key The key to query. |
| * |
| * @return the payload value for the key that was passed to dr_hashtable_add(), |
| * or NULL if no such key is found. |
| */ |
| void * |
| dr_hashtable_lookup(void *drcontext, void *htable, ptr_uint_t key); |
| |
| DR_API |
| /** |
| * Adds a new entry to the hashtable. |
| * |
| * @param[in] drcontext Must be the same context passed to dr_hashtable_create(). |
| * @param[in] htable A pointer to the table itself, returned by dr_hashtable_create(). |
| * @param[in] key The key to add. |
| * @param[in] payload The payload to add. |
| */ |
| void |
| dr_hashtable_add(void *drcontext, void *htable, ptr_uint_t key, void *payload); |
| |
| DR_API |
| /** |
| * Removes an entry for the given key. |
| * |
| * @param[in] drcontext Must be the same context passed to dr_hashtable_create(). |
| * @param[in] htable A pointer to the table itself, returned by dr_hashtable_create(). |
| * @param[in] key The key to remove. |
| * |
| * @return whether the key was found. |
| */ |
| bool |
| dr_hashtable_remove(void *drcontext, void *htable, ptr_uint_t key); |
| |
| #endif /* _DR_TOOLS_H_ */ |