kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

backtrace.h (2793B)


      1 #ifndef KIT_DRIVER_BACKTRACE_H
      2 #define KIT_DRIVER_BACKTRACE_H
      3 
      4 #include <kit/arch.h>
      5 #include <kit/core.h>
      6 #include <kit/dwarf.h>
      7 #include <kit/jit.h>
      8 #include <stddef.h>
      9 #include <stdint.h>
     10 
     11 /* Frame-pointer-chain backtrace shared by `kit dbg` (fault stop + `bt`) and
     12  * `kit run` (in-process crash guard).
     13  *
     14  * kit keeps a frame pointer on every backend and never omits it, so each
     15  * prologue stores a uniform frame record — fp[0] = caller fp, fp[1] = saved
     16  * return address (in units of void*). Walking that chain needs only a way to
     17  * read target memory plus the frame-pointer register value; no .eh_frame, no
     18  * CFI program (the CFI stepper, kit_dwarf_unwind_step, deliberately takes no
     19  * memory provider and so cannot self-unwind a spilled return address). This is
     20  * the same walk rt/lib/stack/backtrace.c performs in-process, lifted to the
     21  * tool side with a caller-supplied memory reader. */
     22 
     23 /* The frame-pointer register's DWARF index for `arch` (aarch64 x29 = 29,
     24  * x86-64 rbp = 6, riscv s0 = 8), or -1 if the arch keeps no walkable FP. */
     25 int driver_bt_fp_dwarf_reg(KitArchKind arch);
     26 
     27 /* Pointer width in bytes for `arch` (8 for the 64-bit native targets, 4 for
     28  * rv32), or 0 if unsupported. */
     29 int driver_bt_ptr_size(KitArchKind arch);
     30 
     31 /* Advance one frame: given the current frame pointer `fp`, read the saved
     32  * return address (fp[1]) and caller frame pointer (fp[0]) through `read`.
     33  * Returns 1 and fills *ra_out / *next_fp_out for a valid caller frame; returns
     34  * 0 at the chain terminator or on garbage (null/non-increasing/misaligned fp,
     35  * null return address, or a failed read) — mirroring __kit_backtrace's guards.
     36  */
     37 int driver_bt_fp_step(KitArchKind arch, KitDwarfReadMemFn read, void* read_user,
     38                       uint64_t fp, uint64_t* ra_out, uint64_t* next_fp_out);
     39 
     40 /* Line sink: receives one NUL-terminated, newline-free frame line. */
     41 typedef void (*DriverBtEmit)(void* user, const char* line);
     42 
     43 typedef struct DriverBtCtx {
     44   KitJit* jit;         /* optional: symbol names + runtime->image PC xlate */
     45   KitDebugInfo* dwarf; /* optional: file:line + func-name fallback */
     46   DriverBtEmit emit;   /* line sink (required) */
     47   void* emit_user;
     48 } DriverBtCtx;
     49 
     50 /* Symbolize a captured list of return addresses (innermost first, as produced
     51  * by the FP walk) and emit one line per frame via ctx->emit:
     52  *   #0  0x401136 <bt_leaf+0x12> at addr2line_prog.c:51:3
     53  * Frames with no symbol/line degrade to "#N 0xADDR". Used by `kit run`, which
     54  * must capture the chain inside its fault handler — before the post-longjmp
     55  * stack is reused — and symbolize it afterward in normal context. */
     56 void driver_backtrace_print_pcs(const DriverBtCtx* ctx, const uint64_t* pcs,
     57                                 int n);
     58 
     59 #endif /* KIT_DRIVER_BACKTRACE_H */