Auto-split and padding symbol fixes

A few issues were causing linker errors:
- Auto-splits could contain symbols that have a
higher alignment than the split itself. Detect
this and create a new auto-split at these symbols.
- The analyzer can miss objects in between other
objects if there are no direct relocations to them.
In these cases, non-zero data could just get totally
lost. Detect and create symbols for these.
This commit is contained in:
Luke Street 2025-02-04 23:45:07 -07:00
parent 7e15810af1
commit bb18a4b253
3 changed files with 59 additions and 11 deletions

6
Cargo.lock generated
View File

@ -339,16 +339,16 @@ checksum = "c2e06f9bce634a3c898eb1e5cb949ff63133cbb218af93cc9b38b31d6f3ea285"
[[package]] [[package]]
name = "cwextab" name = "cwextab"
version = "1.0.2" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5aa7f13cc2fcb2bcfd3abc51bdbbf8f1fb729a69ed8c05ecbaa1a42197d1842" checksum = "003567b96ff9d8ac3275831650385891bca370092937be625157778b1e58f755"
dependencies = [ dependencies = [
"thiserror", "thiserror",
] ]
[[package]] [[package]]
name = "decomp-toolkit" name = "decomp-toolkit"
version = "1.4.0" version = "1.4.1"
dependencies = [ dependencies = [
"aes", "aes",
"anyhow", "anyhow",

View File

@ -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 = "1.4.0" version = "1.4.1"
edition = "2021" edition = "2021"
publish = false publish = false
repository = "https://github.com/encounter/decomp-toolkit" repository = "https://github.com/encounter/decomp-toolkit"

View File

@ -385,6 +385,20 @@ fn create_gap_splits(obj: &mut ObjInfo) -> Result<()> {
new_split_end.address = symbol.address as u32; new_split_end.address = symbol.address as u32;
break; break;
} }
// Create a new split if we need to adjust the alignment
if let Some(align) = symbol.align {
if current_address & (align - 1) != 0 {
log::debug!(
"Auto split {:#010X}..{:#010X} for symbol {} with alignment {}",
current_address,
symbol.address,
symbol.name,
align
);
new_split_end.address = symbol.address as u32;
break;
}
}
} }
ensure!( ensure!(
@ -614,20 +628,54 @@ fn add_padding_symbols(obj: &mut ObjInfo) -> Result<()> {
if let Some(&(_, next_symbol)) = iter.peek() { if let Some(&(_, next_symbol)) = iter.peek() {
( (
next_symbol.name.as_str(), next_symbol.name.as_str(),
next_symbol.address, next_symbol.address as u32,
next_symbol.address + next_symbol.size, (next_symbol.address + next_symbol.size) as u32,
next_symbol.align.unwrap_or(1), next_symbol.align.unwrap_or(1),
) )
} else { } else {
( (
section.name.as_str(), section.name.as_str(),
section.address + section.size, (section.address + section.size) as u32,
section.address + section.size, (section.address + section.size) as u32,
1, 1,
) )
}; };
let aligned_end = align_up((symbol.address + symbol.size) as u32, next_align);
match aligned_end.cmp(&(next_address as u32)) { // Check if symbol is missing data between the end of the symbol and the next symbol
let symbol_end = (symbol.address + symbol.size) as u32;
if section.kind != ObjSectionKind::Code && next_address > symbol_end {
let data = section.data_range(symbol_end, next_address)?;
if data.iter().any(|&x| x != 0) {
log::debug!(
"Non-zero data between {:#010X}..{:#010X}, creating new symbol",
symbol_end,
next_address
);
let name = if obj.module_id == 0 {
format!("lbl_{:08X}", symbol_end)
} else {
format!(
"lbl_{}_{}_{:X}",
obj.module_id,
section.name.trim_start_matches('.'),
symbol_end
)
};
to_add.push(ObjSymbol {
name,
address: symbol_end as u64,
section: Some(section_index),
size: (next_address - symbol_end) as u64,
size_known: true,
kind: ObjSymbolKind::Object,
..Default::default()
});
continue;
}
}
let aligned_end = align_up(symbol_end, next_align);
match aligned_end.cmp(&next_address) {
Ordering::Less => { Ordering::Less => {
let symbol_name = format!( let symbol_name = format!(
"gap_{:02}_{:08X}_{}", "gap_{:02}_{:08X}_{}",
@ -640,7 +688,7 @@ fn add_padding_symbols(obj: &mut ObjInfo) -> Result<()> {
name: symbol_name, name: symbol_name,
address: aligned_end as u64, address: aligned_end as u64,
section: Some(section_index), section: Some(section_index),
size: next_address - aligned_end as u64, size: (next_address - aligned_end) as u64,
size_known: true, size_known: true,
flags: ObjSymbolFlagSet( flags: ObjSymbolFlagSet(
ObjSymbolFlags::Global ObjSymbolFlags::Global