-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Register target features in custom section when using xforms #3967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,11 +6,14 @@ | |
//! * The shadow stack pointer | ||
//! * The canonical linear memory that contains the shadow stack | ||
|
||
use anyhow::{anyhow, bail, Result}; | ||
use std::io::Cursor; | ||
|
||
use anyhow::{anyhow, bail, Context, Result}; | ||
use walrus::{ | ||
ir::Value, ElementId, FunctionBuilder, FunctionId, FunctionKind, GlobalId, GlobalKind, | ||
InitExpr, MemoryId, Module, ValType, | ||
InitExpr, MemoryId, Module, RawCustomSection, ValType, | ||
}; | ||
use wasmparser::BinaryReader; | ||
|
||
/// Get a Wasm module's canonical linear memory. | ||
pub fn get_memory(module: &Module) -> Result<MemoryId> { | ||
|
@@ -148,3 +151,72 @@ pub fn get_or_insert_start_builder(module: &mut Module) -> &mut FunctionBuilder | |
.unwrap_local_mut() | ||
.builder_mut() | ||
} | ||
|
||
pub fn insert_target_feature(module: &mut Module, new_feature: &str) -> Result<()> { | ||
// Taken from <https://github.com/bytecodealliance/wasm-tools/blob/f1898f46bb9d96f0f09682415cb6ccfd6a4dca79/crates/wasmparser/src/limits.rs#L27>. | ||
anyhow::ensure!(new_feature.len() <= 100_000, "feature name too long"); | ||
|
||
// Try to find an existing section. | ||
let section = module | ||
.customs | ||
.iter_mut() | ||
.find(|(_, custom)| custom.name() == "target_features"); | ||
|
||
// If one exists, check if the target feature is already present. | ||
let section = if let Some((_, section)) = section { | ||
let section: &mut RawCustomSection = section | ||
.as_any_mut() | ||
.downcast_mut() | ||
.context("failed to read section")?; | ||
let mut reader = BinaryReader::new(§ion.data); | ||
// The first integer contains the target feature count. | ||
let count = reader.read_var_u32()?; | ||
|
||
// Try to find if the target feature is already present. | ||
for _ in 0..count { | ||
// First byte is the prefix. | ||
let prefix_index = reader.current_position(); | ||
let prefix = reader.read_u8()? as u8; | ||
// Read the feature. | ||
let length = reader.read_var_u32()?; | ||
let feature = reader.read_bytes(length as usize)?; | ||
|
||
// If we found the target feature, we are done here. | ||
if feature == new_feature.as_bytes() { | ||
// Make sure we set any existing prefix to "enabled". | ||
if prefix == b'-' { | ||
section.data[prefix_index] = b'+'; | ||
} | ||
|
||
return Ok(()); | ||
} | ||
} | ||
|
||
section | ||
} else { | ||
let mut data = Vec::new(); | ||
leb128::write::unsigned(&mut data, 0).unwrap(); | ||
let id = module.customs.add(RawCustomSection { | ||
name: String::from("target_features"), | ||
data, | ||
}); | ||
module.customs.get_mut(id).unwrap() | ||
}; | ||
|
||
// If we couldn't find the target feature, insert it. | ||
|
||
// The first byte contains an integer describing the target feature count, which we increase by one. | ||
let mut data = Cursor::new(§ion.data); | ||
let count = leb128::read::unsigned(&mut data).unwrap(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This shouldn't use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can't fail because we already read it successfully beforehand (or return an error on failure) or inserted it correctly ourselves if no section was found. Let me know if I missed something! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, good point, I didn't think about that. |
||
let mut new_count = Vec::new(); | ||
leb128::write::unsigned(&mut new_count, count + 1).unwrap(); | ||
section.data.splice(0..data.position() as usize, new_count); | ||
// Then we insert the "enabled" prefix at the end. | ||
section.data.push(b'+'); | ||
// The next byte contains the length of the target feature string. | ||
leb128::write::unsigned(&mut section.data, new_feature.len() as u64).unwrap(); | ||
// Lastly the target feature string is inserted. | ||
section.data.extend(new_feature.as_bytes()); | ||
|
||
Ok(()) | ||
} |
Uh oh!
There was an error while loading. Please reload this page.