Options for ARM disassembly style (#78)

This commit is contained in:
Aetias 2024-07-15 00:00:57 +02:00 committed by GitHub
parent 233839346a
commit d9fb48853e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 134 additions and 16 deletions

4
Cargo.lock generated
View File

@ -4330,9 +4330,9 @@ dependencies = [
[[package]]
name = "unarm"
version = "1.3.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6bff109f0171a299559d82a7236e056093fc0dcd2a7da86aa745f82281e2d31"
checksum = "379762d9433a2e6e498cde97801fb238318b024a513d0843eeac98b9056b9f3c"
[[package]]
name = "unicase"

View File

@ -817,6 +817,12 @@ impl FunctionDiffUi {
mips_abi: Default::default(), // TODO
mips_instr_category: Default::default(), // TODO
arm_arch_version: Default::default(), // TODO
arm_unified_syntax: true, // TODO
arm_av_registers: false, // TODO
arm_r9_usage: Default::default(), // TODO
arm_sl_usage: false, // TODO
arm_fp_usage: false, // TODO
arm_ip_usage: false, // TODO
};
let target = self
.target_path

View File

@ -56,5 +56,5 @@ iced-x86 = { version = "1.21.0", default-features = false, features = ["std", "d
msvc-demangler = { version = "0.10.0", optional = true }
# arm
unarm = { version = "1.3.0", optional = true }
unarm = { version = "1.4.0", optional = true }
arm-attr = { version = "0.1.1", optional = true }

View File

@ -13,12 +13,12 @@ use object::{
use unarm::{
args::{Argument, OffsetImm, OffsetReg, Register},
parse::{ArmVersion, ParseMode, Parser},
ParsedIns,
DisplayOptions, ParseFlags, ParsedIns, RegNames,
};
use crate::{
arch::{ObjArch, ProcessCodeResult},
diff::{ArmArchVersion, DiffObjConfig},
diff::{ArmArchVersion, ArmR9Usage, DiffObjConfig},
obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection},
};
@ -149,7 +149,24 @@ impl ObjArch for ObjArchArm {
object::Endianness::Little => unarm::Endian::Little,
object::Endianness::Big => unarm::Endian::Big,
};
let mut parser = Parser::new(version, first_mapping, start_addr, endian, code);
let parse_flags = ParseFlags { ual: config.arm_unified_syntax };
let mut parser = Parser::new(version, first_mapping, start_addr, endian, parse_flags, code);
let display_options = DisplayOptions {
reg_names: RegNames {
av_registers: config.arm_av_registers,
r9_use: match config.arm_r9_usage {
ArmR9Usage::GeneralPurpose => unarm::R9Use::GeneralPurpose,
ArmR9Usage::Sb => unarm::R9Use::Pid,
ArmR9Usage::Tr => unarm::R9Use::Tls,
},
explicit_stack_limit: config.arm_sl_usage,
frame_pointer: config.arm_fp_usage,
ip: config.arm_ip_usage,
},
};
while let Some((address, op, ins)) = parser.next() {
if let Some(next) = next_mapping {
@ -187,7 +204,7 @@ impl ObjArch for ObjArchArm {
let (args, branch_dest) = if reloc.is_some() && parser.mode == ParseMode::Data {
(vec![ObjInsArg::Reloc], None)
} else {
push_args(&ins, config, reloc_arg, address)?
push_args(&ins, config, reloc_arg, address, display_options)?
};
ops.push(op.id());
@ -200,7 +217,7 @@ impl ObjArch for ObjArchArm {
reloc,
branch_dest,
line,
formatted: ins.to_string(),
formatted: ins.display(display_options).to_string(),
orig: None,
});
}
@ -281,6 +298,7 @@ fn push_args(
config: &DiffObjConfig,
reloc_arg: Option<usize>,
cur_addr: u32,
display_options: DisplayOptions,
) -> Result<(Vec<ObjInsArg>, Option<u64>)> {
let mut args = vec![];
let mut branch_dest = None;
@ -318,7 +336,9 @@ fn push_args(
deref = true;
args.push(ObjInsArg::PlainText("[".into()));
}
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(reg.reg.to_string().into())));
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
reg.reg.display(display_options.reg_names).to_string().into(),
)));
if reg.writeback {
if reg.deref {
writeback = true;
@ -336,7 +356,10 @@ fn push_args(
args.push(ObjInsArg::PlainText(config.separator().into()));
}
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
Register::parse(i).to_string().into(),
Register::parse(i)
.display(display_options.reg_names)
.to_string()
.into(),
)));
first = false;
}
@ -376,14 +399,16 @@ fn push_args(
Argument::ShiftReg(shift) => {
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(shift.op.to_string().into())));
args.push(ObjInsArg::PlainText(" ".into()));
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(shift.reg.to_string().into())));
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
shift.reg.display(display_options.reg_names).to_string().into(),
)));
}
Argument::OffsetReg(offset) => {
if !offset.add {
args.push(ObjInsArg::PlainText("-".into()));
}
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
offset.reg.to_string().into(),
offset.reg.display(display_options.reg_names).to_string().into(),
)));
}
Argument::CpsrMode(mode) => {
@ -398,9 +423,9 @@ fn push_args(
| Argument::StatusMask(_)
| Argument::Shift(_)
| Argument::CpsrFlags(_)
| Argument::Endian(_) => {
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(arg.to_string().into())))
}
| Argument::Endian(_) => args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
arg.display(display_options).to_string().into(),
))),
}
}
}

View File

@ -117,6 +117,34 @@ pub enum ArmArchVersion {
V6K,
}
#[derive(
Debug,
Copy,
Clone,
Default,
Eq,
PartialEq,
serde::Deserialize,
serde::Serialize,
strum::VariantArray,
strum::EnumMessage,
)]
pub enum ArmR9Usage {
#[default]
#[strum(
message = "R9 or V6 (default)",
detailed_message = "Use R9 as a general-purpose register."
)]
GeneralPurpose,
#[strum(
message = "SB (static base)",
detailed_message = "Used for position-independent data (PID)."
)]
Sb,
#[strum(message = "TR (TLS register)", detailed_message = "Used for thread-local storage.")]
Tr,
}
#[inline]
const fn default_true() -> bool { true }
@ -134,6 +162,12 @@ pub struct DiffObjConfig {
pub mips_instr_category: MipsInstrCategory,
// ARM
pub arm_arch_version: ArmArchVersion,
pub arm_unified_syntax: bool,
pub arm_av_registers: bool,
pub arm_r9_usage: ArmR9Usage,
pub arm_sl_usage: bool,
pub arm_fp_usage: bool,
pub arm_ip_usage: bool,
}
impl Default for DiffObjConfig {
@ -146,6 +180,12 @@ impl Default for DiffObjConfig {
mips_abi: Default::default(),
mips_instr_category: Default::default(),
arm_arch_version: Default::default(),
arm_unified_syntax: true,
arm_av_registers: false,
arm_r9_usage: Default::default(),
arm_sl_usage: false,
arm_fp_usage: false,
arm_ip_usage: false,
}
}
}

View File

@ -16,7 +16,7 @@ use egui::{
use globset::Glob;
use objdiff_core::{
config::{ProjectObject, DEFAULT_WATCH_PATTERNS},
diff::{ArmArchVersion, MipsAbi, MipsInstrCategory, X86Formatter},
diff::{ArmArchVersion, ArmR9Usage, MipsAbi, MipsInstrCategory, X86Formatter},
};
use self_update::cargo_crate_version;
use strum::{EnumMessage, VariantArray};
@ -925,4 +925,51 @@ fn arch_config_ui(ui: &mut egui::Ui, config: &mut AppConfig, _appearance: &Appea
}
}
});
let response = ui
.checkbox(&mut config.diff_obj_config.arm_unified_syntax, "Unified syntax")
.on_hover_text("Disassemble as unified assembly language (UAL).");
if response.changed() {
config.queue_reload = true;
}
let response = ui
.checkbox(&mut config.diff_obj_config.arm_av_registers, "Use A/V registers")
.on_hover_text("Display R0-R3 as A1-A4 and R4-R11 as V1-V8");
if response.changed() {
config.queue_reload = true;
}
egui::ComboBox::new("arm_r9_usage", "Display R9 as")
.selected_text(config.diff_obj_config.arm_r9_usage.get_message().unwrap())
.show_ui(ui, |ui| {
for &usage in ArmR9Usage::VARIANTS {
if ui
.selectable_label(
config.diff_obj_config.arm_r9_usage == usage,
usage.get_message().unwrap(),
)
.on_hover_text(usage.get_detailed_message().unwrap())
.clicked()
{
config.diff_obj_config.arm_r9_usage = usage;
config.queue_reload = true;
}
}
});
let response = ui
.checkbox(&mut config.diff_obj_config.arm_sl_usage, "Display R10 as SL")
.on_hover_text("Used for explicit stack limits.");
if response.changed() {
config.queue_reload = true;
}
let response = ui
.checkbox(&mut config.diff_obj_config.arm_fp_usage, "Display R11 as FP")
.on_hover_text("Used for frame pointers.");
if response.changed() {
config.queue_reload = true;
}
let response = ui
.checkbox(&mut config.diff_obj_config.arm_ip_usage, "Display R12 as IP")
.on_hover_text("Used for interworking and long branches.");
if response.changed() {
config.queue_reload = true;
}
}