Semi-working REL analysis & splitting

This commit is contained in:
2023-08-25 00:54:29 -04:00
parent 3f63f1ef47
commit a2374e4fa0
21 changed files with 1072 additions and 709 deletions

View File

@@ -24,13 +24,13 @@ pub struct SectionAddress {
impl Debug for SectionAddress {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{:#010X}", self.section as isize, self.address)
write!(f, "{}:{:#X}", self.section as isize, self.address)
}
}
impl Display for SectionAddress {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{:#010X}", self.section as isize, self.address)
write!(f, "{}:{:#X}", self.section as isize, self.address)
}
}
@@ -131,9 +131,19 @@ impl AnalyzerState {
section.address,
section.address + section.size
);
let address_str = if obj.module_id == 0 {
format!("{:08X}", addr.address)
} else {
format!(
"{}_{}_{:X}",
obj.module_id,
section.name.trim_start_matches('.'),
addr.address
)
};
obj.add_symbol(
ObjSymbol {
name: format!("jumptable_{:08X}", addr.address),
name: format!("jumptable_{}", address_str),
demangled_name: None,
address: addr.address as u64,
section: Some(addr.section),

View File

@@ -5,7 +5,7 @@ use crate::{
util::split::is_linker_generated_label,
};
pub fn detect_object_boundaries(obj: &mut ObjInfo) -> Result<()> {
pub fn detect_objects(obj: &mut ObjInfo) -> Result<()> {
for (section_index, section) in
obj.sections.iter_mut().filter(|(_, s)| s.kind != ObjSectionKind::Code)
{

View File

@@ -151,8 +151,9 @@ impl AnalysisPass for FindRelCtorsDtors {
let possible_sections = obj
.sections
.iter()
.filter(|&(_, section)| {
.filter(|&(index, section)| {
if section.section_known
|| state.known_sections.contains_key(&index)
|| !matches!(section.kind, ObjSectionKind::Data | ObjSectionKind::ReadOnlyData)
|| section.size < 4
{
@@ -283,3 +284,40 @@ impl AnalysisPass for FindRelCtorsDtors {
Ok(())
}
}
pub struct FindRelRodataData {}
impl AnalysisPass for FindRelRodataData {
fn execute(state: &mut AnalyzerState, obj: &ObjInfo) -> Result<()> {
ensure!(obj.kind == ObjKind::Relocatable);
match (obj.sections.by_name(".rodata")?, obj.sections.by_name(".data")?) {
(None, None) => {}
_ => return Ok(()),
}
let possible_sections = obj
.sections
.iter()
.filter(|&(index, section)| {
!section.section_known
&& !state.known_sections.contains_key(&index)
&& matches!(section.kind, ObjSectionKind::Data | ObjSectionKind::ReadOnlyData)
})
.collect_vec();
if possible_sections.len() != 2 {
log::warn!("Failed to find .rodata and .data");
return Ok(());
}
log::debug!("Found .rodata and .data: {:?}", possible_sections);
let rodata_section_index = possible_sections[0].0;
state.known_sections.insert(rodata_section_index, ".rodata".to_string());
let data_section_index = possible_sections[1].0;
state.known_sections.insert(data_section_index, ".data".to_string());
Ok(())
}
}

View File

@@ -309,8 +309,8 @@ impl FunctionSlices {
}
}
}
BranchTarget::JumpTable { .. } => {
bail!("Conditional jump table unsupported @ {:#010X}", ins_addr);
BranchTarget::JumpTable { address, size } => {
bail!("Conditional jump table unsupported @ {:#010X} -> {:#010X} size {:#X?}", ins_addr, address, size);
}
}
}

View File

@@ -5,6 +5,8 @@ use std::{
use anyhow::{bail, Result};
use ppc750cl::Opcode;
use tracing::{debug_span, info_span};
use tracing_attributes::instrument;
use crate::{
analysis::{
@@ -88,8 +90,8 @@ impl Tracker {
}
}
#[instrument(name = "tracker", skip(self, obj))]
pub fn process(&mut self, obj: &ObjInfo) -> Result<()> {
log::debug!("Processing code sections");
self.process_code(obj)?;
for (section_index, section) in obj
.sections
@@ -151,6 +153,7 @@ impl Tracker {
) -> Result<ExecCbResult<()>> {
let ExecCbData { executor, vm, result, ins_addr, section: _, ins, block_start: _ } = data;
let is_function_addr = |addr: SectionAddress| addr >= function_start && addr < function_end;
let _span = debug_span!("ins", addr = %ins_addr, op = ?ins.op).entered();
match result {
StepResult::Continue => {
@@ -310,8 +313,20 @@ impl Tracker {
executor.push(addr, branch.vm, true);
}
}
BranchTarget::JumpTable { .. } => {
bail!("Conditional jump table unsupported @ {:#010X}", ins_addr)
BranchTarget::JumpTable { address, size } => {
let (entries, _) = uniq_jump_table_entries(
obj,
address,
size,
ins_addr,
function_start,
Some(function_end),
)?;
for target in entries {
if is_function_addr(target) {
executor.push(target, branch.vm.clone_all(), true);
}
}
}
}
}
@@ -326,6 +341,9 @@ impl Tracker {
};
let function_start = SectionAddress::new(section_index, symbol.address as u32);
let function_end = function_start + symbol.size as u32;
let _span =
info_span!("fn", name = %symbol.name, start = %function_start, end = %function_end)
.entered();
// The compiler can sometimes create impossible-to-reach branches,
// but we still want to track them.
@@ -461,6 +479,7 @@ impl Tracker {
.or_else(|| check_symbol(self.sda_base, "_SDA_BASE_"))
}
#[instrument(name = "apply", skip(self, obj))]
pub fn apply(&self, obj: &mut ObjInfo, replace: bool) -> Result<()> {
fn apply_section_name(section: &mut ObjSection, name: &str) {
let module_id = if let Some((_, b)) = section.name.split_once(':') {

View File

@@ -126,8 +126,11 @@ pub fn section_address_for(
let (section_index, _) = obj.sections.at_address(target_addr).ok()?;
return Some(SectionAddress::new(section_index, target_addr));
}
// TODO: relative jumps within relocatable objects?
None
if obj.sections[ins_addr.section].contains(target_addr) {
Some(SectionAddress::new(ins_addr.section, target_addr))
} else {
None
}
}
impl VM {
@@ -180,11 +183,11 @@ impl VM {
pub fn clone_all(&self) -> Box<Self> { Box::new(self.clone()) }
pub fn step(&mut self, obj: &ObjInfo, ins_addr: SectionAddress, ins: &Ins) -> StepResult {
let relocation_target = relocation_target_for(obj, ins_addr, None).ok().flatten();
if let Some(_target) = relocation_target {
let _defs = ins.defs();
// TODO
}
// let relocation_target = relocation_target_for(obj, ins_addr, None).ok().flatten();
// if let Some(_target) = relocation_target {
// let _defs = ins.defs();
// // TODO
// }
match ins.op {
Opcode::Illegal => {