Files
wasmtime/crates/jit/src/unwind/systemv.rs
Alex Crichton 601e8f3094 Remove dependency on the region crate (#4407)
This commit removes Wasmtime's dependency on the `region` crate. The
motivation for this came about when I was updating dependencies and saw
that `region` had a new major version at 3.0.0 as opposed to our
currently used 2.3 track. In reviewing the use cases of `region` within
Wasmtime I found two trends in particular which motivated this commit:

* Some unix-specific areas of `wasmtime_runtime` use
  `rustix::mm::mprotect` instead of `region::protect` already. This
  means that the usage of `region::protect` for changing virtual memory
  protections was already inconsistent.

* Many uses of `region::protect` were already in unix-specific regions
  which could make use of `rustix`.

Overall I opted to remove the dependency on the `region` crate to avoid
chasing its versions over time. Unix-specific changes of protections
were easily changed to `rustix::mm::mprotect`. There were two locations
where a windows/unix split is now required and I subjectively ruled
"that seems ok". Finally removing `region` also meant that the "what is
the current page size" query needed to be inlined into
`wasmtime_runtime`, which I have also subjectively ruled "that seems
fine".

Finally one final refactoring here was that the `unix.rs` and `linux.rs`
split for the pooling allocator was merged. These two files already only
differed in one function so I slapped a `cfg_if!` in there to help
reduce the duplication.
2022-07-07 21:28:25 +00:00

93 lines
3.2 KiB
Rust

//! Module for System V ABI unwind registry.
use anyhow::Result;
/// Represents a registration of function unwind information for System V ABI.
pub struct UnwindRegistration {
registrations: Vec<usize>,
}
extern "C" {
// libunwind import
fn __register_frame(fde: *const u8);
fn __deregister_frame(fde: *const u8);
}
impl UnwindRegistration {
/// Registers precompiled unwinding information with the system.
///
/// The `_base_address` field is ignored here (only used on other
/// platforms), but the `unwind_info` and `unwind_len` parameters should
/// describe an in-memory representation of a `.eh_frame` section. This is
/// typically arranged for by the `wasmtime-obj` crate.
pub unsafe fn new(
_base_address: *const u8,
unwind_info: *const u8,
unwind_len: usize,
) -> Result<UnwindRegistration> {
debug_assert_eq!(
unwind_info as usize % wasmtime_runtime::page_size(),
0,
"The unwind info must always be aligned to a page"
);
let mut registrations = Vec::new();
if cfg!(any(
all(target_os = "linux", target_env = "gnu"),
target_os = "freebsd"
)) {
// On gnu (libgcc), `__register_frame` will walk the FDEs until an
// entry of length 0
__register_frame(unwind_info);
registrations.push(unwind_info as usize);
} else {
// For libunwind, `__register_frame` takes a pointer to a single
// FDE. Note that we subtract 4 from the length of unwind info since
// wasmtime-encode .eh_frame sections always have a trailing 32-bit
// zero for the platforms above.
let start = unwind_info;
let end = start.add(unwind_len - 4);
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;
// Skip over the CIE
if current != start {
__register_frame(current);
registrations.push(current as usize);
}
// Move to the next table entry (+4 because the length itself is
// not inclusive)
current = current.add(len + 4);
}
}
Ok(UnwindRegistration { registrations })
}
pub fn section_name() -> &'static str {
".eh_frame"
}
}
impl Drop for UnwindRegistration {
fn drop(&mut self) {
unsafe {
// libgcc stores the frame entries as a linked list in decreasing
// sort order based on the PC value of the registered entry.
//
// As we store the registrations in increasing order, it would be
// O(N^2) to deregister in that order.
//
// To ensure that we just pop off the first element in the list upon
// every deregistration, walk our list of registrations backwards.
for fde in self.registrations.iter().rev() {
__deregister_frame(*fde as *const _);
}
}
}
}