dol: implement helpers for virtual reads into the dol
Co-authored-by: Richard Patel <me@terorie.dev>
This commit is contained in:
parent
619c935dc4
commit
fd5ac733d7
|
@ -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<bincode::Error> 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<DolSection>,
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Ins> = disasm_iter(&bytes, start_addr).collect();
|
||||
|
|
Loading…
Reference in New Issue