|
Packit |
b1f7ae |
/*
|
|
Packit |
b1f7ae |
* Copyright (c) 2013-2017, Intel Corporation
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Redistribution and use in source and binary forms, with or without
|
|
Packit |
b1f7ae |
* modification, are permitted provided that the following conditions are met:
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* * Redistributions of source code must retain the above copyright notice,
|
|
Packit |
b1f7ae |
* this list of conditions and the following disclaimer.
|
|
Packit |
b1f7ae |
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
Packit |
b1f7ae |
* this list of conditions and the following disclaimer in the documentation
|
|
Packit |
b1f7ae |
* and/or other materials provided with the distribution.
|
|
Packit |
b1f7ae |
* * Neither the name of Intel Corporation nor the names of its contributors
|
|
Packit |
b1f7ae |
* may be used to endorse or promote products derived from this software
|
|
Packit |
b1f7ae |
* without specific prior written permission.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
b1f7ae |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
b1f7ae |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
b1f7ae |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
Packit |
b1f7ae |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit |
b1f7ae |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit |
b1f7ae |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit |
b1f7ae |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit |
b1f7ae |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit |
b1f7ae |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit |
b1f7ae |
* POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#ifndef INTEL_PT_H
|
|
Packit |
b1f7ae |
#define INTEL_PT_H
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#include <stdint.h>
|
|
Packit |
b1f7ae |
#include <string.h>
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#ifdef __cplusplus
|
|
Packit |
b1f7ae |
extern "C" {
|
|
Packit |
b1f7ae |
#endif
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Intel(R) Processor Trace (Intel PT) decoder library.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This file is logically structured into the following sections:
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* - Version
|
|
Packit |
b1f7ae |
* - Opcodes
|
|
Packit |
b1f7ae |
* - Errors
|
|
Packit |
b1f7ae |
* - Configuration
|
|
Packit |
b1f7ae |
* - Packet encoder / decoder
|
|
Packit |
b1f7ae |
* - Query decoder
|
|
Packit |
b1f7ae |
* - Traced image
|
|
Packit |
b1f7ae |
* - Instruction flow decoder
|
|
Packit |
b1f7ae |
* - Block decoder
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
struct pt_encoder;
|
|
Packit |
b1f7ae |
struct pt_packet_decoder;
|
|
Packit |
b1f7ae |
struct pt_query_decoder;
|
|
Packit |
b1f7ae |
struct pt_insn_decoder;
|
|
Packit |
b1f7ae |
struct pt_block_decoder;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* A macro to mark functions as exported. */
|
|
Packit |
b1f7ae |
#ifndef pt_export
|
|
Packit |
b1f7ae |
# if defined(__GNUC__)
|
|
Packit |
b1f7ae |
# define pt_export __attribute__((visibility("default")))
|
|
Packit |
b1f7ae |
# elif defined(_MSC_VER)
|
|
Packit |
b1f7ae |
# define pt_export __declspec(dllimport)
|
|
Packit |
b1f7ae |
# else
|
|
Packit |
b1f7ae |
# error "unknown compiler"
|
|
Packit |
b1f7ae |
# endif
|
|
Packit |
b1f7ae |
#endif
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Version. */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The header version. */
|
|
Packit |
b1f7ae |
#define LIBIPT_VERSION_MAJOR ${PT_VERSION_MAJOR}
|
|
Packit |
b1f7ae |
#define LIBIPT_VERSION_MINOR ${PT_VERSION_MINOR}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#define LIBIPT_VERSION ((LIBIPT_VERSION_MAJOR << 8) + LIBIPT_VERSION_MINOR)
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The library version. */
|
|
Packit |
b1f7ae |
struct pt_version {
|
|
Packit |
b1f7ae |
/** Major version number. */
|
|
Packit |
b1f7ae |
uint8_t major;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Minor version number. */
|
|
Packit |
b1f7ae |
uint8_t minor;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Reserved bits. */
|
|
Packit |
b1f7ae |
uint16_t reserved;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Build number. */
|
|
Packit |
b1f7ae |
uint32_t build;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Version extension. */
|
|
Packit |
b1f7ae |
const char *ext;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Return the library version. */
|
|
Packit |
b1f7ae |
extern pt_export struct pt_version pt_library_version();
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Opcodes. */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A one byte opcode. */
|
|
Packit |
b1f7ae |
enum pt_opcode {
|
|
Packit |
b1f7ae |
pt_opc_pad = 0x00,
|
|
Packit |
b1f7ae |
pt_opc_ext = 0x02,
|
|
Packit |
b1f7ae |
pt_opc_psb = pt_opc_ext,
|
|
Packit |
b1f7ae |
pt_opc_tip = 0x0d,
|
|
Packit |
b1f7ae |
pt_opc_tnt_8 = 0x00,
|
|
Packit |
b1f7ae |
pt_opc_tip_pge = 0x11,
|
|
Packit |
b1f7ae |
pt_opc_tip_pgd = 0x01,
|
|
Packit |
b1f7ae |
pt_opc_fup = 0x1d,
|
|
Packit |
b1f7ae |
pt_opc_mode = 0x99,
|
|
Packit |
b1f7ae |
pt_opc_tsc = 0x19,
|
|
Packit |
b1f7ae |
pt_opc_mtc = 0x59,
|
|
Packit |
b1f7ae |
pt_opc_cyc = 0x03,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* A free opcode to trigger a decode fault. */
|
|
Packit |
b1f7ae |
pt_opc_bad = 0xd9
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A one byte extension code for ext opcodes. */
|
|
Packit |
b1f7ae |
enum pt_ext_code {
|
|
Packit |
b1f7ae |
pt_ext_psb = 0x82,
|
|
Packit |
b1f7ae |
pt_ext_tnt_64 = 0xa3,
|
|
Packit |
b1f7ae |
pt_ext_pip = 0x43,
|
|
Packit |
b1f7ae |
pt_ext_ovf = 0xf3,
|
|
Packit |
b1f7ae |
pt_ext_psbend = 0x23,
|
|
Packit |
b1f7ae |
pt_ext_cbr = 0x03,
|
|
Packit |
b1f7ae |
pt_ext_tma = 0x73,
|
|
Packit |
b1f7ae |
pt_ext_stop = 0x83,
|
|
Packit |
b1f7ae |
pt_ext_vmcs = 0xc8,
|
|
Packit |
b1f7ae |
pt_ext_ext2 = 0xc3,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
pt_ext_bad = 0x04
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A one byte extension 2 code for ext2 extension opcodes. */
|
|
Packit |
b1f7ae |
enum pt_ext2_code {
|
|
Packit |
b1f7ae |
pt_ext2_mnt = 0x88,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
pt_ext2_bad = 0x00
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A one byte opcode mask. */
|
|
Packit |
b1f7ae |
enum pt_opcode_mask {
|
|
Packit |
b1f7ae |
pt_opm_tip = 0x1f,
|
|
Packit |
b1f7ae |
pt_opm_tnt_8 = 0x01,
|
|
Packit |
b1f7ae |
pt_opm_tnt_8_shr = 1,
|
|
Packit |
b1f7ae |
pt_opm_fup = pt_opm_tip,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The bit mask for the compression bits in the opcode. */
|
|
Packit |
b1f7ae |
pt_opm_ipc = 0xe0,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The shift right value for ipc bits. */
|
|
Packit |
b1f7ae |
pt_opm_ipc_shr = 5,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The bit mask for the compression bits after shifting. */
|
|
Packit |
b1f7ae |
pt_opm_ipc_shr_mask = 0x7,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Shift counts and masks for decoding the cyc packet. */
|
|
Packit |
b1f7ae |
pt_opm_cyc = 0x03,
|
|
Packit |
b1f7ae |
pt_opm_cyc_ext = 0x04,
|
|
Packit |
b1f7ae |
pt_opm_cyc_bits = 0xf8,
|
|
Packit |
b1f7ae |
pt_opm_cyc_shr = 3,
|
|
Packit |
b1f7ae |
pt_opm_cycx_ext = 0x01,
|
|
Packit |
b1f7ae |
pt_opm_cycx_shr = 1
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The size of the various opcodes in bytes. */
|
|
Packit |
b1f7ae |
enum pt_opcode_size {
|
|
Packit |
b1f7ae |
pt_opcs_pad = 1,
|
|
Packit |
b1f7ae |
pt_opcs_tip = 1,
|
|
Packit |
b1f7ae |
pt_opcs_tip_pge = 1,
|
|
Packit |
b1f7ae |
pt_opcs_tip_pgd = 1,
|
|
Packit |
b1f7ae |
pt_opcs_fup = 1,
|
|
Packit |
b1f7ae |
pt_opcs_tnt_8 = 1,
|
|
Packit |
b1f7ae |
pt_opcs_mode = 1,
|
|
Packit |
b1f7ae |
pt_opcs_tsc = 1,
|
|
Packit |
b1f7ae |
pt_opcs_mtc = 1,
|
|
Packit |
b1f7ae |
pt_opcs_cyc = 1,
|
|
Packit |
b1f7ae |
pt_opcs_psb = 2,
|
|
Packit |
b1f7ae |
pt_opcs_psbend = 2,
|
|
Packit |
b1f7ae |
pt_opcs_ovf = 2,
|
|
Packit |
b1f7ae |
pt_opcs_pip = 2,
|
|
Packit |
b1f7ae |
pt_opcs_tnt_64 = 2,
|
|
Packit |
b1f7ae |
pt_opcs_cbr = 2,
|
|
Packit |
b1f7ae |
pt_opcs_tma = 2,
|
|
Packit |
b1f7ae |
pt_opcs_stop = 2,
|
|
Packit |
b1f7ae |
pt_opcs_vmcs = 2,
|
|
Packit |
b1f7ae |
pt_opcs_mnt = 3
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The psb magic payload.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The payload is a repeating 2-byte pattern.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
enum pt_psb_pattern {
|
|
Packit |
b1f7ae |
/* The high and low bytes in the pattern. */
|
|
Packit |
b1f7ae |
pt_psb_hi = pt_opc_psb,
|
|
Packit |
b1f7ae |
pt_psb_lo = pt_ext_psb,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Various combinations of the above parts. */
|
|
Packit |
b1f7ae |
pt_psb_lohi = pt_psb_lo | pt_psb_hi << 8,
|
|
Packit |
b1f7ae |
pt_psb_hilo = pt_psb_hi | pt_psb_lo << 8,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The repeat count of the payload, not including opc and ext. */
|
|
Packit |
b1f7ae |
pt_psb_repeat_count = 7,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of the repeated pattern in bytes. */
|
|
Packit |
b1f7ae |
pt_psb_repeat_size = 2
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** An execution mode. */
|
|
Packit |
b1f7ae |
enum pt_exec_mode {
|
|
Packit |
b1f7ae |
ptem_unknown,
|
|
Packit |
b1f7ae |
ptem_16bit,
|
|
Packit |
b1f7ae |
ptem_32bit,
|
|
Packit |
b1f7ae |
ptem_64bit
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The payload details. */
|
|
Packit |
b1f7ae |
enum pt_payload {
|
|
Packit |
b1f7ae |
/* The shift counts for post-processing the PIP payload. */
|
|
Packit |
b1f7ae |
pt_pl_pip_shr = 1,
|
|
Packit |
b1f7ae |
pt_pl_pip_shl = 5,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of a PIP payload in bytes. */
|
|
Packit |
b1f7ae |
pt_pl_pip_size = 6,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The non-root bit in the first byte of the PIP payload. */
|
|
Packit |
b1f7ae |
pt_pl_pip_nr = 0x01,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of a 8bit TNT packet's payload in bits. */
|
|
Packit |
b1f7ae |
pt_pl_tnt_8_bits = 8 - pt_opm_tnt_8_shr,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of a 64bit TNT packet's payload in bytes. */
|
|
Packit |
b1f7ae |
pt_pl_tnt_64_size = 6,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of a 64bit TNT packet's payload in bits. */
|
|
Packit |
b1f7ae |
pt_pl_tnt_64_bits = 48,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of a TSC packet's payload in bytes and in bits. */
|
|
Packit |
b1f7ae |
pt_pl_tsc_size = 7,
|
|
Packit |
b1f7ae |
pt_pl_tsc_bit_size = pt_pl_tsc_size * 8,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of a CBR packet's payload in bytes. */
|
|
Packit |
b1f7ae |
pt_pl_cbr_size = 2,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of a PSB packet's payload in bytes. */
|
|
Packit |
b1f7ae |
pt_pl_psb_size = pt_psb_repeat_count * pt_psb_repeat_size,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of a MODE packet's payload in bytes. */
|
|
Packit |
b1f7ae |
pt_pl_mode_size = 1,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of an IP packet's payload with update-16 compression. */
|
|
Packit |
b1f7ae |
pt_pl_ip_upd16_size = 2,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of an IP packet's payload with update-32 compression. */
|
|
Packit |
b1f7ae |
pt_pl_ip_upd32_size = 4,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of an IP packet's payload with update-48 compression. */
|
|
Packit |
b1f7ae |
pt_pl_ip_upd48_size = 6,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of an IP packet's payload with sext-48 compression. */
|
|
Packit |
b1f7ae |
pt_pl_ip_sext48_size = 6,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of an IP packet's payload with full-ip compression. */
|
|
Packit |
b1f7ae |
pt_pl_ip_full_size = 8,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Byte locations, sizes, and masks for processing TMA packets. */
|
|
Packit |
b1f7ae |
pt_pl_tma_size = 5,
|
|
Packit |
b1f7ae |
pt_pl_tma_ctc_size = 2,
|
|
Packit |
b1f7ae |
pt_pl_tma_ctc_bit_size = pt_pl_tma_ctc_size * 8,
|
|
Packit |
b1f7ae |
pt_pl_tma_ctc_0 = 2,
|
|
Packit |
b1f7ae |
pt_pl_tma_ctc_1 = 3,
|
|
Packit |
b1f7ae |
pt_pl_tma_ctc_mask = (1 << pt_pl_tma_ctc_bit_size) - 1,
|
|
Packit |
b1f7ae |
pt_pl_tma_fc_size = 2,
|
|
Packit |
b1f7ae |
pt_pl_tma_fc_bit_size = 9,
|
|
Packit |
b1f7ae |
pt_pl_tma_fc_0 = 5,
|
|
Packit |
b1f7ae |
pt_pl_tma_fc_1 = 6,
|
|
Packit |
b1f7ae |
pt_pl_tma_fc_mask = (1 << pt_pl_tma_fc_bit_size) - 1,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of a MTC packet's payload in bytes and in bits. */
|
|
Packit |
b1f7ae |
pt_pl_mtc_size = 1,
|
|
Packit |
b1f7ae |
pt_pl_mtc_bit_size = pt_pl_mtc_size * 8,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* A mask for the MTC payload bits. */
|
|
Packit |
b1f7ae |
pt_pl_mtc_mask = (1 << pt_pl_mtc_bit_size) - 1,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The maximal payload size in bytes of a CYC packet. */
|
|
Packit |
b1f7ae |
pt_pl_cyc_max_size = 15,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of a VMCS packet's payload in bytes. */
|
|
Packit |
b1f7ae |
pt_pl_vmcs_size = 5,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The shift counts for post-processing the VMCS payload. */
|
|
Packit |
b1f7ae |
pt_pl_vmcs_shl = 12,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The size of a MNT packet's payload in bytes. */
|
|
Packit |
b1f7ae |
pt_pl_mnt_size = 8
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Mode packet masks. */
|
|
Packit |
b1f7ae |
enum pt_mode_mask {
|
|
Packit |
b1f7ae |
pt_mom_leaf = 0xe0,
|
|
Packit |
b1f7ae |
pt_mom_leaf_shr = 5,
|
|
Packit |
b1f7ae |
pt_mom_bits = 0x1f
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Mode packet leaves. */
|
|
Packit |
b1f7ae |
enum pt_mode_leaf {
|
|
Packit |
b1f7ae |
pt_mol_exec = 0x00,
|
|
Packit |
b1f7ae |
pt_mol_tsx = 0x20
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Mode packet bits. */
|
|
Packit |
b1f7ae |
enum pt_mode_bit {
|
|
Packit |
b1f7ae |
/* mode.exec */
|
|
Packit |
b1f7ae |
pt_mob_exec_csl = 0x01,
|
|
Packit |
b1f7ae |
pt_mob_exec_csd = 0x02,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* mode.tsx */
|
|
Packit |
b1f7ae |
pt_mob_tsx_intx = 0x01,
|
|
Packit |
b1f7ae |
pt_mob_tsx_abrt = 0x02
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The IP compression. */
|
|
Packit |
b1f7ae |
enum pt_ip_compression {
|
|
Packit |
b1f7ae |
/* The bits encode the payload size and the encoding scheme.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* No payload. The IP has been suppressed.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
pt_ipc_suppressed = 0x0,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Payload: 16 bits. Update last IP. */
|
|
Packit |
b1f7ae |
pt_ipc_update_16 = 0x01,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Payload: 32 bits. Update last IP. */
|
|
Packit |
b1f7ae |
pt_ipc_update_32 = 0x02,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Payload: 48 bits. Sign extend to full address. */
|
|
Packit |
b1f7ae |
pt_ipc_sext_48 = 0x03,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Payload: 48 bits. Update last IP. */
|
|
Packit |
b1f7ae |
pt_ipc_update_48 = 0x04,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Payload: 64 bits. Full address. */
|
|
Packit |
b1f7ae |
pt_ipc_full = 0x06
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The size of the various packets in bytes. */
|
|
Packit |
b1f7ae |
enum pt_packet_size {
|
|
Packit |
b1f7ae |
ptps_pad = pt_opcs_pad,
|
|
Packit |
b1f7ae |
ptps_tnt_8 = pt_opcs_tnt_8,
|
|
Packit |
b1f7ae |
ptps_mode = pt_opcs_mode + pt_pl_mode_size,
|
|
Packit |
b1f7ae |
ptps_tsc = pt_opcs_tsc + pt_pl_tsc_size,
|
|
Packit |
b1f7ae |
ptps_mtc = pt_opcs_mtc + pt_pl_mtc_size,
|
|
Packit |
b1f7ae |
ptps_psb = pt_opcs_psb + pt_pl_psb_size,
|
|
Packit |
b1f7ae |
ptps_psbend = pt_opcs_psbend,
|
|
Packit |
b1f7ae |
ptps_ovf = pt_opcs_ovf,
|
|
Packit |
b1f7ae |
ptps_pip = pt_opcs_pip + pt_pl_pip_size,
|
|
Packit |
b1f7ae |
ptps_tnt_64 = pt_opcs_tnt_64 + pt_pl_tnt_64_size,
|
|
Packit |
b1f7ae |
ptps_cbr = pt_opcs_cbr + pt_pl_cbr_size,
|
|
Packit |
b1f7ae |
ptps_tip_supp = pt_opcs_tip,
|
|
Packit |
b1f7ae |
ptps_tip_upd16 = pt_opcs_tip + pt_pl_ip_upd16_size,
|
|
Packit |
b1f7ae |
ptps_tip_upd32 = pt_opcs_tip + pt_pl_ip_upd32_size,
|
|
Packit |
b1f7ae |
ptps_tip_upd48 = pt_opcs_tip + pt_pl_ip_upd48_size,
|
|
Packit |
b1f7ae |
ptps_tip_sext48 = pt_opcs_tip + pt_pl_ip_sext48_size,
|
|
Packit |
b1f7ae |
ptps_tip_full = pt_opcs_tip + pt_pl_ip_full_size,
|
|
Packit |
b1f7ae |
ptps_tip_pge_supp = pt_opcs_tip_pge,
|
|
Packit |
b1f7ae |
ptps_tip_pge_upd16 = pt_opcs_tip_pge + pt_pl_ip_upd16_size,
|
|
Packit |
b1f7ae |
ptps_tip_pge_upd32 = pt_opcs_tip_pge + pt_pl_ip_upd32_size,
|
|
Packit |
b1f7ae |
ptps_tip_pge_upd48 = pt_opcs_tip_pge + pt_pl_ip_upd48_size,
|
|
Packit |
b1f7ae |
ptps_tip_pge_sext48 = pt_opcs_tip_pge + pt_pl_ip_sext48_size,
|
|
Packit |
b1f7ae |
ptps_tip_pge_full = pt_opcs_tip_pge + pt_pl_ip_full_size,
|
|
Packit |
b1f7ae |
ptps_tip_pgd_supp = pt_opcs_tip_pgd,
|
|
Packit |
b1f7ae |
ptps_tip_pgd_upd16 = pt_opcs_tip_pgd + pt_pl_ip_upd16_size,
|
|
Packit |
b1f7ae |
ptps_tip_pgd_upd32 = pt_opcs_tip_pgd + pt_pl_ip_upd32_size,
|
|
Packit |
b1f7ae |
ptps_tip_pgd_upd48 = pt_opcs_tip_pgd + pt_pl_ip_upd48_size,
|
|
Packit |
b1f7ae |
ptps_tip_pgd_sext48 = pt_opcs_tip_pgd + pt_pl_ip_sext48_size,
|
|
Packit |
b1f7ae |
ptps_tip_pgd_full = pt_opcs_tip_pgd + pt_pl_ip_full_size,
|
|
Packit |
b1f7ae |
ptps_fup_supp = pt_opcs_fup,
|
|
Packit |
b1f7ae |
ptps_fup_upd16 = pt_opcs_fup + pt_pl_ip_upd16_size,
|
|
Packit |
b1f7ae |
ptps_fup_upd32 = pt_opcs_fup + pt_pl_ip_upd32_size,
|
|
Packit |
b1f7ae |
ptps_fup_upd48 = pt_opcs_fup + pt_pl_ip_upd48_size,
|
|
Packit |
b1f7ae |
ptps_fup_sext48 = pt_opcs_fup + pt_pl_ip_sext48_size,
|
|
Packit |
b1f7ae |
ptps_fup_full = pt_opcs_fup + pt_pl_ip_full_size,
|
|
Packit |
b1f7ae |
ptps_tma = pt_opcs_tma + pt_pl_tma_size,
|
|
Packit |
b1f7ae |
ptps_stop = pt_opcs_stop,
|
|
Packit |
b1f7ae |
ptps_vmcs = pt_opcs_vmcs + pt_pl_vmcs_size,
|
|
Packit |
b1f7ae |
ptps_mnt = pt_opcs_mnt + pt_pl_mnt_size
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Errors. */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Error codes. */
|
|
Packit |
b1f7ae |
enum pt_error_code {
|
|
Packit |
b1f7ae |
/* No error. Everything is OK. */
|
|
Packit |
b1f7ae |
pte_ok,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Internal decoder error. */
|
|
Packit |
b1f7ae |
pte_internal,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Invalid argument. */
|
|
Packit |
b1f7ae |
pte_invalid,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Decoder out of sync. */
|
|
Packit |
b1f7ae |
pte_nosync,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Unknown opcode. */
|
|
Packit |
b1f7ae |
pte_bad_opc,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Unknown payload. */
|
|
Packit |
b1f7ae |
pte_bad_packet,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Unexpected packet context. */
|
|
Packit |
b1f7ae |
pte_bad_context,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Decoder reached end of trace stream. */
|
|
Packit |
b1f7ae |
pte_eos,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* No packet matching the query to be found. */
|
|
Packit |
b1f7ae |
pte_bad_query,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Decoder out of memory. */
|
|
Packit |
b1f7ae |
pte_nomem,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Bad configuration. */
|
|
Packit |
b1f7ae |
pte_bad_config,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* There is no IP. */
|
|
Packit |
b1f7ae |
pte_noip,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The IP has been suppressed. */
|
|
Packit |
b1f7ae |
pte_ip_suppressed,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* There is no memory mapped at the requested address. */
|
|
Packit |
b1f7ae |
pte_nomap,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* An instruction could not be decoded. */
|
|
Packit |
b1f7ae |
pte_bad_insn,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* No wall-clock time is available. */
|
|
Packit |
b1f7ae |
pte_no_time,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* No core:bus ratio available. */
|
|
Packit |
b1f7ae |
pte_no_cbr,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Bad traced image. */
|
|
Packit |
b1f7ae |
pte_bad_image,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* A locking error. */
|
|
Packit |
b1f7ae |
pte_bad_lock,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The requested feature is not supported. */
|
|
Packit |
b1f7ae |
pte_not_supported,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The return address stack is empty. */
|
|
Packit |
b1f7ae |
pte_retstack_empty,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* A compressed return is not indicated correctly by a taken branch. */
|
|
Packit |
b1f7ae |
pte_bad_retcomp,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The current decoder state does not match the state in the trace. */
|
|
Packit |
b1f7ae |
pte_bad_status_update,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The trace did not contain an expected enabled event. */
|
|
Packit |
b1f7ae |
pte_no_enable,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* An event was ignored. */
|
|
Packit |
b1f7ae |
pte_event_ignored
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Decode a function return value into an pt_error_code. */
|
|
Packit |
b1f7ae |
static inline enum pt_error_code pt_errcode(int status)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
return (status >= 0) ? pte_ok : (enum pt_error_code) -status;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Return a human readable error string. */
|
|
Packit |
b1f7ae |
extern pt_export const char *pt_errstr(enum pt_error_code);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Configuration. */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A cpu vendor. */
|
|
Packit |
b1f7ae |
enum pt_cpu_vendor {
|
|
Packit |
b1f7ae |
pcv_unknown,
|
|
Packit |
b1f7ae |
pcv_intel
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A cpu identifier. */
|
|
Packit |
b1f7ae |
struct pt_cpu {
|
|
Packit |
b1f7ae |
/** The cpu vendor. */
|
|
Packit |
b1f7ae |
enum pt_cpu_vendor vendor;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The cpu family. */
|
|
Packit |
b1f7ae |
uint16_t family;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The cpu model. */
|
|
Packit |
b1f7ae |
uint8_t model;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The stepping. */
|
|
Packit |
b1f7ae |
uint8_t stepping;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A collection of Intel PT errata. */
|
|
Packit |
b1f7ae |
struct pt_errata {
|
|
Packit |
b1f7ae |
/** BDM70: Intel(R) Processor Trace PSB+ Packets May Contain
|
|
Packit |
b1f7ae |
* Unexpected Packets.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Same as: SKD024.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Some Intel Processor Trace packets should be issued only between
|
|
Packit |
b1f7ae |
* TIP.PGE and TIP.PGD packets. Due to this erratum, when a TIP.PGE
|
|
Packit |
b1f7ae |
* packet is generated it may be preceded by a PSB+ that incorrectly
|
|
Packit |
b1f7ae |
* includes FUP and MODE.Exec packets.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t bdm70:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** BDM64: An Incorrect LBR or Intel(R) Processor Trace Packet May Be
|
|
Packit |
b1f7ae |
* Recorded Following a Transactional Abort.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Use of Intel(R) Transactional Synchronization Extensions (Intel(R)
|
|
Packit |
b1f7ae |
* TSX) may result in a transactional abort. If an abort occurs
|
|
Packit |
b1f7ae |
* immediately following a branch instruction, an incorrect branch
|
|
Packit |
b1f7ae |
* target may be logged in an LBR (Last Branch Record) or in an Intel(R)
|
|
Packit |
b1f7ae |
* Processor Trace (Intel(R) PT) packet before the LBR or Intel PT
|
|
Packit |
b1f7ae |
* packet produced by the abort.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t bdm64:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** SKD007: Intel(R) PT Buffer Overflow May Result in Incorrect Packets.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Under complex micro-architectural conditions, an Intel PT (Processor
|
|
Packit |
b1f7ae |
* Trace) OVF (Overflow) packet may be issued after the first byte of a
|
|
Packit |
b1f7ae |
* multi-byte CYC (Cycle Count) packet, instead of any remaining bytes
|
|
Packit |
b1f7ae |
* of the CYC.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t skd007:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** SKD022: VM Entry That Clears TraceEn May Generate a FUP.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If VM entry clears Intel(R) PT (Intel Processor Trace)
|
|
Packit |
b1f7ae |
* IA32_RTIT_CTL.TraceEn (MSR 570H, bit 0) while PacketEn is 1 then a
|
|
Packit |
b1f7ae |
* FUP (Flow Update Packet) will precede the TIP.PGD (Target IP Packet,
|
|
Packit |
b1f7ae |
* Packet Generation Disable). VM entry can clear TraceEn if the
|
|
Packit |
b1f7ae |
* VM-entry MSR-load area includes an entry for the IA32_RTIT_CTL MSR.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t skd022:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** SKD010: Intel(R) PT FUP May be Dropped After OVF.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Same as: SKD014.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Some Intel PT (Intel Processor Trace) OVF (Overflow) packets may not
|
|
Packit |
b1f7ae |
* be followed by a FUP (Flow Update Packet) or TIP.PGE (Target IP
|
|
Packit |
b1f7ae |
* Packet, Packet Generation Enable).
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t skd010:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Reserve a few bytes for the future. */
|
|
Packit |
b1f7ae |
uint32_t reserved[15];
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A collection of decoder-specific configuration flags. */
|
|
Packit |
b1f7ae |
struct pt_conf_flags {
|
|
Packit |
b1f7ae |
/** The decoder variant. */
|
|
Packit |
b1f7ae |
union {
|
|
Packit |
b1f7ae |
/** Flags for the block decoder. */
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** End a block after a call instruction. */
|
|
Packit |
b1f7ae |
uint32_t end_on_call:1;
|
|
Packit |
b1f7ae |
} block;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Reserve a few bytes for future extensions. */
|
|
Packit |
b1f7ae |
uint32_t reserved[4];
|
|
Packit |
b1f7ae |
} variant;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** An unknown packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_unknown;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** An Intel PT decoder configuration.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
struct pt_config {
|
|
Packit |
b1f7ae |
/** The size of the config structure in bytes. */
|
|
Packit |
b1f7ae |
size_t size;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The trace buffer begin address. */
|
|
Packit |
b1f7ae |
uint8_t *begin;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The trace buffer end address. */
|
|
Packit |
b1f7ae |
uint8_t *end;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** An optional callback for handling unknown packets.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If \@callback is not NULL, it is called for any unknown opcode.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** The callback function.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* It shall decode the packet at \@pos into \@unknown.
|
|
Packit |
b1f7ae |
* It shall return the number of bytes read upon success.
|
|
Packit |
b1f7ae |
* It shall return a negative pt_error_code otherwise.
|
|
Packit |
b1f7ae |
* The below context is passed as \@context.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
int (*callback)(struct pt_packet_unknown *unknown,
|
|
Packit |
b1f7ae |
const struct pt_config *config,
|
|
Packit |
b1f7ae |
const uint8_t *pos, void *context);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The user-defined context for this configuration. */
|
|
Packit |
b1f7ae |
void *context;
|
|
Packit |
b1f7ae |
} decode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The cpu on which Intel PT has been recorded. */
|
|
Packit |
b1f7ae |
struct pt_cpu cpu;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The errata to apply when encoding or decoding Intel PT. */
|
|
Packit |
b1f7ae |
struct pt_errata errata;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The CTC frequency.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This is only required if MTC packets have been enabled in
|
|
Packit |
b1f7ae |
* IA32_RTIT_CTRL.MTCEn.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t cpuid_0x15_eax, cpuid_0x15_ebx;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The MTC frequency as defined in IA32_RTIT_CTL.MTCFreq.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This is only required if MTC packets have been enabled in
|
|
Packit |
b1f7ae |
* IA32_RTIT_CTRL.MTCEn.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint8_t mtc_freq;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The nominal frequency as defined in MSR_PLATFORM_INFO[15:8].
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This is only required if CYC packets have been enabled in
|
|
Packit |
b1f7ae |
* IA32_RTIT_CTRL.CYCEn.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If zero, timing calibration will only be able to use MTC and CYC
|
|
Packit |
b1f7ae |
* packets.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If not zero, timing calibration will also be able to use CBR
|
|
Packit |
b1f7ae |
* packets.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint8_t nom_freq;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A collection of decoder-specific flags. */
|
|
Packit |
b1f7ae |
struct pt_conf_flags flags;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Zero-initialize an Intel PT configuration. */
|
|
Packit |
b1f7ae |
static inline void pt_config_init(struct pt_config *config)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
memset(config, 0, sizeof(*config));
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
config->size = sizeof(*config);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Determine errata for a given cpu.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Updates \@errata based on \@cpu.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns 0 on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@errata or \@cpu is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_cpu_errata(struct pt_errata *errata,
|
|
Packit |
b1f7ae |
const struct pt_cpu *cpu);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Packet encoder / decoder. */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* We define a few abbreviations outside of the below enum as we don't
|
|
Packit |
b1f7ae |
* want to handle those in switches.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
enum {
|
|
Packit |
b1f7ae |
ppt_ext = pt_opc_ext << 8,
|
|
Packit |
b1f7ae |
ppt_ext2 = ppt_ext << 8 | pt_ext_ext2 << 8
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Intel PT packet types. */
|
|
Packit |
b1f7ae |
enum pt_packet_type {
|
|
Packit |
b1f7ae |
/* 1-byte header packets. */
|
|
Packit |
b1f7ae |
ppt_pad = pt_opc_pad,
|
|
Packit |
b1f7ae |
ppt_tip = pt_opc_tip,
|
|
Packit |
b1f7ae |
ppt_tnt_8 = pt_opc_tnt_8 | 0xFE,
|
|
Packit |
b1f7ae |
ppt_tip_pge = pt_opc_tip_pge,
|
|
Packit |
b1f7ae |
ppt_tip_pgd = pt_opc_tip_pgd,
|
|
Packit |
b1f7ae |
ppt_fup = pt_opc_fup,
|
|
Packit |
b1f7ae |
ppt_mode = pt_opc_mode,
|
|
Packit |
b1f7ae |
ppt_tsc = pt_opc_tsc,
|
|
Packit |
b1f7ae |
ppt_mtc = pt_opc_mtc,
|
|
Packit |
b1f7ae |
ppt_cyc = pt_opc_cyc,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* 2-byte header packets. */
|
|
Packit |
b1f7ae |
ppt_psb = ppt_ext | pt_ext_psb,
|
|
Packit |
b1f7ae |
ppt_tnt_64 = ppt_ext | pt_ext_tnt_64,
|
|
Packit |
b1f7ae |
ppt_pip = ppt_ext | pt_ext_pip,
|
|
Packit |
b1f7ae |
ppt_stop = ppt_ext | pt_ext_stop,
|
|
Packit |
b1f7ae |
ppt_ovf = ppt_ext | pt_ext_ovf,
|
|
Packit |
b1f7ae |
ppt_psbend = ppt_ext | pt_ext_psbend,
|
|
Packit |
b1f7ae |
ppt_cbr = ppt_ext | pt_ext_cbr,
|
|
Packit |
b1f7ae |
ppt_tma = ppt_ext | pt_ext_tma,
|
|
Packit |
b1f7ae |
ppt_vmcs = ppt_ext | pt_ext_vmcs,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* 3-byte header packets. */
|
|
Packit |
b1f7ae |
ppt_mnt = ppt_ext2 | pt_ext2_mnt,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* A packet decodable by the optional decoder callback. */
|
|
Packit |
b1f7ae |
ppt_unknown = 0x7ffffffe,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* An invalid packet. */
|
|
Packit |
b1f7ae |
ppt_invalid = 0x7fffffff
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A TNT-8 or TNT-64 packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_tnt {
|
|
Packit |
b1f7ae |
/** TNT payload bit size. */
|
|
Packit |
b1f7ae |
uint8_t bit_size;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** TNT payload excluding stop bit. */
|
|
Packit |
b1f7ae |
uint64_t payload;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A packet with IP payload. */
|
|
Packit |
b1f7ae |
struct pt_packet_ip {
|
|
Packit |
b1f7ae |
/** IP compression. */
|
|
Packit |
b1f7ae |
enum pt_ip_compression ipc;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Zero-extended payload ip. */
|
|
Packit |
b1f7ae |
uint64_t ip;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A mode.exec packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_mode_exec {
|
|
Packit |
b1f7ae |
/** The mode.exec csl bit. */
|
|
Packit |
b1f7ae |
uint32_t csl:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The mode.exec csd bit. */
|
|
Packit |
b1f7ae |
uint32_t csd:1;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static inline enum pt_exec_mode
|
|
Packit |
b1f7ae |
pt_get_exec_mode(const struct pt_packet_mode_exec *packet)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (packet->csl)
|
|
Packit |
b1f7ae |
return packet->csd ? ptem_unknown : ptem_64bit;
|
|
Packit |
b1f7ae |
else
|
|
Packit |
b1f7ae |
return packet->csd ? ptem_32bit : ptem_16bit;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static inline struct pt_packet_mode_exec
|
|
Packit |
b1f7ae |
pt_set_exec_mode(enum pt_exec_mode mode)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
struct pt_packet_mode_exec packet;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
switch (mode) {
|
|
Packit |
b1f7ae |
default:
|
|
Packit |
b1f7ae |
packet.csl = 1;
|
|
Packit |
b1f7ae |
packet.csd = 1;
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
case ptem_64bit:
|
|
Packit |
b1f7ae |
packet.csl = 1;
|
|
Packit |
b1f7ae |
packet.csd = 0;
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
case ptem_32bit:
|
|
Packit |
b1f7ae |
packet.csl = 0;
|
|
Packit |
b1f7ae |
packet.csd = 1;
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
case ptem_16bit:
|
|
Packit |
b1f7ae |
packet.csl = 0;
|
|
Packit |
b1f7ae |
packet.csd = 0;
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return packet;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A mode.tsx packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_mode_tsx {
|
|
Packit |
b1f7ae |
/** The mode.tsx intx bit. */
|
|
Packit |
b1f7ae |
uint32_t intx:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The mode.tsx abrt bit. */
|
|
Packit |
b1f7ae |
uint32_t abrt:1;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A mode packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_mode {
|
|
Packit |
b1f7ae |
/** Mode leaf. */
|
|
Packit |
b1f7ae |
enum pt_mode_leaf leaf;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Mode bits. */
|
|
Packit |
b1f7ae |
union {
|
|
Packit |
b1f7ae |
/** Packet: mode.exec. */
|
|
Packit |
b1f7ae |
struct pt_packet_mode_exec exec;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: mode.tsx. */
|
|
Packit |
b1f7ae |
struct pt_packet_mode_tsx tsx;
|
|
Packit |
b1f7ae |
} bits;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A PIP packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_pip {
|
|
Packit |
b1f7ae |
/** The CR3 value. */
|
|
Packit |
b1f7ae |
uint64_t cr3;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The non-root bit. */
|
|
Packit |
b1f7ae |
uint32_t nr:1;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A TSC packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_tsc {
|
|
Packit |
b1f7ae |
/** The TSC value. */
|
|
Packit |
b1f7ae |
uint64_t tsc;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A CBR packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_cbr {
|
|
Packit |
b1f7ae |
/** The core/bus cycle ratio. */
|
|
Packit |
b1f7ae |
uint8_t ratio;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A TMA packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_tma {
|
|
Packit |
b1f7ae |
/** The crystal clock tick counter value. */
|
|
Packit |
b1f7ae |
uint16_t ctc;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The fast counter value. */
|
|
Packit |
b1f7ae |
uint16_t fc;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A MTC packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_mtc {
|
|
Packit |
b1f7ae |
/** The crystal clock tick counter value. */
|
|
Packit |
b1f7ae |
uint8_t ctc;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A CYC packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_cyc {
|
|
Packit |
b1f7ae |
/** The cycle counter value. */
|
|
Packit |
b1f7ae |
uint64_t value;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A VMCS packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_vmcs {
|
|
Packit |
b1f7ae |
/* The VMCS Base Address (i.e. the shifted payload). */
|
|
Packit |
b1f7ae |
uint64_t base;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A MNT packet. */
|
|
Packit |
b1f7ae |
struct pt_packet_mnt {
|
|
Packit |
b1f7ae |
/** The raw payload. */
|
|
Packit |
b1f7ae |
uint64_t payload;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** An unknown packet decodable by the optional decoder callback. */
|
|
Packit |
b1f7ae |
struct pt_packet_unknown {
|
|
Packit |
b1f7ae |
/** Pointer to the raw packet bytes. */
|
|
Packit |
b1f7ae |
const uint8_t *packet;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Optional pointer to a user-defined structure. */
|
|
Packit |
b1f7ae |
void *priv;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** An Intel PT packet. */
|
|
Packit |
b1f7ae |
struct pt_packet {
|
|
Packit |
b1f7ae |
/** The type of the packet.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This also determines the \@payload field.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
enum pt_packet_type type;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The size of the packet including opcode and payload. */
|
|
Packit |
b1f7ae |
uint8_t size;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet specific data. */
|
|
Packit |
b1f7ae |
union {
|
|
Packit |
b1f7ae |
/** Packets: pad, ovf, psb, psbend, stop - no payload. */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: tnt-8, tnt-64. */
|
|
Packit |
b1f7ae |
struct pt_packet_tnt tnt;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: tip, fup, tip.pge, tip.pgd. */
|
|
Packit |
b1f7ae |
struct pt_packet_ip ip;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: mode. */
|
|
Packit |
b1f7ae |
struct pt_packet_mode mode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: pip. */
|
|
Packit |
b1f7ae |
struct pt_packet_pip pip;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: tsc. */
|
|
Packit |
b1f7ae |
struct pt_packet_tsc tsc;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: cbr. */
|
|
Packit |
b1f7ae |
struct pt_packet_cbr cbr;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: tma. */
|
|
Packit |
b1f7ae |
struct pt_packet_tma tma;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: mtc. */
|
|
Packit |
b1f7ae |
struct pt_packet_mtc mtc;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: cyc. */
|
|
Packit |
b1f7ae |
struct pt_packet_cyc cyc;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: vmcs. */
|
|
Packit |
b1f7ae |
struct pt_packet_vmcs vmcs;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: mnt. */
|
|
Packit |
b1f7ae |
struct pt_packet_mnt mnt;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Packet: unknown. */
|
|
Packit |
b1f7ae |
struct pt_packet_unknown unknown;
|
|
Packit |
b1f7ae |
} payload;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Packet encoder. */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Allocate an Intel PT packet encoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The encoder will work on the buffer defined in \@config, it shall contain
|
|
Packit |
b1f7ae |
* raw trace data and remain valid for the lifetime of the encoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The encoder starts at the beginning of the trace buffer.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export struct pt_encoder *
|
|
Packit |
b1f7ae |
pt_alloc_encoder(const struct pt_config *config);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Free an Intel PT packet encoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@encoder must not be used after a successful return.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export void pt_free_encoder(struct pt_encoder *encoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Hard set synchronization point of an Intel PT packet encoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Synchronize \@encoder to \@offset within the trace buffer.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_eos if the given offset is behind the end of the trace buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@encoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_enc_sync_set(struct pt_encoder *encoder,
|
|
Packit |
b1f7ae |
uint64_t offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the current packet encoder position.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Fills the current \@encoder position into \@offset.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This is useful for reporting errors.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@encoder or \@offset is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_enc_get_offset(struct pt_encoder *encoder,
|
|
Packit |
b1f7ae |
uint64_t *offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Return a pointer to \@encoder's configuration.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a non-null pointer on success, NULL if \@encoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export const struct pt_config *
|
|
Packit |
b1f7ae |
pt_enc_get_config(const struct pt_encoder *encoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Encode an Intel PT packet.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Writes \@packet at \@encoder's current position in the Intel PT buffer and
|
|
Packit |
b1f7ae |
* advances the \@encoder beyond the written packet.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@packet.size field is ignored.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* In case of errors, the \@encoder is not advanced and nothing is written
|
|
Packit |
b1f7ae |
* into the Intel PT buffer.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns the number of bytes written on success, a negative error code
|
|
Packit |
b1f7ae |
* otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if \@packet.type is not known.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if \@packet's payload is invalid.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if \@encoder reached the end of the Intel PT buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@encoder or \@packet is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_enc_next(struct pt_encoder *encoder,
|
|
Packit |
b1f7ae |
const struct pt_packet *packet);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Packet decoder. */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Allocate an Intel PT packet decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The decoder will work on the buffer defined in \@config, it shall contain
|
|
Packit |
b1f7ae |
* raw trace data and remain valid for the lifetime of the decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The decoder needs to be synchronized before it can be used.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export struct pt_packet_decoder *
|
|
Packit |
b1f7ae |
pt_pkt_alloc_decoder(const struct pt_config *config);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Free an Intel PT packet decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@decoder must not be used after a successful return.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export void pt_pkt_free_decoder(struct pt_packet_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Synchronize an Intel PT packet decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Search for the next synchronization point in forward or backward direction.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If \@decoder has not been synchronized, yet, the search is started at the
|
|
Packit |
b1f7ae |
* beginning of the trace buffer in case of forward synchronization and at the
|
|
Packit |
b1f7ae |
* end of the trace buffer in case of backward synchronization.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero or a positive value on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_eos if no further synchronization point is found.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_pkt_sync_forward(struct pt_packet_decoder *decoder);
|
|
Packit |
b1f7ae |
extern pt_export int pt_pkt_sync_backward(struct pt_packet_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Hard set synchronization point of an Intel PT decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Synchronize \@decoder to \@offset within the trace buffer.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_eos if the given offset is behind the end of the trace buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_pkt_sync_set(struct pt_packet_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the current decoder position.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Fills the current \@decoder position into \@offset.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This is useful for reporting errors.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@offset is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_pkt_get_offset(struct pt_packet_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the position of the last synchronization point.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Fills the last synchronization position into \@offset.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This is useful when splitting a trace stream for parallel decoding.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@offset is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_pkt_get_sync_offset(struct pt_packet_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Return a pointer to \@decoder's configuration.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a non-null pointer on success, NULL if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export const struct pt_config *
|
|
Packit |
b1f7ae |
pt_pkt_get_config(const struct pt_packet_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Decode the next packet and advance the decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Decodes the packet at \@decoder's current position into \@packet and
|
|
Packit |
b1f7ae |
* adjusts the \@decoder's position by the number of bytes the packet had
|
|
Packit |
b1f7ae |
* consumed.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@size argument must be set to sizeof(struct pt_packet).
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns the number of bytes consumed on success, a negative error code
|
|
Packit |
b1f7ae |
* otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if the packet is unknown.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if an unknown packet payload is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if \@decoder reached the end of the Intel PT buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@packet is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_pkt_next(struct pt_packet_decoder *decoder,
|
|
Packit |
b1f7ae |
struct pt_packet *packet, size_t size);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Query decoder. */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Decoder status flags. */
|
|
Packit |
b1f7ae |
enum pt_status_flag {
|
|
Packit |
b1f7ae |
/** There is an event pending. */
|
|
Packit |
b1f7ae |
pts_event_pending = 1 << 0,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The address has been suppressed. */
|
|
Packit |
b1f7ae |
pts_ip_suppressed = 1 << 1,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** There is no more trace data available. */
|
|
Packit |
b1f7ae |
pts_eos = 1 << 2
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Event types. */
|
|
Packit |
b1f7ae |
enum pt_event_type {
|
|
Packit |
b1f7ae |
/* Tracing has been enabled/disabled. */
|
|
Packit |
b1f7ae |
ptev_enabled,
|
|
Packit |
b1f7ae |
ptev_disabled,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Tracing has been disabled asynchronously. */
|
|
Packit |
b1f7ae |
ptev_async_disabled,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* An asynchronous branch, e.g. interrupt. */
|
|
Packit |
b1f7ae |
ptev_async_branch,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* A synchronous paging event. */
|
|
Packit |
b1f7ae |
ptev_paging,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* An asynchronous paging event. */
|
|
Packit |
b1f7ae |
ptev_async_paging,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Trace overflow. */
|
|
Packit |
b1f7ae |
ptev_overflow,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* An execution mode change. */
|
|
Packit |
b1f7ae |
ptev_exec_mode,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* A transactional execution state change. */
|
|
Packit |
b1f7ae |
ptev_tsx,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Trace Stop. */
|
|
Packit |
b1f7ae |
ptev_stop,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* A synchronous vmcs event. */
|
|
Packit |
b1f7ae |
ptev_vmcs,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* An asynchronous vmcs event. */
|
|
Packit |
b1f7ae |
ptev_async_vmcs
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** An event. */
|
|
Packit |
b1f7ae |
struct pt_event {
|
|
Packit |
b1f7ae |
/** The type of the event. */
|
|
Packit |
b1f7ae |
enum pt_event_type type;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A flag indicating that the event IP has been suppressed. */
|
|
Packit |
b1f7ae |
uint32_t ip_suppressed:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A flag indicating that the event is for status update. */
|
|
Packit |
b1f7ae |
uint32_t status_update:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A flag indicating that the event has timing information. */
|
|
Packit |
b1f7ae |
uint32_t has_tsc:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The time stamp count of the event.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This field is only valid if \@has_tsc is set.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint64_t tsc;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The number of lost mtc and cyc packets.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This gives an idea about the quality of the \@tsc. The more packets
|
|
Packit |
b1f7ae |
* were dropped, the less precise timing is.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t lost_mtc;
|
|
Packit |
b1f7ae |
uint32_t lost_cyc;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Reserved space for future extensions. */
|
|
Packit |
b1f7ae |
uint64_t reserved[2];
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Event specific data. */
|
|
Packit |
b1f7ae |
union {
|
|
Packit |
b1f7ae |
/** Event: enabled. */
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** The address at which tracing resumes. */
|
|
Packit |
b1f7ae |
uint64_t ip;
|
|
Packit |
b1f7ae |
} enabled;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Event: disabled. */
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** The destination of the first branch inside a
|
|
Packit |
b1f7ae |
* filtered area.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This field is not valid if \@ip_suppressed is set.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint64_t ip;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The exact source ip needs to be determined using
|
|
Packit |
b1f7ae |
* disassembly and the filter configuration.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
} disabled;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Event: async disabled. */
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** The source address of the asynchronous branch that
|
|
Packit |
b1f7ae |
* disabled tracing.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint64_t at;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The destination of the first branch inside a
|
|
Packit |
b1f7ae |
* filtered area.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This field is not valid if \@ip_suppressed is set.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint64_t ip;
|
|
Packit |
b1f7ae |
} async_disabled;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Event: async branch. */
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** The branch source address. */
|
|
Packit |
b1f7ae |
uint64_t from;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The branch destination address.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This field is not valid if \@ip_suppressed is set.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint64_t to;
|
|
Packit |
b1f7ae |
} async_branch;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Event: paging. */
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** The updated CR3 value.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The lower 5 bit have been zeroed out.
|
|
Packit |
b1f7ae |
* The upper bits have been zeroed out depending on the
|
|
Packit |
b1f7ae |
* maximum possible address.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint64_t cr3;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A flag indicating whether the cpu is operating in
|
|
Packit |
b1f7ae |
* vmx non-root (guest) mode.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t non_root:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The address at which the event is effective is
|
|
Packit |
b1f7ae |
* obvious from the disassembly.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
} paging;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Event: async paging. */
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** The updated CR3 value.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The lower 5 bit have been zeroed out.
|
|
Packit |
b1f7ae |
* The upper bits have been zeroed out depending on the
|
|
Packit |
b1f7ae |
* maximum possible address.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint64_t cr3;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A flag indicating whether the cpu is operating in
|
|
Packit |
b1f7ae |
* vmx non-root (guest) mode.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t non_root:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The address at which the event is effective. */
|
|
Packit |
b1f7ae |
uint64_t ip;
|
|
Packit |
b1f7ae |
} async_paging;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Event: overflow. */
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** The address at which tracing resumes after overflow.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This field is not valid, if ip_suppressed is set.
|
|
Packit |
b1f7ae |
* In this case, the overflow resolved while tracing
|
|
Packit |
b1f7ae |
* was disabled.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint64_t ip;
|
|
Packit |
b1f7ae |
} overflow;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Event: exec mode. */
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** The execution mode. */
|
|
Packit |
b1f7ae |
enum pt_exec_mode mode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The address at which the event is effective. */
|
|
Packit |
b1f7ae |
uint64_t ip;
|
|
Packit |
b1f7ae |
} exec_mode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Event: tsx. */
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** The address at which the event is effective.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This field is not valid if \@ip_suppressed is set.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint64_t ip;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A flag indicating speculative execution mode. */
|
|
Packit |
b1f7ae |
uint32_t speculative:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A flag indicating speculative execution aborts. */
|
|
Packit |
b1f7ae |
uint32_t aborted:1;
|
|
Packit |
b1f7ae |
} tsx;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Event: vmcs. */
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** The VMCS base address.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The address is zero-extended with the lower 12 bits
|
|
Packit |
b1f7ae |
* all zero.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint64_t base;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The new VMCS base address should be stored and
|
|
Packit |
b1f7ae |
* applied on subsequent VM entries.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
} vmcs;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Event: async vmcs. */
|
|
Packit |
b1f7ae |
struct {
|
|
Packit |
b1f7ae |
/** The VMCS base address.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The address is zero-extended with the lower 12 bits
|
|
Packit |
b1f7ae |
* all zero.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint64_t base;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The address at which the event is effective. */
|
|
Packit |
b1f7ae |
uint64_t ip;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* An async paging event that binds to the same IP
|
|
Packit |
b1f7ae |
* will always succeed this async vmcs event.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
} async_vmcs;
|
|
Packit |
b1f7ae |
} variant;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Allocate an Intel PT query decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The decoder will work on the buffer defined in \@config, it shall contain
|
|
Packit |
b1f7ae |
* raw trace data and remain valid for the lifetime of the decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The decoder needs to be synchronized before it can be used.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export struct pt_query_decoder *
|
|
Packit |
b1f7ae |
pt_qry_alloc_decoder(const struct pt_config *config);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Free an Intel PT query decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@decoder must not be used after a successful return.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export void pt_qry_free_decoder(struct pt_query_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Synchronize an Intel PT query decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Search for the next synchronization point in forward or backward direction.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If \@decoder has not been synchronized, yet, the search is started at the
|
|
Packit |
b1f7ae |
* beginning of the trace buffer in case of forward synchronization and at the
|
|
Packit |
b1f7ae |
* end of the trace buffer in case of backward synchronization.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If \@ip is not NULL, set it to last ip.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a non-negative pt_status_flag bit-vector on success, a negative error
|
|
Packit |
b1f7ae |
* code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if an unknown packet is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if an unknown packet payload is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if no further synchronization point is found.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_qry_sync_forward(struct pt_query_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *ip);
|
|
Packit |
b1f7ae |
extern pt_export int pt_qry_sync_backward(struct pt_query_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *ip);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Manually synchronize an Intel PT query decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Synchronize \@decoder on the syncpoint at \@offset. There must be a PSB
|
|
Packit |
b1f7ae |
* packet at \@offset.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If \@ip is not NULL, set it to last ip.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a non-negative pt_status_flag bit-vector on success, a negative error
|
|
Packit |
b1f7ae |
* code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if an unknown packet is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if an unknown packet payload is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if \@offset lies outside of \@decoder's trace buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if \@decoder reaches the end of its trace buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if there is no syncpoint at \@offset.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_qry_sync_set(struct pt_query_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *ip, uint64_t offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the current decoder position.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Fills the current \@decoder position into \@offset.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This is useful for reporting errors.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@offset is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_qry_get_offset(struct pt_query_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the position of the last synchronization point.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Fills the last synchronization position into \@offset.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This is useful for splitting a trace stream for parallel decoding.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@offset is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_qry_get_sync_offset(struct pt_query_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Return a pointer to \@decoder's configuration.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a non-null pointer on success, NULL if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export const struct pt_config *
|
|
Packit |
b1f7ae |
pt_qry_get_config(const struct pt_query_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Query whether the next unconditional branch has been taken.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* On success, provides 1 (taken) or 0 (not taken) in \@taken for the next
|
|
Packit |
b1f7ae |
* conditional branch and updates \@decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a non-negative pt_status_flag bit-vector on success, a negative error
|
|
Packit |
b1f7ae |
* code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if an unknown packet is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if an unknown packet payload is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_query if no conditional branch is found.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if decoding reached the end of the Intel PT buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@taken is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_qry_cond_branch(struct pt_query_decoder *decoder,
|
|
Packit |
b1f7ae |
int *taken);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the next indirect branch destination.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* On success, provides the linear destination address of the next indirect
|
|
Packit |
b1f7ae |
* branch in \@ip and updates \@decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a non-negative pt_status_flag bit-vector on success, a negative error
|
|
Packit |
b1f7ae |
* code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if an unknown packet is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if an unknown packet payload is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_query if no indirect branch is found.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if decoding reached the end of the Intel PT buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@ip is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_qry_indirect_branch(struct pt_query_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *ip);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Query the next pending event.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* On success, provides the next event \@event and updates \@decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@size argument must be set to sizeof(struct pt_event).
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a non-negative pt_status_flag bit-vector on success, a negative error
|
|
Packit |
b1f7ae |
* code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if an unknown packet is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if an unknown packet payload is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_query if no event is found.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if decoding reached the end of the Intel PT buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@event is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@size is too small.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_qry_event(struct pt_query_decoder *decoder,
|
|
Packit |
b1f7ae |
struct pt_event *event, size_t size);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Query the current time.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* On success, provides the time at \@decoder's current position in \@time.
|
|
Packit |
b1f7ae |
* Since \@decoder is reading ahead until the next indirect branch or event,
|
|
Packit |
b1f7ae |
* the value matches the time for that branch or event.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The time is similar to what a rdtsc instruction would return. Depending
|
|
Packit |
b1f7ae |
* on the configuration, the time may not be fully accurate. If TSC is not
|
|
Packit |
b1f7ae |
* enabled, the time is relative to the last synchronization and can't be used
|
|
Packit |
b1f7ae |
* to correlate with other TSC-based time sources. In this case, -pte_no_time
|
|
Packit |
b1f7ae |
* is returned and the relative time is provided in \@time.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Some timing-related packets may need to be dropped (mostly due to missing
|
|
Packit |
b1f7ae |
* calibration or incomplete configuration). To get an idea about the quality
|
|
Packit |
b1f7ae |
* of the estimated time, we record the number of dropped MTC and CYC packets.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If \@lost_mtc is not NULL, set it to the number of lost MTC packets.
|
|
Packit |
b1f7ae |
* If \@lost_cyc is not NULL, set it to the number of lost CYC packets.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@time is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_no_time if there has not been a TSC packet.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_qry_time(struct pt_query_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *time, uint32_t *lost_mtc,
|
|
Packit |
b1f7ae |
uint32_t *lost_cyc);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Return the current core bus ratio.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* On success, provides the core:bus ratio at \@decoder's current position
|
|
Packit |
b1f7ae |
* in \@cbr.
|
|
Packit |
b1f7ae |
* Since \@decoder is reading ahead until the next indirect branch or event,
|
|
Packit |
b1f7ae |
* the value matches the core:bus ratio for that branch or event.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The ratio is defined as core cycles per bus clock cycle.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@cbr is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_no_cbr if there has not been a CBR packet.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_qry_core_bus_ratio(struct pt_query_decoder *decoder,
|
|
Packit |
b1f7ae |
uint32_t *cbr);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Traced image. */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** An Intel PT address space identifier.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This identifies a particular address space when adding file sections or
|
|
Packit |
b1f7ae |
* when reading memory.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
struct pt_asid {
|
|
Packit |
b1f7ae |
/** The size of this object - set to sizeof(struct pt_asid). */
|
|
Packit |
b1f7ae |
size_t size;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The CR3 value. */
|
|
Packit |
b1f7ae |
uint64_t cr3;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The VMCS Base address. */
|
|
Packit |
b1f7ae |
uint64_t vmcs;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** An unknown CR3 value to be used for pt_asid objects. */
|
|
Packit |
b1f7ae |
static const uint64_t pt_asid_no_cr3 = 0xffffffffffffffffull;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** An unknown VMCS Base value to be used for pt_asid objects. */
|
|
Packit |
b1f7ae |
static const uint64_t pt_asid_no_vmcs = 0xffffffffffffffffull;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Initialize an address space identifier. */
|
|
Packit |
b1f7ae |
static inline void pt_asid_init(struct pt_asid *asid)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
asid->size = sizeof(*asid);
|
|
Packit |
b1f7ae |
asid->cr3 = pt_asid_no_cr3;
|
|
Packit |
b1f7ae |
asid->vmcs = pt_asid_no_vmcs;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A cache of traced image sections. */
|
|
Packit |
b1f7ae |
struct pt_image_section_cache;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Allocate a traced memory image section cache.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* An optional \@name may be given to the cache. The name string is copied.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a new traced memory image section cache on success, NULL otherwise.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export struct pt_image_section_cache *
|
|
Packit |
b1f7ae |
pt_iscache_alloc(const char *name);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Free a traced memory image section cache.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@iscache must have been allocated with pt_iscache_alloc().
|
|
Packit |
b1f7ae |
* The \@iscache must not be used after a successful return.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export void pt_iscache_free(struct pt_image_section_cache *iscache);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the image section cache name.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a pointer to \@iscache's name or NULL if there is no name.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export const char *
|
|
Packit |
b1f7ae |
pt_iscache_name(const struct pt_image_section_cache *iscache);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Add a new file section to the traced memory image section cache.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Adds a new section consisting of \@size bytes starting at \@offset in
|
|
Packit |
b1f7ae |
* \@filename loaded at the virtual address \@vaddr if \@iscache does not
|
|
Packit |
b1f7ae |
* already contain such a section.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns an image section identifier (isid) uniquely identifying that section
|
|
Packit |
b1f7ae |
* in \@iscache.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The section is silently truncated to match the size of \@filename.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a positive isid on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@iscache or \@filename is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@offset is too big.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_iscache_add_file(struct pt_image_section_cache *iscache,
|
|
Packit |
b1f7ae |
const char *filename, uint64_t offset,
|
|
Packit |
b1f7ae |
uint64_t size, uint64_t vaddr);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Read memory from a cached file section
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Reads \@size bytes of memory starting at virtual address \@vaddr in the
|
|
Packit |
b1f7ae |
* section identified by \@isid in \@iscache into \@buffer.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The caller is responsible for allocating a \@buffer of at least \@size bytes.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The read request may be truncated if it crosses section boundaries or if
|
|
Packit |
b1f7ae |
* \@size is getting too big. We support reading at least 4Kbyte in one chunk
|
|
Packit |
b1f7ae |
* unless the read would cross a section boundary.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns the number of bytes read on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@iscache or \@buffer is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@size is zero.
|
|
Packit |
b1f7ae |
* Returns -pte_nomap if \@vaddr is not contained in section \@isid.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_image if \@iscache does not contain \@isid.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_iscache_read(struct pt_image_section_cache *iscache,
|
|
Packit |
b1f7ae |
uint8_t *buffer, uint64_t size, int isid,
|
|
Packit |
b1f7ae |
uint64_t vaddr);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The traced memory image. */
|
|
Packit |
b1f7ae |
struct pt_image;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Allocate a traced memory image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* An optional \@name may be given to the image. The name string is copied.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a new traced memory image on success, NULL otherwise.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export struct pt_image *pt_image_alloc(const char *name);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Free a traced memory image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@image must have been allocated with pt_image_alloc().
|
|
Packit |
b1f7ae |
* The \@image must not be used after a successful return.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export void pt_image_free(struct pt_image *image);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the image name.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a pointer to \@image's name or NULL if there is no name.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export const char *pt_image_name(const struct pt_image *image);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Add a new file section to the traced memory image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Adds \@size bytes starting at \@offset in \@filename. The section is
|
|
Packit |
b1f7ae |
* loaded at the virtual address \@vaddr in the address space \@asid.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@asid may be NULL or (partially) invalid. In that case only the valid
|
|
Packit |
b1f7ae |
* fields are considered when comparing with other address-spaces. Use this
|
|
Packit |
b1f7ae |
* when tracing a single process or when adding sections to all processes.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The section is silently truncated to match the size of \@filename.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Existing sections that would overlap with the new section will be shrunk
|
|
Packit |
b1f7ae |
* or split.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@image or \@filename is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@offset is too big.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_image_add_file(struct pt_image *image,
|
|
Packit |
b1f7ae |
const char *filename, uint64_t offset,
|
|
Packit |
b1f7ae |
uint64_t size,
|
|
Packit |
b1f7ae |
const struct pt_asid *asid,
|
|
Packit |
b1f7ae |
uint64_t vaddr);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Add a section from an image section cache.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Add the section from \@iscache identified by \@isid in address space \@asid.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Existing sections that would overlap with the new section will be shrunk
|
|
Packit |
b1f7ae |
* or split.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@image or \@iscache is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_image if \@iscache does not contain \@isid.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_image_add_cached(struct pt_image *image,
|
|
Packit |
b1f7ae |
struct pt_image_section_cache *iscache,
|
|
Packit |
b1f7ae |
int isid, const struct pt_asid *asid);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Copy an image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Adds all sections from \@src to \@image. Sections that could not be added
|
|
Packit |
b1f7ae |
* will be ignored.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns the number of ignored sections on success, a negative error code
|
|
Packit |
b1f7ae |
* otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@image or \@src is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_image_copy(struct pt_image *image,
|
|
Packit |
b1f7ae |
const struct pt_image *src);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Remove all sections loaded from a file.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Removes all sections loaded from \@filename from the address space \@asid.
|
|
Packit |
b1f7ae |
* Specify the same \@asid that was used for adding sections from \@filename.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns the number of removed sections on success, a negative error code
|
|
Packit |
b1f7ae |
* otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@image or \@filename is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_image_remove_by_filename(struct pt_image *image,
|
|
Packit |
b1f7ae |
const char *filename,
|
|
Packit |
b1f7ae |
const struct pt_asid *asid);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Remove all sections loaded into an address space.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Removes all sections loaded into \@asid. Specify the same \@asid that was
|
|
Packit |
b1f7ae |
* used for adding sections.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns the number of removed sections on success, a negative error code
|
|
Packit |
b1f7ae |
* otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@image is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_image_remove_by_asid(struct pt_image *image,
|
|
Packit |
b1f7ae |
const struct pt_asid *asid);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A read memory callback function.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* It shall read \@size bytes of memory from address space \@asid starting
|
|
Packit |
b1f7ae |
* at \@ip into \@buffer.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* It shall return the number of bytes read on success.
|
|
Packit |
b1f7ae |
* It shall return a negative pt_error_code otherwise.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
typedef int (read_memory_callback_t)(uint8_t *buffer, size_t size,
|
|
Packit |
b1f7ae |
const struct pt_asid *asid,
|
|
Packit |
b1f7ae |
uint64_t ip, void *context);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Set the memory callback for the traced memory image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Sets \@callback for reading memory. The callback is used for addresses
|
|
Packit |
b1f7ae |
* that are not found in file sections. The \@context argument is passed
|
|
Packit |
b1f7ae |
* to \@callback on each use.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* There can only be one callback at any time. A subsequent call will replace
|
|
Packit |
b1f7ae |
* the previous callback. If \@callback is NULL, the callback is removed.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@image is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_image_set_callback(struct pt_image *image,
|
|
Packit |
b1f7ae |
read_memory_callback_t *callback,
|
|
Packit |
b1f7ae |
void *context);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Instruction flow decoder. */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The instruction class.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* We provide only a very coarse classification suitable for reconstructing
|
|
Packit |
b1f7ae |
* the execution flow.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
enum pt_insn_class {
|
|
Packit |
b1f7ae |
/* The instruction could not be classified. */
|
|
Packit |
b1f7ae |
ptic_error,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The instruction is something not listed below. */
|
|
Packit |
b1f7ae |
ptic_other,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The instruction is a near (function) call. */
|
|
Packit |
b1f7ae |
ptic_call,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The instruction is a near (function) return. */
|
|
Packit |
b1f7ae |
ptic_return,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The instruction is a near unconditional jump. */
|
|
Packit |
b1f7ae |
ptic_jump,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The instruction is a near conditional jump. */
|
|
Packit |
b1f7ae |
ptic_cond_jump,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The instruction is a call-like far transfer.
|
|
Packit |
b1f7ae |
* E.g. SYSCALL, SYSENTER, or FAR CALL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
ptic_far_call,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The instruction is a return-like far transfer.
|
|
Packit |
b1f7ae |
* E.g. SYSRET, SYSEXIT, IRET, or FAR RET.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
ptic_far_return,
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* The instruction is a jump-like far transfer.
|
|
Packit |
b1f7ae |
* E.g. FAR JMP.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
ptic_far_jump
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The maximal size of an instruction. */
|
|
Packit |
b1f7ae |
enum {
|
|
Packit |
b1f7ae |
pt_max_insn_size = 15
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A single traced instruction. */
|
|
Packit |
b1f7ae |
struct pt_insn {
|
|
Packit |
b1f7ae |
/** The virtual address in its process. */
|
|
Packit |
b1f7ae |
uint64_t ip;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A coarse classification. */
|
|
Packit |
b1f7ae |
enum pt_insn_class iclass;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The execution mode. */
|
|
Packit |
b1f7ae |
enum pt_exec_mode mode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The raw bytes. */
|
|
Packit |
b1f7ae |
uint8_t raw[pt_max_insn_size];
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The size in bytes. */
|
|
Packit |
b1f7ae |
uint8_t size;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A collection of flags giving additional information:
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* - the instruction was executed speculatively.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t speculative:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - speculative execution was aborted after this instruction. */
|
|
Packit |
b1f7ae |
uint32_t aborted:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - speculative execution was committed after this instruction. */
|
|
Packit |
b1f7ae |
uint32_t committed:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - tracing was disabled after this instruction. */
|
|
Packit |
b1f7ae |
uint32_t disabled:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - tracing was enabled at this instruction. */
|
|
Packit |
b1f7ae |
uint32_t enabled:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - tracing was resumed at this instruction.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* In addition to tracing being enabled, it continues from the IP
|
|
Packit |
b1f7ae |
* at which tracing had been disabled before.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t resumed:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - normal execution flow was interrupted after this instruction. */
|
|
Packit |
b1f7ae |
uint32_t interrupted:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - tracing resumed at this instruction after an overflow. */
|
|
Packit |
b1f7ae |
uint32_t resynced:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - tracing was stopped after this instruction. */
|
|
Packit |
b1f7ae |
uint32_t stopped:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - this instruction is truncated in its image section.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* It starts in the image section identified by \@isid and continues
|
|
Packit |
b1f7ae |
* in one or more other sections.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t truncated:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The image section identifier for the section containing this
|
|
Packit |
b1f7ae |
* instruction.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* A value of zero means that the section did not have an identifier.
|
|
Packit |
b1f7ae |
* The section was not added via an image section cache or the memory
|
|
Packit |
b1f7ae |
* was read via the read memory callback.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
int isid;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Allocate an Intel PT instruction flow decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The decoder will work on the buffer defined in \@config, it shall contain
|
|
Packit |
b1f7ae |
* raw trace data and remain valid for the lifetime of the decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The decoder needs to be synchronized before it can be used.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export struct pt_insn_decoder *
|
|
Packit |
b1f7ae |
pt_insn_alloc_decoder(const struct pt_config *config);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Free an Intel PT instruction flow decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This will destroy the decoder's default image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@decoder must not be used after a successful return.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export void pt_insn_free_decoder(struct pt_insn_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Synchronize an Intel PT instruction flow decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Search for the next synchronization point in forward or backward direction.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If \@decoder has not been synchronized, yet, the search is started at the
|
|
Packit |
b1f7ae |
* beginning of the trace buffer in case of forward synchronization and at the
|
|
Packit |
b1f7ae |
* end of the trace buffer in case of backward synchronization.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero or a positive value on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if an unknown packet is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if an unknown packet payload is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if no further synchronization point is found.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_insn_sync_forward(struct pt_insn_decoder *decoder);
|
|
Packit |
b1f7ae |
extern pt_export int pt_insn_sync_backward(struct pt_insn_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Manually synchronize an Intel PT instruction flow decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Synchronize \@decoder on the syncpoint at \@offset. There must be a PSB
|
|
Packit |
b1f7ae |
* packet at \@offset.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero or a positive value on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if an unknown packet is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if an unknown packet payload is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if \@offset lies outside of \@decoder's trace buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if \@decoder reaches the end of its trace buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if there is no syncpoint at \@offset.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_insn_sync_set(struct pt_insn_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the current decoder position.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Fills the current \@decoder position into \@offset.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This is useful for reporting errors.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@offset is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_insn_get_offset(struct pt_insn_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the position of the last synchronization point.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Fills the last synchronization position into \@offset.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@offset is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_insn_get_sync_offset(struct pt_insn_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the traced image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The returned image may be modified as long as no decoder that uses this
|
|
Packit |
b1f7ae |
* image is running.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a pointer to the traced image the decoder uses for reading memory.
|
|
Packit |
b1f7ae |
* Returns NULL if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export struct pt_image *
|
|
Packit |
b1f7ae |
pt_insn_get_image(struct pt_insn_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Set the traced image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Sets the image that \@decoder uses for reading memory to \@image. If \@image
|
|
Packit |
b1f7ae |
* is NULL, sets the image to \@decoder's default image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Only one image can be active at any time.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
* Return -pte_invalid if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_insn_set_image(struct pt_insn_decoder *decoder,
|
|
Packit |
b1f7ae |
struct pt_image *image);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Return a pointer to \@decoder's configuration.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a non-null pointer on success, NULL if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export const struct pt_config *
|
|
Packit |
b1f7ae |
pt_insn_get_config(const struct pt_insn_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Return the current time.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* On success, provides the time at \@decoder's current position in \@time.
|
|
Packit |
b1f7ae |
* Since \@decoder is reading ahead until the next indirect branch or event,
|
|
Packit |
b1f7ae |
* the value matches the time for that branch or event.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The time is similar to what a rdtsc instruction would return. Depending
|
|
Packit |
b1f7ae |
* on the configuration, the time may not be fully accurate. If TSC is not
|
|
Packit |
b1f7ae |
* enabled, the time is relative to the last synchronization and can't be used
|
|
Packit |
b1f7ae |
* to correlate with other TSC-based time sources. In this case, -pte_no_time
|
|
Packit |
b1f7ae |
* is returned and the relative time is provided in \@time.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Some timing-related packets may need to be dropped (mostly due to missing
|
|
Packit |
b1f7ae |
* calibration or incomplete configuration). To get an idea about the quality
|
|
Packit |
b1f7ae |
* of the estimated time, we record the number of dropped MTC and CYC packets.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If \@lost_mtc is not NULL, set it to the number of lost MTC packets.
|
|
Packit |
b1f7ae |
* If \@lost_cyc is not NULL, set it to the number of lost CYC packets.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@time is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_no_time if there has not been a TSC packet.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_insn_time(struct pt_insn_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *time, uint32_t *lost_mtc,
|
|
Packit |
b1f7ae |
uint32_t *lost_cyc);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Return the current core bus ratio.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* On success, provides the core:bus ratio at \@decoder's current position
|
|
Packit |
b1f7ae |
* in \@cbr.
|
|
Packit |
b1f7ae |
* Since \@decoder is reading ahead until the next indirect branch or event,
|
|
Packit |
b1f7ae |
* the value matches the core:bus ratio for that branch or event.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The ratio is defined as core cycles per bus clock cycle.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@cbr is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_no_cbr if there has not been a CBR packet.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_insn_core_bus_ratio(struct pt_insn_decoder *decoder,
|
|
Packit |
b1f7ae |
uint32_t *cbr);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Determine the next instruction.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* On success, provides the next instruction in execution order in \@insn.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@size argument must be set to sizeof(struct pt_insn).
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a non-negative pt_status_flag bit-vector on success, a negative error
|
|
Packit |
b1f7ae |
* code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns pts_eos to indicate the end of the trace stream. Subsequent calls
|
|
Packit |
b1f7ae |
* to pt_insn_next() will continue to return pts_eos until trace is required
|
|
Packit |
b1f7ae |
* to determine the next instruction.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_context if the decoder encountered an unexpected packet.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if the decoder encountered unknown packets.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if the decoder encountered unknown packet payloads.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_query if the decoder got out of sync.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if decoding reached the end of the Intel PT buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@insn is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nomap if the memory at the instruction address can't be read.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_insn_next(struct pt_insn_decoder *decoder,
|
|
Packit |
b1f7ae |
struct pt_insn *insn, size_t size);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Block decoder. */
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A block of instructions.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Instructions in this block are executed sequentially but are not necessarily
|
|
Packit |
b1f7ae |
* contiguous in memory. Users are expected to follow direct branches.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
struct pt_block {
|
|
Packit |
b1f7ae |
/** The IP of the first instruction in this block. */
|
|
Packit |
b1f7ae |
uint64_t ip;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The IP of the last instruction in this block.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This can be used for error-detection.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint64_t end_ip;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The image section that contains the instructions in this block.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* A value of zero means that the section did not have an identifier.
|
|
Packit |
b1f7ae |
* The section was not added via an image section cache or the memory
|
|
Packit |
b1f7ae |
* was read via the read memory callback.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
int isid;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The execution mode for all instructions in this block. */
|
|
Packit |
b1f7ae |
enum pt_exec_mode mode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The instruction class for the last instruction in this block.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This field may be set to ptic_error to indicate that the instruction
|
|
Packit |
b1f7ae |
* class is not available. The block decoder may choose to not provide
|
|
Packit |
b1f7ae |
* the instruction class in some cases for performance reasons.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
enum pt_insn_class iclass;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The number of instructions in this block. */
|
|
Packit |
b1f7ae |
uint16_t ninsn;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The raw bytes of the last instruction in this block in case the
|
|
Packit |
b1f7ae |
* instruction does not fit entirely into this block's section.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This field is only valid if \@truncated is set.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint8_t raw[pt_max_insn_size];
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** The size of the last instruction in this block in bytes.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This field is only valid if \@truncated is set.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint8_t size;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** A collection of flags giving additional information about the
|
|
Packit |
b1f7ae |
* instructions in this block.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* - all instructions in this block were executed speculatively.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t speculative:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - speculative execution was aborted after this block. */
|
|
Packit |
b1f7ae |
uint32_t aborted:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - speculative execution was committed after this block. */
|
|
Packit |
b1f7ae |
uint32_t committed:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - tracing was disabled after this block. */
|
|
Packit |
b1f7ae |
uint32_t disabled:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - tracing was enabled at this block. */
|
|
Packit |
b1f7ae |
uint32_t enabled:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - tracing was resumed at this block.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* In addition to tracing being enabled, it continues from the IP
|
|
Packit |
b1f7ae |
* at which tracing had been disabled before.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If tracing was disabled at a call instruction, we assume that
|
|
Packit |
b1f7ae |
* tracing will be re-enabled after returning from the call at the
|
|
Packit |
b1f7ae |
* instruction following the call instruction.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t resumed:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - normal execution flow was interrupted after this block. */
|
|
Packit |
b1f7ae |
uint32_t interrupted:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - tracing resumed at this block after an overflow. */
|
|
Packit |
b1f7ae |
uint32_t resynced:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - tracing was stopped after this block. */
|
|
Packit |
b1f7ae |
uint32_t stopped:1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** - the last instruction in this block is truncated.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* It starts in this block's section but continues in one or more
|
|
Packit |
b1f7ae |
* other sections depending on how fragmented the memory image is.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The raw bytes for the last instruction are provided in \@raw and
|
|
Packit |
b1f7ae |
* its size in \@size in this case.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
uint32_t truncated:1;
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Allocate an Intel PT block decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The decoder will work on the buffer defined in \@config, it shall contain
|
|
Packit |
b1f7ae |
* raw trace data and remain valid for the lifetime of the decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The decoder needs to be synchronized before it can be used.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export struct pt_block_decoder *
|
|
Packit |
b1f7ae |
pt_blk_alloc_decoder(const struct pt_config *config);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Free an Intel PT block decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This will destroy the decoder's default image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@decoder must not be used after a successful return.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export void pt_blk_free_decoder(struct pt_block_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Synchronize an Intel PT block decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Search for the next synchronization point in forward or backward direction.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If \@decoder has not been synchronized, yet, the search is started at the
|
|
Packit |
b1f7ae |
* beginning of the trace buffer in case of forward synchronization and at the
|
|
Packit |
b1f7ae |
* end of the trace buffer in case of backward synchronization.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero or a positive value on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if an unknown packet is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if an unknown packet payload is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if no further synchronization point is found.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_blk_sync_forward(struct pt_block_decoder *decoder);
|
|
Packit |
b1f7ae |
extern pt_export int pt_blk_sync_backward(struct pt_block_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Manually synchronize an Intel PT block decoder.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Synchronize \@decoder on the syncpoint at \@offset. There must be a PSB
|
|
Packit |
b1f7ae |
* packet at \@offset.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero or a positive value on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if an unknown packet is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if an unknown packet payload is encountered.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if \@offset lies outside of \@decoder's trace buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if \@decoder reaches the end of its trace buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if there is no syncpoint at \@offset.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_blk_sync_set(struct pt_block_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the current decoder position.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Fills the current \@decoder position into \@offset.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* This is useful for reporting errors.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@offset is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_blk_get_offset(struct pt_block_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the position of the last synchronization point.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Fills the last synchronization position into \@offset.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@offset is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_blk_get_sync_offset(struct pt_block_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *offset);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Get the traced image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The returned image may be modified as long as \@decoder is not running.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a pointer to the traced image \@decoder uses for reading memory.
|
|
Packit |
b1f7ae |
* Returns NULL if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export struct pt_image *
|
|
Packit |
b1f7ae |
pt_blk_get_image(struct pt_block_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Set the traced image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Sets the image that \@decoder uses for reading memory to \@image. If \@image
|
|
Packit |
b1f7ae |
* is NULL, sets the image to \@decoder's default image.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Only one image can be active at any time.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
* Return -pte_invalid if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_blk_set_image(struct pt_block_decoder *decoder,
|
|
Packit |
b1f7ae |
struct pt_image *image);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Return a pointer to \@decoder's configuration.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a non-null pointer on success, NULL if \@decoder is NULL.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export const struct pt_config *
|
|
Packit |
b1f7ae |
pt_blk_get_config(const struct pt_block_decoder *decoder);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Return the current time.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* On success, provides the time at \@decoder's current position in \@time.
|
|
Packit |
b1f7ae |
* Since \@decoder is reading ahead until the next indirect branch or event,
|
|
Packit |
b1f7ae |
* the value matches the time for that branch or event.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The time is similar to what a rdtsc instruction would return. Depending
|
|
Packit |
b1f7ae |
* on the configuration, the time may not be fully accurate. If TSC is not
|
|
Packit |
b1f7ae |
* enabled, the time is relative to the last synchronization and can't be used
|
|
Packit |
b1f7ae |
* to correlate with other TSC-based time sources. In this case, -pte_no_time
|
|
Packit |
b1f7ae |
* is returned and the relative time is provided in \@time.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Some timing-related packets may need to be dropped (mostly due to missing
|
|
Packit |
b1f7ae |
* calibration or incomplete configuration). To get an idea about the quality
|
|
Packit |
b1f7ae |
* of the estimated time, we record the number of dropped MTC and CYC packets.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* If \@lost_mtc is not NULL, set it to the number of lost MTC packets.
|
|
Packit |
b1f7ae |
* If \@lost_cyc is not NULL, set it to the number of lost CYC packets.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@time is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_no_time if there has not been a TSC packet.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_blk_time(struct pt_block_decoder *decoder,
|
|
Packit |
b1f7ae |
uint64_t *time, uint32_t *lost_mtc,
|
|
Packit |
b1f7ae |
uint32_t *lost_cyc);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Return the current core bus ratio.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* On success, provides the core:bus ratio at \@decoder's current position
|
|
Packit |
b1f7ae |
* in \@cbr.
|
|
Packit |
b1f7ae |
* Since \@decoder is reading ahead until the next indirect branch or event,
|
|
Packit |
b1f7ae |
* the value matches the core:bus ratio for that branch or event.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The ratio is defined as core cycles per bus clock cycle.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns zero on success, a negative error code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@cbr is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_no_cbr if there has not been a CBR packet.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_blk_core_bus_ratio(struct pt_block_decoder *decoder,
|
|
Packit |
b1f7ae |
uint32_t *cbr);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/** Determine the next block of instructions.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* On success, provides the next block of instructions in execution order in
|
|
Packit |
b1f7ae |
* \@block.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* The \@size argument must be set to sizeof(struct pt_block).
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns a non-negative pt_status_flag bit-vector on success, a negative error
|
|
Packit |
b1f7ae |
* code otherwise.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns pts_eos to indicate the end of the trace stream. Subsequent calls
|
|
Packit |
b1f7ae |
* to pt_block_next() will continue to return pts_eos until trace is required
|
|
Packit |
b1f7ae |
* to determine the next instruction.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns -pte_bad_context if the decoder encountered an unexpected packet.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_opc if the decoder encountered unknown packets.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_packet if the decoder encountered unknown packet payloads.
|
|
Packit |
b1f7ae |
* Returns -pte_bad_query if the decoder got out of sync.
|
|
Packit |
b1f7ae |
* Returns -pte_eos if decoding reached the end of the Intel PT buffer.
|
|
Packit |
b1f7ae |
* Returns -pte_invalid if \@decoder or \@block is NULL.
|
|
Packit |
b1f7ae |
* Returns -pte_nomap if the memory at the instruction address can't be read.
|
|
Packit |
b1f7ae |
* Returns -pte_nosync if \@decoder is out of sync.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
extern pt_export int pt_blk_next(struct pt_block_decoder *decoder,
|
|
Packit |
b1f7ae |
struct pt_block *block, size_t size);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#ifdef __cplusplus
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
#endif
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#endif /* INTEL_PT_H */
|