Struct wasmtime_jit::CodeMemory
source · pub struct CodeMemory { /* private fields */ }
Expand description
Management of executable memory within a MmapVec
This type consumes ownership of a region of memory and will manage the executable permissions of the contained JIT code as necessary.
Implementations§
source§impl CodeMemory
impl CodeMemory
sourcepub fn new(mmap: MmapVec) -> Result<Self>
pub fn new(mmap: MmapVec) -> Result<Self>
Creates a new CodeMemory
by taking ownership of the provided
MmapVec
.
The returned CodeMemory
manages the internal MmapVec
and the
publish
method is used to actually make the memory executable.
sourcepub fn text(&self) -> &[u8] ⓘ
pub fn text(&self) -> &[u8] ⓘ
Returns the contents of the text section of the ELF executable this represents.
Examples found in repository?
More examples
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
pub unsafe fn vmtrampoline(&self, loc: FunctionLoc) -> VMTrampoline {
let ptr = self.text()[loc.start as usize..][..loc.length as usize].as_ptr();
mem::transmute::<*const u8, VMTrampoline>(ptr)
}
/// Publishes the internal ELF image to be ready for execution.
///
/// This method can only be called once and will panic if called twice. This
/// will parse the ELF image from the original `MmapVec` and do everything
/// necessary to get it ready for execution, including:
///
/// * Change page protections from read/write to read/execute.
/// * Register unwinding information with the OS
///
/// After this function executes all JIT code should be ready to execute.
pub fn publish(&mut self) -> Result<()> {
assert!(!self.published);
self.published = true;
if self.text().is_empty() {
return Ok(());
}
// The unsafety here comes from a few things:
//
// * We're actually updating some page protections to executable memory.
//
// * We're registering unwinding information which relies on the
// correctness of the information in the first place. This applies to
// both the actual unwinding tables as well as the validity of the
// pointers we pass in itself.
unsafe {
let text = self.text();
// Clear the newly allocated code from cache if the processor requires it
//
// Do this before marking the memory as R+X, technically we should be able to do it after
// but there are some CPU's that have had errata about doing this with read only memory.
icache_coherence::clear_cache(text.as_ptr().cast(), text.len())
.expect("Failed cache clear");
// Switch the executable portion from read/write to
// read/execute, notably not using read/write/execute to prevent
// modifications.
self.mmap
.make_executable(self.text.clone(), self.enable_branch_protection)
.expect("unable to make memory executable");
// Flush any in-flight instructions from the pipeline
icache_coherence::pipeline_flush_mt().expect("Failed pipeline flush");
// With all our memory set up use the platform-specific
// `UnwindRegistration` implementation to inform the general
// runtime that there's unwinding information available for all
// our just-published JIT functions.
self.register_unwind_info()?;
}
Ok(())
}
unsafe fn register_unwind_info(&mut self) -> Result<()> {
if self.unwind.len() == 0 {
return Ok(());
}
let text = self.text();
let unwind_info = &self.mmap[self.unwind.clone()];
let registration =
UnwindRegistration::new(text.as_ptr(), unwind_info.as_ptr(), unwind_info.len())
.context("failed to create unwind info registration")?;
*self.unwind_registration = Some(registration);
Ok(())
}
sourcepub fn dwarf_section(&self, section: SectionId) -> &[u8] ⓘ
pub fn dwarf_section(&self, section: SectionId) -> &[u8] ⓘ
Returns the data in the corresponding dwarf section, or an empty slice if the section wasn’t present.
Examples found in repository?
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
pub fn symbolize_context(&self) -> Result<Option<SymbolizeContext<'_>>> {
use gimli::EndianSlice;
if !self.meta.has_wasm_debuginfo {
return Ok(None);
}
let dwarf = gimli::Dwarf::load(|id| -> Result<_> {
let data = self.code_memory().dwarf_section(id);
Ok(EndianSlice::new(data, gimli::LittleEndian))
})?;
let cx = addr2line::Context::from_dwarf(dwarf)
.context("failed to create addr2line dwarf mapping context")?;
Ok(Some(SymbolizeContext {
inner: cx,
code_section_offset: self.meta.code_section_offset,
}))
}
sourcepub fn func_name_data(&self) -> &[u8] ⓘ
pub fn func_name_data(&self) -> &[u8] ⓘ
Returns the data in the ELF_NAME_DATA
section.
Examples found in repository?
466 467 468 469 470 471 472 473 474 475 476 477
pub fn func_name(&self, idx: FuncIndex) -> Option<&str> {
// Find entry for `idx`, if present.
let i = self.func_names.binary_search_by_key(&idx, |n| n.idx).ok()?;
let name = &self.func_names[i];
// Here we `unwrap` the `from_utf8` but this can theoretically be a
// `from_utf8_unchecked` if we really wanted since this section is
// guaranteed to only have valid utf-8 data. Until it's a problem it's
// probably best to double-check this though.
let data = self.code_memory().func_name_data();
Some(str::from_utf8(&data[name.offset as usize..][..name.len as usize]).unwrap())
}
sourcepub fn wasm_data(&self) -> &[u8] ⓘ
pub fn wasm_data(&self) -> &[u8] ⓘ
Returns the concatenated list of all data associated with this wasm module.
This is used for initialization of memories and all data ranges stored
in a Module
are relative to the slice returned here.
sourcepub fn address_map_data(&self) -> &[u8] ⓘ
pub fn address_map_data(&self) -> &[u8] ⓘ
Returns the encoded address map section used to pass to
wasmtime_environ::lookup_file_pos
.
sourcepub fn wasmtime_info(&self) -> &[u8] ⓘ
pub fn wasmtime_info(&self) -> &[u8] ⓘ
Returns the contents of the ELF_WASMTIME_INFO
section, or an empty
slice if it wasn’t found.
sourcepub fn trap_data(&self) -> &[u8] ⓘ
pub fn trap_data(&self) -> &[u8] ⓘ
Returns the contents of the ELF_WASMTIME_TRAPS
section, or an empty
slice if it wasn’t found.
sourcepub unsafe fn vmtrampoline(&self, loc: FunctionLoc) -> VMTrampoline
pub unsafe fn vmtrampoline(&self, loc: FunctionLoc) -> VMTrampoline
Returns a VMTrampoline
function pointer for the given function in the
text section.
Unsafety
This function is unsafe as there’s no guarantee that the returned function pointer is valid.
sourcepub fn publish(&mut self) -> Result<()>
pub fn publish(&mut self) -> Result<()>
Publishes the internal ELF image to be ready for execution.
This method can only be called once and will panic if called twice. This
will parse the ELF image from the original MmapVec
and do everything
necessary to get it ready for execution, including:
- Change page protections from read/write to read/execute.
- Register unwinding information with the OS
After this function executes all JIT code should be ready to execute.