kit

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

addr2line_prog.c (2331B)


      1 /* L3a backtrace round-trip program (driven by test/rt/addr2line.sh).
      2  *
      3  * Wires the weak __kit_backtrace_write sink to a freestanding write(2) and
      4  * calls __kit_print_backtrace() from the bottom of a named, @[.noinline] call
      5  * chain. The emitted "#N 0xADDR" lines go to stdout; the harness pipes the
      6  * addresses to `kit addr2line -f` and checks that bt_leaf / bt_mid / bt_root /
      7  * test_main appear. Built as a static non-PIE ELF, so the return addresses
      8  * printed at run time equal the link-time addresses addr2line resolves.
      9  *
     10  * Linux-only (the rt runtime test tuples are all *-linux); the syscall numbers
     11  * are the generic-unified-ABI write(2) for each arch (x86-64 uses its own). */
     12 #include <kit/backtrace.h>
     13 
     14 static long bt_write(int fd, const char* buf, unsigned long len) {
     15 #if defined(__aarch64__)
     16   register long x8 __asm__("x8") = 64; /* sys_write */
     17   register long x0 __asm__("x0") = fd;
     18   register long x1 __asm__("x1") = (long)buf;
     19   register long x2 __asm__("x2") = (long)len;
     20   __asm__ volatile("svc #0" : "+r"(x0) : "r"(x8), "r"(x1), "r"(x2) : "memory");
     21   return x0;
     22 #elif defined(__x86_64__)
     23   register long rax __asm__("rax") = 1; /* sys_write */
     24   register long rdi __asm__("rdi") = fd;
     25   register long rsi __asm__("rsi") = (long)buf;
     26   register long rdx __asm__("rdx") = (long)len;
     27   __asm__ volatile("syscall"
     28                    : "+r"(rax)
     29                    : "r"(rdi), "r"(rsi), "r"(rdx)
     30                    : "rcx", "r11", "memory");
     31   return rax;
     32 #elif defined(__riscv) && __riscv_xlen == 64
     33   register long a7 __asm__("a7") = 64; /* sys_write */
     34   register long a0 __asm__("a0") = fd;
     35   register long a1 __asm__("a1") = (long)buf;
     36   register long a2 __asm__("a2") = (long)len;
     37   __asm__ volatile("ecall" : "+r"(a0) : "r"(a7), "r"(a1), "r"(a2) : "memory");
     38   return a0;
     39 #else
     40 #error "addr2line_prog.c: unsupported architecture"
     41 #endif
     42 }
     43 
     44 /* Override the weak rt default: route the backtrace bytes to stdout. */
     45 void __kit_backtrace_write(const char* buf, size_t len) {
     46   bt_write(1, buf, (unsigned long)len);
     47 }
     48 
     49 __attribute__((noinline)) int bt_leaf(void) {
     50   __kit_print_backtrace();
     51   return 1;
     52 }
     53 __attribute__((noinline)) int bt_mid(void) { return bt_leaf() + 1; }
     54 __attribute__((noinline)) int bt_root(void) { return bt_mid() + 1; }
     55 
     56 int test_main(void) { return bt_root() == 3 ? 42 : 1; }