Resolve libcall relocations for older CPUs (#5567)
* Resolve libcall relocations for older CPUs Long ago Wasmtime used to have logic for resolving relocations post-compilation for libcalls which I ended up removing during refactorings last year. As #5563 points out, however, it's possible to get Wasmtime to panic by disabling SSE features which forces Cranelift to use libcalls for some floating-point operations instead. Note that this also requires disabling SIMD because SIMD support has a baseline of SSE 4.2. This commit pulls back the old implementations of various libcalls and reimplements logic necessary to have them work on CPUs without SSE 4.2 Closes #5563 * Fix log message in `wast` support * Fix offset listed in relocations Be sure to factor in the offset of the function itself * Review comments
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
//! Generate Cranelift compiler settings.
|
||||
|
||||
use crate::generators::ModuleConfig;
|
||||
use arbitrary::{Arbitrary, Unstructured};
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Choose between matching the host architecture or a cross-compilation target.
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
@@ -32,6 +34,42 @@ impl CodegenSettings {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Features such as sse4.2 are unconditionally enabled on the x86_64 target
|
||||
/// because they are hard required for SIMD, but when SIMD is disabled, for
|
||||
/// example, we support disabling these features.
|
||||
///
|
||||
/// This method will take the wasm feature selection chosen, through
|
||||
/// `module_config`, and possibly try to disable some more features by
|
||||
/// reading more of the input.
|
||||
pub fn maybe_disable_more_features(
|
||||
&mut self,
|
||||
module_config: &ModuleConfig,
|
||||
u: &mut Unstructured<'_>,
|
||||
) -> arbitrary::Result<()> {
|
||||
let flags = match self {
|
||||
CodegenSettings::Target { flags, .. } => flags,
|
||||
_ => return Ok(()),
|
||||
};
|
||||
|
||||
if !module_config.config.simd_enabled {
|
||||
// Note that regardless of architecture these booleans are generated
|
||||
// to have test case failures unrelated to codegen setting input
|
||||
// that fail on one architecture to fail on other architectures as
|
||||
// well.
|
||||
let new_flags = ["has_sse3", "has_ssse3", "has_sse41", "has_sse42"]
|
||||
.into_iter()
|
||||
.map(|name| Ok((name, u.arbitrary()?)))
|
||||
.collect::<arbitrary::Result<HashMap<_, bool>>>()?;
|
||||
|
||||
for (name, val) in flags {
|
||||
if let Some(new_value) = new_flags.get(name.as_str()) {
|
||||
*val = new_value.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Arbitrary<'a> for CodegenSettings {
|
||||
@@ -103,6 +141,9 @@ impl<'a> Arbitrary<'a> for CodegenSettings {
|
||||
// fail if these features are disabled, so unconditionally
|
||||
// enable them as we're not interested in fuzzing without
|
||||
// them.
|
||||
//
|
||||
// Note that these may still be disabled above in
|
||||
// `maybe_disable_more_features`.
|
||||
std:"sse3" => clif:"has_sse3" ratio: 1 in 1,
|
||||
std:"ssse3" => clif:"has_ssse3" ratio: 1 in 1,
|
||||
std:"sse4.1" => clif:"has_sse41" ratio: 1 in 1,
|
||||
|
||||
@@ -294,6 +294,11 @@ impl<'a> Arbitrary<'a> for Config {
|
||||
module_config: u.arbitrary()?,
|
||||
};
|
||||
|
||||
config
|
||||
.wasmtime
|
||||
.codegen
|
||||
.maybe_disable_more_features(&config.module_config, u)?;
|
||||
|
||||
// If using the pooling allocator, constrain the memory and module configurations
|
||||
// to the module limits.
|
||||
if let InstanceAllocationStrategy::Pooling(pooling) = &mut config.wasmtime.strategy {
|
||||
|
||||
Reference in New Issue
Block a user