| Testing the Intel(R) Processor Trace (Intel PT) Decoder Library and Samples {#pttc} |
| =========================================================================== |
| |
| <!--- |
| ! Copyright (c) 2013-2021, Intel Corporation |
| ! |
| ! Redistribution and use in source and binary forms, with or without |
| ! modification, are permitted provided that the following conditions are met: |
| ! |
| ! * Redistributions of source code must retain the above copyright notice, |
| ! this list of conditions and the following disclaimer. |
| ! * Redistributions in binary form must reproduce the above copyright notice, |
| ! this list of conditions and the following disclaimer in the documentation |
| ! and/or other materials provided with the distribution. |
| ! * Neither the name of Intel Corporation nor the names of its contributors |
| ! may be used to endorse or promote products derived from this software |
| ! without specific prior written permission. |
| ! |
| ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| ! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| ! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| ! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
| ! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| ! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| ! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| ! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| ! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| ! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| ! POSSIBILITY OF SUCH DAMAGE. |
| !--> |
| |
| 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_<name>_start* gives the section's offset in the binary file |
| * *section_<name>_vstart* gives the virtual base address of the mapped section |
| * *section_<name>_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. |