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; }