Testing the Intel(R) Processor Trace (Intel PT) Decoder Library and Samples

This chapter documents how to use the pttc tool to generate and run tests. Pttc takes a yasm assembly file and creates a Processor Trace stream from special directives in its input.

Usage

$ pttc path/to/file.ptt

If no error occurs, the following files will be generated in the current working directory:

file.lst
file.bin
file.pt
file-<tool>.exp
file-<src>.sb

The .lst and .bin files are generated by a call to yasm. The .pt file contains the Processor Trace and the .exp files contain the content of the comments after the .exp directive for tool <tool> (see below). The .sb files contain sideband infomrmation from source <src> (see below).

Pttc prints the filenames of the generated .exp and .sb files to stdout.

Syntax

Pttc allows annotations in the comments of yasm assembler source files. The parser recognizes all comments that contain the @pt directive marker.

Every pt directive can be preceded by a label name followed by a colon (:). Refer to the description of the .exp() and .sb() directives below on how to use these labels.

The general syntax for pt directives is as follows:

@pt [label:]directive([arguments])

Intel PT directives

This section lists the directives that are understood by pttc.

raw

@pt raw-8(value)
@pt raw-16(value)
@pt raw-32(value)
@pt raw-64(value)

Writes a raw unsigned 8, 16, 32, or 64 bit value.

psb, psbend, pad, ovf, stop

@pt psb()
@pt psbend()
@pt pad()
@pt ovf()
@pt stop()

These packets do not have any arguments and correspond to the packets from the specification.

tnt, tnt64

@pt tnt(args)
@pt tnt64(args)

The arguments of the tnt and tnt64 packets is a list of Takens t and Not-Takens n. For better readability an arbitrary number of blanks and dots can be intervened.

It is an error if no characters, only blanks or dots, or other characters are in the payload. Additionally for the TNT packet and the TNT64 packet it is an error to have more than 6 and more than 47 t‘s or n’s in the payload, respectively.

tip, tip.pge, tip.pgd, fup

@pt tip(ipc: addr)
@pt tip.pge(ipc: addr)
@pt tip.pgd(ipc: addr)
@pt fup(ipc: addr)

These packets accept arbitrary addresses. Addr must be a parsable integer or a valid label name. Ipc specifies the IP compression bits as integer number.

If addr is given as a label, the address is truncated according to the IP bytes value given in ipc. Otherwise the address needs to be a zero-extended integer no bigger than specified in ipc.

mode.exec, mode.tsx

@pt mode.exec(mode)
@pt mode.tsx(state)

Mode must be either 16bit or 32bit or 64bit; state must be begin or abort or commit.

pip

@pt pip(addr[, nr])

Addr is the value that was written to CR3.

If nr is specified after addr, the non-root bit is set.

tsc

@pt tsc(value)

Value is the timestamp.

cbr

@pt cbr(value)

Value is the core/bus ratio.

tma

@pt tma(ctc, fc)

Ctc is the 16bit crystal clock component. Fc is the 9bit fast counter component.

mtc

@pt mtc(value)

Value is the 8bit crystal clock component.

cyc

@pt cyc(value)

Value is the cycle count.

vmcs

@pt vmcs(value)

Value is the VMCS base address. Beware that only bits 12 to 51 will be used. The rest will be silently ignored.

mnt

@pt mnt(value)

Value is the 8-byte packet payload represented as 64-bit little-endian number.

exstop

@pt exstop([ip])

If ip is specified, the IP bit in the packet opcode is set, it is clear otherwise.

mwait

@pt mwait(hints, ext)

Hints is the 4-byte mwait hints argument in eax. Ext is the 4-byte extensions argument in ecx.

pwre

@pt pwre(c-state[, hw])

C-state is a thread C-state with optional sub C-state in the format c<state>[.<sub>] where both <state> and <sub> are decimal integer values between 0 and 15. If the sub C-state is not specified, it defaults to c0.

If hw is specified, the C-state entry was initiated by hardware.

pwrx

@pt pwrx(wr: last, deepest)

Wr is the wake reason. It must be int, st, or hw.

Last and deepest are the last and deepest achieved core C-state in the format c<state> where <state> is a decimal integer value between 0 and 15.

ptw

@pt ptw(size: payload[, ip])

Size is the payload size; it must be 0 or 1. Payload is the unsigned integer payload. If ip is specified, the IP bit in the packet opcode is set, it is clear otherwise.

.exp

@pt .exp([tool])

Every occurrence of this directive prints all the lines, following this directive, to a file[-tool].exp.

The first occurrence of this directive stops processing of other directives.

In order to have a valid yasm file, it is necessary to put the expected output into yasm comments (with the semi-colon character (;)). Any character up to (and including) the semi-colon is not printed to the .exp file. Trailing white space is removed from each line.

Comments are made with the # character and go to the end of line. Comments and whitespace before comments are not printed in the .exp file.

Each line that contains no yasm comment at all is not printed to the exp file. Empty lines can be used to structure the expected output text.

In .exp files and in sideband directives, the address of a yasm label can be substituted using:

%[?0]label[.<number>].

Labels are prefixed with %, for example, %%label. A label name can consist of alphanumeric characters and underscores. Labels must be unique. The address of label will be substituted with a hex number including leading 0x.

Prefixing the label with 0, for example %0label, prints the address with leading zeroes using 16 hex digits plus the leading 0x.

The least significant n bytes of an address can be masked by appending .n to the label. For example, %%label.2 with label = 0xffffff004c is printed as 0x4c.

Prefixing the label with ? in combination with masking replaces the masked out parts with ? using 16 digits for the address plus the leading 0x. The remaining number is zero extended. For example, %?label.2 with label = 0xc0001 is printed as 0x????????????0001.

The packet number of pt directives can also be substituted in the output. These numbers are printed in decimal. The syntax is as follows:

%label

Special Labels

There is a special label for the byte offset after the last packet: %%eos.

Labels in sections are relative to the section's vstart address. PTTC also adds the following special section labels:

  • section__start gives the section's offset in the binary file
  • section__vstart gives the virtual base address of the mapped section
  • section__length gives the size of the section in bytes

Beware that PTTC does not support switching back and forth between sections.

Sideband Directives

This section lists the sideband directives that are understood by pttc.

primary/secondary [requires SIDEBAND]

@sb primary(format [,src])
@sb secondary(format [,src])

Every occurrence of this directive switches the current sideband file to file[-src]-format-primary.sb or file[-src]-format-secondary.sb respectively. Every subsequent sideband directive will write to the current sideband file.

A primary sideband file is directly related to the trace. For example, it may contain the sideband information for the traced cpu. A secondary sideband file is indirectly related to the trace. For example, it may contain the sideband information for other cpus on the system.

Sideband directive and Intel PT directives can be mixed.

raw [requires SIDEBAND]

@sb raw-8(value)
@sb raw-16(value)
@sb raw-32(value)
@sb raw-64(value)

Writes a raw unsigned 8, 16, 32, or 64 bit value into the current sideband stream.

pevent-sample_type [requires SIDEBAND, PEVENT]

@sb pevent-sample_type(t1[, t2[, t3[...]]])

Sets the perf_event sample_type for subsequent pevent sideband directives for the current sideband file to the bit-wise or ‘|’ of all arguments. Each argument can be:

  • tid representing PERF_SAMPLE_TID
  • time representing PERF_SAMPLE_TIME
  • id representing PERF_SAMPLE_ID
  • cpu representing PERF_SAMPLE_CPU
  • stream representing PERF_SAMPLE_STREAM_ID
  • identifier representing PERF_SAMPLE_IDENTIFIER
  • a 64bit unsigned integer representing a bit-mask of enum perf_event_sample_format values

Subsequent perf event record generating directives must provide the specified number of sample arguments in the above order order. The tid sample type takes two arguments: a pid followed by a tid.

This directive may only be used before the first perf event record generating directive.

pevent-mmap [requires SIDEBAND, PEVENT]

@sb pevent-mmap(pid, tid, addr, len, pgoff, filename[, samples])

Writes a PERF_RECORD_MMAP event into the current sideband stream describing the mapping of filename.

The samples argument is a comma-separated list of samples corresponding to the pevent-sample_type configuration.

pevent-mmap-section [requires SIDEBAND, PEVENT]

@sb pevent-mmap-section(name, pid, tid[, samples])

Writes a PERF_RECORD_MMAP event into the current sideband stream describing the mapping of section name to its vstart address from its start address in the test binary.

The samples argument is a comma-separated list of samples corresponding to the pevent-sample_type configuration.

pevent-lost [requires SIDEBAND, PEVENT]

@sb pevent-lost(id, lost[, samples])

Writes a PERF_RECORD_LOST event into the current sideband stream describing the loss of perf_event records.

The samples argument is a comma-separated list of samples corresponding to the pevent-sample_type configuration.

pevent-comm [requires SIDEBAND, PEVENT]

@sb pevent-comm(pid, tid, comm[, samples])
@sb pevent-comm.exec(pid, tid, comm[, samples])

Writes a PERF_RECORD_COMM event into the current sideband stream describing the command that is being traced.

The samples argument is a comma-separated list of samples corresponding to the pevent-sample_type configuration.

pevent-exit [requires SIDEBAND, PEVENT]

@sb pevent-exit(pid, ppid, tid, ptid, time[, samples])

Writes a PERF_RECORD_EXIT event into the current sideband stream describing the exiting of the current thread. The thread is still running in kernel space but won't return to user space.

The samples argument is a comma-separated list of samples corresponding to the pevent-sample_type configuration.

pevent-fork [requires SIDEBAND, PEVENT]

@sb pevent-fork(pid, ppid, tid, ptid, time[, samples])

Writes a PERF_RECORD_FORK event into the current sideband stream describing the creation of a new thread or process. The event occurs in the context of the parent thread.

The samples argument is a comma-separated list of samples corresponding to the pevent-sample_type configuration.

pevent-aux [requires SIDEBAND, PEVENT]

@sb pevent-aux(offset, size, flags[, samples])

Writes a PERF_RECORD_AUX event into the current sideband stream describing that new data landed in the aux buffer.

The samples argument is a comma-separated list of samples corresponding to the pevent-sample_type configuration.

pevent-itrace-start [requires SIDEBAND, PEVENT]

@sb pevent-itrace-start(pid, tid[, samples])

Writes a PERF_RECORD_ITRACE_START event into the current sideband stream describing that instruction tracing has started.

The samples argument is a comma-separated list of samples corresponding to the pevent-sample_type configuration.

pevent-lost-samples [requires SIDEBAND, PEVENT]

@sb pevent-lost-samples(lost[, samples])

Writes a PERF_RECORD_LOST_SAMPLES event into the current sideband stream describing a loss of sample records.

The samples argument is a comma-separated list of samples corresponding to the pevent-sample_type configuration.

pevent-switch [requires SIDEBAND, PEVENT]

@sb pevent-switch.in([samples])
@sb pevent-switch.out([samples])

Writes a PERF_RECORD_SWITCH event into the current sideband stream describing a switch into or out of context.

The samples argument is a comma-separated list of samples corresponding to the pevent-sample_type configuration.

pevent-switch-cpu-wide [requires SIDEBAND, PEVENT]

@sb pevent-switch-cpu-wide.in(pid, tid[, samples])
@sb pevent-switch-cpu-wide.out(pid, tid[, samples])

Writes a PERF_RECORD_SWITCH_CPU_WIDE event into the current sideband stream describing a switch into or out of context. The pid and tid arguments give the process and thread id of the previous task.

The samples argument is a comma-separated list of samples corresponding to the pevent-sample_type configuration.