Compare commits

...

5 Commits

Author SHA1 Message Date
Luke Street a156c3697f Appease clippy 2024-04-03 00:18:16 -06:00
Luke Street 3497d38ea3 Version 0.7.6 2024-04-03 00:13:42 -06:00
Luke Street d0f39f1d82 Support global labels in REL creation (_savegpr, etc) 2024-04-03 00:13:15 -06:00
Luke Street ccfbfd1a5a Fix for jumptable naming in RELs 2024-04-03 00:12:46 -06:00
Luke Street e9a9ed0453 Fixes for switch analysis
- When finalizing a block, restart analysis at
  the first block
- Check for default case in jump table entries
2024-04-03 00:11:58 -06:00
9 changed files with 30 additions and 14 deletions

2
Cargo.lock generated
View File

@ -269,7 +269,7 @@ checksum = "c2e06f9bce634a3c898eb1e5cb949ff63133cbb218af93cc9b38b31d6f3ea285"
[[package]]
name = "decomp-toolkit"
version = "0.7.5"
version = "0.7.6"
dependencies = [
"anyhow",
"ar",

View File

@ -3,7 +3,7 @@ name = "decomp-toolkit"
description = "Yet another GameCube/Wii decompilation toolkit."
authors = ["Luke Street <luke@street.dev>"]
license = "MIT OR Apache-2.0"
version = "0.7.5"
version = "0.7.6"
edition = "2021"
publish = false
repository = "https://github.com/encounter/decomp-toolkit"

View File

@ -248,8 +248,12 @@ impl AnalyzerState {
}
if self.functions.iter().any(|(_, i)| i.is_unfinalized()) {
log::error!("Failed to finalize functions:");
for (addr, _) in self.functions.iter().filter(|(_, i)| i.is_unfinalized()) {
log::error!(" {:#010X}", addr);
for (addr, info) in self.functions.iter().filter(|(_, i)| i.is_unfinalized()) {
log::error!(
" {:#010X}: blocks [{:?}]",
addr,
info.slices.as_ref().unwrap().possible_blocks.keys()
);
}
bail!("Failed to finalize functions");
}
@ -298,11 +302,15 @@ impl AnalyzerState {
&self.functions,
Some(vm),
)?;
// Start at the beginning of the function again
current = SectionAddress::new(addr.section, 0);
}
TailCallResult::Is => {
log::trace!("Finalized tail call @ {:#010X}", block);
slices.possible_blocks.remove(&block);
slices.function_references.insert(block);
// Start at the beginning of the function again
current = SectionAddress::new(addr.section, 0);
}
TailCallResult::Possible => {
if finalize {

View File

@ -328,7 +328,7 @@ impl FunctionSlices {
function_end.or_else(|| self.end()),
)?;
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| {
self.is_known_function(known_functions, addr)
.is_some_and(|fn_addr| fn_addr != function_start)

View File

@ -295,7 +295,7 @@ fn make(args: MakeArgs) -> Result<()> {
for (module_id, (module, path)) in modules.iter().enumerate() {
let _span = info_span!("file", path = %path.display()).entered();
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()));
}
}

View File

@ -13,7 +13,11 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
use crate::{
analysis::cfa::SectionAddress,
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)]
@ -242,7 +246,11 @@ impl ObjSymbols {
bail!("ABS symbol in relocatable object: {:?}", in_symbol);
};
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 =
if existing.size_known && in_symbol.size_known && existing.size != in_symbol.size {
// TODO fix this and restore to warning

View File

@ -182,6 +182,10 @@ pub fn is_auto_symbol(symbol: &ObjSymbol) -> bool {
|| 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<()>
where
P: AsRef<Path>,

View File

@ -428,7 +428,7 @@ where P: AsRef<Path> {
if path.as_ref().exists() {
set_file_mtime(path, FileTime::now())
} else {
match OpenOptions::new().create(true).write(true).open(path) {
match OpenOptions::new().create(true).truncate(true).write(true).open(path) {
Ok(_) => Ok(()),
Err(e) => Err(e),
}

View File

@ -391,11 +391,7 @@ impl<'parent> Iterator for Nodes<'parent> {
type Item = Node;
fn next(&mut self) -> Option<Self::Item> {
let Some(state) = self.stack.pop() else {
return None;
};
match state {
match self.stack.pop()? {
NodeState::Begin(name) => {
self.stack.push(NodeState::File(name.clone(), 0));
Some(Node::DirectoryBegin { name })