1use std::{
6 fs::File,
7 io::{BufReader, Read},
8 path::{Path, PathBuf},
9};
10
11use clap::Parser;
12use move_binary_format::CompiledModule;
13use move_bytecode_source_map::utils::serialize_to_json_string;
14use move_cli::base;
15use move_disassembler::disassembler::Disassembler;
16use move_ir_types::location::Spanned;
17use move_package::BuildConfig;
18
19#[derive(Parser)]
21#[group(id = "iota-move-disassemmble")]
22pub struct Disassemble {
23 #[arg(name = "module_path")]
25 module_path: PathBuf,
26
27 #[arg(long = "Xdebug")]
29 debug: bool,
30
31 #[arg(short = 'i', long)]
32 interactive: bool,
33
34 #[clap(long = "bytecode-map")]
36 pub bytecode_map: bool,
37}
38
39impl Disassemble {
40 pub fn execute(
41 self,
42 package_path: Option<&Path>,
43 build_config: BuildConfig,
44 ) -> anyhow::Result<()> {
45 if base::reroot_path(Some(&self.module_path)).is_ok() {
46 let module_name = self
49 .module_path
50 .file_stem()
51 .expect("Bad module path")
52 .to_str()
53 .expect("Cannot convert module name to string")
54 .to_owned();
55 move_cli::base::disassemble::Disassemble {
56 interactive: self.interactive,
57 package_name: None,
58 module_or_script_name: module_name,
59 debug: self.debug,
60 bytecode_map: self.bytecode_map,
61 }
62 .execute(package_path, build_config)?;
63 return Ok(());
64 }
65
66 assert!(
68 Path::new(&self.module_path).exists(),
69 "Bad path to .mv file"
70 );
71
72 let mut bytes = Vec::new();
73 let mut file = BufReader::new(File::open(self.module_path)?);
74 file.read_to_end(&mut bytes)?;
75 let module = CompiledModule::deserialize_with_defaults(&bytes)?;
79
80 if self.debug {
81 println!("{module:#?}");
82 } else {
83 let d = Disassembler::from_module(&module, Spanned::unsafe_no_loc(()).loc)?;
84 let (disassemble_string, bcode_map) = d.disassemble_with_source_map()?;
85 if self.bytecode_map {
86 println!("{}", serialize_to_json_string(&bcode_map)?);
87 }
88 println!("{}", disassemble_string);
89 }
90
91 Ok(())
92 }
93}