1d4242001SAdam Bratschi-Kaye //! Memory management for executable code. 2d4242001SAdam Bratschi-Kaye 3*72004aadSNick Fitzgerald use crate::runtime::vm::{libcalls, MmapVec, UnwindRegistration}; 4d4242001SAdam Bratschi-Kaye use anyhow::{anyhow, bail, Context, Result}; 5d4242001SAdam Bratschi-Kaye use object::read::{File, Object, ObjectSection}; 6d4242001SAdam Bratschi-Kaye use object::ObjectSymbol; 7d4242001SAdam Bratschi-Kaye use std::mem::ManuallyDrop; 8d4242001SAdam Bratschi-Kaye use std::ops::Range; 9d4242001SAdam Bratschi-Kaye use wasmtime_environ::obj; 10d4242001SAdam Bratschi-Kaye use wasmtime_jit_icache_coherence as icache_coherence; 11d4242001SAdam Bratschi-Kaye 12d4242001SAdam Bratschi-Kaye /// Management of executable memory within a `MmapVec` 13d4242001SAdam Bratschi-Kaye /// 14d4242001SAdam Bratschi-Kaye /// This type consumes ownership of a region of memory and will manage the 15d4242001SAdam Bratschi-Kaye /// executable permissions of the contained JIT code as necessary. 16d4242001SAdam Bratschi-Kaye pub struct CodeMemory { 17d4242001SAdam Bratschi-Kaye // NB: these are `ManuallyDrop` because `unwind_registration` must be 18d4242001SAdam Bratschi-Kaye // dropped first since it refers to memory owned by `mmap`. 19d4242001SAdam Bratschi-Kaye mmap: ManuallyDrop<MmapVec>, 20d4242001SAdam Bratschi-Kaye unwind_registration: ManuallyDrop<Option<UnwindRegistration>>, 21d4242001SAdam Bratschi-Kaye published: bool, 22d4242001SAdam Bratschi-Kaye enable_branch_protection: bool, 23d4242001SAdam Bratschi-Kaye 24d4242001SAdam Bratschi-Kaye relocations: Vec<(usize, obj::LibCall)>, 25d4242001SAdam Bratschi-Kaye 26d4242001SAdam Bratschi-Kaye // Ranges within `self.mmap` of where the particular sections lie. 27d4242001SAdam Bratschi-Kaye text: Range<usize>, 28d4242001SAdam Bratschi-Kaye unwind: Range<usize>, 29d4242001SAdam Bratschi-Kaye trap_data: Range<usize>, 30d4242001SAdam Bratschi-Kaye wasm_data: Range<usize>, 31d4242001SAdam Bratschi-Kaye address_map_data: Range<usize>, 32d4242001SAdam Bratschi-Kaye func_name_data: Range<usize>, 33d4242001SAdam Bratschi-Kaye info_data: Range<usize>, 34d4242001SAdam Bratschi-Kaye dwarf: Range<usize>, 35d4242001SAdam Bratschi-Kaye } 36d4242001SAdam Bratschi-Kaye 37d4242001SAdam Bratschi-Kaye impl Drop for CodeMemory { 38d4242001SAdam Bratschi-Kaye fn drop(&mut self) { 39d4242001SAdam Bratschi-Kaye // Drop `unwind_registration` before `self.mmap` 40d4242001SAdam Bratschi-Kaye unsafe { 41d4242001SAdam Bratschi-Kaye ManuallyDrop::drop(&mut self.unwind_registration); 42d4242001SAdam Bratschi-Kaye ManuallyDrop::drop(&mut self.mmap); 43d4242001SAdam Bratschi-Kaye } 44d4242001SAdam Bratschi-Kaye } 45d4242001SAdam Bratschi-Kaye } 46d4242001SAdam Bratschi-Kaye 47d4242001SAdam Bratschi-Kaye fn _assert() { 48d4242001SAdam Bratschi-Kaye fn _assert_send_sync<T: Send + Sync>() {} 49d4242001SAdam Bratschi-Kaye _assert_send_sync::<CodeMemory>(); 50d4242001SAdam Bratschi-Kaye } 51d4242001SAdam Bratschi-Kaye 52d4242001SAdam Bratschi-Kaye impl CodeMemory { 53d4242001SAdam Bratschi-Kaye /// Creates a new `CodeMemory` by taking ownership of the provided 54d4242001SAdam Bratschi-Kaye /// `MmapVec`. 55d4242001SAdam Bratschi-Kaye /// 56d4242001SAdam Bratschi-Kaye /// The returned `CodeMemory` manages the internal `MmapVec` and the 57d4242001SAdam Bratschi-Kaye /// `publish` method is used to actually make the memory executable. 58d4242001SAdam Bratschi-Kaye pub fn new(mmap: MmapVec) -> Result<Self> { 59d4242001SAdam Bratschi-Kaye let obj = File::parse(&mmap[..]) 60d4242001SAdam Bratschi-Kaye .with_context(|| "failed to parse internal compilation artifact")?; 61d4242001SAdam Bratschi-Kaye 62d4242001SAdam Bratschi-Kaye let mut relocations = Vec::new(); 63d4242001SAdam Bratschi-Kaye let mut text = 0..0; 64d4242001SAdam Bratschi-Kaye let mut unwind = 0..0; 65d4242001SAdam Bratschi-Kaye let mut enable_branch_protection = None; 66d4242001SAdam Bratschi-Kaye let mut trap_data = 0..0; 67d4242001SAdam Bratschi-Kaye let mut wasm_data = 0..0; 68d4242001SAdam Bratschi-Kaye let mut address_map_data = 0..0; 69d4242001SAdam Bratschi-Kaye let mut func_name_data = 0..0; 70d4242001SAdam Bratschi-Kaye let mut info_data = 0..0; 71d4242001SAdam Bratschi-Kaye let mut dwarf = 0..0; 72d4242001SAdam Bratschi-Kaye for section in obj.sections() { 73d4242001SAdam Bratschi-Kaye let data = section.data()?; 74d4242001SAdam Bratschi-Kaye let name = section.name()?; 75d4242001SAdam Bratschi-Kaye let range = subslice_range(data, &mmap); 76d4242001SAdam Bratschi-Kaye 77d4242001SAdam Bratschi-Kaye // Double-check that sections are all aligned properly. 78d4242001SAdam Bratschi-Kaye if section.align() != 0 && data.len() != 0 { 79d4242001SAdam Bratschi-Kaye if (data.as_ptr() as u64 - mmap.as_ptr() as u64) % section.align() != 0 { 80d4242001SAdam Bratschi-Kaye bail!( 81d4242001SAdam Bratschi-Kaye "section `{}` isn't aligned to {:#x}", 82d4242001SAdam Bratschi-Kaye section.name().unwrap_or("ERROR"), 83d4242001SAdam Bratschi-Kaye section.align() 84d4242001SAdam Bratschi-Kaye ); 85d4242001SAdam Bratschi-Kaye } 86d4242001SAdam Bratschi-Kaye } 87d4242001SAdam Bratschi-Kaye 88d4242001SAdam Bratschi-Kaye match name { 89d4242001SAdam Bratschi-Kaye obj::ELF_WASM_BTI => match data.len() { 90d4242001SAdam Bratschi-Kaye 1 => enable_branch_protection = Some(data[0] != 0), 91d4242001SAdam Bratschi-Kaye _ => bail!("invalid `{name}` section"), 92d4242001SAdam Bratschi-Kaye }, 93d4242001SAdam Bratschi-Kaye ".text" => { 94d4242001SAdam Bratschi-Kaye text = range; 95d4242001SAdam Bratschi-Kaye 96d4242001SAdam Bratschi-Kaye // The text section might have relocations for things like 97d4242001SAdam Bratschi-Kaye // libcalls which need to be applied, so handle those here. 98d4242001SAdam Bratschi-Kaye // 99d4242001SAdam Bratschi-Kaye // Note that only a small subset of possible relocations are 100d4242001SAdam Bratschi-Kaye // handled. Only those required by the compiler side of 101d4242001SAdam Bratschi-Kaye // things are processed. 102d4242001SAdam Bratschi-Kaye for (offset, reloc) in section.relocations() { 103d4242001SAdam Bratschi-Kaye assert_eq!(reloc.kind(), object::RelocationKind::Absolute); 104d4242001SAdam Bratschi-Kaye assert_eq!(reloc.encoding(), object::RelocationEncoding::Generic); 1051fa722e3SWang-Zhongqi assert_eq!(usize::from(reloc.size()), std::mem::size_of::<usize>() * 8); 106d4242001SAdam Bratschi-Kaye assert_eq!(reloc.addend(), 0); 107d4242001SAdam Bratschi-Kaye let sym = match reloc.target() { 108d4242001SAdam Bratschi-Kaye object::RelocationTarget::Symbol(id) => id, 109d4242001SAdam Bratschi-Kaye other => panic!("unknown relocation target {other:?}"), 110d4242001SAdam Bratschi-Kaye }; 111d4242001SAdam Bratschi-Kaye let sym = obj.symbol_by_index(sym).unwrap().name().unwrap(); 112d4242001SAdam Bratschi-Kaye let libcall = obj::LibCall::from_str(sym) 113d4242001SAdam Bratschi-Kaye .unwrap_or_else(|| panic!("unknown symbol relocation: {sym}")); 114d4242001SAdam Bratschi-Kaye 115d4242001SAdam Bratschi-Kaye let offset = usize::try_from(offset).unwrap(); 116d4242001SAdam Bratschi-Kaye relocations.push((offset, libcall)); 117d4242001SAdam Bratschi-Kaye } 118d4242001SAdam Bratschi-Kaye } 119d4242001SAdam Bratschi-Kaye UnwindRegistration::SECTION_NAME => unwind = range, 120d4242001SAdam Bratschi-Kaye obj::ELF_WASM_DATA => wasm_data = range, 121d4242001SAdam Bratschi-Kaye obj::ELF_WASMTIME_ADDRMAP => address_map_data = range, 122d4242001SAdam Bratschi-Kaye obj::ELF_WASMTIME_TRAPS => trap_data = range, 123d4242001SAdam Bratschi-Kaye obj::ELF_NAME_DATA => func_name_data = range, 124d4242001SAdam Bratschi-Kaye obj::ELF_WASMTIME_INFO => info_data = range, 125d4242001SAdam Bratschi-Kaye obj::ELF_WASMTIME_DWARF => dwarf = range, 126d4242001SAdam Bratschi-Kaye 127d4242001SAdam Bratschi-Kaye _ => log::debug!("ignoring section {name}"), 128d4242001SAdam Bratschi-Kaye } 129d4242001SAdam Bratschi-Kaye } 130d4242001SAdam Bratschi-Kaye Ok(Self { 131d4242001SAdam Bratschi-Kaye mmap: ManuallyDrop::new(mmap), 132d4242001SAdam Bratschi-Kaye unwind_registration: ManuallyDrop::new(None), 133d4242001SAdam Bratschi-Kaye published: false, 134d4242001SAdam Bratschi-Kaye enable_branch_protection: enable_branch_protection 135d4242001SAdam Bratschi-Kaye .ok_or_else(|| anyhow!("missing `{}` section", obj::ELF_WASM_BTI))?, 136d4242001SAdam Bratschi-Kaye text, 137d4242001SAdam Bratschi-Kaye unwind, 138d4242001SAdam Bratschi-Kaye trap_data, 139d4242001SAdam Bratschi-Kaye address_map_data, 140d4242001SAdam Bratschi-Kaye func_name_data, 141d4242001SAdam Bratschi-Kaye dwarf, 142d4242001SAdam Bratschi-Kaye info_data, 143d4242001SAdam Bratschi-Kaye wasm_data, 144d4242001SAdam Bratschi-Kaye relocations, 145d4242001SAdam Bratschi-Kaye }) 146d4242001SAdam Bratschi-Kaye } 147d4242001SAdam Bratschi-Kaye 148d4242001SAdam Bratschi-Kaye /// Returns a reference to the underlying `MmapVec` this memory owns. 149d4242001SAdam Bratschi-Kaye #[inline] 150d4242001SAdam Bratschi-Kaye pub fn mmap(&self) -> &MmapVec { 151d4242001SAdam Bratschi-Kaye &self.mmap 152d4242001SAdam Bratschi-Kaye } 153d4242001SAdam Bratschi-Kaye 154d4242001SAdam Bratschi-Kaye /// Returns the contents of the text section of the ELF executable this 155d4242001SAdam Bratschi-Kaye /// represents. 156d4242001SAdam Bratschi-Kaye #[inline] 157d4242001SAdam Bratschi-Kaye pub fn text(&self) -> &[u8] { 158d4242001SAdam Bratschi-Kaye &self.mmap[self.text.clone()] 159d4242001SAdam Bratschi-Kaye } 160d4242001SAdam Bratschi-Kaye 161d4242001SAdam Bratschi-Kaye /// Returns the contents of the `ELF_WASMTIME_DWARF` section. 162d4242001SAdam Bratschi-Kaye #[inline] 163d4242001SAdam Bratschi-Kaye pub fn dwarf(&self) -> &[u8] { 164d4242001SAdam Bratschi-Kaye &self.mmap[self.dwarf.clone()] 165d4242001SAdam Bratschi-Kaye } 166d4242001SAdam Bratschi-Kaye 167d4242001SAdam Bratschi-Kaye /// Returns the data in the `ELF_NAME_DATA` section. 168d4242001SAdam Bratschi-Kaye #[inline] 169d4242001SAdam Bratschi-Kaye pub fn func_name_data(&self) -> &[u8] { 170d4242001SAdam Bratschi-Kaye &self.mmap[self.func_name_data.clone()] 171d4242001SAdam Bratschi-Kaye } 172d4242001SAdam Bratschi-Kaye 173d4242001SAdam Bratschi-Kaye /// Returns the concatenated list of all data associated with this wasm 174d4242001SAdam Bratschi-Kaye /// module. 175d4242001SAdam Bratschi-Kaye /// 176d4242001SAdam Bratschi-Kaye /// This is used for initialization of memories and all data ranges stored 177d4242001SAdam Bratschi-Kaye /// in a `Module` are relative to the slice returned here. 178d4242001SAdam Bratschi-Kaye #[inline] 179d4242001SAdam Bratschi-Kaye pub fn wasm_data(&self) -> &[u8] { 180d4242001SAdam Bratschi-Kaye &self.mmap[self.wasm_data.clone()] 181d4242001SAdam Bratschi-Kaye } 182d4242001SAdam Bratschi-Kaye 183d4242001SAdam Bratschi-Kaye /// Returns the encoded address map section used to pass to 184d4242001SAdam Bratschi-Kaye /// `wasmtime_environ::lookup_file_pos`. 185d4242001SAdam Bratschi-Kaye #[inline] 186d4242001SAdam Bratschi-Kaye pub fn address_map_data(&self) -> &[u8] { 187d4242001SAdam Bratschi-Kaye &self.mmap[self.address_map_data.clone()] 188d4242001SAdam Bratschi-Kaye } 189d4242001SAdam Bratschi-Kaye 190d4242001SAdam Bratschi-Kaye /// Returns the contents of the `ELF_WASMTIME_INFO` section, or an empty 191d4242001SAdam Bratschi-Kaye /// slice if it wasn't found. 192d4242001SAdam Bratschi-Kaye #[inline] 193d4242001SAdam Bratschi-Kaye pub fn wasmtime_info(&self) -> &[u8] { 194d4242001SAdam Bratschi-Kaye &self.mmap[self.info_data.clone()] 195d4242001SAdam Bratschi-Kaye } 196d4242001SAdam Bratschi-Kaye 197d4242001SAdam Bratschi-Kaye /// Returns the contents of the `ELF_WASMTIME_TRAPS` section, or an empty 198d4242001SAdam Bratschi-Kaye /// slice if it wasn't found. 199d4242001SAdam Bratschi-Kaye #[inline] 200d4242001SAdam Bratschi-Kaye pub fn trap_data(&self) -> &[u8] { 201d4242001SAdam Bratschi-Kaye &self.mmap[self.trap_data.clone()] 202d4242001SAdam Bratschi-Kaye } 203d4242001SAdam Bratschi-Kaye 204d4242001SAdam Bratschi-Kaye /// Publishes the internal ELF image to be ready for execution. 205d4242001SAdam Bratschi-Kaye /// 206d4242001SAdam Bratschi-Kaye /// This method can only be called once and will panic if called twice. This 207d4242001SAdam Bratschi-Kaye /// will parse the ELF image from the original `MmapVec` and do everything 208d4242001SAdam Bratschi-Kaye /// necessary to get it ready for execution, including: 209d4242001SAdam Bratschi-Kaye /// 210d4242001SAdam Bratschi-Kaye /// * Change page protections from read/write to read/execute. 211d4242001SAdam Bratschi-Kaye /// * Register unwinding information with the OS 212d4242001SAdam Bratschi-Kaye /// 213d4242001SAdam Bratschi-Kaye /// After this function executes all JIT code should be ready to execute. 214d4242001SAdam Bratschi-Kaye pub fn publish(&mut self) -> Result<()> { 215d4242001SAdam Bratschi-Kaye assert!(!self.published); 216d4242001SAdam Bratschi-Kaye self.published = true; 217d4242001SAdam Bratschi-Kaye 218d4242001SAdam Bratschi-Kaye if self.text().is_empty() { 219d4242001SAdam Bratschi-Kaye return Ok(()); 220d4242001SAdam Bratschi-Kaye } 221d4242001SAdam Bratschi-Kaye 222d4242001SAdam Bratschi-Kaye // The unsafety here comes from a few things: 223d4242001SAdam Bratschi-Kaye // 224d4242001SAdam Bratschi-Kaye // * We're actually updating some page protections to executable memory. 225d4242001SAdam Bratschi-Kaye // 226d4242001SAdam Bratschi-Kaye // * We're registering unwinding information which relies on the 227d4242001SAdam Bratschi-Kaye // correctness of the information in the first place. This applies to 228d4242001SAdam Bratschi-Kaye // both the actual unwinding tables as well as the validity of the 229d4242001SAdam Bratschi-Kaye // pointers we pass in itself. 230d4242001SAdam Bratschi-Kaye unsafe { 231d4242001SAdam Bratschi-Kaye // First, if necessary, apply relocations. This can happen for 232d4242001SAdam Bratschi-Kaye // things like libcalls which happen late in the lowering process 233d4242001SAdam Bratschi-Kaye // that don't go through the Wasm-based libcalls layer that's 234d4242001SAdam Bratschi-Kaye // indirected through the `VMContext`. Note that most modules won't 235d4242001SAdam Bratschi-Kaye // have relocations, so this typically doesn't do anything. 236d4242001SAdam Bratschi-Kaye self.apply_relocations()?; 237d4242001SAdam Bratschi-Kaye 238d4242001SAdam Bratschi-Kaye // Next freeze the contents of this image by making all of the 239d4242001SAdam Bratschi-Kaye // memory readonly. Nothing after this point should ever be modified 240d4242001SAdam Bratschi-Kaye // so commit everything. For a compiled-in-memory image this will 241d4242001SAdam Bratschi-Kaye // mean IPIs to evict writable mappings from other cores. For 242d4242001SAdam Bratschi-Kaye // loaded-from-disk images this shouldn't result in IPIs so long as 243d4242001SAdam Bratschi-Kaye // there weren't any relocations because nothing should have 244d4242001SAdam Bratschi-Kaye // otherwise written to the image at any point either. 245d4242001SAdam Bratschi-Kaye self.mmap.make_readonly(0..self.mmap.len())?; 246d4242001SAdam Bratschi-Kaye 247d4242001SAdam Bratschi-Kaye let text = self.text(); 248d4242001SAdam Bratschi-Kaye 249d4242001SAdam Bratschi-Kaye // Clear the newly allocated code from cache if the processor requires it 250d4242001SAdam Bratschi-Kaye // 251d4242001SAdam Bratschi-Kaye // Do this before marking the memory as R+X, technically we should be able to do it after 252d4242001SAdam Bratschi-Kaye // but there are some CPU's that have had errata about doing this with read only memory. 253d4242001SAdam Bratschi-Kaye icache_coherence::clear_cache(text.as_ptr().cast(), text.len()) 254d4242001SAdam Bratschi-Kaye .expect("Failed cache clear"); 255d4242001SAdam Bratschi-Kaye 256d4242001SAdam Bratschi-Kaye // Switch the executable portion from readonly to read/execute. 257d4242001SAdam Bratschi-Kaye self.mmap 258d4242001SAdam Bratschi-Kaye .make_executable(self.text.clone(), self.enable_branch_protection) 259d4242001SAdam Bratschi-Kaye .context("unable to make memory executable")?; 260d4242001SAdam Bratschi-Kaye 261d4242001SAdam Bratschi-Kaye // Flush any in-flight instructions from the pipeline 262d4242001SAdam Bratschi-Kaye icache_coherence::pipeline_flush_mt().expect("Failed pipeline flush"); 263d4242001SAdam Bratschi-Kaye 264d4242001SAdam Bratschi-Kaye // With all our memory set up use the platform-specific 265d4242001SAdam Bratschi-Kaye // `UnwindRegistration` implementation to inform the general 266d4242001SAdam Bratschi-Kaye // runtime that there's unwinding information available for all 267d4242001SAdam Bratschi-Kaye // our just-published JIT functions. 268d4242001SAdam Bratschi-Kaye self.register_unwind_info()?; 269d4242001SAdam Bratschi-Kaye } 270d4242001SAdam Bratschi-Kaye 271d4242001SAdam Bratschi-Kaye Ok(()) 272d4242001SAdam Bratschi-Kaye } 273d4242001SAdam Bratschi-Kaye 274d4242001SAdam Bratschi-Kaye unsafe fn apply_relocations(&mut self) -> Result<()> { 275d4242001SAdam Bratschi-Kaye if self.relocations.is_empty() { 276d4242001SAdam Bratschi-Kaye return Ok(()); 277d4242001SAdam Bratschi-Kaye } 278d4242001SAdam Bratschi-Kaye 279d4242001SAdam Bratschi-Kaye for (offset, libcall) in self.relocations.iter() { 280d4242001SAdam Bratschi-Kaye let offset = self.text.start + offset; 281d4242001SAdam Bratschi-Kaye let libcall = match libcall { 282d4242001SAdam Bratschi-Kaye obj::LibCall::FloorF32 => libcalls::relocs::floorf32 as usize, 283d4242001SAdam Bratschi-Kaye obj::LibCall::FloorF64 => libcalls::relocs::floorf64 as usize, 284d4242001SAdam Bratschi-Kaye obj::LibCall::NearestF32 => libcalls::relocs::nearestf32 as usize, 285d4242001SAdam Bratschi-Kaye obj::LibCall::NearestF64 => libcalls::relocs::nearestf64 as usize, 286d4242001SAdam Bratschi-Kaye obj::LibCall::CeilF32 => libcalls::relocs::ceilf32 as usize, 287d4242001SAdam Bratschi-Kaye obj::LibCall::CeilF64 => libcalls::relocs::ceilf64 as usize, 288d4242001SAdam Bratschi-Kaye obj::LibCall::TruncF32 => libcalls::relocs::truncf32 as usize, 289d4242001SAdam Bratschi-Kaye obj::LibCall::TruncF64 => libcalls::relocs::truncf64 as usize, 290d4242001SAdam Bratschi-Kaye obj::LibCall::FmaF32 => libcalls::relocs::fmaf32 as usize, 291d4242001SAdam Bratschi-Kaye obj::LibCall::FmaF64 => libcalls::relocs::fmaf64 as usize, 292d4242001SAdam Bratschi-Kaye #[cfg(target_arch = "x86_64")] 293d4242001SAdam Bratschi-Kaye obj::LibCall::X86Pshufb => libcalls::relocs::x86_pshufb as usize, 294d4242001SAdam Bratschi-Kaye #[cfg(not(target_arch = "x86_64"))] 295d4242001SAdam Bratschi-Kaye obj::LibCall::X86Pshufb => unreachable!(), 296d4242001SAdam Bratschi-Kaye }; 297d4242001SAdam Bratschi-Kaye self.mmap 298d4242001SAdam Bratschi-Kaye .as_mut_ptr() 299d4242001SAdam Bratschi-Kaye .add(offset) 300d4242001SAdam Bratschi-Kaye .cast::<usize>() 301d4242001SAdam Bratschi-Kaye .write_unaligned(libcall); 302d4242001SAdam Bratschi-Kaye } 303d4242001SAdam Bratschi-Kaye Ok(()) 304d4242001SAdam Bratschi-Kaye } 305d4242001SAdam Bratschi-Kaye 306d4242001SAdam Bratschi-Kaye unsafe fn register_unwind_info(&mut self) -> Result<()> { 307d4242001SAdam Bratschi-Kaye if self.unwind.len() == 0 { 308d4242001SAdam Bratschi-Kaye return Ok(()); 309d4242001SAdam Bratschi-Kaye } 310d4242001SAdam Bratschi-Kaye let text = self.text(); 311d4242001SAdam Bratschi-Kaye let unwind_info = &self.mmap[self.unwind.clone()]; 312d4242001SAdam Bratschi-Kaye let registration = 313d4242001SAdam Bratschi-Kaye UnwindRegistration::new(text.as_ptr(), unwind_info.as_ptr(), unwind_info.len()) 314d4242001SAdam Bratschi-Kaye .context("failed to create unwind info registration")?; 315d4242001SAdam Bratschi-Kaye *self.unwind_registration = Some(registration); 316d4242001SAdam Bratschi-Kaye Ok(()) 317d4242001SAdam Bratschi-Kaye } 318d4242001SAdam Bratschi-Kaye } 319d4242001SAdam Bratschi-Kaye 320d4242001SAdam Bratschi-Kaye /// Returns the range of `inner` within `outer`, such that `outer[range]` is the 321d4242001SAdam Bratschi-Kaye /// same as `inner`. 322d4242001SAdam Bratschi-Kaye /// 323d4242001SAdam Bratschi-Kaye /// This method requires that `inner` is a sub-slice of `outer`, and if that 324d4242001SAdam Bratschi-Kaye /// isn't true then this method will panic. 325d4242001SAdam Bratschi-Kaye fn subslice_range(inner: &[u8], outer: &[u8]) -> Range<usize> { 326d4242001SAdam Bratschi-Kaye if inner.len() == 0 { 327d4242001SAdam Bratschi-Kaye return 0..0; 328d4242001SAdam Bratschi-Kaye } 329d4242001SAdam Bratschi-Kaye 330d4242001SAdam Bratschi-Kaye assert!(outer.as_ptr() <= inner.as_ptr()); 331d4242001SAdam Bratschi-Kaye assert!((&inner[inner.len() - 1] as *const _) <= (&outer[outer.len() - 1] as *const _)); 332d4242001SAdam Bratschi-Kaye 333d4242001SAdam Bratschi-Kaye let start = inner.as_ptr() as usize - outer.as_ptr() as usize; 334d4242001SAdam Bratschi-Kaye start..start + inner.len() 335d4242001SAdam Bratschi-Kaye } 336