Fuzz-code-coverage motivated improvements (#3905)

* fuzz: Fuzz padding between compiled functions

This commit hooks up the custom
`wasmtime_linkopt_padding_between_functions` configuration option to the
cranelift compiler into the fuzz configuration, enabling us to ensure
that randomly inserting a moderate amount of padding between functions
shouldn't tamper with any results.

* fuzz: Fuzz the `Config::generate_address_map` option

This commit adds fuzz configuration where `generate_address_map` is
either enabled or disabled, unlike how it's always enabled for fuzzing
today.

* Remove unnecessary handling of relocations

This commit removes a number of bits and pieces all related to handling
relocations in JIT code generated by Wasmtime. None of this is necessary
nowadays that the "old backend" has been removed (quite some time ago)
and relocations are no longer expected to be in the JIT code at all.
Additionally with the minimum x86_64 features required to run wasm code
it should be expected that no libcalls are required either for
Wasmtime-based JIT code.
This commit is contained in:
Alex Crichton
2022-03-09 12:58:27 -06:00
committed by GitHub
parent 29298b1f88
commit f21aa98ccb
7 changed files with 48 additions and 193 deletions

View File

@@ -148,18 +148,12 @@ impl CodeMemory {
std::slice::from_raw_parts_mut(ret.text.as_ptr() as *mut u8, ret.text.len());
let text_offset = ret.text.as_ptr() as usize - ret.mmap.as_ptr() as usize;
let text_range = text_offset..text_offset + text_mut.len();
let mut text_section_readwrite = false;
for (offset, r) in text.relocations() {
// If the text section was mapped at readonly we need to make it
// briefly read/write here as we apply relocations.
if !text_section_readwrite && self.mmap.is_readonly() {
self.mmap
.make_writable(text_range.clone())
.expect("unable to make memory writable");
text_section_readwrite = true;
}
crate::link::apply_reloc(&ret.obj, text_mut, offset, r);
}
// Double-check there are no relocations in the text section. At
// this time relocations are not expected at all from loaded code
// since everything should be resolved at compile time. Handling
// must be added here, though, if relocations pop up.
assert!(text.relocations().count() == 0);
// Switch the executable portion from read/write to
// read/execute, notably not using read/write/execute to prevent

View File

@@ -24,7 +24,6 @@ mod code_memory;
mod debug;
mod demangling;
mod instantiate;
mod link;
mod profiling;
mod unwind;

View File

@@ -1,89 +0,0 @@
//! Linking for JIT-compiled code.
use object::read::{Object, Relocation, RelocationTarget};
use object::{File, NativeEndian as NE, ObjectSymbol, RelocationEncoding, RelocationKind};
use std::convert::TryFrom;
use wasmtime_runtime::libcalls;
type I32 = object::I32Bytes<NE>;
type U64 = object::U64Bytes<NE>;
/// Applies the relocation `r` at `offset` within `code`, according to the
/// symbols found in `obj`.
///
/// This method is used at runtime to resolve relocations in ELF images,
/// typically with respect to where the memory was placed in the final address
/// in memory.
pub fn apply_reloc(obj: &File, code: &mut [u8], offset: u64, r: Relocation) {
let target_func_address: usize = match r.target() {
RelocationTarget::Symbol(i) => {
// Processing relocation target is a named symbols that is compiled
// wasm function or runtime libcall.
let sym = obj.symbol_by_index(i).unwrap();
if sym.is_local() {
&code[sym.address() as usize] as *const u8 as usize
} else {
match sym.name() {
Ok(name) => {
if let Some(addr) = to_libcall_address(name) {
addr
} else {
panic!("unknown function to link: {}", name);
}
}
Err(_) => panic!("unexpected relocation target: not a symbol"),
}
}
}
_ => panic!("unexpected relocation target: not a symbol"),
};
match (r.kind(), r.encoding(), r.size()) {
(RelocationKind::Absolute, RelocationEncoding::Generic, 64) => {
let reloc_address = reloc_address::<U64>(code, offset);
let reloc_abs = (target_func_address as u64)
.checked_add(r.addend() as u64)
.unwrap();
reloc_address.set(NE, reloc_abs);
}
// FIXME(#3009) after the old backend is removed this won't ever show up
// again so it can be removed.
(RelocationKind::Relative, RelocationEncoding::Generic, 32) => {
let reloc_address = reloc_address::<I32>(code, offset);
let val = (target_func_address as i64)
.wrapping_add(r.addend())
.wrapping_sub(reloc_address as *const _ as i64);
reloc_address.set(NE, i32::try_from(val).expect("relocation out-of-bounds"));
}
other => panic!("unsupported reloc kind: {:?}", other),
}
}
fn reloc_address<T: object::Pod>(code: &mut [u8], offset: u64) -> &mut T {
let (reloc, _rest) = usize::try_from(offset)
.ok()
.and_then(move |offset| code.get_mut(offset..))
.and_then(|range| object::from_bytes_mut(range).ok())
.expect("invalid reloc offset");
reloc
}
fn to_libcall_address(name: &str) -> Option<usize> {
use self::libcalls::*;
use wasmtime_environ::for_each_libcall;
macro_rules! add_libcall_symbol {
[$(($libcall:ident, $export:ident)),*] => {
Some(match name {
$(
stringify!($export) => $export as usize,
)+
_ => {
return None;
}
})
};
}
for_each_libcall!(add_libcall_symbol)
}