DynamoRIO
|
drmemtrace
traces are records of all user mode retired instructions and memory accesses during the traced window.
A trace is presented to analysis tools as a stream of records. Each record entry is of type dynamorio::drmemtrace::memref_t and represents one instruction or data reference or a metadata operation such as a thread exit or marker. There are built-in scheduling markers providing the timestamp and cpu identifier periodically and before and after each system call. Other built-in markers indicate disruptions in user mode control flow such as signal handler entry and exit.
Each entry contains the common fields type
, pid
, and tid
. The type
field is used to identify the kind of each entry via a value of type dynamorio::drmemtrace::trace_marker_type_t. The pid
and tid
identify the process and software thread owning the entry. By default, all traced software threads are interleaved together, but with offline traces (see Offline Traces and Analysis) each thread's trace can easily be analyzed separately as they are stored in separate files.
Instruction Records
Executed instructions are stored in dynamorio::drmemtrace::_memref_instr_t. The program counter and length of the encoded instruction are provided. The length can be used to compute the address of the subsequent instruction.
The raw encoding of the instruction is provided. This can be decoded using the drdecode decoder or any other decoder. An additional field encoding_is_new
is provided to indicate when any cached decoding information should be invalidated due to possibly changed application code. (For online traces, encodings are not provided unless the option -instr_encodings
is passed, as encodings add overhead and are not needed for many tools.) Cached decoding information might also need to be discarded if there is a dynamorio::drmemtrace::TRACE_MARKER_TYPE_VECTOR_LENGTH marker entry indicating a change of vector length on architectures such as AArch64 which have a dynamic vector length.
Older legacy traces may not contain instruction encodings. For those traces, encodings for static code can be obtained by disassembling the application and library binaries. The provided interfaces module_mapper_t::get_loaded_modules() and module_mapper_t::find_mapped_trace_address() facilitate loading in copies of the binaries and reading the raw bytes for each instruction in order to obtain the opcode and full operand information. See also Core Simulation Support.
Whether conditional branches are taken or untaken is indicated by the instruction types dynamorio::drmemtrace::TRACE_TYPE_INSTR_TAKEN_JUMP and dynamorio::drmemtrace::TRACE_TYPE_INSTR_UNTAKEN_JUMP. The target of each indirect branch is explicitly provided by the "indirect_branch_target" field in dynamorio::drmemtrace::memref_t. If the program flow is changed by the kernel such as by signal delivery, the branch target is explicitly recorded in the trace in a metadata marker entry of type dynamorio::drmemtrace::TRACE_MARKER_TYPE_KERNEL_EVENT.
Memory Access Records
Memory accesses (data loads and stores) are stored in dynamorio::drmemtrace::_memref_data_t. The program counter of the instruction performing the memory access, the virtual address (convertable to physical: see Physical Addresses), and the size are provided.
Other Records
Besides instruction and memory records, other trace entry types include dynamorio::drmemtrace::_memref_marker_t, dynamorio::drmemtrace::_memref_flush_t, dynamorio::drmemtrace::_memref_thread_exit_t, etc. These records provide specific inforamtion about events that can alter the program flow or the system's states.
Trace markers are particularly important to allow reconstruction of the program execution. Marker records in dynamorio::drmemtrace::_memref_marker_t provide metadata identifying some event that occurred at this point in the trace. Each marker record contains two additional fields:
marker_type
- identifies the type of markermarker_value
- carries the value of the marker
Some of the more important markers are:
- dynamorio::drmemtrace::TRACE_MARKER_TYPE_KERNEL_EVENT - This identifies kernel-initiated control transfers such as signal delivery. The next instruction record is the start of the handler for a kernel-initiated event. The value of this type of marker contains the program counter at the kernel interruption point. If the interruption point is just after a branch, this value is the target of that branch.
- dynamorio::drmemtrace::TRACE_MARKER_TYPE_KERNEL_XFER - This identifies a system call that changes control flow, such as a signal return.
- dynamorio::drmemtrace::TRACE_MARKER_TYPE_TIMESTAMP - The marker value provides a timestamp for this point of the trace (in units of microseconds since Jan 1, 1601 UTC). This value can be used to synchronize records from different threads as well as analyze latencies (however, tracing overhead inflates time unevenly, so time deltas should not be considered perfectly representative). It is used in the sequential analysis of a multi-threaded trace.
- dynamorio::drmemtrace::TRACE_MARKER_TYPE_CPU_ID - The marker value contains the CPU identifier on which the subsequent records were collected. It can be used to identify the "as traced" schedule, indicating which threads were on which cores at which times. However, this schedule is not representative and should not be treated as indicating how the application behaves without tracing. See As-Traced Schedule Limitations for further information.
- dynamorio::drmemtrace::TRACE_MARKER_TYPE_FUNC_ID, dynamorio::drmemtrace::TRACE_MARKER_TYPE_FUNC_RETADDR, dynamorio::drmemtrace::TRACE_MARKER_TYPE_FUNC_ARG, dynamorio::drmemtrace::TRACE_MARKER_TYPE_FUNC_RETVAL - These markers are used to capture information about function calls. Which functions to capture must be explicitly selected at tracing time. Typical candiates are heap allocation and freeing functions. See Tracing Function Calls.
- dynamorio::drmemtrace::TRACE_MARKER_TYPE_WINDOW_ID - The marker value contains the ordinal of the trace burst window when the subsequent entries until the next dynamorio::drmemtrace::TRACE_MARKER_TYPE_WINDOW_ID or end-of-trace were collected (see Tracing a Subset of Execution).
- dynamorio::drmemtrace::TRACE_MARKER_TYPE_SYSCALL - This identifies a system call. A timestamp is inserted in the trace before and after marker of this type. This marker should be considered to be the actual system call invocation by the kernel, rather than the prior system call gateway instruction fetch record. Thus, these timestamps provide the system call latency.
- dynamorio::drmemtrace::TRACE_MARKER_TYPE_CORE_IDLE - This is inserted by the trace scheduler (see Trace Scheduler) when there is no work available on a core in core-sharded mode. This is meant to simulate actual idle time on a core.
- dynamorio::drmemtrace::TRACE_MARKER_TYPE_CORE_WAIT - This is inserted by the trace scheduler (see Trace Scheduler) during replay of a previously recorded schedule when one core gets too far ahead of another according to the recorded timestamps. This is an artificial wait to keep the replay on track, as opposed to the natural idle time of dynamorio::drmemtrace::TRACE_MARKER_TYPE_CORE_IDLE.
The full set of markers is listed under the enum dynamorio::drmemtrace::trace_marker_type_t.