Prevent repeated registration of frames on Linux.

This commit calls `__register_frame` once for the entire frame table on
Linux.

On macOS, it still manually walks the frame table and registers each frame with
`__register_frame`.
This commit is contained in:
Peter Huene
2020-04-15 17:37:53 -07:00
parent 2fb7e9f3c2
commit 4d7a283b0c

View File

@@ -99,22 +99,32 @@ impl UnwindRegistry {
}
unsafe fn register_frames(&mut self) {
let start = self.frame_table.as_ptr();
let end = start.add(self.frame_table.len());
let mut current = start;
cfg_if::cfg_if! {
if #[cfg(target_os = "macos")] {
// On macOS, `__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;
// Walk all of the entries in the frame table and register them
while current < end {
let len = std::ptr::read::<u32>(current as *const u32) as usize;
// Walk all of the entries in the frame table and register them
while current < end {
let len = std::ptr::read::<u32>(current as *const u32) as usize;
// Skip over the CIE
if current != start {
__register_frame(current);
self.registrations.push(current as usize);
// Skip over the CIE
if current != start {
__register_frame(current);
self.registrations.push(current as usize);
}
// 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);
}
// Move to the next table entry (+4 because the length itself is not inclusive)
current = current.add(len + 4);
}
}
}