diff --git a/crates/common/src/extension.rs b/crates/common/src/extension.rs index 64e23853..d37fe4c0 100644 --- a/crates/common/src/extension.rs +++ b/crates/common/src/extension.rs @@ -41,3 +41,6 @@ pub static EXTENSION_POLKAVM_ASSEMBLY: &str = "pvmasm"; /// The PolkaVM bytecode file extension. pub static EXTENSION_POLKAVM_BINARY: &str = "pvm"; + +/// The ELF shared object file extension. +pub static EXTENSION_SHARED_OBJECT: &str = "so"; diff --git a/crates/linker/src/lib.rs b/crates/linker/src/lib.rs index b5c81cb5..e49bb378 100644 --- a/crates/linker/src/lib.rs +++ b/crates/linker/src/lib.rs @@ -29,7 +29,7 @@ fn invoke_lld(cmd_args: &[&str]) -> bool { unsafe { LLDELFLink(args.as_ptr(), args.len()) == 0 } } -fn polkavm_linker>(code: T) -> anyhow::Result> { +pub fn polkavm_linker>(code: T) -> anyhow::Result> { let mut config = polkavm_linker::Config::default(); config.set_strip(true); config.set_optimize(true); @@ -79,10 +79,5 @@ pub fn link>(input: T) -> anyhow::Result> { return Err(anyhow::anyhow!("ld.lld failed")); } - if env::var("PVM_LINKER_DUMP_SO").is_ok() { - fs::copy(&output_path, "/tmp/out.so")?; - }; - - let blob = fs::read(&output_path)?; - polkavm_linker(blob) + Ok(fs::read(&output_path)?) } diff --git a/crates/llvm-context/src/debug_config/ir_type.rs b/crates/llvm-context/src/debug_config/ir_type.rs index 2ea88f96..43a44487 100644 --- a/crates/llvm-context/src/debug_config/ir_type.rs +++ b/crates/llvm-context/src/debug_config/ir_type.rs @@ -15,6 +15,8 @@ pub enum IRType { LLVM, /// Whether to dump the assembly code. Assembly, + /// Whether to dump the ELF shared object + SO, /// Whether to jump JSON #[cfg(debug_assertions)] JSON, @@ -31,6 +33,7 @@ impl IRType { Self::Assembly => revive_common::EXTENSION_POLKAVM_ASSEMBLY, #[cfg(debug_assertions)] Self::JSON => revive_common::EXTENSION_JSON, + Self::SO => revive_common::EXTENSION_SHARED_OBJECT, } } } diff --git a/crates/llvm-context/src/debug_config/mod.rs b/crates/llvm-context/src/debug_config/mod.rs index 49c31ac0..f44cb194 100644 --- a/crates/llvm-context/src/debug_config/mod.rs +++ b/crates/llvm-context/src/debug_config/mod.rs @@ -94,6 +94,16 @@ impl DebugConfig { Ok(()) } + /// Dumps the code object. + pub fn dump_object(&self, contract_path: &str, code: &[u8]) -> anyhow::Result<()> { + let mut file_path = self.output_directory.to_owned(); + let full_file_name = Self::full_file_name(contract_path, None, IRType::SO); + file_path.push(full_file_name); + std::fs::write(file_path, code)?; + + Ok(()) + } + /// Dumps the stage output as a json file suitable for use with --recursive-process #[cfg(debug_assertions)] pub fn dump_stage_output( diff --git a/crates/llvm-context/src/polkavm/context/mod.rs b/crates/llvm-context/src/polkavm/context/mod.rs index bf39ded9..9feb9254 100644 --- a/crates/llvm-context/src/polkavm/context/mod.rs +++ b/crates/llvm-context/src/polkavm/context/mod.rs @@ -296,11 +296,17 @@ where ) })?; - let bytecode = revive_linker::link(buffer.as_slice())?; + let shared_object = revive_linker::link(buffer.as_slice())?; + + if let Some(ref debug_config) = self.debug_config { + debug_config.dump_object(contract_path, &shared_object)?; + } + + let polkavm_bytecode = revive_linker::polkavm_linker(shared_object)?; let build = match crate::polkavm::build_assembly_text( contract_path, - &bytecode, + &polkavm_bytecode, metadata_hash, self.debug_config(), ) {