From: Willy Tarreau Date: Mon, 14 Apr 2025 18:06:48 +0000 (+0200) Subject: MINOR: debug: detect call instructions and show the branch target in backtraces X-Git-Tag: v3.2-dev11~64 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3cbbf41cd8772e7376d3f8473b171b9f8016079b;p=thirdparty%2Fhaproxy.git MINOR: debug: detect call instructions and show the branch target in backtraces In backtraces, sometimes it's difficult to know what was called by a given point, because some functions can be fairly long making one doubt about the correct pointer of unresolved ones, others might just use a tail branch instead of a call + return, etc. On common architectures (x86 and aarch64), it's not difficult to detect and decode a relative call, so let's do it on both of these platforms and show the branch location after a '>'. Example: x86_64: call trace(19): | 0x6bd644 <64 8b 38 e8 ac f7 ff ff]: debug_handler+0x84/0x95 > ha_thread_dump_one | 0x7feb3e5383a0 <00 00 00 00 0f 1f 40 00]: libpthread:+0x123a0 | 0x7feb3e53748b main-0x2130 | 0x743862 <8b 7f 68 e8 8e e1 01 00]: sock_conn_ctrl_close+0x12/0x54 > fd_delete | 0x5ac822 main+0xff150 | 0x5be410 <4c 89 e7 e8 c0 e1 ff ff]: main+0x111100 > main+0x10f2c0 | 0x6ae6a4 <28 00 00 00 00 ff 51 58]: cli_io_handler+0x31524 | 0x6aeab4 <7c 24 08 e8 fc fa ff ff]: sc_destroy+0x14/0x2a4 > cli_io_handler+0x31430 | 0x6c685d <48 89 ef e8 43 82 fe ff]: process_chk_conn+0x51d/0x1927 > sc_destroy aarch64: call trace(15): | 0xaaaaad0c1540 <60 6a 60 b8 c3 fd ff 97]: debug_handler+0x9c/0xbc > ha_thread_dump_one | 0xffffa8c177ac sedesc_new | 0xaaaaad0b22a4 <00 00 80 d2 94 f9 ff 97]: sc_new_from_strm+0x1c/0x54 > cli_io_handler+0x28dd0 | 0xaaaaad0167e8 <21 00 80 52 a9 6e 02 94]: stream_new+0x258/0x67c > sc_new_from_strm | 0xaaaaad0b21f8 stream_new | 0xaaaaacfda628 <21 18 40 f9 e7 5e 03 94]: main+0xcaca8 > sc_new_from_endp | 0xaaaaacfdb95c <42 c0 00 d1 02 f3 ff 97]: main+0xcbfdc > main+0xc8be0 | 0xaaaaacfdd3f0 main+0xcba40 --- diff --git a/src/debug.c b/src/debug.c index b0effdd4b..29339413f 100644 --- a/src/debug.c +++ b/src/debug.c @@ -209,6 +209,24 @@ void ha_dump_backtrace(struct buffer *buf, const char *prefix, int dump) bak = *buf; dump_addr_and_bytes(buf, pfx2, callers[j], -8); addr = resolve_sym_name(buf, ": ", callers[j]); + +#if defined(__i386__) || defined(__x86_64__) + /* Try to decode a relative call (0xe8 + 32-bit signed ofs) */ + if (may_access(callers[j] - 5) && may_access(callers[j] - 1) && + *((uchar*)(callers[j] - 5)) == 0xe8) { + int ofs = *((int *)(callers[j] - 4)); + const void *addr2 = callers[j] + ofs; + resolve_sym_name(buf, " > ", addr2); + } +#elif defined(__aarch64__) + /* Try to decode a relative call (0x9X + 26-bit signed ofs) */ + if (may_access(callers[j] - 4) && may_access(callers[j] - 1) && + (*((int*)(callers[j] - 4)) & 0xFC000000) == 0x94000000) { + int ofs = (*((int *)(callers[j] - 4)) << 6) >> 4; // 26-bit signed immed*4 + const void *addr2 = callers[j] - 4 + ofs; + resolve_sym_name(buf, " > ", addr2); + } +#endif if ((dump & 3) == 0) { /* dump not started, will start *after* ha_thread_dump_one(), * ha_panic and ha_backtrace_to_stderr