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 field is used to identify the kind of each entry via a value of type dynamorio::drmemtrace::trace_marker_type_t. The
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.
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.)
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 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.
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 marker
marker_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 is useful to help track thread migrations occurring during execution. This marker is written to the header of each trace buffer when the buffer is flushed. Note that if the thread migrates to a different CPU due to preemption by the kernel before a buffer is full, we do not output a separate dynamorio::drmemtrace::TRACE_MARKER_TYPE_CPU_ID marker to capture the previous CPU identifier. However, we expect such cases to be rare.
- 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.
The full set of markers is listed under the enum dynamorio::drmemtrace::trace_marker_type_t.