DynamoRIO
Core Simulation Support

The drmemtrace trace format includes information intended for use by core simulators as well as pure cache simulators. For traces that are not filtered by an online first-level cache, each data reference is preceded by the instruction fetch entry for the instruction that issued the data request, which includes the instruction encoding with the opcode and operands. Additionally, on x86, string loop instructions involve a single insruction fetch followed by a loop of loads and/or stores. A drmemtrace trace includes a special "no-fetch" instruction entry per iteration so that core simulators have the instruction information to go along with each load and store, while cache simulators can ignore these "no-fetch" entries and avoid incorrectly inflating instruction fetch statistics.

Traces include scheduling markers providing the timestamp and hardware thread identifier on each thread transition, allowing a simulator to more closely match the actual hardware if so desired: but be aware that this "as-traced" schedule is not representative, as shown in As-Traced Schedule Limitations. We recommend instead using dynamic re-scheduling of the software threads: see Dynamic Scheduling. While we suggest keeping traces stored as thread-sharded and using the dynamic scheduler in each run, there is support for running the scheduler once and creating a new set of stored traces in core-sharded format: essentially switching to hardware-thread-oriented traces. This is done using the Record Filter tool in -core_sharded mode. The dynamorio::drmemtrace::TRACE_MARKER_TYPE_TIMESTAMP and dynamorio::drmemtrace::TRACE_MARKER_TYPE_CPU_ID markers are modified by the dynamic scheduler to reflect the new schedule. The new timestamps maintain relative ordering but should not be relied upon to indicate accurate durations between events. When analyzing core-sharded-on-disk traces, -no_core_sharded must be passed when using core-sharded-preferring tools to avoid an error from the framework attempting to re-schedule the already-scheduled trace.

Traces also include markers indicating disruptions in user mode control flow such as signal handler entry and exit.

Offline traces explicitly identify whether each conditional branch was taken or not, and include the actual target of indirect branches, for convenience to avoid having to read either the subsequent entry or the kernel transfer event marker (or infer branch behavior for rseq aborts):

801394 601853: 1159769 ifetch 2 byte(s) @ 0x00007fc2c3aa91e3 7f 1b jnle $0x00007fc2c3aa9200 (untaken)
801395 601854: 1159769 ifetch 4 byte(s) @ 0x00007fc2c3aa91e5 48 83 c4 10 add $0x10, %rsp
801396 601855: 1159769 ifetch 1 byte(s) @ 0x00007fc2c3aa91e9 5b pop %rbx
801397 601855: 1159769 read 8 byte(s) @ 0x00007fff8044f6c0 by PC 0x00007fc2c3aa91e9
801398 601856: 1159769 ifetch 1 byte(s) @ 0x00007fc2c3aa91ea c3 ret (target 0x7fc2c3aa81c1)
801399 601856: 1159769 read 8 byte(s) @ 0x00007fff8044f6c8 by PC 0x00007fc2c3aa91ea
801400 601857: 1159769 ifetch 2 byte(s) @ 0x00007fc2c3aa81c1 89 c5 mov %eax, %ebp

Filtered traces (filtered via -L0_filter) include the dynamic (pre-filtered) per-thread instruction count in a dynamorio::drmemtrace::TRACE_MARKER_TYPE_INSTRUCTION_COUNT marker at each thread buffer boundary and at thread exit.