From 0a141ce901b710ce877ccc59733fe6303c055289 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 27 Mar 2018 15:23:19 +0300 Subject: [PATCH 1/5] add some extended error handling --- build/main.rs | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/build/main.rs b/build/main.rs index ede2bd0..66d0a0c 100644 --- a/build/main.rs +++ b/build/main.rs @@ -19,9 +19,9 @@ use utils::{CREATE_SYMBOL, CALL_SYMBOL, ununderscore_funcs, externalize_mem, shr #[derive(Debug)] pub enum Error { Io(io::Error), + FailedToCopy(String), NoSuitableFile(String), TooManyFiles(String), - NoEnvVar, } impl From for Error { @@ -30,6 +30,18 @@ impl From for Error { } } +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + use Error::*; + match *self { + Io(ref io) => write!(f, "Generic i/o error: {}", io), + FailedToCopy(ref msg) => write!(f, "{}. Did you tried to run \"cargo build\"?", msg), + NoSuitableFile(ref file) => write!(f, "No suitable file to process here: {}. May be run \"cargo build\"?", file), + TooManyFiles(ref file) => write!(f, "To many files to process in there: {}. May be try \"cargo clean\" and then \"cargo build\"?", file), + } + } +} + pub fn wasm_path(input: &source::SourceInput) -> String { let mut path = PathBuf::from(input.target_dir()); path.push(format!("{}.wasm", input.final_name())); @@ -50,7 +62,10 @@ pub fn process_output(input: &source::SourceInput) -> Result<(), Error> { let mut target_path = PathBuf::from(input.target_dir()); target_path.push(format!("{}.wasm", input.final_name())); - fs::copy(cargo_path, target_path)?; + fs::copy(cargo_path.as_path(), target_path.as_path()) + .map_err(|io| Error::FailedToCopy( + format!("Failed to copy '{}' to '{}': {}", cargo_path.display(), target_path.display(), io) + ))?; Ok(()) } @@ -125,7 +140,10 @@ fn main() { source_input = source_input.with_final(final_name); } - process_output(&source_input).expect("Failed to process cargo target directory"); + process_output(&source_input).unwrap_or_else(|e| { + println!("{}", e); + std::process::exit(1) + }); let path = wasm_path(&source_input); From a1bc379d121e4848535a265d4842547f81164163 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 27 Mar 2018 16:47:48 +0300 Subject: [PATCH 2/5] more handling --- build/main.rs | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/build/main.rs b/build/main.rs index 66d0a0c..8de1a6e 100644 --- a/build/main.rs +++ b/build/main.rs @@ -20,8 +20,9 @@ use utils::{CREATE_SYMBOL, CALL_SYMBOL, ununderscore_funcs, externalize_mem, shr pub enum Error { Io(io::Error), FailedToCopy(String), - NoSuitableFile(String), - TooManyFiles(String), + Decoding(elements::Error, String), + Encoding(elements::Error), + Optimizer, } impl From for Error { @@ -30,14 +31,21 @@ impl From for Error { } } +impl From for Error { + fn from(_err: utils::OptimizerError) -> Self { + Error::Optimizer + } +} + impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { use Error::*; match *self { Io(ref io) => write!(f, "Generic i/o error: {}", io), FailedToCopy(ref msg) => write!(f, "{}. Did you tried to run \"cargo build\"?", msg), - NoSuitableFile(ref file) => write!(f, "No suitable file to process here: {}. May be run \"cargo build\"?", file), - TooManyFiles(ref file) => write!(f, "To many files to process in there: {}. May be try \"cargo clean\" and then \"cargo build\"?", file), + Decoding(ref err, ref file) => write!(f, "Decoding error ({}). Must be a valid wasm file {}. Pointed wrong file?", err, file), + Encoding(ref err) => write!(f, "Encoding error ({}). Almost impossible to happen, no free disk space?", err), + Optimizer => write!(f, "Optimization error due to missing export section. Pointed wrong file?"), } } } @@ -78,6 +86,11 @@ fn has_ctor(module: &elements::Module) -> bool { } } +fn die(e: Error) -> ! { + eprintln!("{}", e); + std::process::exit(1) +} + fn main() { utils::init_log(); @@ -140,14 +153,11 @@ fn main() { source_input = source_input.with_final(final_name); } - process_output(&source_input).unwrap_or_else(|e| { - println!("{}", e); - std::process::exit(1) - }); + process_output(&source_input).unwrap_or_else(|e| die(e)); let path = wasm_path(&source_input); - let mut module = parity_wasm::deserialize_file(&path).unwrap(); + let mut module = parity_wasm::deserialize_file(&path).unwrap_or_else(|e| die(Error::Decoding(e, path.to_string()))); if let source::SourceTarget::Emscripten = source_input.target() { module = ununderscore_funcs(module); @@ -184,28 +194,33 @@ fn main() { utils::optimize( &mut module, vec![CALL_SYMBOL] - ).expect("Optimizer to finish without errors"); + ).unwrap_or_else(|e| die(Error::from(e))) } 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"); + .unwrap_or_else(|e| die(Error::Encoding(e))); } - let raw_module = parity_wasm::serialize(module).expect("Failed to serialize module"); + let raw_module = parity_wasm::serialize(module) + .unwrap_or_else(|e| die(Error::Encoding(e))); // If module has an exported function with name=CREATE_SYMBOL // build will pack the module (raw_module) into this funciton and export as CALL_SYMBOL. // Otherwise it will just save an optimised raw_module if has_ctor(&ctor_module) { if !matches.is_present("skip_optimization") { - utils::optimize(&mut ctor_module, vec![CREATE_SYMBOL]).expect("Optimizer to finish without errors"); + utils::optimize(&mut ctor_module, vec![CREATE_SYMBOL]) + .unwrap_or_else(|e| die(Error::from(e))) } let ctor_module = utils::pack_instance(raw_module, ctor_module).expect("Packing failed"); - parity_wasm::serialize_to_file(&path, ctor_module).expect("Failed to serialize to file"); + parity_wasm::serialize_to_file(&path, ctor_module) + .unwrap_or_else(|e| die(Error::Encoding(e))) } else { - let mut file = fs::File::create(&path).expect("Failed to create file"); - file.write_all(&raw_module).expect("Failed to write module to file"); + let mut file = fs::File::create(&path) + .unwrap_or_else(|io| die(Error::from(io))); + file.write_all(&raw_module) + .unwrap_or_else(|io| die(Error::from(io))); } } From abc98189251a2555d75868e6f86dfc4a7d91ae87 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 27 Mar 2018 17:11:00 +0300 Subject: [PATCH 3/5] packing errors also --- build/main.rs | 11 ++++++++++- src/lib.rs | 2 +- src/pack.rs | 17 ++++++++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/build/main.rs b/build/main.rs index 8de1a6e..8bd8526 100644 --- a/build/main.rs +++ b/build/main.rs @@ -22,6 +22,7 @@ pub enum Error { FailedToCopy(String), Decoding(elements::Error, String), Encoding(elements::Error), + Packing(utils::PackingError), Optimizer, } @@ -37,6 +38,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: utils::PackingError) -> Self { + Error::Packing(err) + } +} + impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { use Error::*; @@ -46,6 +53,7 @@ impl std::fmt::Display for Error { Decoding(ref err, ref file) => write!(f, "Decoding error ({}). Must be a valid wasm file {}. Pointed wrong file?", err, file), Encoding(ref err) => write!(f, "Encoding error ({}). Almost impossible to happen, no free disk space?", err), Optimizer => write!(f, "Optimization error due to missing export section. Pointed wrong file?"), + Packing(ref e) => write!(f, "Packing failed due to module structure error: {}. Sure used correct libraries for building contracts?", e), } } } @@ -213,7 +221,8 @@ fn main() { utils::optimize(&mut ctor_module, vec![CREATE_SYMBOL]) .unwrap_or_else(|e| die(Error::from(e))) } - let ctor_module = utils::pack_instance(raw_module, ctor_module).expect("Packing failed"); + let ctor_module = utils::pack_instance(raw_module, ctor_module) + .unwrap_or_else(|e| die(Error::from(e))); parity_wasm::serialize_to_file(&path, ctor_module) .unwrap_or_else(|e| die(Error::Encoding(e))) } else { diff --git a/src/lib.rs b/src/lib.rs index 5e3aec5..8753ec7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,5 +24,5 @@ pub use optimizer::{optimize, Error as OptimizerError}; pub use gas::inject_gas_counter; pub use logger::init_log; pub use ext::{externalize, externalize_mem, underscore_funcs, ununderscore_funcs, shrink_unknown_stack}; -pub use pack::pack_instance; +pub use pack::{pack_instance, Error as PackingError}; pub use runtime_type::inject_runtime_type; diff --git a/src/pack.rs b/src/pack.rs index 9fa66f8..1906dbd 100644 --- a/src/pack.rs +++ b/src/pack.rs @@ -1,3 +1,4 @@ +use std::fmt; use parity_wasm::elements::{ self, Section, Opcode, DataSegment, InitExpr, Internal, External, ImportCountType, @@ -19,10 +20,24 @@ pub enum Error { InvalidCreateSignature, NoCreateSymbol, InvalidCreateMember, - NoRetImported, NoImportSection, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + Error::MalformedModule => write!(f, "Module internal references are inconsistent"), + Error::NoTypeSection => write!(f, "No type section in the module"), + Error::NoExportSection => write!(f, "No export section in the module"), + Error::NoCodeSection => write!(f, "No code section inthe module"), + Error::InvalidCreateSignature => write!(f, "Exported symbol `deploy` has invalid signature, should be () -> ()"), + Error::InvalidCreateMember => write!(f, "Exported symbol `deploy` should be a function"), + Error::NoCreateSymbol => write!(f, "No exported `deploy` symbol"), + Error::NoImportSection => write!(f, "No import section in the module"), + } + } +} + /// If module has an exported "_create" function we want to pack it into "constructor". /// `raw_module` is the actual contract code /// `ctor_module` is the constructor which should return `raw_module` From 12f67a88364292f858222968fcb9047408f1e015 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 27 Mar 2018 17:15:31 +0300 Subject: [PATCH 4/5] fix some spelling --- build/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/main.rs b/build/main.rs index 8bd8526..823e2ae 100644 --- a/build/main.rs +++ b/build/main.rs @@ -49,7 +49,7 @@ impl std::fmt::Display for Error { use Error::*; match *self { Io(ref io) => write!(f, "Generic i/o error: {}", io), - FailedToCopy(ref msg) => write!(f, "{}. Did you tried to run \"cargo build\"?", msg), + FailedToCopy(ref msg) => write!(f, "{}. Have you tried to run \"cargo build\"?", msg), Decoding(ref err, ref file) => write!(f, "Decoding error ({}). Must be a valid wasm file {}. Pointed wrong file?", err, file), Encoding(ref err) => write!(f, "Encoding error ({}). Almost impossible to happen, no free disk space?", err), Optimizer => write!(f, "Optimization error due to missing export section. Pointed wrong file?"), From 2248aa58cf9448634689a456b3b7dfd0322cc35d Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 27 Mar 2018 17:33:10 +0300 Subject: [PATCH 5/5] do_main() thing --- build/main.rs | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/build/main.rs b/build/main.rs index 823e2ae..5bf79d8 100644 --- a/build/main.rs +++ b/build/main.rs @@ -94,12 +94,7 @@ fn has_ctor(module: &elements::Module) -> bool { } } -fn die(e: Error) -> ! { - eprintln!("{}", e); - std::process::exit(1) -} - -fn main() { +fn do_main() -> Result<(), Error> { utils::init_log(); let matches = App::new("wasm-build") @@ -153,7 +148,7 @@ fn main() { } 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); + eprintln!("--target can be: '{}' or '{}'", source::EMSCRIPTEN_TRIPLET, source::UNKNOWN_TRIPLET); ::std::process::exit(1); } @@ -161,11 +156,12 @@ fn main() { source_input = source_input.with_final(final_name); } - process_output(&source_input).unwrap_or_else(|e| die(e)); + process_output(&source_input)?; let path = wasm_path(&source_input); - let mut module = parity_wasm::deserialize_file(&path).unwrap_or_else(|e| die(Error::Decoding(e, path.to_string()))); + let mut module = parity_wasm::deserialize_file(&path) + .map_err(|e| Error::Decoding(e, path.to_string()))?; if let source::SourceTarget::Emscripten = source_input.target() { module = ununderscore_funcs(module); @@ -202,34 +198,36 @@ fn main() { utils::optimize( &mut module, vec![CALL_SYMBOL] - ).unwrap_or_else(|e| die(Error::from(e))) + )?; } if let Some(save_raw_path) = matches.value_of("save_raw") { - parity_wasm::serialize_to_file(save_raw_path, module.clone()) - .unwrap_or_else(|e| die(Error::Encoding(e))); + parity_wasm::serialize_to_file(save_raw_path, module.clone()).map_err(Error::Encoding)?; } - let raw_module = parity_wasm::serialize(module) - .unwrap_or_else(|e| die(Error::Encoding(e))); + let raw_module = parity_wasm::serialize(module).map_err(Error::Encoding)?; // If module has an exported function with name=CREATE_SYMBOL // build will pack the module (raw_module) into this funciton and export as CALL_SYMBOL. // Otherwise it will just save an optimised raw_module if has_ctor(&ctor_module) { if !matches.is_present("skip_optimization") { - utils::optimize(&mut ctor_module, vec![CREATE_SYMBOL]) - .unwrap_or_else(|e| die(Error::from(e))) + utils::optimize(&mut ctor_module, vec![CREATE_SYMBOL])?; } - let ctor_module = utils::pack_instance(raw_module, ctor_module) - .unwrap_or_else(|e| die(Error::from(e))); - parity_wasm::serialize_to_file(&path, ctor_module) - .unwrap_or_else(|e| die(Error::Encoding(e))) + let ctor_module = utils::pack_instance(raw_module, ctor_module)?; + parity_wasm::serialize_to_file(&path, ctor_module).map_err(Error::Encoding)?; } else { - let mut file = fs::File::create(&path) - .unwrap_or_else(|io| die(Error::from(io))); - file.write_all(&raw_module) - .unwrap_or_else(|io| die(Error::from(io))); + let mut file = fs::File::create(&path)?; + file.write_all(&raw_module)?; + } + + Ok(()) +} + +fn main() { + if let Err(e) = do_main() { + eprintln!("{}", e); + std::process::exit(1) } }