Automatically check for invalid extab relocations (#75)
* Begin work on extab reloc analysis code * Refactoring * Make format happy * Address feedback + improvements
This commit is contained in:
parent
c106123877
commit
26f52f65b7
|
@ -393,6 +393,15 @@ dependencies = [
|
|||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cwextab"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5aa7f13cc2fcb2bcfd3abc51bdbbf8f1fb729a69ed8c05ecbaa1a42197d1842"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "decomp-toolkit"
|
||||
version = "1.0.0"
|
||||
|
@ -404,6 +413,7 @@ dependencies = [
|
|||
"base64",
|
||||
"crossterm",
|
||||
"cwdemangle",
|
||||
"cwextab 1.0.2",
|
||||
"enable-ansi-support",
|
||||
"filetime",
|
||||
"fixedbitset 0.5.7",
|
||||
|
@ -1018,7 +1028,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"byteorder",
|
||||
"cwdemangle",
|
||||
"cwextab",
|
||||
"cwextab 0.3.1",
|
||||
"filetime",
|
||||
"flagset",
|
||||
"log",
|
||||
|
|
|
@ -32,6 +32,7 @@ base16ct = "0.2"
|
|||
base64 = "0.22"
|
||||
crossterm = "0.28"
|
||||
cwdemangle = "1.0"
|
||||
cwextab = "1.0.2"
|
||||
enable-ansi-support = "0.2"
|
||||
filetime = "0.2"
|
||||
fixedbitset = "0.5"
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use cwextab::decode_extab;
|
||||
use ppc750cl::Opcode;
|
||||
use tracing::{debug_span, info_span};
|
||||
use tracing_attributes::instrument;
|
||||
|
@ -120,6 +121,7 @@ impl Tracker {
|
|||
self.process_data(obj, section_index, section)?;
|
||||
}
|
||||
}
|
||||
self.check_extab_relocations(obj)?;
|
||||
self.reject_invalid_relocations(obj)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -147,6 +149,62 @@ impl Tracker {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Check all of the extab relocations, and reject any invalid ones by checking against the decoded table data
|
||||
/// of each table.
|
||||
fn check_extab_relocations(&mut self, obj: &ObjInfo) -> Result<()> {
|
||||
let mut to_reject = vec![];
|
||||
let Some((section_index, section)) = obj.sections.by_name("extab")? else {
|
||||
// No extab section found, return
|
||||
return Ok(());
|
||||
};
|
||||
let mut decoded_reloc_addrs: BTreeSet<u32> = BTreeSet::new();
|
||||
|
||||
// Decode each exception table, and collect all of the relocations from the decoded data for each
|
||||
for (_, symbol) in obj.symbols.for_section(section_index) {
|
||||
let extab_name = &symbol.name;
|
||||
let extab_start_addr: u32 = symbol.address as u32;
|
||||
let extab_end_addr: u32 = extab_start_addr + symbol.size as u32;
|
||||
let Ok(extab_data) = section.data_range(extab_start_addr, extab_end_addr) else {
|
||||
log::warn!("Failed to get extab data for symbol {}", extab_name);
|
||||
continue;
|
||||
};
|
||||
let data = match decode_extab(extab_data) {
|
||||
Ok(decoded_data) => decoded_data,
|
||||
Err(e) => {
|
||||
log::warn!(
|
||||
"Exception table decoding failed for symbol {}, reason: {}",
|
||||
extab_name,
|
||||
e
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
for reloc in data.relocations {
|
||||
let reloc_addr = extab_start_addr + reloc.offset;
|
||||
decoded_reloc_addrs.insert(reloc_addr);
|
||||
}
|
||||
}
|
||||
|
||||
let section_start_addr = SectionAddress::new(section_index, section.address as u32);
|
||||
let section_end_addr = section_start_addr + (section.size as u32);
|
||||
|
||||
// Check all the extab relocations against the list of relocations from the decoded tables. Any
|
||||
// relocations that aren't in the list are invalid, and are removed (if a table fails to decode,
|
||||
// however, its relocations are all removed).
|
||||
for (&address, _) in self.relocations.range(section_start_addr..section_end_addr) {
|
||||
if !decoded_reloc_addrs.contains(&address.address) {
|
||||
log::debug!("Rejecting invalid extab relocation @ {}", address);
|
||||
to_reject.push(address);
|
||||
}
|
||||
}
|
||||
|
||||
for address in to_reject {
|
||||
self.relocations.remove(&address);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process_code(&mut self, obj: &ObjInfo) -> Result<()> {
|
||||
if let Some(entry) = obj.entry {
|
||||
let (section_index, _) = obj.sections.at_address(entry as u32)?;
|
||||
|
|
Loading…
Reference in New Issue