alignment; more verbose error log

This commit is contained in:
🪞👃🪞 2025-02-24 15:50:51 +02:00
parent 830e75db19
commit 32a693e1c4
5 changed files with 59 additions and 44 deletions

View file

@ -173,7 +173,7 @@ impl CallSite {
_ => {} _ => {}
}, },
0xff => match opcodes[1] { 0xff => match opcodes[1] {
0x10 | 0x12 | 0x13 | 0x10 | 0x12 | 0x13 | 0x16 |
0x50 | 0x51 | 0x52 | 0x53 | 0x54 | 0x55 | 0x56 | 0x57 | 0x50 | 0x51 | 0x52 | 0x53 | 0x54 | 0x55 | 0x56 | 0x57 |
0x60 | 0x90 | 0x92 | 0x93 | 0x94 | 0x97 => return true, 0x60 | 0x90 | 0x92 | 0x93 | 0x94 | 0x97 => return true,
_ => {} _ => {}

View file

@ -6,9 +6,13 @@ impl Module {
println!(" {DIM}(load-imports){RESET}"); println!(" {DIM}(load-imports){RESET}");
} }
let pe = self.pe.clone(); 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![]; 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 (module_name, imports) = Self::parse_import(pe.as_ref(), descriptor)?;
let create = !self.namespace.read().unwrap().contains_key(&module_name); let create = !self.namespace.read().unwrap().contains_key(&module_name);
if create { if create {

View file

@ -75,13 +75,18 @@ fn main () -> Usually<()> {
// Parse command line arguments. // Parse command line arguments.
let args = cli().get_matches(); let args = cli().get_matches();
if let Some(path) = args.get_one::<PathBuf>("path") { if let Some(path) = args.get_one::<PathBuf>("path") {
Arc::new(Module::from_path(path, *(args.get_one::<bool>("verbose").unwrap_or(&false)))?) Module::from_path(path, *(args.get_one::<bool>("verbose").unwrap_or(&false)))
.map(Arc::new)
.unwrap_or_else(|e|panic!("failed to open: {e:?}"))
.search(std::env::current_dir()?) .search(std::env::current_dir()?)
.search(canonicalize(path.clone().parent().expect("invalid parent path"))?) .search(canonicalize(path.clone().parent().expect("invalid parent path"))?)
.search("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32") .search("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32")
.load(true)? .load(true)
.resolve(true)? .unwrap_or_else(|e|panic!("failed to load: {e:?}"))
.relink()?; .resolve(true)
.unwrap_or_else(|e|panic!("failed to resolve: {e:?}"))
.relink()
.unwrap_or_else(|e|panic!("failed to relink: {e:?}"));
} else { } else {
println!("Pass a path to a VST DLL"); println!("Pass a path to a VST DLL");
} }
@ -99,7 +104,6 @@ impl Module {
let (code, code_start, code_size) = read_code(&pe)?; let (code, code_start, code_size) = read_code(&pe)?;
Ok(Self { Ok(Self {
bang, bang,
name: to_dll_name(&path),
path: path.as_ref().to_path_buf().into(), path: path.as_ref().to_path_buf().into(),
code, code,
code_start, code_start,
@ -114,6 +118,11 @@ impl Module {
call_sites: Default::default(), call_sites: Default::default(),
pe, pe,
verbose, verbose,
name: Arc::from(path.as_ref()
.file_name()
.expect("no file name")
.to_str()
.expect("non-unicode filename")),
}) })
} }
/// Add a search path /// Add a search path
@ -138,7 +147,8 @@ impl Module {
} }
/// Load the dependency tree reachable from this module. /// Load the dependency tree reachable from this module.
fn load (self: Arc<Self>, recurse: bool) -> Usually<Arc<Self>> { fn load (self: Arc<Self>, recurse: bool) -> Usually<Arc<Self>> {
let module = self.load_exports()?.load_imports(recurse)?; let module = self.load_exports()?;
let module = module.load_imports(recurse)?;
if module.verbose { if module.verbose {
println!("{:?}", &module); println!("{:?}", &module);
} }
@ -192,14 +202,6 @@ impl Module {
} }
} }
fn to_dll_name (path: &impl AsRef<Path>) -> Arc<str> {
Arc::from(path.as_ref()
.file_name()
.expect("no file name")
.to_str()
.expect("non-unicode filename"))
}
fn read_pe (path: &impl AsRef<Path>) -> Usually<(Arc<VecPE>, Arc<[u8]>, Arc<[u8]>)> { fn read_pe (path: &impl AsRef<Path>) -> Usually<(Arc<VecPE>, Arc<[u8]>, Arc<[u8]>)> {
let (bang, data) = crate::bang::slice_shebang(read(path.as_ref())?.as_slice()); let (bang, data) = crate::bang::slice_shebang(read(path.as_ref())?.as_slice());
let pe = Arc::new(VecPE::from_disk_data(data.clone())); let pe = Arc::new(VecPE::from_disk_data(data.clone()));
@ -207,11 +209,15 @@ fn read_pe (path: &impl AsRef<Path>) -> Usually<(Arc<VecPE>, Arc<[u8]>, Arc<[u8]
} }
fn read_code (pe: &VecPE) -> Usually<(Arc<[u8]>, usize, usize)> { fn read_code (pe: &VecPE) -> Usually<(Arc<[u8]>, usize, usize)> {
if let Ok(code) = pe.get_section_by_name(".text") {
let 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 start = code.pointer_to_raw_data.0 as usize;
let size = code.size_of_raw_data as usize; let size = code.size_of_raw_data as usize;
let text = &pe.as_slice()[start..start+size]; let text = &pe.as_slice()[start..start+size];
Ok((text.into(), start, size)) Ok((text.into(), start, size))
} else {
Ok(([].into(), 0, 0))
}
} }
fn base_of_code (pe: &VecPE) -> Usually<u32> { fn base_of_code (pe: &VecPE) -> Usually<u32> {

View file

@ -46,12 +46,7 @@ impl Log {
depth: Option<usize>, depth: Option<usize>,
) { ) {
if show { if show {
if let Some(depth) = depth { call.show(depth.unwrap_or(0), opcodes);
for i in 0..depth {
print!(" ");
}
}
call.show(opcodes);
} }
} }
pub fn call_sites ( pub fn call_sites (
@ -61,19 +56,14 @@ impl Log {
depth: Option<usize> depth: Option<usize>
) { ) {
for (target, call_sites) in targets.iter() { for (target, call_sites) in targets.iter() {
if let Some(depth) = depth { //if let Some(depth) = depth {
for i in 0..depth { //for i in 0..depth {
print!(" "); //print!(" ");
} //}
} //}
//println!(" (call {:15} {})", name.as_ref(), fmt_num(*target as usize)); //println!(" (call {:15} {})", name.as_ref(), fmt_num(*target as usize));
for call_site in call_sites.iter() { for call_site in call_sites.iter() {
if let Some(depth) = depth { call_site.show(depth.unwrap_or(0), None);
for i in 0..depth {
print!(" ");
}
}
call_site.show(None);
} }
} }
} }
@ -184,14 +174,17 @@ impl Module {
print!("{output}"); print!("{output}");
} }
} }
impl CallSite { 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) 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}")); .unwrap_or_else(||format!("{RED}unresolved{RESET}"));
println!(" {DIM}╰->{RESET} (call {:15} {} {} {DIM}{:20}{RESET} {} {BOLD}{}{RESET})", write!(&mut call, "{DIM}╰->{RESET} (call {}", &self.caller.name);
&self.caller.name, println!("{call:40} {} {} {DIM}{:20}{RESET} {} {BOLD}{}{RESET})",
fmt_num(self.offset as usize), fmt_num(self.offset as usize),
fmt_num(self.source as usize), fmt_num(self.source as usize),
fmt_bytes(opcodes.unwrap_or(&[])), fmt_bytes(opcodes.unwrap_or(&[])),

12
license.txt Normal file
View file

@ -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.