Disassemble const pool reloc

This commit is contained in:
Aetias 2024-05-17 18:09:02 +02:00
parent e9b8730b66
commit 609a6689a1

View File

@ -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 = &section.data let mut code = &section.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(())
}