diff --git a/Cargo.lock b/Cargo.lock index 83b92bf..425e3f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,12 +106,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - [[package]] name = "hermit-abi" version = "0.1.19" @@ -129,8 +123,6 @@ dependencies = [ "byteorder", "hlbc-derive", "petgraph", - "strum", - "strum_macros", ] [[package]] @@ -146,7 +138,7 @@ dependencies = [ [[package]] name = "hlbc-derive" -version = "0.1.1" +version = "0.2.0" dependencies = [ "quote", "syn", @@ -208,31 +200,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rustversion" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" - -[[package]] -name = "strum" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96acfc1b70604b8b2f1ffa4c57e59176c7dbb05d556c71ecd2f5498a1dee7f8" - -[[package]] -name = "strum_macros" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn", -] - [[package]] name = "syn" version = "1.0.95" diff --git a/Cargo.toml b/Cargo.toml index 315b8d3..0504f58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,11 +16,9 @@ members = ["hlbc-cli", "hlbc-derive"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -hlbc-derive = { version = "0.1", path = "hlbc-derive" } +hlbc-derive = { version = "0.2", path = "hlbc-derive" } byteorder = "1" anyhow = "1" -strum = "0.24" -strum_macros = "0.24" petgraph = { version = "0.6", default-features = false, features = ["graphmap"], optional = true } [features] diff --git a/hlbc-cli/src/command.rs b/hlbc-cli/src/command.rs index 51adf62..71e3b33 100644 --- a/hlbc-cli/src/command.rs +++ b/hlbc-cli/src/command.rs @@ -135,12 +135,12 @@ fn index_range(max: usize) -> impl Parser> let a = a.unwrap_or(0).max(0); let b = b.unwrap_or(max); if range == ".." { - Box::new((a..b.min(max)).into_iter()) as IndexIter + Box::new(a..b.min(max)) as IndexIter } else { - Box::new((a..=b.min(max - 1)).into_iter()) as IndexIter + Box::new(a..=b.min(max - 1)) as IndexIter } }), - num().map(|i| Box::new((i..(i + 1)).into_iter()) as IndexIter), + num().map(|i| Box::new(i..(i + 1)) as IndexIter), )) .labelled("index range") } diff --git a/hlbc-cli/src/decompiler.rs b/hlbc-cli/src/decompiler.rs index 7010791..f189480 100644 --- a/hlbc-cli/src/decompiler.rs +++ b/hlbc-cli/src/decompiler.rs @@ -11,10 +11,10 @@ pub fn decompile_class(code: &Bytecode, obj: &TypeObj) -> String { writeln!( &mut buf, "class {} {}{{", - obj.name.display(&code), + obj.name.display(code), if let Some(e) = obj.super_ { is_static = e.0 == 12; - format!("extends {} ", e.display(&code)) + format!("extends {} ", e.display(code)) } else { "".to_string() } @@ -34,8 +34,8 @@ pub fn decompile_class(code: &Bytecode, obj: &TypeObj) -> String { &mut buf, "{indent}{}var {}: {}", if is_static { "static " } else { "" }, - f.name.display(&code), - f.t.display(&code) + f.name.display(code), + f.t.display(code) ) .unwrap(); } @@ -152,7 +152,7 @@ pub fn decompile_function_body(code: &Bytecode, indent: &str, f: &Function) -> S write!( &mut buf, "{dst} = {}", - decompile_closure(code, &indent, fun.resolve_as_fn(code).unwrap()) + decompile_closure(code, indent, fun.resolve_as_fn(code).unwrap()) ) .unwrap(); } diff --git a/hlbc-cli/src/main.rs b/hlbc-cli/src/main.rs index a712c38..a05f38c 100644 --- a/hlbc-cli/src/main.rs +++ b/hlbc-cli/src/main.rs @@ -144,8 +144,7 @@ callgraph | Create a dot call graph froma function and a max Command::Entrypoint => { println!( "{}", - code.functions[code.findexes.get(&code.entrypoint).unwrap().0] - .display_header(&code) + code.functions[code.findexes.get(&code.entrypoint).unwrap().0].display_header(code) ); } Command::Int(range) => { @@ -194,31 +193,31 @@ callgraph | Create a dot call graph froma function and a max for i in range { print_i!(i); let t = &code.types[i]; - println!("{}", t.display(&code)); + println!("{}", t.display(code)); match t { Type::Obj(obj) => { if let Some(sup) = obj.super_ { - println!("extends {}", sup.display(&code)); + println!("extends {}", sup.display(code)); } println!("global: {}", obj.global.0); println!("fields:"); for f in &obj.own_fields { - println!(" {}: {}", f.name.display(&code), f.t.display(&code)); + println!(" {}: {}", f.name.display(code), f.t.display(code)); } println!("protos:"); for p in &obj.protos { println!( " {}: {}", - p.name.display(&code), - p.findex.display_header(&code) + p.name.display(code), + p.findex.display_header(code) ); } println!("bindings:"); for (fi, fun) in &obj.bindings { println!( " {}: {}", - fi.display_obj(t, &code), - fun.display_header(&code) + fi.display_obj(t, code), + fun.display_header(code) ); } } @@ -233,11 +232,11 @@ callgraph | Create a dot call graph froma function and a max if c.name.0 == 0 { "_".to_string() } else { - c.name.display(&code) + c.name.display(code) } ); for (i, p) in c.params.iter().enumerate() { - println!(" {i}: {}", p.display(&code)); + println!(" {i}: {}", p.display(code)); } } } @@ -248,13 +247,13 @@ callgraph | Create a dot call graph froma function and a max Command::Global(range) => { for i in range { print_i!(i); - println!("{}", code.globals[i].display(&code)); + println!("{}", code.globals[i].display(code)); } } Command::Native(range) => { for i in range { print_i!(i); - println!("{}", code.natives[i].display_header(&code)); + println!("{}", code.natives[i].display_header(code)); } } Command::Constant(range) => { @@ -268,9 +267,9 @@ callgraph | Create a dot call graph froma function and a max print_i!(findex); if let Some(&(i, fun)) = code.findexes.get(&RefFun(findex)) { if fun { - println!("{}", code.functions[i].display_header(&code)); + println!("{}", code.functions[i].display_header(code)); } else { - println!("{}", code.natives[i].display_header(&code)); + println!("{}", code.natives[i].display_header(code)); } } else { println!("unknown"); @@ -282,9 +281,9 @@ callgraph | Create a dot call graph froma function and a max print_i!(findex); if let Some(&(i, fun)) = code.findexes.get(&RefFun(findex)) { if fun { - println!("{}", code.functions[i].display(&code)); + println!("{}", code.functions[i].display(code)); } else { - println!("{}", code.natives[i].display_header(&code)); + println!("{}", code.natives[i].display_header(code)); } } else { println!("unknown"); @@ -294,7 +293,7 @@ callgraph | Create a dot call graph froma function and a max Command::SearchFunction(str) => { // TODO search for function if let Some(&i) = code.fnames.get(&str) { - println!("{}", code.functions[i].display_header(&code)); + println!("{}", code.functions[i].display_header(code)); } else { println!("unknown"); } @@ -305,7 +304,7 @@ callgraph | Create a dot call graph froma function and a max FileOrIndex::File(str) => { if let Some(idx) = debug_files - .into_iter() + .iter() .enumerate() .find_map( |(i, d): (usize, &String)| { @@ -321,7 +320,7 @@ callgraph | Create a dot call graph froma function and a max for (i, f) in code.functions.iter().enumerate() { if f.debug_info.as_ref().unwrap()[f.ops.len() - 1].0 == idx { print_i!(i); - println!("{}", f.display_header(&code)); + println!("{}", f.display_header(code)); } } } else { @@ -333,7 +332,7 @@ callgraph | Create a dot call graph froma function and a max for (i, f) in code.functions.iter().enumerate() { if f.debug_info.as_ref().unwrap()[f.ops.len() - 1].0 == idx { print_i!(i); - println!("{}", f.display_header(&code)); + println!("{}", f.display_header(code)); } } } @@ -341,18 +340,18 @@ callgraph | Create a dot call graph froma function and a max } Command::FileOf(idx) => { let debug_files = require_debug_info!(); - if let Some(p) = RefFun(idx).resolve(&code) { + if let Some(p) = RefFun(idx).resolve(code) { match p { RefFunPointee::Fun(f) => { let idx = f.debug_info.as_ref().unwrap()[f.ops.len() - 1].0; println!( "{} is in file@{idx} : {}", - f.display_header(&code), + f.display_header(code), &debug_files[idx] ); } RefFunPointee::Native(n) => { - println!("{} can't be in any file", n.display_header(&code)) + println!("{} can't be in any file", n.display_header(code)) } } } @@ -366,8 +365,8 @@ callgraph | Create a dot call graph froma function and a max { use hlbc::analysis::graph::{call_graph, display_graph}; - let graph = call_graph(&code, RefFun(idx), depth); - println!("{}", display_graph(&graph, &code)); + let graph = call_graph(code, RefFun(idx), depth); + println!("{}", display_graph(&graph, code)); } #[cfg(not(feature = "graph"))] @@ -388,13 +387,10 @@ callgraph | Create a dot call graph froma function and a max "constant@{i} expanding to global@{} (now also searching for global)", c.global.0 ); - iter_ops(&code).for_each(|(f, (i, o))| match o { + iter_ops(code).for_each(|(f, (i, o))| match o { Opcode::GetGlobal { global, .. } => { if *global == c.global { - println!( - "in {} at {i}: GetGlobal", - f.display_header(&code) - ); + println!("in {} at {i}: GetGlobal", f.display_header(code)); } } _ => {} @@ -403,10 +399,10 @@ callgraph | Create a dot call graph froma function and a max } } } - iter_ops(&code).for_each(|(f, (i, o))| match o { + iter_ops(code).for_each(|(f, (i, o))| match o { Opcode::String { ptr, .. } => { if ptr.0 == idx { - println!("{} at {i}: String", f.display_header(&code)); + println!("{} at {i}: String", f.display_header(code)); } } _ => {} @@ -415,7 +411,7 @@ callgraph | Create a dot call graph froma function and a max ElementRef::Global(idx) => { println!( "Finding references to global@{idx} : {}\n", - code.globals[idx].display(&code) + code.globals[idx].display(code) ); if let Some(constants) = &code.constants { for (i, c) in constants.iter().enumerate() { @@ -426,10 +422,10 @@ callgraph | Create a dot call graph froma function and a max } println!(); - iter_ops(&code).for_each(|(f, (i, o))| match o { + iter_ops(code).for_each(|(f, (i, o))| match o { Opcode::GetGlobal { global, .. } | Opcode::SetGlobal { global, .. } => { if global.0 == idx { - println!("{} at {i}: {}", f.display_header(&code), o.name()); + println!("{} at {i}: {}", f.display_header(code), o.name()); } } _ => {} @@ -438,14 +434,14 @@ callgraph | Create a dot call graph froma function and a max ElementRef::Fn(idx) => { println!( "Finding references to fn@{idx} : {}\n", - RefFun(idx).display_header(&code) + RefFun(idx).display_header(code) ); code.functions .iter() .flat_map(|f| repeat(f).zip(find_fun_refs(f))) .for_each(|(f, (i, o, fun))| { if fun.0 == idx { - println!("{} at {i}: {}", f.display_header(&code), o.name()); + println!("{} at {i}: {}", f.display_header(code), o.name()); } }); } @@ -454,8 +450,8 @@ callgraph | Create a dot call graph froma function and a max let ty = &code.types[idx]; match ty { Type::Obj(obj) => { - println!("Dumping type@{idx} : {}", ty.display(&code)); - println!("{}", decompiler::decompile_class(&code, obj)); + println!("Dumping type@{idx} : {}", ty.display(code)); + println!("{}", decompiler::decompile_class(code, obj)); } _ => println!("Type {idx} is not an obj"), } diff --git a/hlbc-derive/Cargo.toml b/hlbc-derive/Cargo.toml index eb9460c..714d376 100644 --- a/hlbc-derive/Cargo.toml +++ b/hlbc-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hlbc-derive" -version = "0.1.1" +version = "0.2.0" edition = "2021" license = "MIT" description = "Procedural macros for the 'hlbc' crate" diff --git a/hlbc-derive/src/lib.rs b/hlbc-derive/src/lib.rs index 18f5773..af940a9 100644 --- a/hlbc-derive/src/lib.rs +++ b/hlbc-derive/src/lib.rs @@ -2,10 +2,10 @@ use proc_macro::TokenStream; use quote::quote; use syn::__private::TokenStream2; -use syn::{Data, DeriveInput, GenericArgument, Ident, PathArguments, Type, Variant}; +use syn::{Data, DeriveInput, GenericArgument, Ident, LitStr, PathArguments, Type, Variant}; #[proc_macro_attribute] -pub fn gen_decode(_: TokenStream, input: TokenStream) -> TokenStream { +pub fn derive_opcode(_: TokenStream, input: TokenStream) -> TokenStream { let ast = syn::parse_macro_input!(input as DeriveInput); let variants = match &ast.data { Data::Enum(v) => Some(&v.variants), @@ -21,6 +21,10 @@ pub fn gen_decode(_: TokenStream, input: TokenStream) -> TokenStream { .iter() .enumerate() .map(|(i, v)| gen_initw(name, v, i as u8)); + let vname = variants.iter().map(|v| &v.ident); + let vname_str = variants + .iter() + .map(|v| LitStr::new(&v.ident.to_string(), v.ident.span())); TokenStream::from(quote! { #ast @@ -51,6 +55,12 @@ pub fn gen_decode(_: TokenStream, input: TokenStream) -> TokenStream { Ok(()) } + + pub fn name(&self) -> &'static str { + match self { + #( #name::#vname { .. } => #vname_str, )* + } + } } }) } diff --git a/src/fmt.rs b/src/fmt.rs index 931bbd6..27019c6 100644 --- a/src/fmt.rs +++ b/src/fmt.rs @@ -90,16 +90,16 @@ impl Type { } parents.push(self as *const Type); - fn display_type_fun(ty: &TypeFun, ctx: &Bytecode, parents: &Vec<*const Type>) -> String { + fn display_type_fun(ty: &TypeFun, ctx: &Bytecode, parents: &[*const Type]) -> String { let args: Vec = ty .args .iter() - .map(|a| a.display_rec(ctx, parents.clone())) + .map(|a| a.display_rec(ctx, parents.to_owned())) .collect(); format!( "({}) -> ({})", args.join(", "), - ty.ret.display_rec(ctx, parents.clone()) + ty.ret.display_rec(ctx, parents.to_owned()) ) } diff --git a/src/lib.rs b/src/lib.rs index a8d3e8a..60d8f98 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -252,7 +252,7 @@ impl Bytecode { /// Serialize the bytecode to any sink. /// Bytecode is serialized to the same format. pub fn serialize(&self, w: &mut impl Write) -> Result<()> { - w.write(&[b'H', b'L', b'B'])?; + w.write_all(&[b'H', b'L', b'B'])?; w.write_u8(self.version)?; w.write_vi32(if self.debug_files.is_some() { 1 } else { 0 })?; w.write_vi32(self.ints.len() as i32)?; @@ -278,7 +278,7 @@ impl Bytecode { w.write_strings(&self.strings)?; if let Some(bytes) = &self.bytes { w.write_i32::(bytes.len() as i32)?; - w.write(bytes)?; + w.write_all(bytes)?; // TODO write bytes pos } if let Some(debug_files) = &self.debug_files { diff --git a/src/opcodes.rs b/src/opcodes.rs index 3e28ed3..f9aae92 100644 --- a/src/opcodes.rs +++ b/src/opcodes.rs @@ -16,8 +16,8 @@ pub type JumpOffset = i32; /// Opcodes definitions. /// The fields are the opcode arguments. -#[hlbc_derive::gen_decode] -#[derive(Debug, Clone, strum_macros::IntoStaticStr)] +#[hlbc_derive::derive_opcode] +#[derive(Debug, Clone)] pub enum Opcode { Mov { dst: Reg, @@ -460,9 +460,10 @@ pub enum Opcode { Nop, } +/* impl Opcode { /// Get the opcode name pub fn name(&self) -> &'static str { Into::into(self) } -} +}*/ diff --git a/src/ser.rs b/src/ser.rs index bfeff75..42d4aa1 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -62,7 +62,7 @@ impl WriteHlExt for T { .unwrap_or(0); self.write_i32::(size as i32)?; for s in cstr.iter() { - self.write(s.as_bytes_with_nul())?; + self.write_all(s.as_bytes_with_nul())?; } for s in cstr.iter() { self.write_vi32(s.as_bytes().len() as i32)?;