From fd5ac733d746617b5ea971b4821c017319f79ca0 Mon Sep 17 00:00:00 2001 From: InusualZ Date: Wed, 1 Jun 2022 20:48:02 -0400 Subject: [PATCH 1/4] dol: implement helpers for virtual reads into the dol Co-authored-by: Richard Patel --- dol/src/lib.rs | 54 ++++++++++++++++++++++++++++++++++++++---- flow-graph/src/main.rs | 3 ++- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/dol/src/lib.rs b/dol/src/lib.rs index 4d53b44..890d322 100644 --- a/dol/src/lib.rs +++ b/dol/src/lib.rs @@ -24,6 +24,8 @@ pub enum Error { OverlappingSections(u32, u32), #[error("Section sizes too large")] SectionsTooLarge, + #[error("Attempted to access {0:08X} past DOL bounds")] + OutOfBounds(u32), } impl From for Error { @@ -107,11 +109,38 @@ impl Dol { }) } - /// Reads bytes into a destination buffer given a virtual address. - pub fn virtual_read(&self, dest: &mut [u8], virtual_addr: u32) { + pub fn section_data(&self, section: &DolSection) -> &[u8] { + self.virtual_data_at(section.target, section.size).unwrap() + } + + /// Returns a slice of DOL data. Does not support bss. + pub fn virtual_data_at(&self, virtual_addr: u32, read_len: u32) -> Result<&[u8]> { + if virtual_addr < self.memory_offset { + return Err(Error::OutOfBounds(virtual_addr)); + } + let offset = (virtual_addr - self.memory_offset) as usize; - // TODO Gracefully handle errors. - dest.copy_from_slice(&self.memory[offset..offset + dest.len()]) + if offset + (read_len as usize) < self.memory.len() { + Ok(&self.memory[offset..offset + (read_len as usize)]) + } else { + Err(Error::OutOfBounds(virtual_addr + read_len)) + } + } + + /// Reads bytes into a destination buffer given a virtual address. + pub fn virtual_read(&self, data: &mut [u8], virtual_addr: u32) -> Result<()> { + if virtual_addr < self.memory_offset { + return Err(Error::OutOfBounds(virtual_addr)); + } + + let offset = (virtual_addr - self.memory_offset) as usize; + let read_len = data.len(); + if offset + read_len < self.memory.len() { + data.copy_from_slice(&self.memory[offset..offset + data.len()]); + Ok(()) + } else { + Err(Error::OutOfBounds(virtual_addr + (read_len as u32))) + } } } @@ -132,6 +161,7 @@ pub struct DolSection { pub struct DolHeader { pub sections: Vec, + pub entry_point: u32, } impl From<&DolHeaderData> for DolHeader { @@ -159,7 +189,21 @@ impl From<&DolHeaderData> for DolHeader { } // Sort sections by target address to prepare them for mapping. sections.sort_by_key(|s| s.target); - Self { sections } + Self { + sections, + entry_point: header.entry_point, + } + } +} + +impl DolHeader { + pub fn section_at(&self, addr: u32) -> Option<&DolSection> { + for section in &self.sections { + if (section.target..(section.target + section.size)).contains(&addr) { + return Some(section); + } + } + None } } diff --git a/flow-graph/src/main.rs b/flow-graph/src/main.rs index de2c5cd..5f27efa 100644 --- a/flow-graph/src/main.rs +++ b/flow-graph/src/main.rs @@ -44,7 +44,8 @@ fn main() { let dol = Dol::read_from(&dol_file).expect("Invalid DOL file"); drop(dol_file); let mut bytes = vec![0u8; (stop_addr - start_addr) as usize]; - dol.virtual_read(&mut bytes, start_addr); + dol.virtual_read(&mut bytes, start_addr) + .expect("Invalid address range"); // Create control flow graph. let ins_list: Vec = disasm_iter(&bytes, start_addr).collect(); From 2de9ecc8440aa77814e08dbd0332270375b17590 Mon Sep 17 00:00:00 2001 From: InusualZ Date: Wed, 1 Jun 2022 20:51:03 -0400 Subject: [PATCH 2/4] dol: add and use new `DolSectionType::Text` --- dol/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dol/src/lib.rs b/dol/src/lib.rs index 890d322..94059b2 100644 --- a/dol/src/lib.rs +++ b/dol/src/lib.rs @@ -146,6 +146,7 @@ impl Dol { #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum DolSectionType { + Text, Data, Bss, } @@ -168,9 +169,15 @@ impl From<&DolHeaderData> for DolHeader { fn from(header: &DolHeaderData) -> Self { let mut sections = Vec::with_capacity(DolHeaderData::SECTION_COUNT); for i in 0..DolHeaderData::SECTION_COUNT { + let kind = if i < 7 { + DolSectionType::Text + } else { + DolSectionType::Data + }; + if header.section_sizes[i] > 0 { sections.push(DolSection { - kind: DolSectionType::Data, + kind, index: i, offset: header.section_offsets[i], target: header.section_targets[i], From d23fb912b8a7034264be6b1b5fdfd1d113c87beb Mon Sep 17 00:00:00 2001 From: InusualZ Date: Wed, 8 Jun 2022 20:53:31 -0400 Subject: [PATCH 3/4] disasm: fix failing tests --- disasm/tests/test_disasm.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/disasm/tests/test_disasm.rs b/disasm/tests/test_disasm.rs index e0df349..210cd81 100644 --- a/disasm/tests/test_disasm.rs +++ b/disasm/tests/test_disasm.rs @@ -498,7 +498,7 @@ fn test_ins_mfmsr() { #[test] fn test_ins_mfspr() { - assert_asm!(0x7E1A02A6, "mfspr r16, 832"); + assert_asm!(0x7E1A02A6, "mfspr r16, 26"); } #[test] @@ -508,7 +508,7 @@ fn test_ins_mfsr() { #[test] fn test_ins_mftb() { - assert_asm!(0x7C8C42E6, "mftb r4, 392"); + assert_asm!(0x7C8C42E6, "mftb r4, 268"); } #[test] @@ -539,7 +539,7 @@ fn test_ins_mtmsr() { #[test] fn test_ins_mtspr() { - assert_asm!(0x7E75FBA6, "mtspr 703, r19"); + assert_asm!(0x7E75FBA6, "mtspr 1013, r19"); } #[test] From 65a68166b6c7aa01f0d37faecc557b27bb5a81ca Mon Sep 17 00:00:00 2001 From: Richard Patel Date: Thu, 9 Jun 2022 07:30:08 +0200 Subject: [PATCH 4/4] cargo fmt --- disasm/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/disasm/src/lib.rs b/disasm/src/lib.rs index aa55169..856978b 100644 --- a/disasm/src/lib.rs +++ b/disasm/src/lib.rs @@ -298,7 +298,10 @@ impl Ins { } pub fn is_branch(&self) -> bool { - matches!(self.op, Opcode::B | Opcode::Bc | Opcode::Bcctr | Opcode::Bclr) + matches!( + self.op, + Opcode::B | Opcode::Bc | Opcode::Bcctr | Opcode::Bclr + ) } pub fn is_direct_branch(&self) -> bool {