--- title: "/include/dr_os_utils.h File Reference" layout: default permalink: /dr__os__utils_8h.html ---
DynamoRIO
|
Operating-system-specific querying routines. More...
Data Structures | |
struct | _dr_app_arg_t |
struct | _dr_os_version_info_t |
struct | _dr_mem_info_t |
Macros | |
#define | DR_MEMPROT_NONE 0x00 |
#define | DR_MEMPROT_READ 0x01 |
#define | DR_MEMPROT_WRITE 0x02 |
#define | DR_MEMPROT_EXEC 0x04 |
#define | DR_MEMPROT_GUARD 0x08 |
#define | DR_MEMPROT_PRETEND_WRITE 0x10 |
#define | DR_MEMPROT_VDSO 0x20 |
#define | PAGE_SIZE dr_page_size() |
#define | PAGE_START(x) (((ptr_uint_t)(x)) & ~(dr_page_size() - 1)) |
#define | DR_TRY_EXCEPT(drcontext, try_statement, except_statement) |
Typedefs | |
typedef struct _dr_app_arg_t | dr_app_arg_t |
typedef struct _dr_os_version_info_t | dr_os_version_info_t |
typedef void * | dr_auxlib_handle_t |
typedef void(* | dr_auxlib_routine_ptr_t) () |
typedef struct _dr_mem_info_t | dr_mem_info_t |
Functions | |
DR_API bool | dr_using_app_state (void *drcontext) |
DR_API void | dr_switch_to_app_state (void *drcontext) |
DR_API void | dr_switch_to_app_state_ex (void *drcontext, dr_state_flags_t flags) |
DR_API void | dr_switch_to_dr_state (void *drcontext) |
DR_API void | dr_switch_to_dr_state_ex (void *drcontext, dr_state_flags_t flags) |
DR_API int | dr_get_app_args (OUT dr_app_arg_t *args_array, int args_count) |
DR_API int | dr_num_app_args (void) |
const DR_API char * | dr_app_arg_as_cstring (IN dr_app_arg_t *app_arg, char *buf, int buf_size) |
const DR_API char * | dr_get_application_name (void) |
DR_API process_id_t | dr_get_process_id (void) |
DR_API process_id_t | dr_get_process_id_from_drcontext (void *drcontext) |
DR_API process_id_t | dr_get_parent_id (void) |
DR_API bool | dr_get_os_version (dr_os_version_info_t *info) |
DR_API bool | dr_is_wow64 (void) |
DR_API void * | dr_get_app_PEB (void) |
DR_API process_id_t | dr_convert_handle_to_pid (HANDLE process_handle) |
DR_API HANDLE | dr_convert_pid_to_handle (process_id_t pid) |
DR_API dr_auxlib_handle_t | dr_load_aux_library (const char *name, byte **lib_start, byte **lib_end) |
DR_API dr_auxlib_routine_ptr_t | dr_lookup_aux_library_routine (dr_auxlib_handle_t lib, const char *name) |
DR_API bool | dr_unload_aux_library (dr_auxlib_handle_t lib) |
DR_API size_t | dr_page_size (void) |
DR_API bool | dr_memory_is_readable (const byte *pc, size_t size) |
DR_API bool | dr_query_memory (const byte *pc, byte **base_pc, size_t *size, uint *prot) |
DR_API bool | dr_query_memory_ex (const byte *pc, OUT dr_mem_info_t *info) |
DR_API size_t | dr_virtual_query (const byte *pc, MEMORY_BASIC_INFORMATION *mbi, size_t mbi_size) |
DR_API bool | dr_safe_read (const void *base, size_t size, void *out_buf, size_t *bytes_read) |
DR_API bool | dr_safe_write (void *base, size_t size, const void *in_buf, size_t *bytes_written) |
DR_API void | dr_try_setup (void *drcontext, void **try_cxt) |
DR_API int | dr_try_start (void *buf) |
DR_API void | dr_try_stop (void *drcontext, void *try_cxt) |
DR_API bool | dr_memory_protect (void *base, size_t size, uint new_prot) |
DR_API bool | dr_memory_is_dr_internal (const byte *pc) |
DR_API bool | dr_memory_is_in_client (const byte *pc) |
Operating-system-specific querying routines.
#define DR_MEMPROT_EXEC 0x04 |
Execute privileges.
#define DR_MEMPROT_GUARD 0x08 |
Guard page (Windows only)
#define DR_MEMPROT_NONE 0x00 |
No read, write, or execute privileges.
#define DR_MEMPROT_PRETEND_WRITE 0x10 |
DR's default cache consistency strategy modifies the page protection of pages containing code, making them read-only. It pretends on application and client queries that the page is writable. On a write fault to such a region by the application or by client-added instrumentation, DR automatically handles the fault and makes the page writable. This requires flushing the code from the code cache, which can only be done safely when in an application context. Thus, a client writing to such a page is only supported when these criteria are met:
A client write fault that does not meet the first two criteria will result in a fatal error report and an abort. It is up to the client to ensure it satisifies the third criterion.
Even when client writes do meet these criteria, for performance it's best for clients to avoid writing to such memory.
#define DR_MEMPROT_READ 0x01 |
Read privileges.
#define DR_MEMPROT_VDSO 0x20 |
In addition to the appropriate DR_MEMPROT_READ and/or DR_MEMPROT_EXEC flags, this flag will be set for the VDSO and VVAR pages on Linux. The VVAR pages may only be identified by DR on kernels that explicitly label the pages in the /proc/self/maps file (kernel 3.15 and above). In some cases, accessing the VVAR pages can cause problems (e.g., https://github.com/DynamoRIO/drmemory/issues/1778).
#define DR_MEMPROT_WRITE 0x02 |
Write privileges.
#define DR_TRY_EXCEPT | ( | drcontext, | |
try_statement, | |||
except_statement | |||
) |
Simple try..except support for executing operations that might fault and recovering if they do. Be careful with this feature as it has some limitations:
For fault-free reads in isolation, use dr_safe_read() instead. dr_safe_read() out-performs DR_TRY_EXCEPT.
For fault-free writes in isolation, dr_safe_write() can be used, although on Windows it invokes a system call and can be less performant than DR_TRY_EXCEPT.
#define PAGE_SIZE dr_page_size() |
Size of a page of memory. This uses a function call so be careful where performance is critical.
#define PAGE_START | ( | x | ) | (((ptr_uint_t)(x)) & ~(dr_page_size() - 1)) |
Convenience macro to align to the start of a page of memory. It uses a function call so be careful where performance is critical.
typedef struct _dr_app_arg_t dr_app_arg_t |
Contains information regarding an application's command-line argument.
typedef void* dr_auxlib_handle_t |
A handle to a loaded client auxiliary library. This is a different type than module_handle_t and is not necessarily the base address.
typedef void(* dr_auxlib_routine_ptr_t) () |
An exported routine in a loaded client auxiliary library.
typedef struct _dr_mem_info_t dr_mem_info_t |
Describes a memory region. Used by dr_query_memory_ex().
typedef struct _dr_os_version_info_t dr_os_version_info_t |
Data structure used with dr_get_os_version()
enum dr_mem_type_t |
Flags describing memory used by dr_query_memory_ex().
enum dr_os_version_t |
Windows versions
enum dr_state_flags_t |
Flags that control the behavior of dr_switch_to_app_state_ex() and dr_switch_to_dr_state_ex().
Enumerator | |
---|---|
DR_STATE_PEB | Switch the PEB pointer. |
DR_STATE_TEB_MISC | Switch miscellaneous TEB fields. |
DR_STATE_STACK_BOUNDS | Switch the TEB stack bounds fields. |
DR_STATE_ALL | Switch all state. |
const DR_API char* dr_app_arg_as_cstring | ( | IN dr_app_arg_t * | app_arg, |
char * | buf, | ||
int | buf_size | ||
) |
Returns the passed argument app_arg
as a string. buf
is used only if needed, and therefore the caller should not assume that the string is in the buf
. In other words, always use the returned value to refer to the string. Returns NULL on error such as when buf
is needed as storage and the size of the buffer buf_size
is not sufficient.
To obtain a suitable upper-bound size of the string buffer, get the size of the argument from the dr_app_arg_t value retrieved via dr_get_app_args().
DR_API process_id_t dr_convert_handle_to_pid | ( | HANDLE | process_handle | ) |
Converts a process handle to a process id.
DR_API HANDLE dr_convert_pid_to_handle | ( | process_id_t | pid | ) |
Converts a process id to a process handle.
DR_API int dr_get_app_args | ( | OUT dr_app_arg_t * | args_array, |
int | args_count | ||
) |
Provides information about the app's arguments by setting args_array
up to the count denoted by args_count
. Therefore, args_count
is not the size of the buffer in bytes but the number of dr_app_arg_t values that args_array
can store. Returns the number of args set or -1 on error.
Use dr_app_arg_as_cstring() to get the argument as a string.
Use dr_num_app_args() to query the total number of command-line arguments passed to the application.
DR_API void* dr_get_app_PEB | ( | void | ) |
Returns a pointer to the application's Process Environment Block (PEB). DR swaps to a private PEB when running client code, in order to isolate the client and its dependent libraries from the application, so conventional methods of reading the PEB will obtain the private PEB instead of the application PEB.
const DR_API char* dr_get_application_name | ( | void | ) |
Returns the image name (without path) of the current application.
DR_API bool dr_get_os_version | ( | dr_os_version_info_t * | info | ) |
Returns information about the version of the operating system. Returns whether successful.
DR_API process_id_t dr_get_parent_id | ( | void | ) |
Returns the process id of the parent of the current process.
DR_API process_id_t dr_get_process_id | ( | void | ) |
Returns the process id of the current process.
DR_API process_id_t dr_get_process_id_from_drcontext | ( | void * | drcontext | ) |
Returns the process id of the process associated with drcontext drcontext
. The returned value may be different from dr_get_process_id() if the passed context was created in a different process, which may happen in thread exit callbacks.
DR_API bool dr_is_wow64 | ( | void | ) |
Returns true if this process is a 32-bit process operating on a 64-bit Windows kernel, known as Windows-On-Windows-64, or WOW64. Returns false otherwise.
DR_API dr_auxlib_handle_t dr_load_aux_library | ( | const char * | name, |
byte ** | lib_start, | ||
byte ** | lib_end | ||
) |
Loads the library with the given path as an auxiliary client library. The library is not treated as an application module but as an extension of DR. The library will be included in dr_memory_is_in_client() and any faults in the library will be considered client faults. The bounds of the loaded library are returned in the optional out variables. On failure, returns NULL.
If only a filename and not a full path is given, this routine will search for the library in the standard search locations for DR's private loader.
DR_API dr_auxlib_routine_ptr_t dr_lookup_aux_library_routine | ( | dr_auxlib_handle_t | lib, |
const char * | name | ||
) |
Looks up the exported routine with the given name in the given client auxiliary library loaded by dr_load_aux_library(). Returns NULL on failure.
DR_API bool dr_memory_is_dr_internal | ( | const byte * | pc | ) |
Returns true iff pc is memory allocated by DR for its own purposes, and would not exist if the application were run natively.
DR_API bool dr_memory_is_in_client | ( | const byte * | pc | ) |
Returns true iff pc is located inside a client library, an Extension library used by a client, or an auxiliary client library (see dr_load_aux_library()).
DR_API bool dr_memory_is_readable | ( | const byte * | pc, |
size_t | size | ||
) |
Checks to see that all bytes with addresses in the range [pc
, pc
+ size
- 1] are readable and that reading from that range won't generate an exception (see also dr_safe_read() and DR_TRY_EXCEPT()).
DR_API bool dr_memory_protect | ( | void * | base, |
size_t | size, | ||
uint | new_prot | ||
) |
Modifies the memory protections of the region from start
through start
+ size
. Modification of memory allocated by DR or of the DR or client libraries themselves is allowed under the assumption that the client knows what it is doing. Modification of the ntdll.dll library on Windows is not allowed. Returns true if successful.
DR_API int dr_num_app_args | ( | void | ) |
Returns the number of command-line arguments passed to the application.
DR_API size_t dr_page_size | ( | void | ) |
Returns the size of a page of memory.
DR_API bool dr_query_memory | ( | const byte * | pc, |
byte ** | base_pc, | ||
size_t * | size, | ||
uint * | prot | ||
) |
An os neutral method for querying a memory address. Returns true iff a memory region containing pc
is found. If found additional information about the memory region is returned in the optional out arguments base_pc
, size
, and prot
where base_pc
is the start address of the memory region continaing pc
, size
is the size of said memory region and prot
is an ORed combination of DR_MEMPROT_* flags describing its current protection.
prot
. DR_API bool dr_query_memory_ex | ( | const byte * | pc, |
OUT dr_mem_info_t * | info | ||
) |
Provides additional information beyond dr_query_memory(). Returns true if it was able to obtain information (including about free regions) and sets the fields of info
. This routine can be used to iterate over the entire address space. Such an iteration should stop on reaching the top of the address space, or on reaching kernel memory (look for DR_MEMTYPE_ERROR_WINKERNEL) on Windows.
Returns false on failure and sets info->type to a DR_MEMTYPE_ERROR* code indicating the reason for failure.
info->prot
. DR_API bool dr_safe_read | ( | const void * | base, |
size_t | size, | ||
void * | out_buf, | ||
size_t * | bytes_read | ||
) |
Safely reads size
bytes from address base
into buffer out_buf
. Reading is done without the possibility of an exception occurring. Returns true if the entire size
bytes were read; otherwise returns false and if bytes_read
is non-NULL returns the partial number of bytes read in bytes_read
.
DR_API bool dr_safe_write | ( | void * | base, |
size_t | size, | ||
const void * | in_buf, | ||
size_t * | bytes_written | ||
) |
Safely writes size
bytes from buffer in_buf
to address base
. Writing is done without the possibility of an exception occurring. Returns true if the entire size
bytes were written; otherwise returns false and if bytes_written
is non-NULL returns the partial number of bytes written in bytes_written
.
DR_API void dr_switch_to_app_state | ( | void * | drcontext | ) |
Equivalent to dr_switch_to_app_state_ex(drcontext, DR_STATE_ALL).
DR_API void dr_switch_to_app_state_ex | ( | void * | drcontext, |
dr_state_flags_t | flags | ||
) |
Swaps to the application version of any system state for the given thread. This is meant to be used prior to examining application memory, when private libraries are in use and there are two versions of system state. Invoking non-DR library routines while the application state is in place can lead to unpredictable results: call dr_switch_to_dr_state() (or the _ex version) before doing so.
This function does not affect whether the current machine context (registers) contains application state or not.
The flags
argument allows selecting a subset of the state to swap.
DR_API void dr_switch_to_dr_state | ( | void * | drcontext | ) |
Equivalent to dr_switch_to_dr_state_ex(drcontext, DR_STATE_ALL).
DR_API void dr_switch_to_dr_state_ex | ( | void * | drcontext, |
dr_state_flags_t | flags | ||
) |
Should only be called after calling dr_switch_to_app_state() (or the _ex version), or in certain cases where a client is running its own code in an application state. Swaps from the application version of system state for the given thread back to the DR and client version.
This function does not affect whether the current machine context (registers) contains application state or not.
A client must call dr_switch_to_dr_state() in order to safely call private library routines if it is running in an application context where dr_using_app_state() returns true. On Windows, this is the case for any application context, as the system state is always swapped. On Linux, however, execution of application code in the code cache only swaps the machine context and not the system state. Thus, on Linux, while in the code cache, dr_using_app_state() will return false, and it is safe to invoke private library routines without calling dr_switch_to_dr_state(). Only if client or client-invoked code will examine a segment selector or descriptor does the state need to be swapped. A state swap is much more expensive on Linux (it requires a system call) than on Windows.
The same flags that were passed to dr_switch_to_app_state_ex() should be passed here.
DR_API void dr_try_setup | ( | void * | drcontext, |
void ** | try_cxt | ||
) |
Do not call this directly: use the DR_TRY_EXCEPT macro instead.
DR_API int dr_try_start | ( | void * | buf | ) |
Do not call this directly: use the DR_TRY_EXCEPT macro instead.
DR_API void dr_try_stop | ( | void * | drcontext, |
void * | try_cxt | ||
) |
Do not call this directly: use the DR_TRY_EXCEPT macro instead.
DR_API bool dr_unload_aux_library | ( | dr_auxlib_handle_t | lib | ) |
Unloads the given library, which must have been loaded by dr_load_aux_library(). Returns whether successful.
DR_API bool dr_using_app_state | ( | void * | drcontext | ) |
Returns whether the given thread indicated by drcontext
is currently using the application version of its system state.
This function does not indicate whether the machine context (registers) contains application state or not.
On Linux, DR very rarely switches the system state, while on Windows DR switches the system state to the DR and client version on every event callback or clean call.
DR_API size_t dr_virtual_query | ( | const byte * | pc, |
MEMORY_BASIC_INFORMATION * | mbi, | ||
size_t | mbi_size | ||
) |
Equivalent to the win32 API function VirtualQuery(). See that routine for a description of arguments and return values.