Update ppc750cl, add Itanium demangler & cleanup

This commit is contained in:
2024-03-21 21:36:23 -06:00
parent e7991cb28d
commit 30d14870ef
17 changed files with 198 additions and 237 deletions

View File

@@ -1,4 +1,4 @@
use std::{borrow::Cow, collections::BTreeMap};
use std::borrow::Cow;
use anyhow::{bail, Result};
use object::{elf, Endian, Endianness, File, Object, Relocation, RelocationFlags};
@@ -7,7 +7,7 @@ use rabbitizer::{config, Abi, InstrCategory, Instruction, OperandType};
use crate::{
arch::{ObjArch, ProcessCodeResult},
diff::DiffObjConfig,
obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection},
obj::{ObjInfo, ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection, SymbolRef},
};
fn configure_rabbitizer() {
@@ -21,27 +21,31 @@ pub struct ObjArchMips {
}
impl ObjArchMips {
pub fn new(object: &File) -> Result<Self> { Ok(Self { endianness: object.endianness() }) }
pub fn new(object: &File) -> Result<Self> {
configure_rabbitizer();
Ok(Self { endianness: object.endianness() })
}
}
impl ObjArch for ObjArchMips {
fn process_code(
&self,
obj: &ObjInfo,
symbol_ref: SymbolRef,
config: &DiffObjConfig,
data: &[u8],
start_address: u64,
relocs: &[ObjReloc],
line_info: &Option<BTreeMap<u64, u64>>,
) -> Result<ProcessCodeResult> {
configure_rabbitizer();
let (section, symbol) = obj.section_symbol(symbol_ref);
let code = &section.data
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
let end_address = start_address + data.len() as u64;
let ins_count = data.len() / 4;
let start_address = symbol.address;
let end_address = symbol.address + symbol.size;
let ins_count = code.len() / 4;
let mut ops = Vec::<u16>::with_capacity(ins_count);
let mut insts = Vec::<ObjIns>::with_capacity(ins_count);
let mut cur_addr = start_address as u32;
for chunk in data.chunks_exact(4) {
let reloc = relocs.iter().find(|r| (r.address as u32 & !3) == cur_addr);
for chunk in code.chunks_exact(4) {
let reloc = section.relocations.iter().find(|r| (r.address as u32 & !3) == cur_addr);
let code = self.endianness.read_u32_bytes(chunk.try_into()?);
let instruction = Instruction::new(code, cur_addr, InstrCategory::CPU);
@@ -61,11 +65,7 @@ impl ObjArch for ObjArchMips {
let mut args = Vec::with_capacity(operands.len() + 1);
for (idx, op) in operands.iter().enumerate() {
if idx > 0 {
if config.space_between_args {
args.push(ObjInsArg::PlainText(", ".to_string()));
} else {
args.push(ObjInsArg::PlainText(",".to_string()));
}
args.push(ObjInsArg::PlainText(config.separator().into()));
}
match op {
@@ -85,7 +85,7 @@ impl ObjArch for ObjArchMips {
}
} else {
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
op.disassemble(&instruction, None),
op.disassemble(&instruction, None).into(),
)));
}
}
@@ -94,23 +94,24 @@ impl ObjArch for ObjArchMips {
push_reloc(&mut args, reloc)?;
} else {
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
OperandType::cpu_immediate.disassemble(&instruction, None),
OperandType::cpu_immediate.disassemble(&instruction, None).into(),
)));
}
args.push(ObjInsArg::PlainText("(".to_string()));
args.push(ObjInsArg::PlainText("(".into()));
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
OperandType::cpu_rs.disassemble(&instruction, None),
OperandType::cpu_rs.disassemble(&instruction, None).into(),
)));
args.push(ObjInsArg::PlainText(")".to_string()));
args.push(ObjInsArg::PlainText(")".into()));
}
_ => {
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
op.disassemble(&instruction, None),
op.disassemble(&instruction, None).into(),
)));
}
}
}
let line = line_info
let line = obj
.line_info
.as_ref()
.and_then(|map| map.range(..=cur_addr as u64).last().map(|(_, &b)| b));
insts.push(ObjIns {
@@ -161,9 +162,9 @@ impl ObjArch for ObjArchMips {
elf::R_MIPS_GPREL16 => Cow::Borrowed("R_MIPS_GPREL16"),
elf::R_MIPS_32 => Cow::Borrowed("R_MIPS_32"),
elf::R_MIPS_26 => Cow::Borrowed("R_MIPS_26"),
_ => Cow::Owned(format!("<Elf {r_type:?}>")),
_ => Cow::Owned(format!("<{flags:?}>")),
},
flags => Cow::Owned(format!("<{flags:?}>")),
_ => Cow::Owned(format!("<{flags:?}>")),
}
}
}
@@ -172,29 +173,29 @@ fn push_reloc(args: &mut Vec<ObjInsArg>, reloc: &ObjReloc) -> Result<()> {
match reloc.flags {
RelocationFlags::Elf { r_type } => match r_type {
elf::R_MIPS_HI16 => {
args.push(ObjInsArg::PlainText("%hi(".to_string()));
args.push(ObjInsArg::PlainText("%hi(".into()));
args.push(ObjInsArg::Reloc);
args.push(ObjInsArg::PlainText(")".to_string()));
args.push(ObjInsArg::PlainText(")".into()));
}
elf::R_MIPS_LO16 => {
args.push(ObjInsArg::PlainText("%lo(".to_string()));
args.push(ObjInsArg::PlainText("%lo(".into()));
args.push(ObjInsArg::Reloc);
args.push(ObjInsArg::PlainText(")".to_string()));
args.push(ObjInsArg::PlainText(")".into()));
}
elf::R_MIPS_GOT16 => {
args.push(ObjInsArg::PlainText("%got(".to_string()));
args.push(ObjInsArg::PlainText("%got(".into()));
args.push(ObjInsArg::Reloc);
args.push(ObjInsArg::PlainText(")".to_string()));
args.push(ObjInsArg::PlainText(")".into()));
}
elf::R_MIPS_CALL16 => {
args.push(ObjInsArg::PlainText("%call16(".to_string()));
args.push(ObjInsArg::PlainText("%call16(".into()));
args.push(ObjInsArg::Reloc);
args.push(ObjInsArg::PlainText(")".to_string()));
args.push(ObjInsArg::PlainText(")".into()));
}
elf::R_MIPS_GPREL16 => {
args.push(ObjInsArg::PlainText("%gp_rel(".to_string()));
args.push(ObjInsArg::PlainText("%gp_rel(".into()));
args.push(ObjInsArg::Reloc);
args.push(ObjInsArg::PlainText(")".to_string()));
args.push(ObjInsArg::PlainText(")".into()));
}
elf::R_MIPS_32 | elf::R_MIPS_26 => {
args.push(ObjInsArg::Reloc);

View File

@@ -1,11 +1,11 @@
use std::{borrow::Cow, collections::BTreeMap};
use std::borrow::Cow;
use anyhow::{bail, Result};
use object::{Architecture, Object, Relocation, RelocationFlags};
use crate::{
diff::DiffObjConfig,
obj::{ObjIns, ObjReloc, ObjSection},
obj::{ObjInfo, ObjIns, ObjSection, SymbolRef},
};
#[cfg(feature = "mips")]
@@ -18,11 +18,9 @@ mod x86;
pub trait ObjArch: Send + Sync {
fn process_code(
&self,
obj: &ObjInfo,
symbol_ref: SymbolRef,
config: &DiffObjConfig,
data: &[u8],
address: u64,
relocs: &[ObjReloc],
line_info: &Option<BTreeMap<u64, u64>>,
) -> Result<ProcessCodeResult>;
fn implcit_addend(&self, section: &ObjSection, address: u64, reloc: &Relocation)

View File

@@ -1,13 +1,13 @@
use std::{borrow::Cow, collections::BTreeMap};
use std::borrow::Cow;
use anyhow::{bail, Result};
use object::{elf, File, Relocation, RelocationFlags};
use ppc750cl::{disasm_iter, Argument, SimplifiedIns, GPR};
use ppc750cl::{Argument, GPR};
use crate::{
arch::{ObjArch, ProcessCodeResult},
diff::DiffObjConfig,
obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection},
obj::{ObjInfo, ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection, SymbolRef},
};
// Relative relocation, can be Simm, Offset or BranchDest
@@ -31,30 +31,37 @@ impl ObjArchPpc {
impl ObjArch for ObjArchPpc {
fn process_code(
&self,
obj: &ObjInfo,
symbol_ref: SymbolRef,
config: &DiffObjConfig,
data: &[u8],
address: u64,
relocs: &[ObjReloc],
line_info: &Option<BTreeMap<u64, u64>>,
) -> Result<ProcessCodeResult> {
let ins_count = data.len() / 4;
let (section, symbol) = obj.section_symbol(symbol_ref);
let code = &section.data
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
let ins_count = code.len() / 4;
let mut ops = Vec::<u16>::with_capacity(ins_count);
let mut insts = Vec::<ObjIns>::with_capacity(ins_count);
for mut ins in disasm_iter(data, address as u32) {
let reloc = relocs.iter().find(|r| (r.address as u32 & !3) == ins.addr);
let mut cur_addr = symbol.address as u32;
for chunk in code.chunks_exact(4) {
let mut code = u32::from_be_bytes(chunk.try_into()?);
let reloc = section.relocations.iter().find(|r| (r.address as u32 & !3) == cur_addr);
if let Some(reloc) = reloc {
// Zero out relocations
ins.code = match reloc.flags {
RelocationFlags::Elf { r_type: elf::R_PPC_EMB_SDA21 } => ins.code & !0x1FFFFF,
RelocationFlags::Elf { r_type: elf::R_PPC_REL24 } => ins.code & !0x3FFFFFC,
RelocationFlags::Elf { r_type: elf::R_PPC_REL14 } => ins.code & !0xFFFC,
code = match reloc.flags {
RelocationFlags::Elf { r_type: elf::R_PPC_EMB_SDA21 } => code & !0x1FFFFF,
RelocationFlags::Elf { r_type: elf::R_PPC_REL24 } => code & !0x3FFFFFC,
RelocationFlags::Elf { r_type: elf::R_PPC_REL14 } => code & !0xFFFC,
RelocationFlags::Elf {
r_type: elf::R_PPC_ADDR16_HI | elf::R_PPC_ADDR16_HA | elf::R_PPC_ADDR16_LO,
} => ins.code & !0xFFFF,
_ => ins.code,
} => code & !0xFFFF,
_ => code,
};
}
let simplified = ins.clone().simplified();
let ins = ppc750cl::Ins::new(code);
let orig = ins.basic().to_string();
let simplified = ins.simplified();
let mut reloc_arg = None;
if let Some(reloc) = reloc {
@@ -77,13 +84,9 @@ impl ObjArch for ObjArchPpc {
let mut args = vec![];
let mut branch_dest = None;
let mut writing_offset = false;
for (idx, arg) in simplified.args.iter().enumerate() {
for (idx, arg) in simplified.args_iter().enumerate() {
if idx > 0 && !writing_offset {
if config.space_between_args {
args.push(ObjInsArg::PlainText(", ".to_string()));
} else {
args.push(ObjInsArg::PlainText(",".to_string()));
}
args.push(ObjInsArg::PlainText(config.separator().into()));
}
if reloc_arg == Some(idx) {
@@ -108,41 +111,45 @@ impl ObjArch for ObjArchPpc {
args.push(ObjInsArg::Arg(ObjInsArgValue::Signed(offset.0 as i64)));
}
Argument::BranchDest(dest) => {
let dest = ins.addr.wrapping_add_signed(dest.0) as u64;
let dest = cur_addr.wrapping_add_signed(dest.0) as u64;
args.push(ObjInsArg::BranchDest(dest));
branch_dest = Some(dest);
}
_ => {
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(arg.to_string())));
args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(
arg.to_string().into(),
)));
}
};
}
if writing_offset {
args.push(ObjInsArg::PlainText(")".to_string()));
args.push(ObjInsArg::PlainText(")".into()));
writing_offset = false;
}
if is_offset_arg(arg) {
args.push(ObjInsArg::PlainText("(".to_string()));
args.push(ObjInsArg::PlainText("(".into()));
writing_offset = true;
}
}
ops.push(simplified.ins.op as u16);
let line = line_info
ops.push(ins.op as u16);
let line = obj
.line_info
.as_ref()
.and_then(|map| map.range(..=simplified.ins.addr as u64).last().map(|(_, &b)| b));
.and_then(|map| map.range(..=cur_addr as u64).last().map(|(_, &b)| b));
insts.push(ObjIns {
address: simplified.ins.addr as u64,
address: cur_addr as u64,
size: 4,
mnemonic: format!("{}{}", simplified.mnemonic, simplified.suffix),
mnemonic: simplified.mnemonic.to_string(),
args,
reloc: reloc.cloned(),
op: ins.op as u16,
branch_dest,
line,
orig: Some(format!("{}", SimplifiedIns::basic_form(ins))),
orig: Some(orig),
});
cur_addr += 4;
}
Ok(ProcessCodeResult { ops, insts })
}
@@ -157,7 +164,7 @@ impl ObjArch for ObjArchPpc {
}
fn demangle(&self, name: &str) -> Option<String> {
cwdemangle::demangle(name, &Default::default())
cwdemangle::demangle(name, &cwdemangle::DemangleOptions::default())
}
fn display_reloc(&self, flags: RelocationFlags) -> Cow<'static, str> {
@@ -171,9 +178,9 @@ impl ObjArch for ObjArchPpc {
elf::R_PPC_UADDR32 => Cow::Borrowed("R_PPC_UADDR32"),
elf::R_PPC_REL24 => Cow::Borrowed("R_PPC_REL24"),
elf::R_PPC_REL14 => Cow::Borrowed("R_PPC_REL14"),
_ => Cow::Owned(format!("<Elf {r_type:?}>")),
_ => Cow::Owned(format!("<{flags:?}>")),
},
flags => Cow::Owned(format!("<{flags:?}>")),
_ => Cow::Owned(format!("<{flags:?}>")),
}
}
}
@@ -183,19 +190,19 @@ fn push_reloc(args: &mut Vec<ObjInsArg>, reloc: &ObjReloc) -> Result<()> {
RelocationFlags::Elf { r_type } => match r_type {
elf::R_PPC_ADDR16_LO => {
args.push(ObjInsArg::Reloc);
args.push(ObjInsArg::PlainText("@l".to_string()));
args.push(ObjInsArg::PlainText("@l".into()));
}
elf::R_PPC_ADDR16_HI => {
args.push(ObjInsArg::Reloc);
args.push(ObjInsArg::PlainText("@h".to_string()));
args.push(ObjInsArg::PlainText("@h".into()));
}
elf::R_PPC_ADDR16_HA => {
args.push(ObjInsArg::Reloc);
args.push(ObjInsArg::PlainText("@ha".to_string()));
args.push(ObjInsArg::PlainText("@ha".into()));
}
elf::R_PPC_EMB_SDA21 => {
args.push(ObjInsArg::Reloc);
args.push(ObjInsArg::PlainText("@sda21".to_string()));
args.push(ObjInsArg::PlainText("@sda21".into()));
}
elf::R_PPC_ADDR32 | elf::R_PPC_UADDR32 | elf::R_PPC_REL24 | elf::R_PPC_REL14 => {
args.push(ObjInsArg::Reloc);

View File

@@ -1,4 +1,4 @@
use std::{borrow::Cow, collections::BTreeMap};
use std::borrow::Cow;
use anyhow::{anyhow, bail, ensure, Result};
use iced_x86::{
@@ -11,7 +11,7 @@ use object::{pe, Endian, Endianness, File, Object, Relocation, RelocationFlags};
use crate::{
arch::{ObjArch, ProcessCodeResult},
diff::{DiffObjConfig, X86Formatter},
obj::{ObjIns, ObjInsArg, ObjInsArgValue, ObjReloc, ObjSection},
obj::{ObjInfo, ObjIns, ObjInsArg, ObjInsArgValue, ObjSection, SymbolRef},
};
pub struct ObjArchX86 {
@@ -28,14 +28,16 @@ impl ObjArchX86 {
impl ObjArch for ObjArchX86 {
fn process_code(
&self,
obj: &ObjInfo,
symbol_ref: SymbolRef,
config: &DiffObjConfig,
data: &[u8],
start_address: u64,
relocs: &[ObjReloc],
line_info: &Option<BTreeMap<u64, u64>>,
) -> Result<ProcessCodeResult> {
let (section, symbol) = obj.section_symbol(symbol_ref);
let code = &section.data
[symbol.section_address as usize..(symbol.section_address + symbol.size) as usize];
let mut result = ProcessCodeResult { ops: Vec::new(), insts: Vec::new() };
let mut decoder = Decoder::with_ip(self.bits, data, start_address, DecoderOptions::NONE);
let mut decoder = Decoder::with_ip(self.bits, code, symbol.address, DecoderOptions::NONE);
let mut formatter: Box<dyn Formatter> = match config.x86_formatter {
X86Formatter::Intel => Box::new(IntelFormatter::new()),
X86Formatter::Gas => Box::new(GasFormatter::new()),
@@ -66,7 +68,8 @@ impl ObjArch for ObjArchX86 {
let address = instruction.ip();
let op = instruction.mnemonic() as u16;
let reloc = relocs
let reloc = section
.relocations
.iter()
.find(|r| r.address >= address && r.address < address + instruction.len() as u64);
output.ins = ObjIns {
@@ -77,7 +80,7 @@ impl ObjArch for ObjArchX86 {
args: vec![],
reloc: reloc.cloned(),
branch_dest: None,
line: line_info.as_ref().and_then(|m| m.get(&address).cloned()),
line: obj.line_info.as_ref().and_then(|m| m.get(&address).cloned()),
orig: None,
};
// Run the formatter, which will populate output.ins
@@ -141,7 +144,9 @@ impl ObjArch for ObjArchX86 {
if name.starts_with('?') {
msvc_demangler::demangle(name, msvc_demangler::DemangleFlags::llvm()).ok()
} else {
None
cpp_demangle::Symbol::new(name)
.ok()
.and_then(|s| s.demangle(&cpp_demangle::DemangleOptions::default()).ok())
}
}
@@ -150,9 +155,9 @@ impl ObjArch for ObjArchX86 {
RelocationFlags::Coff { typ } => match typ {
pe::IMAGE_REL_I386_DIR32 => Cow::Borrowed("IMAGE_REL_I386_DIR32"),
pe::IMAGE_REL_I386_REL32 => Cow::Borrowed("IMAGE_REL_I386_REL32"),
_ => Cow::Owned(format!("<Coff {typ:?}>")),
_ => Cow::Owned(format!("<{flags:?}>")),
},
flags => Cow::Owned(format!("<{flags:?}>")),
_ => Cow::Owned(format!("<{flags:?}>")),
}
}
}
@@ -214,10 +219,10 @@ impl FormatterOutput for InstructionFormatterOutput {
self.ins_operands.push(None);
match kind {
FormatterTextKind::Text | FormatterTextKind::Punctuation => {
self.ins.args.push(ObjInsArg::PlainText(text.to_string()));
self.ins.args.push(ObjInsArg::PlainText(text.to_string().into()));
}
FormatterTextKind::Keyword | FormatterTextKind::Operator => {
self.ins.args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(text.to_string())));
self.ins.args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(text.to_string().into())));
}
_ => {
if self.error.is_none() {
@@ -230,7 +235,7 @@ impl FormatterOutput for InstructionFormatterOutput {
fn write_prefix(&mut self, _instruction: &Instruction, text: &str, _prefix: PrefixKind) {
self.formatted.push_str(text);
self.ins_operands.push(None);
self.ins.args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(text.to_string())));
self.ins.args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(text.to_string().into())));
}
fn write_mnemonic(&mut self, _instruction: &Instruction, text: &str) {
@@ -318,7 +323,7 @@ impl FormatterOutput for InstructionFormatterOutput {
) {
self.formatted.push_str(text);
self.ins_operands.push(instruction_operand);
self.ins.args.push(ObjInsArg::PlainText(text.to_string()));
self.ins.args.push(ObjInsArg::PlainText(text.to_string().into()));
}
fn write_register(
@@ -331,6 +336,6 @@ impl FormatterOutput for InstructionFormatterOutput {
) {
self.formatted.push_str(text);
self.ins_operands.push(instruction_operand);
self.ins.args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(text.to_string())));
self.ins.args.push(ObjInsArg::Arg(ObjInsArgValue::Opaque(text.to_string().into())));
}
}