| /* ********************************************************** |
| * Copyright (c) 2012-2025 Google, Inc. All rights reserved. |
| * Copyright (c) 2007-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. |
| */ |
| |
| /** |
| **************************************************************************** |
| **************************************************************************** |
| **************************************************************************** |
| \page transparency Client Transparency |
| |
| DynamoRIO must avoid interfering with the semantics of a program while it |
| executes. Shifting execution from the original application code into a |
| cache that occupies the application's own address space provides |
| flexibility but complicates transparency. To achieve transparency, |
| DynamoRIO cannot make any assumptions about a program's stack usage, heap |
| usage, or any of its dependencies on the instruction set architecture or |
| operating system. DynamoRIO's transparency restrictions necessarily apply |
| to a client as well. |
| |
| Contents: |
| - \ref sec_trans_resource |
| - \ref sec_trans_unmod |
| - \ref sec_trans_pretend |
| - \ref sec_trans_alertable |
| |
| We first describe each of the three transparency categories for DynamoRIO |
| and their ramifications for clients using the code cache. |
| |
| *************************************************************************** |
| \section sec_trans_resource Resource Usage Conflicts |
| |
| Ideally, DynamoRIO and its client's resources should be completely disjoint |
| from the application's, to avoid conflicts in the usage of libraries, heap, |
| input/output, and locks. Library conflicts are the most relevant to a |
| client. |
| |
| \par Library Transparency |
| |
| Sharing libraries with the application can cause problems with re-entrancy |
| and corruption of persistent state like error codes. DynamoRIO's dispatch |
| code can execute at arbitrary points in the middle of application code; a |
| client's instrumentation is similarly executed. If both the application |
| and DynamoRIO use the same non-re-entrant library routine, DynamoRIO might |
| call the routine while the application is inside it, causing incorrect |
| behavior. We have learned this lesson the hard way, having run into it |
| several times. The solution is for DynamoRIO's external resources to come |
| only from system calls and never from user libraries. This is |
| straightforward to accomplish on Linux, and most operating systems, where |
| the system call interface is a standard mechanism for requesting services |
| (\e a in the figure below). However, on Windows, the documented method of |
| interacting with the operating system is not via system calls but instead |
| through an application programming interface (the {\em Win32 API}) built |
| with user libraries on top of the system call interface (\e b in the |
| figure). If DynamoRIO uses this interface, re-entrancy and other resource |
| usage conflicts can, and will, occur. To achieve full transparency on |
| Windows, the system call interface (\e c in the figure) must be used, |
| rather than the API layer. |
| |
| \image html windows.png |
| \image latex windows.eps "Native API" width=10cm |
| |
| DynamoRIO provides access to resources to clients via a cross-platform |
| API. We do not recommend that a client invoke its own system calls as |
| this bypasses DynamoRIO's monitoring of changes to the process address |
| space and changes to threads or control flow. |
| |
| DynamoRIO does have its own loader and through it support is provided |
| to clients to use external libraries while isolating them from the |
| libraries used by the application: see \ref sec_extlibs. This support |
| is limited, however, and there are libraries that are not supported |
| today. |
| |
| In addition to Library Transparency, several other types of transparency |
| are of concern to a client: |
| |
| \par Heap Transparency |
| |
| Sharing heap allocation routines with the application violates Library |
| Transparency. Most heap allocation routines are not re-entrant |
| (they are thread-safe, but not re-entrant). Additionally, DynamoRIO |
| should not interfere with the data layout of the application (Data |
| Transparency: see below) or with application memory bugs (Error |
| Transparency: see below). DynamoRIO obtains its memory directly from |
| system calls and parcels it out internally with a custom memory manager. |
| It exports its heap allocation routines through its API to ensure that |
| clients maintain Heap Transparency (see \ref sec_utils). Calls to malloc in |
| external libraries used by clients are also redirected to DynamoRIO's internal |
| heap. |
| |
| \par Input/Output Transparency |
| |
| DynamoRIO uses its own input/output routines to avoid interfering with |
| the application's buffering. As with heap transparency, DynamoRIO |
| exports its input/output routines to clients to ensure that transparency |
| is not violated (see \ref sec_utils). |
| |
| \par Synchronization Transparency |
| |
| DynamoRIO and its clients must avoid acquiring locks that the application |
| also acquires, such as the \p LoaderLock on Windows. Additionally, there |
| are restrictions imposed by DynamoRIO on when its own locks (including |
| client locks) can be acquired, to allow it to safely synchronize with |
| multiple threads: no lock should be held while application code is |
| executing in the code cache. Locks can be used while inside client code |
| reached from clean calls out of the code cache, but they must be released |
| before returning to the cache. Failing to follow these restrictions can |
| lead to deadlocks. |
| |
| *************************************************************************** |
| \section sec_trans_unmod Leaving the Application Unchanged When Possible |
| |
| As many aspects of the application as possible should be left unchanged: |
| |
| \anchor sec_trans_floating_point |
| \par X87 Floating Point State Transparency |
| |
| Because it is expensive to do so and rarely necessary, on x86 DynamoRIO does |
| \e NOT save or restore the x87 floating point state or MMX (64-bit) registers |
| during a context switch away from the application. The larger multimedia |
| registers (XMM, YMM, ZMM, whether holding floating-point or integer values) |
| are preserved, but if at any time a |
| client wishes to use x87 floating point or MMX operations, it |
| must explicitly preserve the state. The dr_insert_clean_call() routine |
| takes a boolean indicating whether x87 floating point state should be preserved |
| across the call; this is the most convenient method for saving the state. |
| |
| The state can alternatively be saved explicitly from C code using: |
| |
| \code |
| proc_save_fpstate(byte *buf) |
| proc_restore_fpstate(byte *buf) |
| \endcode |
| |
| Saving can be done from inlined code in the code cache using: |
| |
| \code dr_insert_save_fpstate(), dr_insert_restore_fpstate() \endcode |
| |
| These routines require a buffer that is 16-byte-aligned and of a certain |
| size (512 bytes for processors with the FXSR feature, and 108 bytes for |
| those without). Here is a sample usage: |
| |
| \code |
| byte fp_raw[512 + 16]; |
| byte *fp_align = (byte *) ( (((ptr_uint_t)fp_raw) + 16) & ((ptr_uint_t)-16) ); |
| proc_save_fpstate(fp_align); |
| \endcode |
| |
| Note that floating point operations include almost any operation that |
| acts on a float, even printing one with %%f, on older compilers. Modern compilers |
| typically do not use x87 operations. |
| |
| The XMM (128-bit) and larger registers are saved by DynamoRIO on context switches and |
| clean calls. See also the dr_mcontext_xmm_fields_valid() routine. |
| |
| On ARM/AArch64, DynamoRIO saves and restores all the registers, |
| including the SIMD/FP registers, during a context switch away from the |
| application. The functions proc_save_fpstate and proc_restore_fpstate |
| are provided, but do nothing. |
| |
| \anchor sec_trans_thread |
| \par Thread Transparency |
| |
| For full transparency, if DynamoRIO or a client creates extra threads |
| they should be hidden from any introspection performed by the |
| application. |
| |
| \par Executable Transparency |
| |
| The program binary and shared library files on disk should not be |
| modified. |
| |
| \par Data Transparency |
| |
| DynamoRIO leaves application data unmodified, including heap layout. |
| |
| \par Stack Transparency |
| |
| The application stack must look exactly like it does natively. It is |
| tempting to use the application stack for scratch space, but we have seen |
| applications like Microsoft Office access data beyond the top of the stack |
| (i.e., the application stores data on the top of the stack, moves the stack |
| pointer to the previous location, and then accesses the data). Using the |
| application stack for scratch space would clobber such data. Additionally, |
| hand-crafted code might use the stack pointer as a general-purpose |
| register. Other and better options for temporary space are available. |
| DynamoRIO provides thread-local storage through its API. |
| |
| DynamoRIO provides a separate stack to use for itself and for the client, |
| and never assumes even that the application stack is valid. Many |
| applications examine their stack and may not work properly if something |
| is slightly different than expected. |
| |
| *************************************************************************** |
| \section sec_trans_pretend Pretending The Application Is Unchanged When It Is Not |
| |
| For changes that are necessary (such as executing out of a code cache), |
| DynamoRIO must warp events like interrupts, signals, and exceptions such |
| that they appear to have occurred natively. |
| |
| \par Cache Consistency |
| |
| DynamoRIO must keep its cached copies of the application code consistent |
| with the actual copy in memory. If the application unloads a shared |
| library and loads a new one in its place, or modifies its own code, |
| DynamoRIO must change its code cache to reflect those changes to avoid |
| incorrectly executing stale code. If the client needs to modify |
| application code, it should do so through the basic block event, rather |
| than directly. |
| \if future |
| XXX: if we provide routine to modify app memory should |
| talk about it here. |
| \endif |
| |
| \par Address Space Transparency |
| |
| DynamoRIO must pretend that it is not perturbing the application's |
| address space. An application bug that writes to invalid memory and |
| generates an exception should do the same thing under DynamoRIO, even if |
| we have allocated memory at that location that would natively have been |
| invalid. This requires protecting all DynamoRIO memory from inadvertent |
| (or malicious) writes by the application. Furthermore, DynamoRIO |
| hides itself from introspection by manipulating memory queries. |
| |
| \par Application Address Transparency |
| |
| Although the application's code is moved into a cache, every address |
| manipulated by the application must remain an original application |
| address. DynamoRIO must translate indirect branch targets from |
| application addresses to code cache addresses, and conversely if a code |
| cache address is ever exposed to the application, DynamoRIO must |
| translate it back to its original application address. The latter occurs |
| when the operating system hands a machine context to a signal or |
| exception handler. In that case both the faulting or interrupted address |
| and the complete register state must be made to look like the signal or |
| exception occurred natively, rather than inside the code cache where it |
| actually occurred. |
| |
| To save space, DynamoRIO does not store any mappings from code cache |
| state to application state. Since our cache consistency guarantees that |
| the original application code cannot have changed since we built a |
| fragment, we re-create the fragment from the original code, applying all |
| the same transformations we applied when we first copied it into our code |
| cache. We then walk through the reproduction and the code cache version |
| in lockstep until we reach the target instruction. In order to |
| accomplish this algorithm in code that has been modified or re-arranged |
| by a client, DynamoRIO needs client support. We have not yet implemented |
| this support. \if future XXX: say anything else? \endif |
| |
| \par Error Transparency |
| |
| Application errors under DynamoRIO must occur as they would natively. We |
| accomplish this by maintaining Heap Transparency, Data Transparency, |
| Stack Transparency, and Address Space Transparency, We have seen many |
| cases of applications that access invalid memory natively, handle the |
| exception, and carry on. Without Error Transparency such applications |
| would not work properly under DynamoRIO. |
| |
| \par Timing Transparency |
| |
| We would like to make it impossible for the application to determine |
| whether it is executing inside of DynamoRIO. However, this may not be |
| attainable for some aspects of execution, such as the exact timing of |
| certain operations. This brings efficiency into the transparency |
| equation. |
| |
| Changing the timing of multi-threaded applications can uncover behavior |
| that does not normally happen natively. We have encountered race |
| conditions while executing under DynamoRIO that are difficult to |
| reproduce outside of our system. These are not strictly speaking |
| transparency violations, as the errors \e could have occurred without |
| us, but are best avoided. |
| |
| \par Debugging Transparency |
| |
| A debugger should be able to attach to a process under DynamoRIO's |
| control just like it would natively. Previously discussed transparency |
| issues overlap with Debugging Transparency. Stack Transparency and Data |
| Transparency ensure that callstacks and application memory show up |
| correctly. However, DynamoRIO can't entirely hide the fact that the |
| application is running out of a code cache from the debugger. The |
| debugger will see the wrong eip value when breaking in and execution |
| break points will not work correctly (and in fact can lead to |
| corruption of the DynamoRIO code cache). Debugging Tools for Windows and |
| \p gdb are known to work with DynamoRIO with the exception of the |
| issues noted above. |
| |
| *************************************************************************** |
| \section sec_trans_alertable Alertable System Calls |
| |
| On Windows, DynamoRIO does not support a client making alertable system |
| calls. See \ref sec_alertable for more information. |
| |
| *************************************************************************** |
| **************************************************************************** |
| **************************************************************************** |
| */ |