Skip to content

Commit e1eeab1

Browse files
committed
Fix musl unwinding
libunwind as a custom unwinder
1 parent faad98b commit e1eeab1

File tree

4 files changed

+63
-2
lines changed

4 files changed

+63
-2
lines changed

crashtracker/build.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fn main() {
2+
println!("cargo:rerun-if-changed=build.rs");
3+
4+
// Link the system `libunwind`
5+
println!("cargo:rustc-link-lib=unwind");
6+
7+
// Link `libgcc_s` (needed for `_Unwind` symbols)
8+
println!("cargo:rustc-link-lib=dylib=gcc_s");
9+
// todo: avoid hard coding these paths
10+
// Specify library search paths
11+
println!("cargo:rustc-link-search=native=/usr/local/lib");
12+
println!("cargo:rustc-link-search=native=/usr/lib");
13+
}

crashtracker/src/collector/crash_handler.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,10 +658,11 @@ unsafe fn register_signal_handler(
658658
} else {
659659
SaFlags::empty()
660660
};
661+
661662

662663
let sig_action = SigAction::new(
663664
SigHandler::SigAction(handle_posix_sigaction),
664-
SaFlags::SA_NODEFER | extra_saflags,
665+
SaFlags::SA_NODEFER | extra_saflags | SaFlags::SA_SIGINFO,
665666
signal::SigSet::empty(),
666667
);
667668

crashtracker/src/collector/emitters.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,51 @@ unsafe fn emit_backtrace_by_frames(
8181
Ok(())
8282
}
8383

84+
85+
// libunwind structures and functions
86+
#[repr(C)]
87+
struct UnwContext([u8; 1024]); // Placeholder size for unw_context_t
88+
89+
#[repr(C)]
90+
struct UnwCursor([u8; 1024]); // Placeholder size for unw_cursor_t
91+
92+
extern "C" {
93+
fn _ULx86_64_init_local(cursor: *mut UnwCursor, context: *mut UnwContext) -> i32;
94+
fn _ULx86_64_step(cursor: *mut UnwCursor) -> i32;
95+
fn _ULx86_64_get_reg(cursor: *mut UnwCursor, reg: i32, valp: *mut u64) -> i32;
96+
}
97+
98+
const UNW_REG_IP: i32 = 16; // Register number for Instruction Pointer
99+
const UNW_REG_SP: i32 = 17; // Register number for Stack Pointer
100+
101+
fn emit_backtrace_libuwnind(w: &mut impl Write, ucontext: *const ucontext_t) -> anyhow::Result<()> {
102+
unsafe {
103+
let mut context = UnwContext([0; 1024]);
104+
let mut cursor = UnwCursor([0; 1024]);
105+
106+
if _ULx86_64_init_local(&mut cursor, &mut context) != 0 {
107+
writeln!(w, "Failed to initialize libunwind cursor")?;
108+
return Ok(());
109+
}
110+
111+
writeln!(w, "{DD_CRASHTRACK_BEGIN_STACKTRACE}")?;
112+
while _ULx86_64_step(&mut cursor) > 0 {
113+
let mut ip: u64 = 0;
114+
let mut sp: u64 = 0;
115+
if _ULx86_64_get_reg(&mut cursor, UNW_REG_IP, &mut ip) == 0 &&
116+
_ULx86_64_get_reg(&mut cursor, UNW_REG_SP, &mut sp) == 0 {
117+
writeln!(w, "{{ \"ip\": \"{:x}\", \"sp\": \"{:x}\" }}", ip, sp)?;
118+
} else {
119+
writeln!(w, "Failed to get registers")?;
120+
break;
121+
}
122+
}
123+
writeln!(w, "{DD_CRASHTRACK_END_STACKTRACE}")?;
124+
}
125+
Ok(())
126+
}
127+
128+
84129
pub(crate) fn emit_crashreport(
85130
pipe: &mut impl Write,
86131
config: &CrashtrackerConfiguration,
@@ -109,7 +154,9 @@ pub(crate) fn emit_crashreport(
109154
// https://doc.rust-lang.org/src/std/backtrace.rs.html#332
110155
// Do this last, so even if it crashes, we still get the other info.
111156
if config.resolve_frames != StacktraceCollection::Disabled {
112-
unsafe { emit_backtrace_by_frames(pipe, config.resolve_frames)? };
157+
// todo: add a switch between musl / glibc
158+
// unsafe { emit_backtrace_by_frames(pipe, config.resolve_frames)? };
159+
emit_backtrace_libuwnind(pipe, ucontext)?;
113160
}
114161
writeln!(pipe, "{DD_CRASHTRACK_DONE}")?;
115162
pipe.flush()?;

docs/RFCs/0008-custom-unwinder.md

Whitespace-only changes.

0 commit comments

Comments
 (0)