mirror of
https://github.com/encounter/objdiff.git
synced 2025-07-03 11:45:57 +00:00
Disassemble const pool reloc
This commit is contained in:
parent
e9b8730b66
commit
609a6689a1
@ -26,21 +26,32 @@ impl ObjArch for ObjArchArm {
|
|||||||
config: &DiffObjConfig,
|
config: &DiffObjConfig,
|
||||||
) -> Result<ProcessCodeResult> {
|
) -> Result<ProcessCodeResult> {
|
||||||
let (section, symbol) = obj.section_symbol(symbol_ref);
|
let (section, symbol) = obj.section_symbol(symbol_ref);
|
||||||
let code = §ion.data
|
let mut code = §ion.data
|
||||||
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
|
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
|
||||||
|
|
||||||
let ins_count = code.len() / 4;
|
let ins_count = code.len() / 4;
|
||||||
let mut ops = Vec::<u16>::with_capacity(ins_count);
|
let mut ops = Vec::<u16>::with_capacity(ins_count);
|
||||||
let mut insts = Vec::<ObjIns>::with_capacity(ins_count);
|
let mut insts = Vec::<ObjIns>::with_capacity(ins_count);
|
||||||
for (cur_addr, mut ins) in arm::InsIter::new(code, symbol.address as u32) {
|
let mut cur_addr = symbol.address as u32;
|
||||||
let reloc = section.relocations.iter().find(|r| (r.address as u32 & !3) == cur_addr);
|
|
||||||
if let Some(reloc) = reloc {
|
|
||||||
ins.code = match reloc.flags {
|
|
||||||
RelocationFlags::Elf { r_type: elf::R_ARM_PC24 } => ins.code & !0xffffff,
|
|
||||||
_ => bail!("Unhandled relocation flags {:?}", reloc.flags),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
while code.len() >= 4 {
|
||||||
|
let bytes = [code[0], code[1], code[2], code[3]];
|
||||||
|
code = &code[4..];
|
||||||
|
let ins_code = u32::from_le_bytes(bytes);
|
||||||
|
|
||||||
|
let line = obj
|
||||||
|
.line_info
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|map| map.range(..=cur_addr as u64).last().map(|(_, &b)| b));
|
||||||
|
|
||||||
|
let reloc = section.relocations.iter().find(|r| (r.address as u32 & !3) == cur_addr);
|
||||||
|
let ins_code = mask_reloc_from_code(ins_code, reloc)?;
|
||||||
|
let is_data = is_data(reloc)?;
|
||||||
|
|
||||||
|
let (op, mnemonic, args, branch_dest) = if is_data {
|
||||||
|
(u16::MAX, ".word", vec![ObjInsArg::Reloc], None)
|
||||||
|
} else {
|
||||||
|
let ins = arm::Ins::new(ins_code);
|
||||||
let parsed_ins = arm::ParsedIns::parse(ins);
|
let parsed_ins = arm::ParsedIns::parse(ins);
|
||||||
|
|
||||||
let mut reloc_arg = None;
|
let mut reloc_arg = None;
|
||||||
@ -53,6 +64,86 @@ impl ObjArch for ObjArchArm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (args, branch_dest) = push_args(&parsed_ins, config, reloc_arg, cur_addr)?;
|
||||||
|
(ins.op as u16, parsed_ins.mnemonic, args, branch_dest)
|
||||||
|
};
|
||||||
|
|
||||||
|
ops.push(op);
|
||||||
|
insts.push(ObjIns {
|
||||||
|
address: cur_addr as u64,
|
||||||
|
size: 4,
|
||||||
|
op,
|
||||||
|
mnemonic: mnemonic.to_string(),
|
||||||
|
args,
|
||||||
|
reloc: reloc.cloned(),
|
||||||
|
branch_dest,
|
||||||
|
line,
|
||||||
|
orig: None,
|
||||||
|
});
|
||||||
|
cur_addr += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ProcessCodeResult { ops, insts })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn implcit_addend(
|
||||||
|
&self,
|
||||||
|
_section: &ObjSection,
|
||||||
|
address: u64,
|
||||||
|
reloc: &Relocation,
|
||||||
|
) -> anyhow::Result<i64> {
|
||||||
|
bail!("Unsupported ARM implicit relocation {:#x}{:?}", address, reloc.flags())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn demangle(&self, name: &str) -> Option<String> {
|
||||||
|
cpp_demangle::Symbol::new(name)
|
||||||
|
.ok()
|
||||||
|
.and_then(|s| s.demangle(&cpp_demangle::DemangleOptions::default()).ok())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn display_reloc(&self, flags: RelocationFlags) -> Cow<'static, str> {
|
||||||
|
Cow::Owned(format!("<{flags:?}>"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_data(reloc: Option<&ObjReloc>) -> Result<bool> {
|
||||||
|
if let Some(reloc) = reloc {
|
||||||
|
match reloc.flags {
|
||||||
|
RelocationFlags::Elf { r_type } => match r_type {
|
||||||
|
elf::R_ARM_PC24 | elf::R_ARM_THM_PC22 | elf::R_ARM_THM_XPC22 => Ok(false),
|
||||||
|
elf::R_ARM_ABS32 => Ok(true),
|
||||||
|
_ => bail!("Unhandled ELF relocation type {:?}", r_type),
|
||||||
|
},
|
||||||
|
_ => bail!("Unhandled relocation flags {:?}", reloc.flags),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mask_reloc_from_code(code: u32, reloc: Option<&ObjReloc>) -> Result<u32> {
|
||||||
|
if let Some(reloc) = reloc {
|
||||||
|
match reloc.flags {
|
||||||
|
RelocationFlags::Elf { r_type } => match r_type {
|
||||||
|
elf::R_ARM_PC24 => Ok(code & !0xffffff),
|
||||||
|
elf::R_ARM_ABS32 => Ok(code),
|
||||||
|
elf::R_ARM_THM_PC22 => Ok(code & !0x7ff),
|
||||||
|
elf::R_ARM_THM_XPC22 => Ok(code & !0x7ff),
|
||||||
|
_ => bail!("Unhandled ELF relocation type {:?}", r_type),
|
||||||
|
},
|
||||||
|
_ => bail!("Unhandled relocation flags {:?}", reloc.flags),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_args(
|
||||||
|
parsed_ins: &arm::ParsedIns,
|
||||||
|
config: &DiffObjConfig,
|
||||||
|
reloc_arg: Option<usize>,
|
||||||
|
cur_addr: u32,
|
||||||
|
) -> Result<(Vec<ObjInsArg>, Option<u64>)> {
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
let mut branch_dest = None;
|
let mut branch_dest = None;
|
||||||
let mut writeback = false;
|
let mut writeback = false;
|
||||||
@ -80,39 +171,30 @@ impl ObjArch for ObjArchArm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if reloc_arg == Some(i) {
|
if reloc_arg == Some(i) {
|
||||||
let reloc = reloc.unwrap();
|
args.push(ObjInsArg::Reloc);
|
||||||
push_reloc(&mut args, reloc)?;
|
|
||||||
} else {
|
} else {
|
||||||
match arg {
|
match arg {
|
||||||
arm::Argument::RegWb(reg) => {
|
arm::Argument::RegWb(reg) => {
|
||||||
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
|
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(reg.to_string().into())));
|
||||||
reg.to_string().into(),
|
|
||||||
)));
|
|
||||||
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque("!".into())));
|
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque("!".into())));
|
||||||
}
|
}
|
||||||
arm::Argument::RegDeref(reg) => {
|
arm::Argument::RegDeref(reg) => {
|
||||||
deref = true;
|
deref = true;
|
||||||
args.push(ObjInsArg::PlainText("[".into()));
|
args.push(ObjInsArg::PlainText("[".into()));
|
||||||
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
|
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(reg.to_string().into())));
|
||||||
reg.to_string().into(),
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
arm::Argument::RegDerefWb(reg) => {
|
arm::Argument::RegDerefWb(reg) => {
|
||||||
deref = true;
|
deref = true;
|
||||||
writeback = true;
|
writeback = true;
|
||||||
args.push(ObjInsArg::PlainText("[".into()));
|
args.push(ObjInsArg::PlainText("[".into()));
|
||||||
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
|
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(reg.to_string().into())));
|
||||||
reg.to_string().into(),
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
arm::Argument::RegList(reg_list) => {
|
arm::Argument::RegList(reg_list) => {
|
||||||
push_reg_list(reg_list, &mut args, config);
|
push_reg_list(reg_list, &mut args, config);
|
||||||
}
|
}
|
||||||
arm::Argument::RegListC(reg_list) => {
|
arm::Argument::RegListC(reg_list) => {
|
||||||
push_reg_list(reg_list, &mut args, config);
|
push_reg_list(reg_list, &mut args, config);
|
||||||
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
|
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque("^".to_string().into())));
|
||||||
"^".to_string().into(),
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
arm::Argument::UImm(value) | arm::Argument::CoOpcode(value) => {
|
arm::Argument::UImm(value) | arm::Argument::CoOpcode(value) => {
|
||||||
args.push(ObjInsArg::PlainText("#".into()));
|
args.push(ObjInsArg::PlainText("#".into()));
|
||||||
@ -135,12 +217,9 @@ impl ObjArch for ObjArchArm {
|
|||||||
args.push(ObjInsArg::PlainText("}".into()));
|
args.push(ObjInsArg::PlainText("}".into()));
|
||||||
}
|
}
|
||||||
arm::Argument::CoprocNum(value) => {
|
arm::Argument::CoprocNum(value) => {
|
||||||
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
|
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(format!("p{}", value).into())));
|
||||||
format!("p{}", value).into(),
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
_ => args
|
_ => args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(arg.to_string().into()))),
|
||||||
.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(arg.to_string().into()))),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,46 +229,7 @@ impl ObjArch for ObjArchArm {
|
|||||||
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque("!".into())));
|
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque("!".into())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok((args, branch_dest))
|
||||||
ops.push(ins.op as u16);
|
|
||||||
let line = obj
|
|
||||||
.line_info
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|map| map.range(..=cur_addr as u64).last().map(|(_, &b)| b));
|
|
||||||
insts.push(ObjIns {
|
|
||||||
address: cur_addr as u64,
|
|
||||||
size: 4,
|
|
||||||
op: ins.op as u16,
|
|
||||||
mnemonic: parsed_ins.mnemonic.to_string(),
|
|
||||||
args,
|
|
||||||
reloc: reloc.cloned(),
|
|
||||||
branch_dest,
|
|
||||||
line,
|
|
||||||
orig: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(ProcessCodeResult { ops, insts })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn implcit_addend(
|
|
||||||
&self,
|
|
||||||
_section: &ObjSection,
|
|
||||||
address: u64,
|
|
||||||
reloc: &Relocation,
|
|
||||||
) -> anyhow::Result<i64> {
|
|
||||||
bail!("Unsupported ARM implicit relocation {:#x}{:?}", address, reloc.flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn demangle(&self, name: &str) -> Option<String> {
|
|
||||||
cpp_demangle::Symbol::new(name)
|
|
||||||
.ok()
|
|
||||||
.and_then(|s| s.demangle(&cpp_demangle::DemangleOptions::default()).ok())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn display_reloc(&self, flags: RelocationFlags) -> Cow<'static, str> {
|
|
||||||
Cow::Owned(format!("<{flags:?}>"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_reg_list(reg_list: &u32, args: &mut Vec<ObjInsArg>, config: &DiffObjConfig) {
|
fn push_reg_list(reg_list: &u32, args: &mut Vec<ObjInsArg>, config: &DiffObjConfig) {
|
||||||
@ -208,17 +248,3 @@ fn push_reg_list(reg_list: &u32, args: &mut Vec<ObjInsArg>, config: &DiffObjConf
|
|||||||
}
|
}
|
||||||
args.push(ObjInsArg::PlainText("}".into()));
|
args.push(ObjInsArg::PlainText("}".into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_reloc(args: &mut Vec<ObjInsArg>, reloc: &ObjReloc) -> Result<()> {
|
|
||||||
match reloc.flags {
|
|
||||||
RelocationFlags::Elf { r_type } => match r_type {
|
|
||||||
elf::R_ARM_PC24 => {
|
|
||||||
args.push(ObjInsArg::Reloc);
|
|
||||||
args.push(ObjInsArg::PlainText("@pc24".into()));
|
|
||||||
}
|
|
||||||
_ => bail!("Unsupported ELF ARM relocation type {r_type}"),
|
|
||||||
},
|
|
||||||
flags => bail!("Unsupported ARM relocation kind: {flags:?}"),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user