Skip to content

Commit 9d7c979

Browse files
authored
Add the concept of a "known custom section" to wasmparser (#1544)
* Add the concept of a "known custom section" to wasmparser There are a number of places throughout wasm-tools which process custom sections, and as surfaced in #1540 they're not necessarily all handled uniformly due to the flexible nature of custom sections. This commit aims to improve the parsing of custom sections in the future by having a `wasmparser::KnownCustom` enum which statically enumerates all custom sections that are known to wasmparser and can be parsed. This additionally provides a nice convenience for creating the typed parsers as well. * Add a known "linking" section, add it to `dump`, and test it * Add reloc to known custom sections
1 parent f5880b2 commit 9d7c979

13 files changed

Lines changed: 1250 additions & 197 deletions

File tree

crates/wasm-encoder/src/core/dump.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ impl Encode for CoreDumpValue {
336336
mod tests {
337337
use super::*;
338338
use crate::Module;
339-
use wasmparser::{BinaryReader, FromReader, Parser, Payload};
339+
use wasmparser::{KnownCustom, Parser, Payload};
340340

341341
// Create new core dump section and test whether it is properly encoded and
342342
// parsed back out by wasmparser
@@ -361,10 +361,10 @@ mod tests {
361361
match payload {
362362
Payload::CustomSection(section) => {
363363
assert_eq!(section.name(), "core");
364-
let core = wasmparser::CoreDumpSection::from_reader(&mut BinaryReader::new(
365-
section.data(),
366-
))
367-
.expect("data is readable into a core dump section");
364+
let core = match section.as_known() {
365+
KnownCustom::CoreDump(s) => s,
366+
_ => panic!("not coredump"),
367+
};
368368
assert_eq!(core.name, "test.wasm");
369369
}
370370
_ => panic!("unexpected payload"),
@@ -394,10 +394,10 @@ mod tests {
394394
match payload {
395395
Payload::CustomSection(section) => {
396396
assert_eq!(section.name(), "coremodules");
397-
let modules = wasmparser::CoreDumpModulesSection::from_reader(
398-
&mut BinaryReader::new(section.data()),
399-
)
400-
.expect("data is readable into a core dump modules section");
397+
let modules = match section.as_known() {
398+
KnownCustom::CoreDumpModules(s) => s,
399+
_ => panic!("not coremodules"),
400+
};
401401
assert_eq!(modules.modules[0], "test_module");
402402
}
403403
_ => panic!("unexpected payload"),
@@ -429,10 +429,10 @@ mod tests {
429429
match payload {
430430
Payload::CustomSection(section) => {
431431
assert_eq!(section.name(), "coreinstances");
432-
let coreinstances = wasmparser::CoreDumpInstancesSection::from_reader(
433-
&mut BinaryReader::new(section.data()),
434-
)
435-
.expect("data is readable into a core dump instances section");
432+
let coreinstances = match section.as_known() {
433+
KnownCustom::CoreDumpInstances(s) => s,
434+
_ => panic!("not coreinstances"),
435+
};
436436
assert_eq!(coreinstances.instances.len(), 1);
437437
let instance = coreinstances
438438
.instances
@@ -475,10 +475,10 @@ mod tests {
475475
match payload {
476476
Payload::CustomSection(section) => {
477477
assert_eq!(section.name(), "corestack");
478-
let corestack = wasmparser::CoreDumpStackSection::from_reader(
479-
&mut BinaryReader::new(section.data()),
480-
)
481-
.expect("data is readable into a core dump stack section");
478+
let corestack = match section.as_known() {
479+
KnownCustom::CoreDumpStack(s) => s,
480+
_ => panic!("not a corestack section"),
481+
};
482482
assert_eq!(corestack.name, "main");
483483
assert_eq!(corestack.frames.len(), 1);
484484
let frame = corestack
@@ -570,7 +570,7 @@ mod tests {
570570
// 0x0, module_idx
571571
0x0, 0,
572572
// memories count, memories
573-
1, 42,
573+
1, 42,
574574
// globals count, globals
575575
1, 17
576576
]);
@@ -595,7 +595,7 @@ mod tests {
595595
encoded,
596596
vec![
597597
// section length
598-
27,
598+
27,
599599
// length of name.
600600
9,
601601
// section name (corestack)

crates/wasm-encoder/src/core/producers.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ mod test {
121121
#[test]
122122
fn roundtrip_example() {
123123
use crate::{Module, ProducersField, ProducersSection};
124-
use wasmparser::{Parser, Payload, ProducersSectionReader};
124+
use wasmparser::{KnownCustom, Parser, Payload};
125125

126126
// Create a new producers section.
127127
let mut field = ProducersField::new();
@@ -151,9 +151,10 @@ mod test {
151151
match payload {
152152
Payload::CustomSection(c) => {
153153
assert_eq!(c.name(), "producers");
154-
let mut section = ProducersSectionReader::new(c.data(), c.data_offset())
155-
.expect("readable as a producers section")
156-
.into_iter();
154+
let mut section = match c.as_known() {
155+
KnownCustom::Producers(s) => s.into_iter(),
156+
_ => panic!("unknown custom section"),
157+
};
157158
let field = section
158159
.next()
159160
.expect("section has an element")

crates/wasm-metadata/src/lib.rs

Lines changed: 84 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use std::mem;
99
use std::ops::Range;
1010
use wasm_encoder::{ComponentSection as _, ComponentSectionId, Encode, Section};
1111
use wasmparser::{
12-
ComponentNameSectionReader, NameSectionReader, Parser, Payload::*, ProducersSectionReader,
12+
ComponentNameSectionReader, KnownCustom, NameSectionReader, Parser, Payload::*,
13+
ProducersSectionReader,
1314
};
1415

1516
/// A representation of a WebAssembly producers section.
@@ -50,9 +51,11 @@ impl Producers {
5051
match payload {
5152
ModuleSection { .. } | ComponentSection { .. } => depth += 1,
5253
End { .. } => depth -= 1,
53-
CustomSection(c) if c.name() == "producers" && depth == 0 => {
54-
let producers = Self::from_bytes(c.data(), c.data_offset())?;
55-
return Ok(Some(producers));
54+
CustomSection(c) if depth == 0 => {
55+
if let KnownCustom::Producers(_) = c.as_known() {
56+
let producers = Self::from_bytes(c.data(), c.data_offset())?;
57+
return Ok(Some(producers));
58+
}
5659
}
5760
_ => {}
5861
}
@@ -290,57 +293,60 @@ fn rewrite_wasm(
290293
_ => {}
291294
}
292295

293-
// Process the wasm sections:
294-
match payload {
295-
// Only rewrite the outermost producers section:
296-
CustomSection(c) if c.name() == "producers" && stack.len() == 0 => {
297-
producers_found = true;
298-
let mut producers = Producers::from_bytes(c.data(), c.data_offset())?;
299-
// Add to the section according to the command line flags:
300-
producers.merge(&add_producers);
301-
// Encode into output:
302-
producers.section().append_to(&mut output);
303-
}
304-
305-
CustomSection(c) if c.name() == "name" && stack.len() == 0 => {
306-
names_found = true;
307-
let mut names = ModuleNames::from_bytes(c.data(), c.data_offset())?;
308-
names.merge(&ModuleNames::from_name(add_name));
309-
310-
names.section()?.as_custom().append_to(&mut output);
311-
}
312-
313-
CustomSection(c) if c.name() == "component-name" && stack.len() == 0 => {
314-
names_found = true;
315-
let mut names = ComponentNames::from_bytes(c.data(), c.data_offset())?;
316-
names.merge(&ComponentNames::from_name(add_name));
317-
names.section()?.as_custom().append_to(&mut output);
318-
}
319-
320-
CustomSection(c) if c.name() == "registry-metadata" && stack.len() == 0 => {
321-
// Pass section through if a new registry metadata isn't provided, otherwise ignore and overwrite with new
322-
if add_registry_metadata.is_none() {
323-
let registry: RegistryMetadata = RegistryMetadata::from_bytes(&c.data(), 0)?;
324-
325-
let registry_metadata = wasm_encoder::CustomSection {
326-
name: Cow::Borrowed("registry-metadata"),
327-
data: Cow::Owned(serde_json::to_vec(&registry)?),
328-
};
329-
registry_metadata.append_to(&mut output);
330-
}
331-
}
296+
// Only rewrite the outermost custom sections
297+
if let CustomSection(c) = &payload {
298+
if stack.len() == 0 {
299+
match c.as_known() {
300+
KnownCustom::Producers(_) => {
301+
producers_found = true;
302+
let mut producers = Producers::from_bytes(c.data(), c.data_offset())?;
303+
// Add to the section according to the command line flags:
304+
producers.merge(&add_producers);
305+
// Encode into output:
306+
producers.section().append_to(&mut output);
307+
continue;
308+
}
309+
KnownCustom::Name(_) => {
310+
names_found = true;
311+
let mut names = ModuleNames::from_bytes(c.data(), c.data_offset())?;
312+
names.merge(&ModuleNames::from_name(add_name));
332313

333-
// All other sections get passed through unmodified:
334-
_ => {
335-
if let Some((id, range)) = payload.as_section() {
336-
wasm_encoder::RawSection {
337-
id,
338-
data: &input[range],
314+
names.section()?.as_custom().append_to(&mut output);
315+
continue;
316+
}
317+
KnownCustom::ComponentName(_) => {
318+
names_found = true;
319+
let mut names = ComponentNames::from_bytes(c.data(), c.data_offset())?;
320+
names.merge(&ComponentNames::from_name(add_name));
321+
names.section()?.as_custom().append_to(&mut output);
322+
continue;
339323
}
340-
.append_to(&mut output);
324+
KnownCustom::Unknown if c.name() == "registry-metadata" => {
325+
// Pass section through if a new registry metadata isn't provided, otherwise ignore and overwrite with new
326+
if add_registry_metadata.is_none() {
327+
let registry: RegistryMetadata =
328+
RegistryMetadata::from_bytes(&c.data(), 0)?;
329+
330+
let registry_metadata = wasm_encoder::CustomSection {
331+
name: Cow::Borrowed("registry-metadata"),
332+
data: Cow::Owned(serde_json::to_vec(&registry)?),
333+
};
334+
registry_metadata.append_to(&mut output);
335+
continue;
336+
}
337+
}
338+
_ => {}
341339
}
342340
}
343341
}
342+
// All other sections get passed through unmodified:
343+
if let Some((id, range)) = payload.as_section() {
344+
wasm_encoder::RawSection {
345+
id,
346+
data: &input[range],
347+
}
348+
.append_to(&mut output);
349+
}
344350
}
345351
if !names_found && add_name.is_some() {
346352
if output.starts_with(&wasm_encoder::Component::HEADER) {
@@ -434,39 +440,42 @@ impl Metadata {
434440
metadata.last_mut().unwrap().push_child(finished);
435441
}
436442
}
437-
CustomSection(c) if c.name() == "name" => {
438-
let names = ModuleNames::from_bytes(c.data(), c.data_offset())?;
439-
if let Some(name) = names.get_name() {
443+
CustomSection(c) => match c.as_known() {
444+
KnownCustom::Name(_) => {
445+
let names = ModuleNames::from_bytes(c.data(), c.data_offset())?;
446+
if let Some(name) = names.get_name() {
447+
metadata
448+
.last_mut()
449+
.expect("non-empty metadata stack")
450+
.set_name(&name);
451+
}
452+
}
453+
KnownCustom::ComponentName(_) => {
454+
let names = ComponentNames::from_bytes(c.data(), c.data_offset())?;
455+
if let Some(name) = names.get_name() {
456+
metadata
457+
.last_mut()
458+
.expect("non-empty metadata stack")
459+
.set_name(name);
460+
}
461+
}
462+
KnownCustom::Producers(_) => {
463+
let producers = Producers::from_bytes(c.data(), c.data_offset())?;
440464
metadata
441465
.last_mut()
442466
.expect("non-empty metadata stack")
443-
.set_name(&name);
467+
.set_producers(producers);
444468
}
445-
}
446-
CustomSection(c) if c.name() == "component-name" => {
447-
let names = ComponentNames::from_bytes(c.data(), c.data_offset())?;
448-
if let Some(name) = names.get_name() {
469+
KnownCustom::Unknown if c.name() == "registry-metadata" => {
470+
let registry: RegistryMetadata =
471+
RegistryMetadata::from_bytes(&c.data(), 0)?;
449472
metadata
450473
.last_mut()
451474
.expect("non-empty metadata stack")
452-
.set_name(name);
475+
.set_registry_metadata(registry);
453476
}
454-
}
455-
CustomSection(c) if c.name() == "producers" => {
456-
let producers = Producers::from_bytes(c.data(), c.data_offset())?;
457-
metadata
458-
.last_mut()
459-
.expect("non-empty metadata stack")
460-
.set_producers(producers);
461-
}
462-
CustomSection(c) if c.name() == "registry-metadata" => {
463-
let registry: RegistryMetadata = RegistryMetadata::from_bytes(&c.data(), 0)?;
464-
metadata
465-
.last_mut()
466-
.expect("non-empty metadata stack")
467-
.set_registry_metadata(registry);
468-
}
469-
477+
_ => {}
478+
},
470479
_ => {}
471480
}
472481
}

0 commit comments

Comments
 (0)