Compare commits
5 Commits
9249fa67b8
...
a156c3697f
Author | SHA1 | Date |
---|---|---|
Luke Street | a156c3697f | |
Luke Street | 3497d38ea3 | |
Luke Street | d0f39f1d82 | |
Luke Street | ccfbfd1a5a | |
Luke Street | e9a9ed0453 |
|
@ -269,7 +269,7 @@ checksum = "c2e06f9bce634a3c898eb1e5cb949ff63133cbb218af93cc9b38b31d6f3ea285"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "decomp-toolkit"
|
name = "decomp-toolkit"
|
||||||
version = "0.7.5"
|
version = "0.7.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"ar",
|
"ar",
|
||||||
|
|
|
@ -3,7 +3,7 @@ name = "decomp-toolkit"
|
||||||
description = "Yet another GameCube/Wii decompilation toolkit."
|
description = "Yet another GameCube/Wii decompilation toolkit."
|
||||||
authors = ["Luke Street <luke@street.dev>"]
|
authors = ["Luke Street <luke@street.dev>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
version = "0.7.5"
|
version = "0.7.6"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
publish = false
|
publish = false
|
||||||
repository = "https://github.com/encounter/decomp-toolkit"
|
repository = "https://github.com/encounter/decomp-toolkit"
|
||||||
|
|
|
@ -248,8 +248,12 @@ impl AnalyzerState {
|
||||||
}
|
}
|
||||||
if self.functions.iter().any(|(_, i)| i.is_unfinalized()) {
|
if self.functions.iter().any(|(_, i)| i.is_unfinalized()) {
|
||||||
log::error!("Failed to finalize functions:");
|
log::error!("Failed to finalize functions:");
|
||||||
for (addr, _) in self.functions.iter().filter(|(_, i)| i.is_unfinalized()) {
|
for (addr, info) in self.functions.iter().filter(|(_, i)| i.is_unfinalized()) {
|
||||||
log::error!(" {:#010X}", addr);
|
log::error!(
|
||||||
|
" {:#010X}: blocks [{:?}]",
|
||||||
|
addr,
|
||||||
|
info.slices.as_ref().unwrap().possible_blocks.keys()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
bail!("Failed to finalize functions");
|
bail!("Failed to finalize functions");
|
||||||
}
|
}
|
||||||
|
@ -298,11 +302,15 @@ impl AnalyzerState {
|
||||||
&self.functions,
|
&self.functions,
|
||||||
Some(vm),
|
Some(vm),
|
||||||
)?;
|
)?;
|
||||||
|
// Start at the beginning of the function again
|
||||||
|
current = SectionAddress::new(addr.section, 0);
|
||||||
}
|
}
|
||||||
TailCallResult::Is => {
|
TailCallResult::Is => {
|
||||||
log::trace!("Finalized tail call @ {:#010X}", block);
|
log::trace!("Finalized tail call @ {:#010X}", block);
|
||||||
slices.possible_blocks.remove(&block);
|
slices.possible_blocks.remove(&block);
|
||||||
slices.function_references.insert(block);
|
slices.function_references.insert(block);
|
||||||
|
// Start at the beginning of the function again
|
||||||
|
current = SectionAddress::new(addr.section, 0);
|
||||||
}
|
}
|
||||||
TailCallResult::Possible => {
|
TailCallResult::Possible => {
|
||||||
if finalize {
|
if finalize {
|
||||||
|
|
|
@ -328,7 +328,7 @@ impl FunctionSlices {
|
||||||
function_end.or_else(|| self.end()),
|
function_end.or_else(|| self.end()),
|
||||||
)?;
|
)?;
|
||||||
log::debug!("-> size {}: {:?}", size, entries);
|
log::debug!("-> size {}: {:?}", size, entries);
|
||||||
if entries.contains(&next_address)
|
if (entries.contains(&next_address) || self.blocks.contains_key(&next_address))
|
||||||
&& !entries.iter().any(|&addr| {
|
&& !entries.iter().any(|&addr| {
|
||||||
self.is_known_function(known_functions, addr)
|
self.is_known_function(known_functions, addr)
|
||||||
.is_some_and(|fn_addr| fn_addr != function_start)
|
.is_some_and(|fn_addr| fn_addr != function_start)
|
||||||
|
|
|
@ -295,7 +295,7 @@ fn make(args: MakeArgs) -> Result<()> {
|
||||||
for (module_id, (module, path)) in modules.iter().enumerate() {
|
for (module_id, (module, path)) in modules.iter().enumerate() {
|
||||||
let _span = info_span!("file", path = %path.display()).entered();
|
let _span = info_span!("file", path = %path.display()).entered();
|
||||||
for symbol in module.symbols() {
|
for symbol in module.symbols() {
|
||||||
if symbol.is_definition() && symbol.scope() == object::SymbolScope::Dynamic {
|
if symbol.scope() == object::SymbolScope::Dynamic {
|
||||||
symbol_map.entry(symbol.name_bytes()?).or_insert((module_id, symbol.index()));
|
symbol_map.entry(symbol.name_bytes()?).or_insert((module_id, symbol.index()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,11 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
use crate::{
|
use crate::{
|
||||||
analysis::cfa::SectionAddress,
|
analysis::cfa::SectionAddress,
|
||||||
obj::{ObjKind, ObjRelocKind},
|
obj::{ObjKind, ObjRelocKind},
|
||||||
util::{config::is_auto_symbol, nested::NestedVec, split::is_linker_generated_label},
|
util::{
|
||||||
|
config::{is_auto_jump_table, is_auto_label, is_auto_symbol},
|
||||||
|
nested::NestedVec,
|
||||||
|
split::is_linker_generated_label,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||||
|
@ -242,7 +246,11 @@ impl ObjSymbols {
|
||||||
bail!("ABS symbol in relocatable object: {:?}", in_symbol);
|
bail!("ABS symbol in relocatable object: {:?}", in_symbol);
|
||||||
};
|
};
|
||||||
let target_symbol_idx = if let Some((symbol_idx, existing)) = opt {
|
let target_symbol_idx = if let Some((symbol_idx, existing)) = opt {
|
||||||
let replace = replace || (is_auto_symbol(existing) && !is_auto_symbol(&in_symbol));
|
let replace = replace
|
||||||
|
// Replace auto symbols with known symbols
|
||||||
|
|| (is_auto_symbol(existing) && !is_auto_symbol(&in_symbol))
|
||||||
|
// Replace lbl_ with jumptable_
|
||||||
|
|| (is_auto_label(existing) && is_auto_jump_table(&in_symbol));
|
||||||
let size =
|
let size =
|
||||||
if existing.size_known && in_symbol.size_known && existing.size != in_symbol.size {
|
if existing.size_known && in_symbol.size_known && existing.size != in_symbol.size {
|
||||||
// TODO fix this and restore to warning
|
// TODO fix this and restore to warning
|
||||||
|
|
|
@ -182,6 +182,10 @@ pub fn is_auto_symbol(symbol: &ObjSymbol) -> bool {
|
||||||
|| symbol.name.starts_with("pad_")
|
|| symbol.name.starts_with("pad_")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_auto_label(symbol: &ObjSymbol) -> bool { symbol.name.starts_with("lbl_") }
|
||||||
|
|
||||||
|
pub fn is_auto_jump_table(symbol: &ObjSymbol) -> bool { symbol.name.starts_with("jumptable_") }
|
||||||
|
|
||||||
fn write_if_unchanged<P, Cb>(path: P, cb: Cb, cached_file: Option<FileReadInfo>) -> Result<()>
|
fn write_if_unchanged<P, Cb>(path: P, cb: Cb, cached_file: Option<FileReadInfo>) -> Result<()>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
|
|
|
@ -428,7 +428,7 @@ where P: AsRef<Path> {
|
||||||
if path.as_ref().exists() {
|
if path.as_ref().exists() {
|
||||||
set_file_mtime(path, FileTime::now())
|
set_file_mtime(path, FileTime::now())
|
||||||
} else {
|
} else {
|
||||||
match OpenOptions::new().create(true).write(true).open(path) {
|
match OpenOptions::new().create(true).truncate(true).write(true).open(path) {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
|
|
|
@ -391,11 +391,7 @@ impl<'parent> Iterator for Nodes<'parent> {
|
||||||
type Item = Node;
|
type Item = Node;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let Some(state) = self.stack.pop() else {
|
match self.stack.pop()? {
|
||||||
return None;
|
|
||||||
};
|
|
||||||
|
|
||||||
match state {
|
|
||||||
NodeState::Begin(name) => {
|
NodeState::Begin(name) => {
|
||||||
self.stack.push(NodeState::File(name.clone(), 0));
|
self.stack.push(NodeState::File(name.clone(), 0));
|
||||||
Some(Node::DirectoryBegin { name })
|
Some(Node::DirectoryBegin { name })
|
||||||
|
|
Loading…
Reference in New Issue