mirror of
https://github.com/pezkuwichain/wasm-instrument.git
synced 2026-06-09 20:11:06 +00:00
Merge pull request #45 from paritytech/unknown-target
Allow wasm-build to handle wasm32-unknown-unknown
This commit is contained in:
+2
-1
@@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
authors = ["NikVolf <nikvolf@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
parity-wasm = "0.15"
|
||||
parity-wasm = "0.18"
|
||||
log = "0.3"
|
||||
env_logger = "0.4"
|
||||
lazy_static = "0.2"
|
||||
@@ -14,6 +14,7 @@ byteorder = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
tempdir = "0.3"
|
||||
pwasm-emscripten = { git = "https://github.com/paritytech/parity-wasm", path = "pwasm-emscripten" }
|
||||
|
||||
[lib]
|
||||
|
||||
|
||||
Generated
+4
-4
@@ -123,7 +123,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parity-wasm"
|
||||
version = "0.15.4"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -275,7 +275,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-wasm 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasm-utils 0.1.0",
|
||||
]
|
||||
@@ -290,7 +290,7 @@ dependencies = [
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-wasm 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -321,7 +321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
|
||||
"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
|
||||
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
|
||||
"checksum parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)" = "235801e9531998c4bb307f4ea6833c9f40a4cf132895219ac8c2cd25a9b310f7"
|
||||
"checksum parity-wasm 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f02e35fda913b8873799b817dcab145d1f935a900722ab7274027949d9947a56"
|
||||
"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e"
|
||||
"checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595"
|
||||
"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ authors = ["NikVolf <nikvolf@gmail.com>"]
|
||||
glob = "0.2"
|
||||
wasm-utils = { path = "../" }
|
||||
clap = "2.24"
|
||||
parity-wasm = "0.15"
|
||||
parity-wasm = "0.18"
|
||||
|
||||
[dev-dependencies]
|
||||
tempdir = "0.3"
|
||||
|
||||
+60
-15
@@ -5,6 +5,8 @@ extern crate wasm_utils;
|
||||
extern crate clap;
|
||||
extern crate parity_wasm;
|
||||
|
||||
mod source;
|
||||
|
||||
use std::{fs, io};
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
@@ -12,7 +14,7 @@ use std::path::PathBuf;
|
||||
use clap::{App, Arg};
|
||||
use parity_wasm::elements;
|
||||
|
||||
use wasm_utils::{CREATE_SYMBOL, CALL_SYMBOL};
|
||||
use wasm_utils::{CREATE_SYMBOL, CALL_SYMBOL, underscore_funcs};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
@@ -28,21 +30,26 @@ impl From<io::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wasm_path(target_dir: &str, bin_name: &str) -> String {
|
||||
let mut path = PathBuf::from(target_dir);
|
||||
path.push(format!("{}.wasm", bin_name));
|
||||
pub fn wasm_path(input: &source::SourceInput) -> String {
|
||||
let mut path = PathBuf::from(input.target_dir());
|
||||
path.push(format!("{}.wasm", input.final_name()));
|
||||
path.to_string_lossy().to_string()
|
||||
}
|
||||
|
||||
pub fn process_output(target_dir: &str, bin_name: &str) -> Result<(), Error> {
|
||||
let mut cargo_path = PathBuf::from(target_dir);
|
||||
let wasm_name = bin_name.to_string().replace("-", "_");
|
||||
cargo_path.push("wasm32-unknown-emscripten");
|
||||
pub fn process_output(input: &source::SourceInput) -> Result<(), Error> {
|
||||
let mut cargo_path = PathBuf::from(input.target_dir());
|
||||
let wasm_name = input.bin_name().to_string().replace("-", "_");
|
||||
cargo_path.push(
|
||||
match input.target() {
|
||||
source::SourceTarget::Emscripten => source::EMSCRIPTEN_TRIPLET,
|
||||
source::SourceTarget::Unknown => source::UNKNOWN_TRIPLET,
|
||||
}
|
||||
);
|
||||
cargo_path.push("release");
|
||||
cargo_path.push(format!("{}.wasm", wasm_name));
|
||||
|
||||
let mut target_path = PathBuf::from(target_dir);
|
||||
target_path.push(format!("{}.wasm", bin_name));
|
||||
let mut target_path = PathBuf::from(input.target_dir());
|
||||
target_path.push(format!("{}.wasm", input.final_name()));
|
||||
fs::copy(cargo_path, target_path)?;
|
||||
|
||||
Ok(())
|
||||
@@ -79,17 +86,48 @@ fn main() {
|
||||
.help("Injects RUNTIME_VERSION global export")
|
||||
.takes_value(true)
|
||||
.long("runtime-version"))
|
||||
.arg(Arg::with_name("source_target")
|
||||
.help("Cargo target type kind ('wasm32-unknown-unknown' or 'wasm32-unknown-emscripten'")
|
||||
.takes_value(true)
|
||||
.long("target"))
|
||||
.arg(Arg::with_name("final_name")
|
||||
.help("Final wasm binary name")
|
||||
.takes_value(true)
|
||||
.long("final"))
|
||||
.arg(Arg::with_name("save_raw")
|
||||
.help("Save intermediate raw bytecode to path")
|
||||
.takes_value(true)
|
||||
.long("save-raw"))
|
||||
.get_matches();
|
||||
|
||||
let target_dir = matches.value_of("target").expect("is required; qed");
|
||||
let wasm_binary = matches.value_of("wasm").expect("is required; qed");
|
||||
let mut source_input = source::SourceInput::new(target_dir, wasm_binary);
|
||||
|
||||
process_output(target_dir, wasm_binary).expect("Failed to process cargo target directory");
|
||||
let source_target_val = matches.value_of("source_target").unwrap_or_else(|| source::EMSCRIPTEN_TRIPLET);
|
||||
if source_target_val == source::UNKNOWN_TRIPLET {
|
||||
source_input = source_input.unknown()
|
||||
} else if source_target_val == source::EMSCRIPTEN_TRIPLET {
|
||||
source_input = source_input.emscripten()
|
||||
} else {
|
||||
println!("--target can be: '{}' or '{}'", source::EMSCRIPTEN_TRIPLET, source::UNKNOWN_TRIPLET);
|
||||
::std::process::exit(1);
|
||||
}
|
||||
|
||||
let path = wasm_path(target_dir, wasm_binary);
|
||||
if let Some(final_name) = matches.value_of("final_name") {
|
||||
source_input = source_input.with_final(final_name);
|
||||
}
|
||||
|
||||
process_output(&source_input).expect("Failed to process cargo target directory");
|
||||
|
||||
let path = wasm_path(&source_input);
|
||||
|
||||
let mut module = parity_wasm::deserialize_file(&path).unwrap();
|
||||
|
||||
if let source::SourceTarget::Unknown = source_input.target() {
|
||||
module = underscore_funcs(module)
|
||||
}
|
||||
|
||||
if let Some(runtime_type) = matches.value_of("runtime_type") {
|
||||
let runtime_type: &[u8] = runtime_type.as_bytes();
|
||||
if runtime_type.len() != 4 {
|
||||
@@ -106,6 +144,11 @@ fn main() {
|
||||
wasm_utils::optimize(&mut module, vec![CALL_SYMBOL]).expect("Optimizer to finish without errors");
|
||||
}
|
||||
|
||||
if let Some(save_raw_path) = matches.value_of("save_raw") {
|
||||
parity_wasm::serialize_to_file(save_raw_path, module.clone())
|
||||
.expect("Failed to write intermediate module");
|
||||
}
|
||||
|
||||
let raw_module = parity_wasm::serialize(module).expect("Failed to serialize module");
|
||||
|
||||
// If module has an exported function with name=CREATE_SYMBOL
|
||||
@@ -121,7 +164,6 @@ fn main() {
|
||||
let mut file = fs::File::create(&path).expect("Failed to create file");
|
||||
file.write_all(&raw_module).expect("Failed to write module to file");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -132,6 +174,7 @@ mod tests {
|
||||
use std::fs;
|
||||
|
||||
use super::process_output;
|
||||
use super::source::SourceInput;
|
||||
|
||||
#[test]
|
||||
fn processes_cargo_output() {
|
||||
@@ -148,11 +191,13 @@ mod tests {
|
||||
f.write(b"\0asm").expect("write file failed");
|
||||
}
|
||||
|
||||
process_output(&tmp_dir.path().to_string_lossy(), "example-wasm").expect("process output failed");
|
||||
let path = tmp_dir.path().to_string_lossy();
|
||||
let input = SourceInput::new(&path, "example-wasm");
|
||||
|
||||
process_output(&input).expect("process output failed");
|
||||
|
||||
assert!(
|
||||
fs::metadata(tmp_dir.path().join("example-wasm.wasm")).expect("metadata failed").is_file()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
//! Configuration of source binaries
|
||||
|
||||
pub const UNKNOWN_TRIPLET: &str = "wasm32-unknown-unknown";
|
||||
pub const EMSCRIPTEN_TRIPLET: &str = "wasm32-unknown-emscripten";
|
||||
|
||||
/// Target configiration of previous build step
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum SourceTarget {
|
||||
Emscripten,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// Configuration of previous build step (cargo compilation)
|
||||
#[derive(Debug)]
|
||||
pub struct SourceInput<'a> {
|
||||
target_dir: &'a str,
|
||||
bin_name: &'a str,
|
||||
final_name: &'a str,
|
||||
target: SourceTarget,
|
||||
}
|
||||
|
||||
impl<'a> SourceInput<'a> {
|
||||
pub fn new<'b>(target_dir: &'b str, bin_name: &'b str) -> SourceInput<'b> {
|
||||
SourceInput {
|
||||
target_dir: target_dir,
|
||||
bin_name: bin_name,
|
||||
final_name: bin_name,
|
||||
target: SourceTarget::Emscripten,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unknown(mut self) -> Self {
|
||||
self.target = SourceTarget::Unknown;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn emscripten(mut self) -> Self {
|
||||
self.target = SourceTarget::Emscripten;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_final(mut self, final_name: &'a str) -> Self {
|
||||
self.final_name = final_name;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn target_dir(&self) -> &str {
|
||||
self.target_dir
|
||||
}
|
||||
|
||||
pub fn bin_name(&self) -> &str {
|
||||
self.bin_name
|
||||
}
|
||||
|
||||
pub fn final_name(&self) -> &str {
|
||||
self.final_name
|
||||
}
|
||||
|
||||
pub fn target(&self) -> SourceTarget {
|
||||
self.target
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,5 +4,5 @@ version = "0.1.0"
|
||||
authors = ["NikVolf <nikvolf@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
parity-wasm = "0.15"
|
||||
parity-wasm = "0.18"
|
||||
wasm-utils = { path = "../" }
|
||||
+1
-1
@@ -4,5 +4,5 @@ version = "0.1.0"
|
||||
authors = ["NikVolf <nikvolf@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
parity-wasm = "0.15"
|
||||
parity-wasm = "0.18"
|
||||
wasm-utils = { path = "../" }
|
||||
+1
-1
@@ -4,6 +4,6 @@ version = "0.1.0"
|
||||
authors = ["NikVolf <nikvolf@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
parity-wasm = "0.15"
|
||||
parity-wasm = "0.18"
|
||||
wasm-utils = { path = "../" }
|
||||
clap = "2.24"
|
||||
|
||||
+45
@@ -1,4 +1,5 @@
|
||||
use parity_wasm::{elements, builder};
|
||||
use optimizer::{import_section, export_section};
|
||||
|
||||
type Insertion = (usize, u32, u32, String);
|
||||
|
||||
@@ -18,6 +19,50 @@ pub fn update_call_index(opcodes: &mut elements::Opcodes, original_imports: usiz
|
||||
}
|
||||
}
|
||||
|
||||
pub fn memory_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::MemorySection> {
|
||||
for section in module.sections_mut() {
|
||||
match section {
|
||||
&mut elements::Section::Memory(ref mut sect) => {
|
||||
return Some(sect);
|
||||
},
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn externalize_mem(mut module: elements::Module) -> elements::Module {
|
||||
let entry = memory_section(&mut module)
|
||||
.expect("Memory section to exist")
|
||||
.entries_mut()
|
||||
.pop()
|
||||
.expect("Own memory entry to exist in memory section");
|
||||
|
||||
import_section(&mut module).expect("Import section to exist").entries_mut().push(
|
||||
elements::ImportEntry::new(
|
||||
"env".to_owned(),
|
||||
"memory".to_owned(),
|
||||
elements::External::Memory(entry),
|
||||
)
|
||||
);
|
||||
|
||||
module
|
||||
}
|
||||
|
||||
pub fn underscore_funcs(mut module: elements::Module) -> elements::Module {
|
||||
for entry in import_section(&mut module).expect("Import section to exist").entries_mut() {
|
||||
if let elements::External::Function(_) = *entry.external() {
|
||||
entry.field_mut().insert(0, '_');
|
||||
}
|
||||
}
|
||||
for entry in export_section(&mut module).expect("Import section to exist").entries_mut() {
|
||||
if let elements::Internal::Function(_) = *entry.internal() {
|
||||
entry.field_mut().insert(0, '_');
|
||||
}
|
||||
}
|
||||
module
|
||||
}
|
||||
|
||||
pub fn externalize(
|
||||
module: elements::Module,
|
||||
replaced_funcs: Vec<&str>,
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ mod runtime_type;
|
||||
pub use optimizer::{optimize, Error as OptimizerError};
|
||||
pub use gas::inject_gas_counter;
|
||||
pub use logger::init_log;
|
||||
pub use ext::externalize;
|
||||
pub use ext::{externalize, externalize_mem, underscore_funcs};
|
||||
pub use pack::pack_instance;
|
||||
pub use nondeterminism_check::is_deterministic;
|
||||
pub use runtime_type::inject_runtime_type;
|
||||
|
||||
+6
-7
@@ -129,8 +129,8 @@ pub fn pack_instance(raw_module: Vec<u8>, mut ctor_module: elements::Module) ->
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
extern crate pwasm_emscripten;
|
||||
extern crate parity_wasm;
|
||||
extern crate byteorder;
|
||||
|
||||
use parity_wasm::builder;
|
||||
use parity_wasm::interpreter;
|
||||
@@ -139,6 +139,7 @@ mod test {
|
||||
use super::*;
|
||||
use super::super::optimize;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use self::pwasm_emscripten::program_with_emscripten_env;
|
||||
|
||||
#[test]
|
||||
fn call_returns_code() {
|
||||
@@ -194,14 +195,13 @@ mod test {
|
||||
let raw_module = parity_wasm::serialize(module).unwrap();
|
||||
let ctor_module = pack_instance(raw_module.clone(), ctor_module).expect("Packing failed");
|
||||
|
||||
let program = parity_wasm::DefaultProgramInstance::new().expect("Program instance failed to load");
|
||||
let program = program_with_emscripten_env(Default::default()).expect("Wasm program to be created");
|
||||
let env_instance = program.module("env").expect("Wasm program to contain env module");
|
||||
let env_memory = env_instance.memory(interpreter::ItemIndex::Internal(0)).expect("Linear memory to exist in wasm runtime");
|
||||
|
||||
let execution_params = interpreter::ExecutionParams::default();
|
||||
let constructor_module = program.add_module("contract", ctor_module, None).expect("Failed to initialize module");
|
||||
|
||||
let _ = constructor_module.execute_export(CALL_SYMBOL, execution_params.add_argument(RuntimeValue::I32(1024)));
|
||||
let _ = constructor_module.execute_export(CALL_SYMBOL, vec![RuntimeValue::I32(1024)].into());
|
||||
|
||||
let pointer = LittleEndian::read_u32(&env_memory.get(1024 + 8, 4).unwrap());
|
||||
let len = LittleEndian::read_u32(&env_memory.get(1024 + 12, 4).unwrap());
|
||||
@@ -212,10 +212,9 @@ mod test {
|
||||
|
||||
let contract_module: elements::Module = parity_wasm::deserialize_buffer(contract_code).expect("Constructed contract module is not valid");
|
||||
|
||||
let program = parity_wasm::DefaultProgramInstance::new().expect("Program2 instance failed to load");
|
||||
let program = program_with_emscripten_env(Default::default()).expect("Wasm program to be created");
|
||||
let contract_module_instance = program.add_module("contract", contract_module, None).expect("Failed to initialize constructed contract module");
|
||||
let execution_params = interpreter::ExecutionParams::default();
|
||||
|
||||
contract_module_instance.execute_export(CALL_SYMBOL, execution_params).expect("Constructed contract failed to execute");
|
||||
contract_module_instance.execute_export(CALL_SYMBOL, Default::default()).expect("Constructed contract failed to execute");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user