PT_INSN_NEXT(3)

πŸ“¦ version 2.1.2, in fedora 43, fedora 44

✨ PT_INSN_NEXT(3) ✨

okay so bestie, welcome to PT_INSN_NEXT(3) πŸ’– this is the page about iterating over traced instructions, and honestly? it's giving "the main character of the Intel PT decoder API." let's get into it, no cap.


🌸 NAME 🌸

pt_insn_next, pt_insn β€” iterate over traced instructions πŸ¦‹


πŸŽ€ SYNOPSIS πŸŽ€

#include <intel-pt.h>
struct pt_insn;
int pt_insn_next(struct pt_insn_decoder *decoder,
                 struct pt_insn *insn, size_t size);

Link with -lipt.


πŸ’… DESCRIPTION πŸ’…

pt_insn_next() hands you the next instruction in execution order, described by the pt_insn structure. one at a time, in order, like a little conga line of instructions 🫢

The size argument must be set to sizeof(struct pt_insn). the function will provide at most size bytes of the pt_insn structure. and here's the vibe: a newer decoder library may truncate an extended pt_insn object to size bytes. lowkey important, so set it right ✨

An older decoder library may provide less pt_insn fields. Fields that are not provided will be zero-initialized. For fields where zero is a valid value (e.g. for bit-fields), check the decoder library version to determine which fields are valid. See pt_library_version(3). πŸ‘‘

On success, the next instruction is provided in the pt_insn object pointed to by the insn argument. The pt_insn structure is declared as:

/** A single traced instruction. */
struct pt_insn {
    /** The virtual address in its process. */
    uint64_t ip;

    /** The image section identifier for the section containing this
     * instruction.
     *
     * A value of zero means that the section did not have an identifier.
     * The section was not added via an image section cache or the memory
     * was read via the read memory callback.
     */
    int isid;

    /** The execution mode. */
    enum pt_exec_mode mode;

    /** A coarse classification. */
    enum pt_insn_class iclass;

    /** The raw bytes. */
    uint8_t raw[pt_max_insn_size];

    /** The size in bytes. */
    uint8_t size;

    /** A collection of flags giving additional information:
     *
     * - the instruction was executed speculatively.
     */
    uint32_t speculative:1;

    /** - this instruction is truncated in its image section.
     *
     *    It starts in the image section identified by \@isid and continues
     *    in one or more other sections.
     */
    uint32_t truncated:1;
};

The fields of the pt_insn structure are described in more detail below. buckle up, we're doing a field-by-field tour 🌈

  • ip β€” The virtual address of the instruction. The address should be interpreted in the current address space context.
  • isid β€” The image section identifier of the section from which the instruction originated. This will be zero unless the instruction came from a section that was added via an image section cache. See pt_image_add_cached(3).

The image section identifier can be used to trace an instruction back to its binary file and from there to source code. it's literally the receipts for where this instruction came from πŸ”₯

  • mode β€” The execution mode at which the instruction was executed. The pt_exec_mode enumeration is declared as:
/** An execution mode. */
enum pt_exec_mode {
    ptem_unknown,
    ptem_16bit,
    ptem_32bit,
    ptem_64bit
};
  • iclass β€” A coarse classification of the instruction suitable for constructing a call back trace. The pt_insn_class enumeration is declared as:
/** The instruction class.
 *
 * We provide only a very coarse classification suitable for
 * reconstructing the execution flow.
 */
enum pt_insn_class {
    /* The instruction has not been classified. */
    ptic_unknown,

    /* The instruction is something not listed below. */
    ptic_other,

    /* The instruction is a near (function) call. */
    ptic_call,

    /* The instruction is a near (function) return. */
    ptic_return,

    /* The instruction is a near unconditional jump. */
    ptic_jump,

    /* The instruction is a near conditional jump. */
    ptic_cond_jump,

    /* The instruction is a call-like far transfer.
     * E.g. SYSCALL, SYSENTER, or FAR CALL.
     */
    ptic_far_call,

    /* The instruction is a return-like far transfer.
     * E.g. SYSRET, SYSEXIT, IRET, or FAR RET.
     */
    ptic_far_return,

    /* The instruction is a jump-like far transfer.
     * E.g. FAR JMP.
     */
    ptic_far_jump,

    /* The instruction is a PTWRITE. */
    ptic_ptwrite,

    /* The instruction is an indirect jump or a far transfer. */
    ptic_indirect
};
  • raw β€” The memory containing the instruction. the actual bytes, bestie πŸ’€
  • size β€” The size of the instruction in bytes.
  • speculative β€” A flag giving the speculative execution status of the instruction. If set, the instruction was executed speculatively. Otherwise, the instruction was executed normally.
  • truncated β€” A flag saying whether this instruction spans more than one image section. If clear, this instruction originates from a single section identified by isid. If set, the instruction overlaps two or more image sections. In this case, isid identifies the section that contains the first byte. 🧚

⭐ RETURN VALUE ⭐

pt_insn_next() returns zero or a positive value on success or a negative pt_error_code enumeration constant in case of an error.

On success, a bit-vector of pt_status_flag enumeration constants is returned. The pt_status_flag enumeration is declared as:

/** Decoder status flags. */
enum pt_status_flag {
    /** There is an event pending. */
    pts_event_pending   = 1 << 0,

    /** The address has been suppressed. */
    pts_ip_suppressed   = 1 << 1,

    /** There is no more trace data available. */
    pts_eos             = 1 << 2
};

The pts_event_pending flag indicates that one or more events are pending. Use pt_insn_event(3) to process pending events before calling pt_insn_next() again. don't skip this step bestie, it's the whole vibe πŸ™ˆ

The pt_eos flag indicates that the information contained in the Intel PT stream has been consumed. Further calls to pt_insn_next() will continue to provide instructions as long as the instruction's address can be determined without further trace. yes she keeps going, iconic behavior πŸ’–


πŸ’€ ERRORS πŸ’€

  • pte_invalid β€” The decoder or insn argument is NULL or the size argument is too small. (so like... pass sizeof(struct pt_insn), fr fr)
  • pte_eos β€” Decode reached the end of the trace stream.
  • pte_nosync β€” The decoder has not been synchronized onto the trace stream. Use pt_insn_sync_forward(3), pt_insn_sync_backward(3), or pt_insn_sync_set(3) to synchronize decoder.
  • pte_bad_opc β€” The decoder encountered an unsupported Intel PT packet opcode.
  • pte_bad_packet β€” The decoder encountered an unsupported Intel PT packet payload.
  • pte_bad_query β€” Execution flow reconstruction and trace got out of sync.

This typically means that, on its way to the virtual address of the next event, the decoder encountered a conditional or indirect branch for which it did not find guidance in the trace. 😭 the trace left her on read.


πŸ¦‹ SEE ALSO πŸ¦‹

pt_insn_alloc_decoder(3), pt_insn_free_decoder(3), pt_insn_sync_forward(3), pt_insn_sync_backward(3), pt_insn_sync_set(3), pt_insn_time(3), pt_insn_core_bus_ratio(3), pt_insn_event(3)


and that's the whole page, no notes πŸ’…

okay love u, bye!! this was the PT_INSN_NEXT(3) page from the Intel PT / intel-pt.h family β€” it signs off at the bottom as PT_INSN_NEXT(3), so that's the source and that's the stamp. mwah πŸŽ€βœ¨πŸ«Ά

πŸ“¦ where this page comes from