Add a custom section hook to ModuleEnvironment

This commit adds a hook to the `ModuleEnvironment` trait to learn when a
custom section in a wasm file is read. This hook can in theory be used
to parse and handle custom sections as they appear in the wasm file
without having to re-iterate over the wasm file after cranelift has
already parsed the wasm file.

The `translate_module` function is now less strict in that it doesn't
require sections to be in a particular order, but it's figured that the
wasm file is already validated elsewhere to verify the section order.
This commit is contained in:
Alex Crichton
2019-08-13 13:11:22 -07:00
committed by Dan Gohman
parent 8fd1128990
commit dfda794f55
2 changed files with 79 additions and 124 deletions

View File

@@ -467,4 +467,14 @@ pub trait ModuleEnvironment<'data> {
offset: usize, offset: usize,
data: &'data [u8], data: &'data [u8],
) -> WasmResult<()>; ) -> WasmResult<()>;
/// Indicates that a custom section has been found in the wasm file
fn custom_section(
&mut self,
name: &'data str,
data: &'data [u8],
) -> WasmResult<()> {
drop((name, data));
Ok(())
}
} }

View File

@@ -18,134 +18,79 @@ pub fn translate_module<'data>(
let _tt = timing::wasm_translate_module(); let _tt = timing::wasm_translate_module();
let mut reader = ModuleReader::new(data)?; let mut reader = ModuleReader::new(data)?;
reader.skip_custom_sections()?; while !reader.eof() {
if reader.eof() { let section = reader.read()?;
return Ok(()); match section.code {
} SectionCode::Type => {
let mut section = reader.read()?;
if let SectionCode::Type = section.code {
let types = section.get_type_section_reader()?; let types = section.get_type_section_reader()?;
parse_type_section(types, environ)?; parse_type_section(types, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
} }
if let SectionCode::Import = section.code { SectionCode::Import => {
let imports = section.get_import_section_reader()?; let imports = section.get_import_section_reader()?;
parse_import_section(imports, environ)?; parse_import_section(imports, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
} }
if let SectionCode::Function = section.code { SectionCode::Function => {
let functions = section.get_function_section_reader()?; let functions = section.get_function_section_reader()?;
parse_function_section(functions, environ)?; parse_function_section(functions, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
} }
if let SectionCode::Table = section.code { SectionCode::Table => {
let tables = section.get_table_section_reader()?; let tables = section.get_table_section_reader()?;
parse_table_section(tables, environ)?; parse_table_section(tables, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
} }
if let SectionCode::Memory = section.code { SectionCode::Memory => {
let memories = section.get_memory_section_reader()?; let memories = section.get_memory_section_reader()?;
parse_memory_section(memories, environ)?; parse_memory_section(memories, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
} }
if let SectionCode::Global = section.code { SectionCode::Global => {
let globals = section.get_global_section_reader()?; let globals = section.get_global_section_reader()?;
parse_global_section(globals, environ)?; parse_global_section(globals, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
} }
if let SectionCode::Export = section.code { SectionCode::Export => {
let exports = section.get_export_section_reader()?; let exports = section.get_export_section_reader()?;
parse_export_section(exports, environ)?; parse_export_section(exports, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
} }
if let SectionCode::Start = section.code { SectionCode::Start => {
let start = section.get_start_section_content()?; let start = section.get_start_section_content()?;
parse_start_section(start, environ)?; parse_start_section(start, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
} }
if let SectionCode::Element = section.code { SectionCode::Element => {
let elements = section.get_element_section_reader()?; let elements = section.get_element_section_reader()?;
parse_element_section(elements, environ)?; parse_element_section(elements, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
} }
if let SectionCode::Code = section.code { SectionCode::Code => {
let code = section.get_code_section_reader()?; let code = section.get_code_section_reader()?;
parse_code_section(code, environ)?; parse_code_section(code, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
} }
if let SectionCode::Data = section.code { SectionCode::Data => {
let data = section.get_data_section_reader()?; let data = section.get_data_section_reader()?;
parse_data_section(data, environ)?; parse_data_section(data, environ)?;
} }
reader.skip_custom_sections()?; SectionCode::DataCount => {
if !reader.eof() {
return Err(WasmError::InvalidWebAssembly { return Err(WasmError::InvalidWebAssembly {
message: "sections must occur at most once and in the prescribed order", message: "don't know how to handle the data count section yet",
offset: reader.current_position(), offset: reader.current_position(),
}); });
} }
SectionCode::Custom { name, kind: _ } => {
let mut reader = section.get_binary_reader();
let len = reader.bytes_remaining();
let payload = reader.read_bytes(len)?;
environ.custom_section(name, payload)?;
}
}
}
Ok(()) Ok(())
} }