he32 [...] yes, I patched the other two libc
crates as well,[...]
Looks like you got them all. (I figured it using:)
$ fgrep -r backtrace rustc-1.60.0-src/ | fgrep freebsd
$ fgrep -r backtrace rustc-1.60.0-src/ | fgrep netbsd
he32 However, I suspect that rust has not yet been taught to use the execinfo
functions
$ fgrep -r -- -lexecinfo rustc-1.60.0-src
rustc-1.60.0-src/vendor/openssl-src/openssl/Configure: push @{$config{ex_libs}}, "-lexecinfo";
rustc-1.60.0-src/src/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp: CmdArgs.push_back("-lexecinfo");
rustc-1.60.0-src/src/llvm-project/compiler-rt/test/msan/lit.cfg.py: clang_msan_cflags += ["-lexecinfo", "-fPIC"]
rustc-1.60.0-src/src/llvm-project/compiler-rt/lib/orc/unittests/CMakeLists.txt: append_list_if(COMPILER_RT_HAS_LIBEXECINFO -lexecinfo ORC_UNITTEST_LINK_FLAGS)
rustc-1.60.0-src/src/llvm-project/compiler-rt/lib/xray/tests/CMakeLists.txt: append_list_if(COMPILER_RT_HAS_LIBEXECINFO -lexecinfo XRAY_UNITTEST_LINK_FLAGS)
$
Only one file, Driver/ToolChains/CommonArgs.cpp
seems relevant here and that does link -lexecinfo
on all the BSDs--but, I think that it's brought in only for Sanitizers, and, their tests.
he32 everywhere else I search I only see references to LLVM's unwind
library for this functionality.
The unwind
library will only get you the stack frames, I think. You need to grub around in the executable's ELF sections (either in .dynsym
or .symtab
and their string-table sections depending on whether -rdynamic
is passed or not when compiling) to translate the IP location into a function name:
unwind.c
/**
* cc -pie -fPIE unwind.c
* ./a.out
https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/libgcc-s.html
https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-AMD64/LSB-Core-AMD64/libgcc-s.html
https://dwarfstd.org/Home.php
*/
#include <stdio.h>
#include <stdlib.h>
#include <unwind.h>
static void f1(void);
static void f2(void);
static void f3(void);
static void f4(void);
static void pr_bt(void);
static _Unwind_Reason_Code bt_fn(struct _Unwind_Context *ctx, void *arg);
int
main(void)
{
f1();
return 0;
}
static void f1(void) {
f2();
}
static void f2(void) {
f3();
}
static void f3(void) {
f4();
}
static void f4(void) {
pr_bt();
}
static void
pr_bt(void)
{
_Unwind_Backtrace(bt_fn, NULL);
}
static _Unwind_Reason_Code
bt_fn(struct _Unwind_Context *ctx, void *arg)
{
_Unwind_Ptr ip = _Unwind_GetIP(ctx);
if (ip == (_Unwind_Ptr)NULL)
return _URC_END_OF_STACK;
printf("0x%lx\n", ip);
return _URC_NO_REASON;
}