Skip to content

Commit 1d78224

Browse files
sozudencounter
andauthored
Add data info for superh (#198)
* Add data info for superh * fmt * Fetch symbol data dynamically from resolved.section * Remove unused var --------- Co-authored-by: Luke Street <luke@street.dev>
1 parent a1499f4 commit 1d78224

File tree

2 files changed

+153
-1
lines changed

2 files changed

+153
-1
lines changed

objdiff-core/src/arch/superh/mod.rs

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use alloc::{string::String, vec::Vec};
2+
use std::collections::HashMap;
23

34
use anyhow::{Result, bail};
45
use object::elf;
@@ -20,6 +21,11 @@ impl ArchSuperH {
2021
pub fn new(_file: &object::File) -> Result<Self> { Ok(Self {}) }
2122
}
2223

24+
struct DataInfo {
25+
address: u64,
26+
size: u32,
27+
}
28+
2329
impl Arch for ArchSuperH {
2430
fn scan_instructions(
2531
&self,
@@ -31,6 +37,7 @@ impl Arch for ArchSuperH {
3137
) -> Result<Vec<ScannedInstruction>> {
3238
let mut ops = Vec::<ScannedInstruction>::with_capacity(code.len() / 2);
3339
let mut offset = address;
40+
3441
for chunk in code.chunks_exact(2) {
3542
let opcode = u16::from_be_bytes(chunk.try_into().unwrap());
3643
let mut parts: Vec<InstructionPart> = vec![];
@@ -67,8 +74,60 @@ impl Arch for ArchSuperH {
6774
let opcode = u16::from_be_bytes(resolved.code.try_into().unwrap());
6875
let mut parts: Vec<InstructionPart> = vec![];
6976
let mut branch_dest: Option<u64> = None;
77+
7078
sh2_disasm(0, opcode, true, &mut parts, &resolved, &mut branch_dest);
7179

80+
if let Some(symbol_data) = resolved.section.symbol_data(resolved.symbol) {
81+
// scan for data
82+
// map of instruction offsets to data target offsets
83+
let mut data_offsets: HashMap<u64, DataInfo> = HashMap::<u64, DataInfo>::new();
84+
85+
let mut pos: u64 = 0;
86+
for chunk in symbol_data.chunks_exact(2) {
87+
let opcode = u16::from_be_bytes(chunk.try_into().unwrap());
88+
// mov.w
89+
if (opcode & 0xf000) == 0x9000 {
90+
let target = (opcode as u64 & 0xff) * 2 + 4 + pos;
91+
let data_info = DataInfo { address: target, size: 2 };
92+
data_offsets.insert(pos, data_info);
93+
}
94+
// mov.l
95+
else if (opcode & 0xf000) == 0xd000 {
96+
let target = ((opcode as u64 & 0xff) * 4 + 4 + pos) & 0xfffffffc;
97+
let data_info = DataInfo { address: target, size: 4 };
98+
data_offsets.insert(pos, data_info);
99+
}
100+
pos += 2;
101+
}
102+
103+
let pos = resolved.ins_ref.address - resolved.symbol.address;
104+
105+
// add the data info
106+
if let Some(value) = data_offsets.get(&pos) {
107+
if value.size == 2 && value.address as usize + 1 < symbol_data.len() {
108+
let data = u16::from_be_bytes(
109+
symbol_data[value.address as usize..value.address as usize + 2]
110+
.try_into()
111+
.unwrap(),
112+
);
113+
parts.push(InstructionPart::basic(" /* "));
114+
parts.push(InstructionPart::basic("0x"));
115+
parts.push(InstructionPart::basic(format!("{:04X}", data)));
116+
parts.push(InstructionPart::basic(" */"));
117+
} else if value.size == 4 && value.address as usize + 3 < symbol_data.len() {
118+
let data = u32::from_be_bytes(
119+
symbol_data[value.address as usize..value.address as usize + 4]
120+
.try_into()
121+
.unwrap(),
122+
);
123+
parts.push(InstructionPart::basic(" /* "));
124+
parts.push(InstructionPart::basic("0x"));
125+
parts.push(InstructionPart::basic(format!("{:08X}", data)));
126+
parts.push(InstructionPart::basic(" */"));
127+
}
128+
}
129+
}
130+
72131
for part in parts {
73132
cb(part)?;
74133
}
@@ -153,7 +212,7 @@ mod test {
153212
use std::fmt::{self, Display};
154213

155214
use super::*;
156-
use crate::obj::InstructionArg;
215+
use crate::obj::{InstructionArg, Section, SectionData, Symbol};
157216

158217
impl Display for InstructionPart<'_> {
159218
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -634,4 +693,92 @@ mod test {
634693
assert_eq!(joined_str, expected_str.to_string());
635694
}
636695
}
696+
697+
#[test]
698+
fn test_func_0606_f378_mov_w_data_labeling() {
699+
let arch = ArchSuperH {};
700+
let ops: &[(u16, u32, &str)] = &[(0x9000, 0x0606F378, "mov.w @(0x4, pc), r0 /* 0x00B0 */")];
701+
702+
let mut code = Vec::new();
703+
code.extend_from_slice(&0x9000_u16.to_be_bytes());
704+
code.extend_from_slice(&0x0009_u16.to_be_bytes());
705+
code.extend_from_slice(&0x00B0_u16.to_be_bytes());
706+
707+
for &(opcode, addr, expected_str) in ops {
708+
let mut parts = Vec::new();
709+
710+
arch.display_instruction(
711+
ResolvedInstructionRef {
712+
ins_ref: InstructionRef { address: addr as u64, size: 2, opcode },
713+
code: &opcode.to_be_bytes(),
714+
symbol: &Symbol {
715+
address: 0x0606F378, // func base address
716+
size: code.len() as u64,
717+
..Default::default()
718+
},
719+
section: &Section {
720+
address: 0x0606F378,
721+
size: code.len() as u64,
722+
data: SectionData(code.clone()),
723+
..Default::default()
724+
},
725+
..Default::default()
726+
},
727+
&DiffObjConfig::default(),
728+
&mut |part| {
729+
parts.push(part.into_static());
730+
Ok(())
731+
},
732+
)
733+
.unwrap();
734+
735+
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
736+
assert_eq!(joined_str, expected_str.to_string());
737+
}
738+
}
739+
740+
#[test]
741+
fn test_func_0606_f378_mov_l_data_labeling() {
742+
let arch = ArchSuperH {};
743+
let ops: &[(u16, u32, &str)] =
744+
&[(0xd000, 0x0606F378, "mov.l @(0x4, pc), r0 /* 0x00B000B0 */")];
745+
746+
let mut code = Vec::new();
747+
code.extend_from_slice(&0xd000_u16.to_be_bytes());
748+
code.extend_from_slice(&0x0009_u16.to_be_bytes());
749+
code.extend_from_slice(&0x00B0_u16.to_be_bytes());
750+
code.extend_from_slice(&0x00B0_u16.to_be_bytes());
751+
752+
for &(opcode, addr, expected_str) in ops {
753+
let mut parts = Vec::new();
754+
755+
arch.display_instruction(
756+
ResolvedInstructionRef {
757+
ins_ref: InstructionRef { address: addr as u64, size: 2, opcode },
758+
code: &opcode.to_be_bytes(),
759+
symbol: &Symbol {
760+
address: 0x0606F378, // func base address
761+
size: code.len() as u64,
762+
..Default::default()
763+
},
764+
section: &Section {
765+
address: 0x0606F378,
766+
size: code.len() as u64,
767+
data: SectionData(code.clone()),
768+
..Default::default()
769+
},
770+
..Default::default()
771+
},
772+
&DiffObjConfig::default(),
773+
&mut |part| {
774+
parts.push(part.into_static());
775+
Ok(())
776+
},
777+
)
778+
.unwrap();
779+
780+
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
781+
assert_eq!(joined_str, expected_str.to_string());
782+
}
783+
}
637784
}

objdiff-core/src/obj/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ impl Section {
109109
}
110110
}
111111

112+
pub fn symbol_data(&self, symbol: &Symbol) -> Option<&[u8]> {
113+
let offset = symbol.address.checked_sub(self.address)?;
114+
self.data.get(offset as usize..offset as usize + symbol.size as usize)
115+
}
116+
112117
// The alignment to use when "Combine data/text sections" is enabled.
113118
pub fn combined_alignment(&self) -> u64 {
114119
const MIN_ALIGNMENT: u64 = 4;

0 commit comments

Comments
 (0)