--- title: "How to Run" layout: default permalink: /page_deploy.html ---
DynamoRIO
|
Once the DynamoRIO distribution contents are unpacked (see Distribution Contents), configuration and execution of applications under DynamoRIO is handled by a set of libraries and tools. On Windows, the tools are drconfig.exe
, drrun.exe
, and drinject.exe
. The corresponding libraries (whose APIs are exposed by the tools) are drconfiglib.dll
and drinjectlib.dll
with header files dr_config.h
and dr_inject.h
. On Linux, the tools are named drconfig
, drrun
, and drinject
, and the libraries are libdrconfiglib.a
and libdrinjectlib.a
.
When using DynamoRIO as a third-party disassembly library (see Disassembly Library), no deployment is needed, as DynamoRIO does not control a target application when used as a regular library.
There are two methods for running a process under DynamoRIO: the one-time configure-and-run, and the two-step separate configuration and execution. The drrun.exe
tool supports the first, simpler model, while the drconfig.exe
and drinject.exe
tools support the second, more powerful model. The drconfig.exe
tool, or the corresponding the drconfiglib.dll
library, can also be used to nudge running processes.
Configuration information is stored in files in the current user's profile directory, which is obtained from the environment variable USERPROFILE
. Thus, configurations are persistent across reboots and are private to each user. If the DYNAMORIO_CONFIGDIR
environment variable is set, its value is used instead of USERPROFILE
. If neither is set, a temp directory will be used when creating new configuration files for configure-and-run execution.
DynamoRIO also supports global configurations, which are stored in the "config" subdirectory of the directory specified by the DYNAMORIO_HOME
registry value in the registry key \HKLM\SOFTWARE\DynamoRIO\DynamoRIO
(or for 32-bit on 64-bit Windows (WOW64) \HKLM\SOFTWARE\Wow6432Node\DynamoRIO\DynamoRIO
). Setting that DYNAMORIO_HOME
value and creating the directory it points to must be done manually. The provided tools support reading and writing both local and global configuration files, and automatically creating the local directory. DynamoRIO gives local files precedence when both exist. Note that applications that do not have a USEPROFILE
environment variable can be controlled using DYNAMORIO_CONFIGDIR
or global configurations. Also note that by default USERPROFILE
is not set over cygwin ssh and must be explicitly set in the shell startup files.
Configurations are per-process, with the basename of the process used for identification (e.g., notepad.exe
). One-time configuration also uses the process id to specify that the configuration is for that process instance only.
As an example, assume you have unpacked the DynamoRIO distribution and your current directory is its base directory. Run notepad.exe
with the bbsize sample client using the following configure-and-run command:
Alternatively, you can first run notepad.exe
, and then use drrun
to attach to it, but please note that attaching is an experimental feature and is not yet as well-supported as launching a new process:
Then, you can also detach DynamoRIO from the process of notepad.exe
without affecting the normal execution of notepad.exe
.
To use system-wide injection, allowing for an application to be run under DynamoRIO regardless of how it is invoked, configure the application first (-syswide_on requires administrative privileges):
The next time notepad.exe
is started by the current user, it will run under DynamoRIO with the bbsize client.
To unregister notepad.exe
, issue the following command:
Invoke any of the drconfig.exe
, drrun.exe
, or drinject.exe
tools with no arguments to see the full list of options available.
By default, DynamoRIO follows into all child processes, with the parent's settings inherited by the child if there is no configuration set up ahead of time for the child application. To instead only follow children that are configured (via drconfig.exe
), use the -no_follow_children runtime option.
To ensure a client is loaded into a child process of a different bitwidth (i.e., a 32-bit child created by a 64-bit parent), use the -c32
and -c64
options to drconfig
or drrun
, with --
ending the first client's options:
bin32/drrun.exe -c32 samples/bin32/bbsize.dll – -c64 samples/bin64/bbsize.dll – notepad
The order matters: -c32
must come first.
To nudge all instances of notepad.exe
running under DynamoRIO with argument "5", use:
This will result in a nudge event with argument=5 delivered to the client callback registered with dr_register_nudge_event() in all notepad.exe
processes running under DynamoRIO. The third argument, 0, is an ID supplied at registration which uniquely identifies the target client (see dr_deploy.h for details).
To view 32-bit or WOW64 processes running under DynamoRIO the drview.exe
tool can be used. The bin64 version will display both 32-bit and 64-bit processes and will indicate which are 32-bit. The bin32 version will display 64-bit processes but is unable to determine whether DynamoRIO is present.
DynamoRIO uses the \HKLM\SOFTWARE\Microsoft\Windows\Windows NT\CurrentVersion\AppInit_DLLs
key (for 32-bit on 64-bit Windows (WOW64), \HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs
) for -syswide_on to inject into new processes without having to directly launch them drrun.exe
or drinject.exe
. For injection to work, the registered process must statically link to user32.dll (only a few small non-graphical windows applications don't link user32.dll). If a target application does not link to user32.dll, DynamoRIO can still inject if the process is launched with drinject.exe
or if the parent process (usually cmd.exe or explorer.exe for user launched processes) is running under DynamoRIO. The drinject.exe tool uses the configuration information set by drconfig.exe
for the target application.
drconfig.exe
and drrun.exe
in these scenarios, be sure that the cmd shell being used was started with elevated permissions.An alternative method to run an application under DynamoRIO is the app_start()/app_stop() interface, which requires modifying application source code.
Once DynamoRIO has been unpacked, the same set of helper binaries as on Windows provide flexibility in configuring and executing applications.
There are two methods for invoking an application under DynamoRIO:
drrun
drconfig
and launch via drinject
As an example of the simpler method, the following command runs ls
under DynamoRIO with the bbsize sample client:
Alternatively, you can first run the target, and then use drrun
to attach to it, but please note that attaching is an experimental feature and is not yet as well-supported as launching a new process. In particular, if the application is in the middle of a blocking syscall, DynamoRIO will wait for that to finish. To instead force interruption of the syscall, additionally pass -skip_syscall.
This attach feature requires ptrace capabilities, which can be enabled with this command:
Run drrun
with no options to get a list of the options and environment variable shortcuts it supports. To disable following across child execve calls, use the -no_follow_children runtime option.
Use the tools in bin32/
for 32-bit applications and the tools in bin64/
for 64-bit applications.
The two-step method allows for greater control over child processes. The drconfig
tool writes a configuration file for a given application name. DynamoRIO reads its options from the configuration file at runtime. Once each process name is configured, the drinject
tool can be used to invoke the parent process. The drrun
tool can also be used but it creates a temporary configuration file that will override settings requested via drconfig
. The configuration file for each application is stored in $DYNAMORIO_CONFIGDIR/.dynamorio/<appname>.config32
(or a config64
suffix for 64-bit). If DYNAMORIO_CONFIGDIR
is not set, $HOME/.dynamorio/<appname>.config32
is used; if neither is set, a temp directory will be used when creating new configuration files for configure-and-run execution. On Android, if neither /data/local/tmp
nor the current working directory are writable, you will need to specify a writable directory by setting the DYNAMORIO_CONFIGDIR
environment variable.
DynamoRIO also supports global configuration files in /etc/dynamorio/<appname>.config32
when a local configuration file is not found. drconfig
does not support directly writing a global config file but such files can be copied from or modeled on local files.
If a target application executes an execve
that discards the HOME
environment variable, the resulting process will still run under DynamoRIO control with the same settings as the parent process. Use DYNAMORIO_CONFIGDIR
or global configuration files to specify separate options for such a child process.
When running scripts it is best to explicitly invoke the interpreter rather than invoking the script directly:
To nudge a process with pid targetpid
running under DynamoRIO and pass argument "5" to the nudge callback, use the drnudgeunix
tool:
This will result in a nudge event with argument=5 delivered to the client callback registered with dr_register_nudge_event() in the target process. The 0 argument is an ID supplied at registration which uniquely identifies the target client (see dr_deploy.h for details). If you used the -c argument to drrun or drconfig to register the client, the client's id defaults to 0.
An alternative method to run an application under DynamoRIO is the app_start()/app_stop() interface, which requires modifying application source code.
Android deployment is generally the same as Linux Deployment except for the following differences.
For pure native applications, the default configuration file location (if DYNAMORIO_CONFIGDIR
is not explicitly set) is usually (depending on whether $HOME
happens to be writable) /data/local/tmp
.
For Android applications on recent versions of Android, SELinux prevents writing to /data/local/tmp
. The application's data directory should be pointed at in the TMPDIR
or DYNAMORIO_CONFIGDIR
environment variables, as shown below in the example wrapper script. We recommend using TMPDIR
as its value will also be used by tools such as Dr. Memory for their log files.
To launch an Android application under DynamoRIO, use a wrapper script and point at the script via the logwrapper
property set on your application's name prefixed by
. For example, if your application's name is wrap
.com.myco.appname
, set the property for wrap.com.myco.appname
, truncating to 31 characters:
The wrapper shell script should contain the command line prefix you wish to use to launch your application under DynamoRIO:
Be sure to place the DynamoRIO binaries and the wrapper script in an executable location, such as /system/xbin
. Alternatively, disable SELinux via setenforce 0
.
If you run into problems with configuration files being created due to SELinux denials (look in the logs for such denials), it may be simplest to disable SELinux via setenforce 0
. We have attempted to get everything to work without this step, but we are not able to test on all versions or configurations of Android.
To run DynamoRIO under QEMU, use the -xarch_root option to point at the base directory of the guest system libraries. This is the same path passed to QEMU's -L
option:
Be sure to install both the qemu-user
and qemu-user-binfmt
packages in order for QEMU to impose itself across an execve:
If using a custom build of QEMU, be sure to update the binfmt rule to ensure the proper build is used across execve: QEMU does not ensure that the same build is preserved and instead relies on the global binfmt rule. On an Ubuntu system, edit /usr/share/binfmts/qemu-arm
and replace the interpreter
path. Then run:
Confirm the change took effect:
On Fedora, edit /usr/lib/binfmt.d/qemu-arm-dynamic.conf
and then run:
All of the earlier examples did not need to pass any arguments to the client. When using the -c argument to set the client, all arguments between the client path and the double dash are passed to the client. When using the -client argument to drrun, the third argument following -client is passed through to the client. For example, all these invocations of drrun pass '-op1 -op2 "value with spaces"' to the client:
On Linux:
When using a two-step model, the options are passed to drconfig:
The client's options are passed directly to its dr_client_main()
initialization routine, in the same manner as arguments are passed to a regular application's main()
routine. To match standalone application conventions, argv
[0] is set to the client library path, with the actual parameters starting at index 1. The client can also optionally call dr_get_option_array() to retrieve the options passed to it. C++ clients can use the convenience of the DynamoRIO Option Parser.
Client options are not allowed to contain semicolons. Additionally, the client option string combined with the path to the client library cannot contain all three quote characters (', ", `) simultaneously. To ensure a client is loaded into a child process of a different bitwidth (i.e., a 32-bit child created by a 64-bit parent), use the \c -c32 and \c -c64 options to \c drconfig or \c drrun, with \c -- ending the first client's options: bin32/drrun -c32 samples/bin32/bbsize.dll – -c64 samples/bin64/bbsize.dll – notepad The order matters: \c -c32 must come first. @section multi_client Multiple Clients DynamoRIO does support multiple clients. It is each client's responsibility, however, to ensure compatibility with other clients. DynamoRIO makes no attempt to force cooperation among clients. For example, instruction stream modifcations made by one client are visible to other clients. Systems employing multiple clients must be aware of such interactions and design accordingly. Client registration requires users to specify the \em priority of each client. DynamoRIO calls each client's dr_client_main() routine sequentially according to this priority. Clients with a numerically lower priority value are called first and therefore given the first opportunity to register callbacks (the client with priority 0 is called first). Since DynamoRIO delivers event callbacks sequentially, client priority and the order of event registration is important. For a given event, the \em first registered callback is called \em last. This scheme gives precedence to the first registered callback since that callback is given the final opportunity to modify the instruction stream or influence DynamoRIO's operation. @section tool_frontend End-User Tools A client can be packaged up with DynamoRIO to create an end-user tool. For many tools, a separate front-end executable is not necessary, and \p drrun is sufficient. Using \p drrun for a tool is made simpler by the \p -t option. To use the option, first create a file in the \p tools subdirectory of the root of the DynamoRIO installation called \p toolname.drrun32 or \p toolname.drrun64, depending on the target architecture. Here, \p toolname is the desired external name of the tool. This file should contain one of the following lines, or two if they are a pair of CLIENT32_* and CLIENT64_* specifiers: @code CLIENT_ABS=/absolute/path/to/client CLIENT32_ABS=/absolute/path/to/32-bit-client CLIENT64_ABS=/absolute/path/to/64-bit-client \endcode or @code CLIENT_REL=relative/path/to/client/from/DynamoRIO/root CLIENT32_REL=relative/path/to/32-bit-client/from/DynamoRIO/root CLIENT64_REL=relative/path/to/64-bit-client/from/DynamoRIO/root \endcode This enables \p drrun to locate the tool's client library. The 32 and 64 specifiers allow pointing at alternate-bitwidth paths for use if the target application creates a child process of a different bitwidth. The file can also modify the default DynamoRIO runtime options (see \ref sec_options) via \p DR_OP= lines. Each line contains only one option string token. For example: @code DR_OP=-persist DR_OP=-persist_dir DR_OP=c:\\path with spaces\\subdir \endcode Tool options can also be specified, but normally the defaults should be set up appropriately in the client itself: @code TOOL_OP=-custom_op1 TOOL_OP=-custom_op2 \endcode Lines beginning with \p # are considered comments. When \p drrun is passed the option string <tt>-t toolname</tt>, it looks for <tt>tools/toolname.drrun64</tt> or <tt>tools/toolname.drrun32</tt> and reads the file to determine the client library to use and the default DynamoRIO options. This makes for a simpler launching command, rather than the end user needing to name the exact location of the client library. For example, this command: @code bin64/drrun -t mytool -tool_option1 -tool_option2 -- myapp \endcode can be made to expand to this equivalent command: @code bin64/drrun -mytool_dr_option1 -mytool_dr_option2 -c tools/mytool/libmytool.so -tool_option1 -tool_option2 -- myapp \endcode For more extensive actions on launching the tool, a custom front-end executable can be created that replaces \p drrun by using \p drinjectlib, \p drconfiglib, and \p drfrontendlib. These three libraries facilitate creating cross-platform tools for configuring and launching applications under DynamoRIO. For more information about the interfaces they provide, see their header files: dr_inject.h, dr_config.h, dr_frontend.h. A custom front-end executable can be invoked via a \p drrun \p -t configuration file using one of the following lines: @code FRONTEND_ABS=/absolute/path/to/front-end \endcode or @code FRONTEND_REL=relative/path/to/front-end/from/DynamoRIO/root \endcode This will cause \p drrun to transfer control to the specified front-end executable, passing any tool arguments (including client paths, if \p CLIENT{,32,64}_{ABS,REL} appears after the \p FRONTEND_* command) followed by "--" and the target application command line. The path to the DynamoRIO install base can be included in the front-end options via this line @code TOOL_OP_DR_PATH \endcode The DynamoRIO runtime options can be included in a single token, preceded by a prefix, via this line, using "-dr_ops" as an example prefix: @code TOOL_OP_DR_BUNDLE=-dr_ops \endcode A warning message can be presented up front to the user with: @code USER_NOTICE=This tool is currently experimental. Please report issues to mytool.com/issues. \endcode @section sec_startstop Running a Subset of an Application An alternative to running an entire application under DynamoRIO control is to use the Application Interface to specify a portion of the application to run. This interface consists of the following routines: @code dr_app_setup() dr_app_start() dr_app_stop() dr_app_cleanup() dr_app_take_over() dr_app_setup_and_start() dr_app_stop_and_cleanup() dr_app_stop_and_cleanup_with_stats() dr_app_running_under_dynamorio() \endcode When building an executable that uses DynamoRIO's Application Interface, follow the steps for \ref page_build_client to include the header files and link with the DynamoRIO library, but omit the linker flags requesting no standard libraries or startup files. DynamoRIO's CMake support does this automatically, as the linker flags for shared libraries are separate from those for executables. @section sec_options DynamoRIO Runtime Options DynamoRIO's behavior can be fine-tuned using runtime parameters. Options are specified via \c drconfig, \c drrun, or dr_register_process(). See \ref page_deploy. - \b -no_follow_children:@anchor op_children By default, DynamoRIO follows all child processes. When this option is disabled via \p -no_follow_children, DynamoRIO follows only into child processes for which a configuration file exists (typically created by \c drconfig; see \ref page_deploy). On Linux, forked children are always followed and this option only affects execve. To follow all children in general but exclude certain children, leave \p -follow_children on (the default) and create config files that exclude the desired applications by running \c drconfig with the \c -norun option. - \b -xarch_root:@anchor op_xarch_root Support for running under an emulator, in particular QEMU. This option takes a string pointing at the base directory for guest system libraries, which DynamoRIO uses to prefix the application executable's interpreter, client library paths, and SYS_openat. The option also enables workarounds for problems with QEMU's threads which would otherwise cause a hang while DynamoRIO tries to take them over. - \b -opt_memory:@anchor op_memory Reduce memory usage, but potentially at the cost of performance. This option can result in memory savings as high as 20%, and usually incurs no noticable performance degradation. However, it conflicts with the \ref op_enable "-enable_full_api option" and cannot be used with dr_unlink_flush_region(). - \b -opt_cleancall \e \<number\>:@anchor op_cleancall Optimize (shrink or inline) the clean call sequences (see \ref sec_clean_call). When DynamoRIO analyzes the callee and optimizes each clean call invocation, it assumes that a client will not modify the clean call callee or application instructions after the inserted clean call. If a client changes application instructions after an inserted clean call, the client may need to reduce the -opt_cleancall level to preserve correct execution. There are four optimization levels: - 0: no optimization. - 1: callee register usage analysis and optimization on context switch. - 2: simple callee inline optimization, callee-save register analysis, and aflags usage analysis on the instruction list to be inserted. - 3: more aggressive, but potentially unsafe, optimizations. By default, the clean call optimization level is 2. The clean call will only be optimized if it is a leaf function. Currently, the callee will be inlined only if it is small, has at most one argument, and has no control flow other than for the PIC base. Compiling the client with optimizations makes clean call sequences more likely to be optimized. The optimization results (e.g. whether the inserted clean call is inlined or not, and which registers were saved on each context switch) are logged. Users can run DynamoRIO debug build with the runtime option "-loglevel 2 -logmask 0x02000000" (the logmask is optional but reduces the logfile size significantly) and grep for "CLEANCALL" in the log file to retrieve the information about clean call optimization.
-persist_dir
. See Persisting Code for more details.Options controlling notifications from DynamoRIO:
-msgbox_mask 0xN: Controls whether DynamoRIO uses pop-up message boxes on Windows, or waits for a key press on Linux, when presenting information. The mask takes the following bitfields:
dr_messagebox() is not affected by -msgbox_mask. For the provided Windows debug build -msgbox_mask defaults to 0xC. On Linux the default is 0, as this feature reads from standard input and might conflict with some applications. On Linux the pause can be changed to use an infinite loop rather than reading from standard input by passing the -pause_via_loop runtime option, which allows attaching a debugger.
cmd
console on Windows 7 or earlier or on any Windows version when running a graphical application in cmd
(even with dr_enable_console_printing(), as that only affects clients calling dr_printf() or dr_fprintf()) but the output can be viewed from cmd
by redirecting to a file. For the provided Linux debug builds, -stderr_mask defaults to 0xF; for the Linux release builds, its default is 0xE. The default on Windows is 0.Options aiding in debugging:
Options available only in the debug build of DynamoRIO:
drconfig
, or drrun
configuration for the target application. The runtime option -logdir can be used to override the default directory. There is one main log file per directory named app.0.TID.html, where TID is the thread identifier of the initial thread. There is also a log file per thread, named log.N.TID.html, where N is the thread's creation ordinal and TID is its thread identifier. The loglevel may be changed during program execution, but if it began at 0 then it cannot be raised later. The -logmask parameter can be used to control which DynamoRIO modules output data to the log files. dr_log() allows the client to write to the above logfiles.