Skip to content

Commit

Permalink
Semi-working REL analysis & splitting
Browse files Browse the repository at this point in the history
  • Loading branch information
encounter committed Aug 24, 2023
1 parent 3f63f1e commit a2374e4
Show file tree
Hide file tree
Showing 21 changed files with 1,070 additions and 707 deletions.
400 changes: 227 additions & 173 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ base64 = "0.21.2"
byteorder = "1.4.3"
cwdemangle = "0.1.5"
dol = { git = "https://github.com/encounter/ppc750cl", rev = "5f6e991bf495388c4104f188d2e90c79da9f78de" }
env_logger = "0.10.0"
filetime = "0.2.21"
fixedbitset = "0.4.2"
flagset = { version = "0.4.3", features = ["serde"] }
Expand All @@ -45,15 +44,20 @@ multimap = "0.9.0"
num_enum = "0.6.1"
object = { version = "0.31.1", features = ["read_core", "std", "elf", "write_std"], default-features = false }
once_cell = "1.18.0"
path-slash = "0.2.1"
petgraph = "0.6.3"
ppc750cl = { git = "https://github.com/encounter/ppc750cl", rev = "5f6e991bf495388c4104f188d2e90c79da9f78de" }
rayon = "1.7.0"
regex = "1.9.0"
serde = "1.0.166"
serde_json = "1.0.104"
serde_repr = "0.1.14"
serde_yaml = "0.9.22"
sha-1 = "0.10.1"
smallvec = "1.11.0"
tracing = "0.1.37"
tracing-attributes = "0.1.26"
tracing-subscriber = "0.3.17"

[build-dependencies]
anyhow = { version = "1.0.71", features = ["backtrace"] }
Expand Down
26 changes: 26 additions & 0 deletions assets/ldscript_partial.lcf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
SECTIONS
{
GROUP:
{
.init :{}
.text :{}
.ctors :{}
.dtors :{}
.rodata :{}
.data :{ *(.data) *(extabindex) *(extab) }
.bss :{}
}
}

FORCEACTIVE
{
_unresolved
_prolog
_epilog
$FORCEACTIVE
}

FORCEFILES
{
$FORCEFILES
}
16 changes: 13 additions & 3 deletions src/analysis/cfa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
40 changes: 39 additions & 1 deletion src/analysis/pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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(())
}
}
4 changes: 2 additions & 2 deletions src/analysis/slices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
25 changes: 22 additions & 3 deletions src/analysis/tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 => {
Expand Down Expand Up @@ -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);
}
}
}
}
}
Expand All @@ -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.
Expand Down Expand Up @@ -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(':') {
Expand Down
17 changes: 10 additions & 7 deletions src/analysis/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 => {
Expand Down
Loading

0 comments on commit a2374e4

Please sign in to comment.