mirror of https://github.com/encounter/objdiff.git
Options for ARM disassembly style (#78)
This commit is contained in:
parent
233839346a
commit
d9fb48853e
|
@ -4330,9 +4330,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unarm"
|
name = "unarm"
|
||||||
version = "1.3.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c6bff109f0171a299559d82a7236e056093fc0dcd2a7da86aa745f82281e2d31"
|
checksum = "379762d9433a2e6e498cde97801fb238318b024a513d0843eeac98b9056b9f3c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
|
|
|
@ -817,6 +817,12 @@ impl FunctionDiffUi {
|
||||||
mips_abi: Default::default(), // TODO
|
mips_abi: Default::default(), // TODO
|
||||||
mips_instr_category: Default::default(), // TODO
|
mips_instr_category: Default::default(), // TODO
|
||||||
arm_arch_version: 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
|
let target = self
|
||||||
.target_path
|
.target_path
|
||||||
|
|
|
@ -56,5 +56,5 @@ iced-x86 = { version = "1.21.0", default-features = false, features = ["std", "d
|
||||||
msvc-demangler = { version = "0.10.0", optional = true }
|
msvc-demangler = { version = "0.10.0", optional = true }
|
||||||
|
|
||||||
# arm
|
# arm
|
||||||
unarm = { version = "1.3.0", optional = true }
|
unarm = { version = "1.4.0", optional = true }
|
||||||
arm-attr = { version = "0.1.1", optional = true }
|
arm-attr = { version = "0.1.1", optional = true }
|
||||||
|
|
|
@ -13,12 +13,12 @@ use object::{
|
||||||
use unarm::{
|
use unarm::{
|
||||||
args::{Argument, OffsetImm, OffsetReg, Register},
|
args::{Argument, OffsetImm, OffsetReg, Register},
|
||||||
parse::{ArmVersion, ParseMode, Parser},
|
parse::{ArmVersion, ParseMode, Parser},
|
||||||
ParsedIns,
|
DisplayOptions, ParseFlags, ParsedIns, RegNames,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{ObjArch, ProcessCodeResult},
|
arch::{ObjArch, ProcessCodeResult},
|
||||||
diff::{ArmArchVersion, DiffObjConfig},
|
diff::{ArmArchVersion, ArmR9Usage, DiffObjConfig},
|
||||||
obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection},
|
obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -149,7 +149,24 @@ impl ObjArch for ObjArchArm {
|
||||||
object::Endianness::Little => unarm::Endian::Little,
|
object::Endianness::Little => unarm::Endian::Little,
|
||||||
object::Endianness::Big => unarm::Endian::Big,
|
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() {
|
while let Some((address, op, ins)) = parser.next() {
|
||||||
if let Some(next) = next_mapping {
|
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 {
|
let (args, branch_dest) = if reloc.is_some() && parser.mode == ParseMode::Data {
|
||||||
(vec![ObjInsArg::Reloc], None)
|
(vec![ObjInsArg::Reloc], None)
|
||||||
} else {
|
} else {
|
||||||
push_args(&ins, config, reloc_arg, address)?
|
push_args(&ins, config, reloc_arg, address, display_options)?
|
||||||
};
|
};
|
||||||
|
|
||||||
ops.push(op.id());
|
ops.push(op.id());
|
||||||
|
@ -200,7 +217,7 @@ impl ObjArch for ObjArchArm {
|
||||||
reloc,
|
reloc,
|
||||||
branch_dest,
|
branch_dest,
|
||||||
line,
|
line,
|
||||||
formatted: ins.to_string(),
|
formatted: ins.display(display_options).to_string(),
|
||||||
orig: None,
|
orig: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -281,6 +298,7 @@ fn push_args(
|
||||||
config: &DiffObjConfig,
|
config: &DiffObjConfig,
|
||||||
reloc_arg: Option<usize>,
|
reloc_arg: Option<usize>,
|
||||||
cur_addr: u32,
|
cur_addr: u32,
|
||||||
|
display_options: DisplayOptions,
|
||||||
) -> Result<(Vec<ObjInsArg>, Option<u64>)> {
|
) -> Result<(Vec<ObjInsArg>, Option<u64>)> {
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
let mut branch_dest = None;
|
let mut branch_dest = None;
|
||||||
|
@ -318,7 +336,9 @@ fn push_args(
|
||||||
deref = true;
|
deref = true;
|
||||||
args.push(ObjInsArg::PlainText("[".into()));
|
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.writeback {
|
||||||
if reg.deref {
|
if reg.deref {
|
||||||
writeback = true;
|
writeback = true;
|
||||||
|
@ -336,7 +356,10 @@ fn push_args(
|
||||||
args.push(ObjInsArg::PlainText(config.separator().into()));
|
args.push(ObjInsArg::PlainText(config.separator().into()));
|
||||||
}
|
}
|
||||||
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
|
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;
|
first = false;
|
||||||
}
|
}
|
||||||
|
@ -376,14 +399,16 @@ fn push_args(
|
||||||
Argument::ShiftReg(shift) => {
|
Argument::ShiftReg(shift) => {
|
||||||
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(shift.op.to_string().into())));
|
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(shift.op.to_string().into())));
|
||||||
args.push(ObjInsArg::PlainText(" ".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) => {
|
Argument::OffsetReg(offset) => {
|
||||||
if !offset.add {
|
if !offset.add {
|
||||||
args.push(ObjInsArg::PlainText("-".into()));
|
args.push(ObjInsArg::PlainText("-".into()));
|
||||||
}
|
}
|
||||||
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
|
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
|
||||||
offset.reg.to_string().into(),
|
offset.reg.display(display_options.reg_names).to_string().into(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
Argument::CpsrMode(mode) => {
|
Argument::CpsrMode(mode) => {
|
||||||
|
@ -398,9 +423,9 @@ fn push_args(
|
||||||
| Argument::StatusMask(_)
|
| Argument::StatusMask(_)
|
||||||
| Argument::Shift(_)
|
| Argument::Shift(_)
|
||||||
| Argument::CpsrFlags(_)
|
| Argument::CpsrFlags(_)
|
||||||
| Argument::Endian(_) => {
|
| Argument::Endian(_) => args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
|
||||||
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(arg.to_string().into())))
|
arg.display(display_options).to_string().into(),
|
||||||
}
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,34 @@ pub enum ArmArchVersion {
|
||||||
V6K,
|
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]
|
#[inline]
|
||||||
const fn default_true() -> bool { true }
|
const fn default_true() -> bool { true }
|
||||||
|
|
||||||
|
@ -134,6 +162,12 @@ pub struct DiffObjConfig {
|
||||||
pub mips_instr_category: MipsInstrCategory,
|
pub mips_instr_category: MipsInstrCategory,
|
||||||
// ARM
|
// ARM
|
||||||
pub arm_arch_version: ArmArchVersion,
|
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 {
|
impl Default for DiffObjConfig {
|
||||||
|
@ -146,6 +180,12 @@ impl Default for DiffObjConfig {
|
||||||
mips_abi: Default::default(),
|
mips_abi: Default::default(),
|
||||||
mips_instr_category: Default::default(),
|
mips_instr_category: Default::default(),
|
||||||
arm_arch_version: 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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ use egui::{
|
||||||
use globset::Glob;
|
use globset::Glob;
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
config::{ProjectObject, DEFAULT_WATCH_PATTERNS},
|
config::{ProjectObject, DEFAULT_WATCH_PATTERNS},
|
||||||
diff::{ArmArchVersion, MipsAbi, MipsInstrCategory, X86Formatter},
|
diff::{ArmArchVersion, ArmR9Usage, MipsAbi, MipsInstrCategory, X86Formatter},
|
||||||
};
|
};
|
||||||
use self_update::cargo_crate_version;
|
use self_update::cargo_crate_version;
|
||||||
use strum::{EnumMessage, VariantArray};
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue