Skip to content

Commit d9fb488

Browse files
authored
Options for ARM disassembly style (#78)
1 parent 2338393 commit d9fb488

File tree

6 files changed

+134
-16
lines changed

6 files changed

+134
-16
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

objdiff-cli/src/cmd/diff.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,12 @@ impl FunctionDiffUi {
817817
mips_abi: Default::default(), // TODO
818818
mips_instr_category: Default::default(), // TODO
819819
arm_arch_version: Default::default(), // TODO
820+
arm_unified_syntax: true, // TODO
821+
arm_av_registers: false, // TODO
822+
arm_r9_usage: Default::default(), // TODO
823+
arm_sl_usage: false, // TODO
824+
arm_fp_usage: false, // TODO
825+
arm_ip_usage: false, // TODO
820826
};
821827
let target = self
822828
.target_path

objdiff-core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,5 @@ iced-x86 = { version = "1.21.0", default-features = false, features = ["std", "d
5656
msvc-demangler = { version = "0.10.0", optional = true }
5757

5858
# arm
59-
unarm = { version = "1.3.0", optional = true }
59+
unarm = { version = "1.4.0", optional = true }
6060
arm-attr = { version = "0.1.1", optional = true }

objdiff-core/src/arch/arm.rs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ use object::{
1313
use unarm::{
1414
args::{Argument, OffsetImm, OffsetReg, Register},
1515
parse::{ArmVersion, ParseMode, Parser},
16-
ParsedIns,
16+
DisplayOptions, ParseFlags, ParsedIns, RegNames,
1717
};
1818

1919
use crate::{
2020
arch::{ObjArch, ProcessCodeResult},
21-
diff::{ArmArchVersion, DiffObjConfig},
21+
diff::{ArmArchVersion, ArmR9Usage, DiffObjConfig},
2222
obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection},
2323
};
2424

@@ -149,7 +149,24 @@ impl ObjArch for ObjArchArm {
149149
object::Endianness::Little => unarm::Endian::Little,
150150
object::Endianness::Big => unarm::Endian::Big,
151151
};
152-
let mut parser = Parser::new(version, first_mapping, start_addr, endian, code);
152+
153+
let parse_flags = ParseFlags { ual: config.arm_unified_syntax };
154+
155+
let mut parser = Parser::new(version, first_mapping, start_addr, endian, parse_flags, code);
156+
157+
let display_options = DisplayOptions {
158+
reg_names: RegNames {
159+
av_registers: config.arm_av_registers,
160+
r9_use: match config.arm_r9_usage {
161+
ArmR9Usage::GeneralPurpose => unarm::R9Use::GeneralPurpose,
162+
ArmR9Usage::Sb => unarm::R9Use::Pid,
163+
ArmR9Usage::Tr => unarm::R9Use::Tls,
164+
},
165+
explicit_stack_limit: config.arm_sl_usage,
166+
frame_pointer: config.arm_fp_usage,
167+
ip: config.arm_ip_usage,
168+
},
169+
};
153170

154171
while let Some((address, op, ins)) = parser.next() {
155172
if let Some(next) = next_mapping {
@@ -187,7 +204,7 @@ impl ObjArch for ObjArchArm {
187204
let (args, branch_dest) = if reloc.is_some() && parser.mode == ParseMode::Data {
188205
(vec![ObjInsArg::Reloc], None)
189206
} else {
190-
push_args(&ins, config, reloc_arg, address)?
207+
push_args(&ins, config, reloc_arg, address, display_options)?
191208
};
192209

193210
ops.push(op.id());
@@ -200,7 +217,7 @@ impl ObjArch for ObjArchArm {
200217
reloc,
201218
branch_dest,
202219
line,
203-
formatted: ins.to_string(),
220+
formatted: ins.display(display_options).to_string(),
204221
orig: None,
205222
});
206223
}
@@ -281,6 +298,7 @@ fn push_args(
281298
config: &DiffObjConfig,
282299
reloc_arg: Option<usize>,
283300
cur_addr: u32,
301+
display_options: DisplayOptions,
284302
) -> Result<(Vec<ObjInsArg>, Option<u64>)> {
285303
let mut args = vec![];
286304
let mut branch_dest = None;
@@ -318,7 +336,9 @@ fn push_args(
318336
deref = true;
319337
args.push(ObjInsArg::PlainText("[".into()));
320338
}
321-
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(reg.reg.to_string().into())));
339+
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
340+
reg.reg.display(display_options.reg_names).to_string().into(),
341+
)));
322342
if reg.writeback {
323343
if reg.deref {
324344
writeback = true;
@@ -336,7 +356,10 @@ fn push_args(
336356
args.push(ObjInsArg::PlainText(config.separator().into()));
337357
}
338358
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
339-
Register::parse(i).to_string().into(),
359+
Register::parse(i)
360+
.display(display_options.reg_names)
361+
.to_string()
362+
.into(),
340363
)));
341364
first = false;
342365
}
@@ -376,14 +399,16 @@ fn push_args(
376399
Argument::ShiftReg(shift) => {
377400
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(shift.op.to_string().into())));
378401
args.push(ObjInsArg::PlainText(" ".into()));
379-
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(shift.reg.to_string().into())));
402+
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
403+
shift.reg.display(display_options.reg_names).to_string().into(),
404+
)));
380405
}
381406
Argument::OffsetReg(offset) => {
382407
if !offset.add {
383408
args.push(ObjInsArg::PlainText("-".into()));
384409
}
385410
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
386-
offset.reg.to_string().into(),
411+
offset.reg.display(display_options.reg_names).to_string().into(),
387412
)));
388413
}
389414
Argument::CpsrMode(mode) => {
@@ -398,9 +423,9 @@ fn push_args(
398423
| Argument::StatusMask(_)
399424
| Argument::Shift(_)
400425
| Argument::CpsrFlags(_)
401-
| Argument::Endian(_) => {
402-
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(arg.to_string().into())))
403-
}
426+
| Argument::Endian(_) => args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
427+
arg.display(display_options).to_string().into(),
428+
))),
404429
}
405430
}
406431
}

objdiff-core/src/diff/mod.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,34 @@ pub enum ArmArchVersion {
117117
V6K,
118118
}
119119

120+
#[derive(
121+
Debug,
122+
Copy,
123+
Clone,
124+
Default,
125+
Eq,
126+
PartialEq,
127+
serde::Deserialize,
128+
serde::Serialize,
129+
strum::VariantArray,
130+
strum::EnumMessage,
131+
)]
132+
pub enum ArmR9Usage {
133+
#[default]
134+
#[strum(
135+
message = "R9 or V6 (default)",
136+
detailed_message = "Use R9 as a general-purpose register."
137+
)]
138+
GeneralPurpose,
139+
#[strum(
140+
message = "SB (static base)",
141+
detailed_message = "Used for position-independent data (PID)."
142+
)]
143+
Sb,
144+
#[strum(message = "TR (TLS register)", detailed_message = "Used for thread-local storage.")]
145+
Tr,
146+
}
147+
120148
#[inline]
121149
const fn default_true() -> bool { true }
122150

@@ -134,6 +162,12 @@ pub struct DiffObjConfig {
134162
pub mips_instr_category: MipsInstrCategory,
135163
// ARM
136164
pub arm_arch_version: ArmArchVersion,
165+
pub arm_unified_syntax: bool,
166+
pub arm_av_registers: bool,
167+
pub arm_r9_usage: ArmR9Usage,
168+
pub arm_sl_usage: bool,
169+
pub arm_fp_usage: bool,
170+
pub arm_ip_usage: bool,
137171
}
138172

139173
impl Default for DiffObjConfig {
@@ -146,6 +180,12 @@ impl Default for DiffObjConfig {
146180
mips_abi: Default::default(),
147181
mips_instr_category: Default::default(),
148182
arm_arch_version: Default::default(),
183+
arm_unified_syntax: true,
184+
arm_av_registers: false,
185+
arm_r9_usage: Default::default(),
186+
arm_sl_usage: false,
187+
arm_fp_usage: false,
188+
arm_ip_usage: false,
149189
}
150190
}
151191
}

objdiff-gui/src/views/config.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use egui::{
1616
use globset::Glob;
1717
use objdiff_core::{
1818
config::{ProjectObject, DEFAULT_WATCH_PATTERNS},
19-
diff::{ArmArchVersion, MipsAbi, MipsInstrCategory, X86Formatter},
19+
diff::{ArmArchVersion, ArmR9Usage, MipsAbi, MipsInstrCategory, X86Formatter},
2020
};
2121
use self_update::cargo_crate_version;
2222
use strum::{EnumMessage, VariantArray};
@@ -925,4 +925,51 @@ fn arch_config_ui(ui: &mut egui::Ui, config: &mut AppConfig, _appearance: &Appea
925925
}
926926
}
927927
});
928+
let response = ui
929+
.checkbox(&mut config.diff_obj_config.arm_unified_syntax, "Unified syntax")
930+
.on_hover_text("Disassemble as unified assembly language (UAL).");
931+
if response.changed() {
932+
config.queue_reload = true;
933+
}
934+
let response = ui
935+
.checkbox(&mut config.diff_obj_config.arm_av_registers, "Use A/V registers")
936+
.on_hover_text("Display R0-R3 as A1-A4 and R4-R11 as V1-V8");
937+
if response.changed() {
938+
config.queue_reload = true;
939+
}
940+
egui::ComboBox::new("arm_r9_usage", "Display R9 as")
941+
.selected_text(config.diff_obj_config.arm_r9_usage.get_message().unwrap())
942+
.show_ui(ui, |ui| {
943+
for &usage in ArmR9Usage::VARIANTS {
944+
if ui
945+
.selectable_label(
946+
config.diff_obj_config.arm_r9_usage == usage,
947+
usage.get_message().unwrap(),
948+
)
949+
.on_hover_text(usage.get_detailed_message().unwrap())
950+
.clicked()
951+
{
952+
config.diff_obj_config.arm_r9_usage = usage;
953+
config.queue_reload = true;
954+
}
955+
}
956+
});
957+
let response = ui
958+
.checkbox(&mut config.diff_obj_config.arm_sl_usage, "Display R10 as SL")
959+
.on_hover_text("Used for explicit stack limits.");
960+
if response.changed() {
961+
config.queue_reload = true;
962+
}
963+
let response = ui
964+
.checkbox(&mut config.diff_obj_config.arm_fp_usage, "Display R11 as FP")
965+
.on_hover_text("Used for frame pointers.");
966+
if response.changed() {
967+
config.queue_reload = true;
968+
}
969+
let response = ui
970+
.checkbox(&mut config.diff_obj_config.arm_ip_usage, "Display R12 as IP")
971+
.on_hover_text("Used for interworking and long branches.");
972+
if response.changed() {
973+
config.queue_reload = true;
974+
}
928975
}

0 commit comments

Comments
 (0)