diff --git a/crates/vestal/src/call_sites.rs b/crates/vestal/src/call_sites.rs index 379d29b..584e8ac 100644 --- a/crates/vestal/src/call_sites.rs +++ b/crates/vestal/src/call_sites.rs @@ -173,7 +173,7 @@ impl CallSite { _ => {} }, 0xff => match opcodes[1] { - 0x10 | 0x12 | 0x13 | + 0x10 | 0x12 | 0x13 | 0x16 | 0x50 | 0x51 | 0x52 | 0x53 | 0x54 | 0x55 | 0x56 | 0x57 | 0x60 | 0x90 | 0x92 | 0x93 | 0x94 | 0x97 => return true, _ => {} diff --git a/crates/vestal/src/imports.rs b/crates/vestal/src/imports.rs index 36b38f7..99a5409 100644 --- a/crates/vestal/src/imports.rs +++ b/crates/vestal/src/imports.rs @@ -6,9 +6,13 @@ impl Module { println!(" {DIM}(load-imports){RESET}"); } let pe = self.pe.clone(); - let directory = ImportDirectory::parse(pe.as_ref())?; + let directory = ImportDirectory::parse(pe.as_ref()); + if let Err(e) = directory { + println!("failed to parse import directory of {}: {e:?}", &self.name); + return Ok(self) + } let mut new_modules = vec![]; - for descriptor in directory.descriptors.iter() { + for descriptor in directory.unwrap().descriptors.iter() { let (module_name, imports) = Self::parse_import(pe.as_ref(), descriptor)?; let create = !self.namespace.read().unwrap().contains_key(&module_name); if create { diff --git a/crates/vestal/src/main.rs b/crates/vestal/src/main.rs index 6f2f451..096f471 100644 --- a/crates/vestal/src/main.rs +++ b/crates/vestal/src/main.rs @@ -75,13 +75,18 @@ fn main () -> Usually<()> { // Parse command line arguments. let args = cli().get_matches(); if let Some(path) = args.get_one::("path") { - Arc::new(Module::from_path(path, *(args.get_one::("verbose").unwrap_or(&false)))?) + Module::from_path(path, *(args.get_one::("verbose").unwrap_or(&false))) + .map(Arc::new) + .unwrap_or_else(|e|panic!("failed to open: {e:?}")) .search(std::env::current_dir()?) .search(canonicalize(path.clone().parent().expect("invalid parent path"))?) .search("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32") - .load(true)? - .resolve(true)? - .relink()?; + .load(true) + .unwrap_or_else(|e|panic!("failed to load: {e:?}")) + .resolve(true) + .unwrap_or_else(|e|panic!("failed to resolve: {e:?}")) + .relink() + .unwrap_or_else(|e|panic!("failed to relink: {e:?}")); } else { println!("Pass a path to a VST DLL"); } @@ -99,7 +104,6 @@ impl Module { let (code, code_start, code_size) = read_code(&pe)?; Ok(Self { bang, - name: to_dll_name(&path), path: path.as_ref().to_path_buf().into(), code, code_start, @@ -114,6 +118,11 @@ impl Module { call_sites: Default::default(), pe, verbose, + name: Arc::from(path.as_ref() + .file_name() + .expect("no file name") + .to_str() + .expect("non-unicode filename")), }) } /// Add a search path @@ -138,7 +147,8 @@ impl Module { } /// Load the dependency tree reachable from this module. fn load (self: Arc, recurse: bool) -> Usually> { - let module = self.load_exports()?.load_imports(recurse)?; + let module = self.load_exports()?; + let module = module.load_imports(recurse)?; if module.verbose { println!("{:?}", &module); } @@ -192,14 +202,6 @@ impl Module { } } -fn to_dll_name (path: &impl AsRef) -> Arc { - Arc::from(path.as_ref() - .file_name() - .expect("no file name") - .to_str() - .expect("non-unicode filename")) -} - fn read_pe (path: &impl AsRef) -> Usually<(Arc, Arc<[u8]>, Arc<[u8]>)> { let (bang, data) = crate::bang::slice_shebang(read(path.as_ref())?.as_slice()); let pe = Arc::new(VecPE::from_disk_data(data.clone())); @@ -207,11 +209,15 @@ fn read_pe (path: &impl AsRef) -> Usually<(Arc, Arc<[u8]>, Arc<[u8] } fn read_code (pe: &VecPE) -> Usually<(Arc<[u8]>, usize, usize)> { - let code = pe.get_section_by_name(".text")?; - let start = code.pointer_to_raw_data.0 as usize; - let size = code.size_of_raw_data as usize; - let text = &pe.as_slice()[start..start+size]; - Ok((text.into(), start, size)) + if let Ok(code) = pe.get_section_by_name(".text") { + let code = pe.get_section_by_name(".text")?; + let start = code.pointer_to_raw_data.0 as usize; + let size = code.size_of_raw_data as usize; + let text = &pe.as_slice()[start..start+size]; + Ok((text.into(), start, size)) + } else { + Ok(([].into(), 0, 0)) + } } fn base_of_code (pe: &VecPE) -> Usually { diff --git a/crates/vestal/src/show.rs b/crates/vestal/src/show.rs index 5165093..2062b95 100644 --- a/crates/vestal/src/show.rs +++ b/crates/vestal/src/show.rs @@ -46,12 +46,7 @@ impl Log { depth: Option, ) { if show { - if let Some(depth) = depth { - for i in 0..depth { - print!(" "); - } - } - call.show(opcodes); + call.show(depth.unwrap_or(0), opcodes); } } pub fn call_sites ( @@ -61,19 +56,14 @@ impl Log { depth: Option ) { for (target, call_sites) in targets.iter() { - if let Some(depth) = depth { - for i in 0..depth { - print!(" "); - } - } + //if let Some(depth) = depth { + //for i in 0..depth { + //print!(" "); + //} + //} //println!(" (call {:15} {})", name.as_ref(), fmt_num(*target as usize)); for call_site in call_sites.iter() { - if let Some(depth) = depth { - for i in 0..depth { - print!(" "); - } - } - call_site.show(None); + call_site.show(depth.unwrap_or(0), None); } } } @@ -184,14 +174,17 @@ impl Module { print!("{output}"); } } - impl CallSite { - pub fn show (&self, opcodes: Option<&[u8]>) { + pub fn show (&self, depth: usize, opcodes: Option<&[u8]>) { + let mut call = String::new(); + for i in 0..depth { + write!(&mut call, " "); + } let label = self.caller.imports.read().unwrap().get(&self.target) - .map(|(module, method)|format!("{GREEN}{module}::{method}{RESET}")) + .map(|(module, method)|format!("{GREEN}{}{module}::{method}{RESET}", if depth > 0 { DIM } else { "" })) .unwrap_or_else(||format!("{RED}unresolved{RESET}")); - println!(" {DIM}╰->{RESET} (call {:15} {} {} {DIM}{:20}{RESET} {} {BOLD}{}{RESET})", - &self.caller.name, + write!(&mut call, "{DIM}╰->{RESET} (call {}", &self.caller.name); + println!("{call:40} {} {} {DIM}{:20}{RESET} {} {BOLD}{}{RESET})", fmt_num(self.offset as usize), fmt_num(self.source as usize), fmt_bytes(opcodes.unwrap_or(&[])), diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..d379119 --- /dev/null +++ b/license.txt @@ -0,0 +1,12 @@ +Copyright (C) 2023 - 2025 by H. L. Goldberg. + +The contained software is given to use under a freeware license. +This software is provided free of charge but the author retains copyright. + +You are not allowed to make any copies or redistribute this software including but not limited to making the software available for download or making this software part of a software CD/DVD/Blue-ray compilation. + +You are not allowed to sell or to rent this software. You are not allowed to reverse engineer this software. + +You are allowed to use this software for any artistic application including commercial music production. + +This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. \ No newline at end of file