Skip to content

Commit 93c049d

Browse files
committed
Add data info for superh
1 parent 39b1b49 commit 93c049d

File tree

8 files changed

+251
-67
lines changed

8 files changed

+251
-67
lines changed

objdiff-core/src/arch/arm.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ impl Arch for ArchArm {
330330
&self,
331331
resolved: ResolvedInstructionRef,
332332
diff_config: &DiffObjConfig,
333+
_code: Option<&[u8]>,
333334
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
334335
) -> Result<()> {
335336
let (ins, parsed_ins) = self.parse_ins_ref(resolved.ins_ref, resolved.code, diff_config)?;

objdiff-core/src/arch/arm64.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ impl Arch for ArchArm64 {
8080
&self,
8181
resolved: ResolvedInstructionRef,
8282
_diff_config: &DiffObjConfig,
83+
_code: Option<&[u8]>,
8384
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
8485
) -> Result<()> {
8586
let mut reader = U8Reader::new(resolved.code);

objdiff-core/src/arch/mips.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ impl Arch for ArchMips {
219219
&self,
220220
resolved: ResolvedInstructionRef,
221221
diff_config: &DiffObjConfig,
222+
_code: Option<&[u8]>,
222223
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
223224
) -> Result<()> {
224225
let instruction = self.parse_ins_ref(resolved.ins_ref, resolved.code, diff_config)?;

objdiff-core/src/arch/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ pub trait Arch: Send + Sync + Debug {
208208
) -> Result<ParsedInstruction> {
209209
let mut mnemonic = None;
210210
let mut args = Vec::with_capacity(8);
211-
self.display_instruction(resolved, diff_config, &mut |part| {
211+
self.display_instruction(resolved, diff_config, None, &mut |part| {
212212
match part {
213213
InstructionPart::Opcode(m, _) => mnemonic = Some(Cow::Owned(m.into_owned())),
214214
InstructionPart::Arg(arg) => args.push(arg.into_static()),
@@ -236,6 +236,7 @@ pub trait Arch: Send + Sync + Debug {
236236
&self,
237237
resolved: ResolvedInstructionRef,
238238
diff_config: &DiffObjConfig,
239+
code: Option<&[u8]>,
239240
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
240241
) -> Result<()>;
241242

@@ -344,6 +345,7 @@ impl Arch for ArchDummy {
344345
&self,
345346
_resolved: ResolvedInstructionRef,
346347
_diff_config: &DiffObjConfig,
348+
_code: Option<&[u8]>,
347349
_cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
348350
) -> Result<()> {
349351
Ok(())

objdiff-core/src/arch/ppc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ impl Arch for ArchPpc {
110110
&self,
111111
resolved: ResolvedInstructionRef,
112112
_diff_config: &DiffObjConfig,
113+
_code: Option<&[u8]>,
113114
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
114115
) -> Result<()> {
115116
let ins = self.parse_ins_ref(resolved)?.simplified();

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

Lines changed: 154 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ use crate::{
77
arch::{Arch, superh::disasm::sh2_disasm},
88
diff::{DiffObjConfig, display::InstructionPart},
99
obj::{
10-
InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef, ScannedInstruction,
10+
InstructionRef, Relocation, RelocationFlags, ResolvedInstructionRef, ScannedInstruction
1111
},
1212
};
1313

14+
use std::collections::HashMap;
15+
1416
pub mod disasm;
1517

1618
#[derive(Debug)]
@@ -20,6 +22,12 @@ impl ArchSuperH {
2022
pub fn new(_file: &object::File) -> Result<Self> { Ok(Self {}) }
2123
}
2224

25+
26+
struct DataInfo {
27+
address: u64,
28+
size: u32,
29+
}
30+
2331
impl Arch for ArchSuperH {
2432
fn scan_instructions(
2533
&self,
@@ -31,6 +39,7 @@ impl Arch for ArchSuperH {
3139
) -> Result<Vec<ScannedInstruction>> {
3240
let mut ops = Vec::<ScannedInstruction>::with_capacity(code.len() / 2);
3341
let mut offset = address;
42+
3443
for chunk in code.chunks_exact(2) {
3544
let opcode = u16::from_be_bytes(chunk.try_into().unwrap());
3645
let mut parts: Vec<InstructionPart> = vec![];
@@ -62,13 +71,68 @@ impl Arch for ArchSuperH {
6271
&self,
6372
resolved: ResolvedInstructionRef,
6473
_diff_config: &DiffObjConfig,
74+
_code: Option<&[u8]>,
6575
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
6676
) -> Result<()> {
6777
let opcode = u16::from_be_bytes(resolved.code.try_into().unwrap());
6878
let mut parts: Vec<InstructionPart> = vec![];
6979
let mut branch_dest: Option<u64> = None;
80+
7081
sh2_disasm(0, opcode, true, &mut parts, &resolved, &mut branch_dest);
7182

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

155219
use super::*;
156220
use crate::obj::InstructionArg;
221+
use crate::obj::Symbol;
157222

158223
impl Display for InstructionPart<'_> {
159224
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -201,6 +266,7 @@ mod test {
201266
..Default::default()
202267
},
203268
&DiffObjConfig::default(),
269+
None,
204270
&mut |part| {
205271
parts.push(part.into_static());
206272
Ok(())
@@ -279,6 +345,7 @@ mod test {
279345
..Default::default()
280346
},
281347
&DiffObjConfig::default(),
348+
None,
282349
&mut |part| {
283350
parts.push(part.into_static());
284351
Ok(())
@@ -362,6 +429,7 @@ mod test {
362429
..Default::default()
363430
},
364431
&DiffObjConfig::default(),
432+
None,
365433
&mut |part| {
366434
parts.push(part.into_static());
367435
Ok(())
@@ -399,6 +467,7 @@ mod test {
399467
..Default::default()
400468
},
401469
&DiffObjConfig::default(),
470+
None,
402471
&mut |part| {
403472
parts.push(part.into_static());
404473
Ok(())
@@ -448,6 +517,7 @@ mod test {
448517
..Default::default()
449518
},
450519
&DiffObjConfig::default(),
520+
None,
451521
&mut |part| {
452522
parts.push(part.into_static());
453523
Ok(())
@@ -484,6 +554,7 @@ mod test {
484554
..Default::default()
485555
},
486556
&DiffObjConfig::default(),
557+
None,
487558
&mut |part| {
488559
parts.push(part.into_static());
489560
Ok(())
@@ -523,6 +594,7 @@ mod test {
523594
..Default::default()
524595
},
525596
&DiffObjConfig::default(),
597+
None,
526598
&mut |part| {
527599
parts.push(part.into_static());
528600
Ok(())
@@ -562,6 +634,7 @@ mod test {
562634
..Default::default()
563635
},
564636
&DiffObjConfig::default(),
637+
None,
565638
&mut |part| {
566639
parts.push(part.into_static());
567640
Ok(())
@@ -594,6 +667,7 @@ mod test {
594667
..Default::default()
595668
},
596669
&DiffObjConfig::default(),
670+
None,
597671
&mut |part| {
598672
parts.push(part.into_static());
599673
Ok(())
@@ -623,6 +697,85 @@ mod test {
623697
..Default::default()
624698
},
625699
&DiffObjConfig::default(),
700+
None,
701+
&mut |part| {
702+
parts.push(part.into_static());
703+
Ok(())
704+
},
705+
)
706+
.unwrap();
707+
708+
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
709+
assert_eq!(joined_str, expected_str.to_string());
710+
}
711+
}
712+
713+
#[test]
714+
fn test_func_0606_f378_mov_w_data_labeling() {
715+
let arch = ArchSuperH {};
716+
let ops: &[(u16, u32, &str)] = &[(0x9000, 0x0606F378, "mov.w @(0x4, pc), r0 /* 0x00B0 */")];
717+
718+
let mut code = Vec::new();
719+
code.extend_from_slice(&0x9000_u16.to_be_bytes());
720+
code.extend_from_slice(&0x0009_u16.to_be_bytes());
721+
code.extend_from_slice(&0x00B0_u16.to_be_bytes());
722+
723+
for &(opcode, addr, expected_str) in ops {
724+
let code_slice = &code;
725+
let mut parts = Vec::new();
726+
727+
arch.display_instruction(
728+
ResolvedInstructionRef {
729+
ins_ref: InstructionRef { address: addr as u64, size: 2, opcode },
730+
code: &opcode.to_be_bytes(),
731+
symbol: &Symbol {
732+
address: 0x0606F378, // func base address
733+
..Default::default()
734+
},
735+
..Default::default()
736+
},
737+
&DiffObjConfig::default(),
738+
Some(code_slice),
739+
&mut |part| {
740+
parts.push(part.into_static());
741+
Ok(())
742+
},
743+
)
744+
.unwrap();
745+
746+
let joined_str: String = parts.iter().map(|part| format!("{}", part)).collect();
747+
assert_eq!(joined_str, expected_str.to_string());
748+
}
749+
}
750+
751+
#[test]
752+
fn test_func_0606_f378_mov_l_data_labeling() {
753+
let arch = ArchSuperH {};
754+
let ops: &[(u16, u32, &str)] =
755+
&[(0xd000, 0x0606F378, "mov.l @(0x4, pc), r0 /* 0x00B000B0 */")];
756+
757+
let mut code = Vec::new();
758+
code.extend_from_slice(&0xd000_u16.to_be_bytes());
759+
code.extend_from_slice(&0x0009_u16.to_be_bytes());
760+
code.extend_from_slice(&0x00B0_u16.to_be_bytes());
761+
code.extend_from_slice(&0x00B0_u16.to_be_bytes());
762+
763+
for &(opcode, addr, expected_str) in ops {
764+
let code_slice = &code;
765+
let mut parts = Vec::new();
766+
767+
arch.display_instruction(
768+
ResolvedInstructionRef {
769+
ins_ref: InstructionRef { address: addr as u64, size: 2, opcode },
770+
code: &opcode.to_be_bytes(),
771+
symbol: &Symbol {
772+
address: 0x0606F378, // func base address
773+
..Default::default()
774+
},
775+
..Default::default()
776+
},
777+
&DiffObjConfig::default(),
778+
Some(code_slice),
626779
&mut |part| {
627780
parts.push(part.into_static());
628781
Ok(())

objdiff-core/src/arch/x86.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ impl Arch for ArchX86 {
150150
&self,
151151
resolved: ResolvedInstructionRef,
152152
diff_config: &DiffObjConfig,
153+
_code: Option<&[u8]>,
153154
cb: &mut dyn FnMut(InstructionPart) -> Result<()>,
154155
) -> Result<()> {
155156
if resolved.ins_ref.opcode == DATA_OPCODE {
@@ -482,6 +483,7 @@ mod test {
482483
..Default::default()
483484
},
484485
&DiffObjConfig::default(),
486+
None,
485487
&mut |part| {
486488
parts.push(part.into_static());
487489
Ok(())
@@ -527,6 +529,7 @@ mod test {
527529
..Default::default()
528530
},
529531
&DiffObjConfig::default(),
532+
None,
530533
&mut |part| {
531534
parts.push(part.into_static());
532535
Ok(())
@@ -572,6 +575,7 @@ mod test {
572575
..Default::default()
573576
},
574577
&DiffObjConfig::default(),
578+
None,
575579
&mut |part| {
576580
parts.push(part.into_static());
577581
Ok(())
@@ -615,6 +619,7 @@ mod test {
615619
..Default::default()
616620
},
617621
&DiffObjConfig::default(),
622+
None,
618623
&mut |part| {
619624
parts.push(part.into_static());
620625
Ok(())
@@ -646,6 +651,7 @@ mod test {
646651
..Default::default()
647652
},
648653
&DiffObjConfig::default(),
654+
None,
649655
&mut |part| {
650656
parts.push(part.into_static());
651657
Ok(())
@@ -685,6 +691,7 @@ mod test {
685691
..Default::default()
686692
},
687693
&DiffObjConfig::default(),
694+
None,
688695
&mut |part| {
689696
parts.push(part.into_static());
690697
Ok(())
@@ -724,6 +731,7 @@ mod test {
724731
..Default::default()
725732
},
726733
&DiffObjConfig::default(),
734+
None,
727735
&mut |part| {
728736
parts.push(part.into_static());
729737
Ok(())

0 commit comments

Comments
 (0)