gdb.ptwrite (Debugging with GDB)

#### 23.3.4.4 gdb.ptwrite ¶

This module provides additional functionality for recording programs that make use of the `PTWRITE` instruction. `PTWRITE` is a x86 instruction that allows to write values into the Intel Processor Trace (see Recording Inferior’s Execution and Replaying It). The GCC intrinsics for it are:

    void _ptwrite32 (unsigned int a)
    void _ptwrite64 (unsigned __int64 a)

If an inferior uses the instruction, GDB by default inserts the raw payload value as auxiliary information into the execution history. Auxiliary information is by default printed during `record instruction-history`, `record function-call-history`, and all stepping commands, and is accessible in Python as a `RecordAuxiliary` object (see Recordings In Python).

Sample program:

    #include <immintrin.h>

    void
    ptwrite64 (unsigned long long value)
    {
      _ptwrite64 (value);
    }

    int
    main (void)
    {
      ptwrite64 (0x42);
      return 0; /* break here.  */
    }

GDB output after recording the sample program in pt format:

    (gdb) record instruction-history 12,14
    12         0x0040074c <ptwrite64+16>:   ptwrite %rbx
    13           [0x42]
    14         0x00400751 <ptwrite64+21>:   mov -0x8(%rbp),%rbx
    (gdb) record function-call-history
    1       main
    2       ptwrite64
              [0x42]
    3       main

The `gdb.ptwrite` module allows customizing the default output of `PTWRITE` auxiliary information. A custom Python function can be registered as the `PTWRITE` filter function. This function will be called with the `PTWRITE` payload and PC as arguments during trace decoding. The function can return a string, which will be printed by GDB during the aforementioned commands, or `None`, resulting in no output. To register such a filter function, the user needs to provide a filter factory function, which returns a new filter function object to be called by GDB.

Function: register_filter_factory (filter_factory) ¶

  Used to register the `PTWRITE` filter factory. This filter factory can be any callable object that accepts one argument, the current thread as a `gdb.InferiorThread`. It can return None or a callable. This callable is the `PTWRITE` filter function for the specified thread. If `None` is returned by the factory function, the default auxiliary information will be printed.

Function: get_filter () ¶

  Return the currently active `PTWRITE` filter function.

An example:

    (gdb) python-interactive
    >>> class my_filter():
    ...    def __init__(self):
    ...        self.var = 0
    ...    def __call__(self, payload, ip):
    ...        self.var += 1
    ...        return f"counter: {self.var}, ip: {ip:#x}"
    ...
    >>> def my_filter_factory(thread):
    ...    if thread.global_num == 1:
    ...        return my_filter()
    ...    else:
    ...        return None
    ...
    >>> import gdb.ptwrite
    >>> gdb.ptwrite.register_filter_factory(my_filter_factory)
    >>>

    (gdb) record function-call-history 59,64
    59      pthread_create@GLIBC_2.2.5
    60      job()
    61      task(void*)
    62      ptwrite64(unsigned long)
              [counter: 1, ip: 0x401156]
    63      task(void*)
    64      ptwrite32(unsigned int)
              [counter: 2, ip: 0x40116c]

    (gdb) info threads
    * 1    Thread 0x7ffff7fd8740 (LWP 25796) "ptw_threads" task ()
        at bin/ptwrite/ptw_threads.c:45
      2    Thread 0x7ffff6eb8700 (LWP 25797) "ptw_threads" task ()
        at bin/ptwrite/ptw_threads.c:45

    (gdb) thread 2
    [Switching to thread 2 (Thread 0x7ffff6eb8700 (LWP 25797))]
    #0  task (arg=0x0) at ptwrite_threads.c:45
    45        return NULL;

    (gdb) record function-call-history 10,14
    10    start_thread
    11    task(void*)
    12    ptwrite64(unsigned long)
            [0x42]
    13    task(void*)
    14    ptwrite32(unsigned int)
            [0x43]

This GDB feature is dependent on hardware and operating system support and requires the Intel Processor Trace decoder library in version 2.0.0 or newer.