Register individual FDEs for musl libc.
When targeting musl, libunwind is used for the `__register_frame`
implementation.
Unlike when targeting libgcc which expects an entire frame table, the libunwind
implementation expects a single FDE.
This change ensures Wasmtime registers each individual FDE when targeting musl.
Fixes
@@ -90,8 +90,10 @@ impl UnwindRegistry {
let mut eh_frame = EhFrame(EndianVec::new(RunTimeEndian::default()));
table.write_eh_frame(&mut eh_frame).unwrap();
- // GCC expects a terminating "empty" length, so write a 0 length at the end of the table.
+ if cfg!(all(target_os = "linux", target_env = "gnu")) {
+ // libgcc expects a terminating "empty" length, so write a 0 length at the end of the table.
eh_frame.0.write_u32(0).unwrap();
+ }
self.frame_table = eh_frame.0.into_vec();
@@ -99,9 +101,13 @@ impl UnwindRegistry {
}
unsafe fn register_frames(&mut self) {
- cfg_if::cfg_if! {
- if #[cfg(target_os = "macos")] {
- // On macOS, `__register_frame` takes a pointer to a single FDE
+ if cfg!(all(target_os = "linux", target_env = "gnu")) {
+ // On gnu (libgcc), `__register_frame` will walk the FDEs until an entry of length 0
+ let ptr = self.frame_table.as_ptr();
+ __register_frame(ptr);
+ self.registrations.push(ptr as usize);
+ } else {
+ // For libunwind, `__register_frame` takes a pointer to a single FDE
let start = self.frame_table.as_ptr();
let end = start.add(self.frame_table.len());
let mut current = start;
@@ -119,12 +125,6 @@ impl UnwindRegistry {
// Move to the next table entry (+4 because the length itself is not inclusive)
current = current.add(len + 4);
}
- } else {
- // On other platforms, `__register_frame` will walk the FDEs until an entry of length 0
- let ptr = self.frame_table.as_ptr();
- __register_frame(ptr);
- self.registrations.push(ptr as usize);
- }
}
}
}
