PT_QRY_COND_BRANCH(3)

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

πŸ’– PT_QRY_COND_BRANCH β€” bestie edition πŸ’–

okay so welcome to pt_qry_cond_branch(3), aka the manual page for pt_qry_cond_branch and pt_qry_indirect_branch, two little functions that query an Intel(R) Processor Trace query decoder. yes that's a lot of "query" in one sentence, we love that for us. ✨


✨ NAME ✨

pt_qry_cond_branch, pt_qry_indirect_branch β€” query an Intel(R) Processor Trace query decoder πŸ¦‹


🌸 SYNOPSIS 🌸

#include <intel-pt.h>
int pt_qry_cond_branch(struct pt_query_decoder *decoder,
                       int *taken);
int pt_qry_indirect_branch(struct pt_query_decoder *decoder,
                           **uint64_t *ip);

and bestie, don't forget to link with -lipt or nothing works, no cap. πŸ’…


πŸ‘‘ DESCRIPTION πŸ‘‘

pt_qry_cond_branch() πŸ’…

okay so pt_qry_cond_branch() uses Intel Processor Trace (Intel PT) to figure out whether the next conditional branch in the traced code was taken or not taken. the decoder argument must point to an Intel PT query decoder, like, non-negotiable.

on success, it sets the variable that the taken argument points to: a non-zero value if the next condition branch is taken, and zero if it is not taken. iconic behavior honestly.

pt_qry_indirect_branch() πŸ¦‹

and then pt_qry_indirect_branch() uses Intel Processor Trace (Intel PT) to figure out the destination virtual address of the next indirect branch in the traced code. main character energy fr fr.

on success, it hands you the destination address in the integer variable pointed to be the ip argument. and listen β€” if that destination address has been suppressed in the Intel PT trace, the lack of an IP gets indicated in the return value by setting the pts_ip_suppressed bit. so like, check your return value, bestie, i'm begging. 😭


⭐ RETURN VALUE ⭐

both functions return zero or a positive value on success, or a negative pt_error_code enumeration constant in case of an error. periodt.

on success, you get back a bit-vector of pt_status_flag enumeration constants. 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
};

look at those little bit flags living their best lives. πŸŽ€


πŸ’€ ERRORS πŸ’€

  • pte_invalid β€” the decoder argument, or the taken argument (for pt_qry_cond_branch()) or the ip argument (for pt_qry_indirect_branch()), is NULL. yeah she's null, she's not coming back. πŸ™ˆ
  • pte_eos β€” decode reached the end of the trace stream. that's it, that's the whole stream, we're done here. πŸ’€
  • pte_nosync β€” the decoder has not been synchronized onto the trace stream. use pt_qry_sync_forward(3), pt_qry_sync_backward(3), or pt_qry_sync_set(3) to synchronize the decoder. go sync your decoder bestie, it's giving lost. 🧭
  • 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 β€” the query does not match the data provided in the Intel PT stream. based on the trace, the decoder expected a call to the other query function or a call to pt_qry_event(3). this usually means that execution flow reconstruction and trace got out of sync. 🚨 like they broke up. it's messy.

🌈 EXAMPLE 🌈

the following example sketches an execution flow reconstruction loop. asynchronous events have been omitted.

int foo(struct pt_query_decoder *decoder, uint64_t ip) {
    for (;;) {
        if (insn_is_cond_branch(ip)) {
            int errcode, taken;

            errcode = pt_qry_cond_branch(decoder, &taken);
            if (errcode < 0)
                return errcode;

            if (taken)
                ip = insn_destination(ip);
            else
                ip = insn_next_ip(ip);
        } else if (insn_is_indirect_branch(ip)) {
            int errcode;

            errcode = pt_qry_indirect_branch(decoder, &ip);
            if (errcode < 0)
                return errcode;
        } else
            ip = insn_next_ip(ip);
    }
}

she loops, she checks, she queries, she slays. πŸ”₯ (also note: async events are omitted here, so don't come for me about the events.)


🫢 SEE ALSO 🫢

pt_qry_alloc_decoder(3), pt_qry_free_decoder(3), pt_qry_event(3), pt_qry_time(3), pt_qry_core_bus_ratio(3)

go read those too, they're part of the friend group. ✨


and that's the whole page bestie!! PT_QRY_COND_BRANCH(3) β€” that's the manual section it lives in, and yes, it's giving legend behavior. πŸ’œ mwah, go reconstruct some execution flow, ily. πŸŽ€

πŸ“¦ where this page comes from