From 1ddb164a786ec191823fcf59041f2779673e94a8 Mon Sep 17 00:00:00 2001 From: ia0 Date: Sun, 23 Apr 2023 13:21:14 +0200 Subject: [PATCH 1/3] Try to guess symbol address in Wasm --- src/read/wasm.rs | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/read/wasm.rs b/src/read/wasm.rs index 16d39328..e9a8eb7d 100644 --- a/src/read/wasm.rs +++ b/src/read/wasm.rs @@ -106,6 +106,8 @@ impl<'data, R: ReadRef<'data>> WasmFile<'data, R> { let mut entry_func_id = None; let mut code_range_start = 0; let mut code_func_index = 0; + // One-to-one mapping of globals to their value (if the global is a constant i32). + let mut global_i32_values = Vec::new(); for payload in parser { let payload = payload.read_error("Invalid Wasm section header")?; @@ -168,6 +170,23 @@ impl<'data, R: ReadRef<'data>> WasmFile<'data, R> { } wp::Payload::GlobalSection(section) => { file.add_section(SectionId::Global, section.range(), ""); + for global in section { + let global = global.read_error("Couldn't read a global item")?; + let mut address = None; + const I32_CONST: wp::GlobalType = wp::GlobalType { + content_type: wp::ValType::I32, + mutable: false, + }; + if global.ty == I32_CONST { + // There should be exactly one instruction, which is an `i32.const`. + let init = global.init_expr.get_operators_reader().read(); + let init = init.read_error("Couldn't read a global init expr")?; + if let wp::Operator::I32Const { value } = init { + address = Some(value as u64); + } + } + global_i32_values.push(address); + } } wp::Payload::ExportSection(section) => { file.add_section(SectionId::Export, section.range(), ""); @@ -205,9 +224,17 @@ impl<'data, R: ReadRef<'data>> WasmFile<'data, R> { wp::ExternalKind::Tag => continue, }; + // Try to guess the symbol address. + let mut address = 0; + if export.kind == wp::ExternalKind::Global { + if let Some(&Some(x)) = global_i32_values.get(export.index as usize) { + address = x; + } + } + file.symbols.push(WasmSymbolInternal { name: export.name, - address: 0, + address, size: 0, kind, section: SymbolSection::Section(SectionIndex(section_idx as usize)), From ffa2497ab1a2e6eafadee383e928f865b7c724e5 Mon Sep 17 00:00:00 2001 From: ia0 Date: Sun, 23 Apr 2023 16:37:40 +0200 Subject: [PATCH 2/3] Support memory64 proposal --- src/read/wasm.rs | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/read/wasm.rs b/src/read/wasm.rs index e9a8eb7d..8e9c4fc1 100644 --- a/src/read/wasm.rs +++ b/src/read/wasm.rs @@ -106,8 +106,10 @@ impl<'data, R: ReadRef<'data>> WasmFile<'data, R> { let mut entry_func_id = None; let mut code_range_start = 0; let mut code_func_index = 0; - // One-to-one mapping of globals to their value (if the global is a constant i32). - let mut global_i32_values = Vec::new(); + // One-to-one mapping of globals to their value (if the global is a constant usize). + let mut global_usize_values = Vec::new(); + // Whether the first linear memory is 64-bits. + let mut is_memory64 = false; for payload in parser { let payload = payload.read_error("Invalid Wasm section header")?; @@ -167,25 +169,32 @@ impl<'data, R: ReadRef<'data>> WasmFile<'data, R> { } wp::Payload::MemorySection(section) => { file.add_section(SectionId::Memory, section.range(), ""); + for memory in section { + let memory = memory.read_error("Couldn't read a memory item")?; + is_memory64 = memory.memory64; + break; + } } wp::Payload::GlobalSection(section) => { file.add_section(SectionId::Global, section.range(), ""); + let usize_type = if is_memory64 { + wp::ValType::I64 + } else { + wp::ValType::I32 + }; for global in section { let global = global.read_error("Couldn't read a global item")?; let mut address = None; - const I32_CONST: wp::GlobalType = wp::GlobalType { - content_type: wp::ValType::I32, - mutable: false, - }; - if global.ty == I32_CONST { - // There should be exactly one instruction, which is an `i32.const`. + if !global.ty.mutable && global.ty.content_type == usize_type { + // There should be exactly one instruction. let init = global.init_expr.get_operators_reader().read(); - let init = init.read_error("Couldn't read a global init expr")?; - if let wp::Operator::I32Const { value } = init { - address = Some(value as u64); - } + address = match init.read_error("Couldn't read a global init expr")? { + wp::Operator::I32Const { value } => Some(value as u64), + wp::Operator::I64Const { value } => Some(value as u64), + _ => None, + }; } - global_i32_values.push(address); + global_usize_values.push(address); } } wp::Payload::ExportSection(section) => { @@ -227,7 +236,7 @@ impl<'data, R: ReadRef<'data>> WasmFile<'data, R> { // Try to guess the symbol address. let mut address = 0; if export.kind == wp::ExternalKind::Global { - if let Some(&Some(x)) = global_i32_values.get(export.index as usize) { + if let Some(&Some(x)) = global_usize_values.get(export.index as usize) { address = x; } } From fe14ddff6d6dd29682782badcd5c6ed00d2cefcc Mon Sep 17 00:00:00 2001 From: ia0 Date: Tue, 25 Apr 2023 20:38:12 +0200 Subject: [PATCH 3/3] Simplify code assuming valid wasm module --- src/read/wasm.rs | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/read/wasm.rs b/src/read/wasm.rs index 8e9c4fc1..4cad57af 100644 --- a/src/read/wasm.rs +++ b/src/read/wasm.rs @@ -106,10 +106,8 @@ impl<'data, R: ReadRef<'data>> WasmFile<'data, R> { let mut entry_func_id = None; let mut code_range_start = 0; let mut code_func_index = 0; - // One-to-one mapping of globals to their value (if the global is a constant usize). - let mut global_usize_values = Vec::new(); - // Whether the first linear memory is 64-bits. - let mut is_memory64 = false; + // One-to-one mapping of globals to their value (if the global is a constant integer). + let mut global_values = Vec::new(); for payload in parser { let payload = payload.read_error("Invalid Wasm section header")?; @@ -169,23 +167,13 @@ impl<'data, R: ReadRef<'data>> WasmFile<'data, R> { } wp::Payload::MemorySection(section) => { file.add_section(SectionId::Memory, section.range(), ""); - for memory in section { - let memory = memory.read_error("Couldn't read a memory item")?; - is_memory64 = memory.memory64; - break; - } } wp::Payload::GlobalSection(section) => { file.add_section(SectionId::Global, section.range(), ""); - let usize_type = if is_memory64 { - wp::ValType::I64 - } else { - wp::ValType::I32 - }; for global in section { let global = global.read_error("Couldn't read a global item")?; let mut address = None; - if !global.ty.mutable && global.ty.content_type == usize_type { + if !global.ty.mutable { // There should be exactly one instruction. let init = global.init_expr.get_operators_reader().read(); address = match init.read_error("Couldn't read a global init expr")? { @@ -194,7 +182,7 @@ impl<'data, R: ReadRef<'data>> WasmFile<'data, R> { _ => None, }; } - global_usize_values.push(address); + global_values.push(address); } } wp::Payload::ExportSection(section) => { @@ -233,10 +221,11 @@ impl<'data, R: ReadRef<'data>> WasmFile<'data, R> { wp::ExternalKind::Tag => continue, }; - // Try to guess the symbol address. + // Try to guess the symbol address. Rust and C export a global containing + // the address in linear memory of the symbol. let mut address = 0; if export.kind == wp::ExternalKind::Global { - if let Some(&Some(x)) = global_usize_values.get(export.index as usize) { + if let Some(&Some(x)) = global_values.get(export.index as usize) { address = x; } }