mirror of https://github.com/encounter/objdiff.git
Fix resolving symbols for section-relative relocations
Also fixes MIPS `j` handling when jumping within the function. Reworks `ObjReloc` struct to be a little more sensible.
This commit is contained in:
parent
83de98b5ee
commit
676488433f
|
@ -1526,15 +1526,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.30"
|
version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.30"
|
version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
|
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-lite"
|
name = "futures-lite"
|
||||||
|
@ -1551,9 +1551,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.30"
|
version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1562,21 +1562,21 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.30"
|
version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
|
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.30"
|
version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.30"
|
version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-io",
|
"futures-io",
|
||||||
|
@ -2861,7 +2861,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff-cli"
|
name = "objdiff-cli"
|
||||||
version = "2.3.1"
|
version = "2.3.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"argp",
|
"argp",
|
||||||
|
@ -2883,7 +2883,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff-core"
|
name = "objdiff-core"
|
||||||
version = "2.3.1"
|
version = "2.3.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arm-attr",
|
"arm-attr",
|
||||||
|
@ -2923,7 +2923,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff-gui"
|
name = "objdiff-gui"
|
||||||
version = "2.3.1"
|
version = "2.3.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
|
|
@ -13,7 +13,7 @@ strip = "debuginfo"
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "2.3.1"
|
version = "2.3.2"
|
||||||
authors = ["Luke Street <luke@street.dev>"]
|
authors = ["Luke Street <luke@street.dev>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
|
@ -70,7 +70,6 @@ feature-depth = 1
|
||||||
# A list of advisory IDs to ignore. Note that ignored advisories will still
|
# A list of advisory IDs to ignore. Note that ignored advisories will still
|
||||||
# output a note when they are encountered.
|
# output a note when they are encountered.
|
||||||
ignore = [
|
ignore = [
|
||||||
"RUSTSEC-2024-0370",
|
|
||||||
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
|
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
|
||||||
#"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish
|
#"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish
|
||||||
#{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" },
|
#{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" },
|
||||||
|
@ -240,7 +239,7 @@ allow-git = []
|
||||||
|
|
||||||
[sources.allow-org]
|
[sources.allow-org]
|
||||||
# github.com organizations to allow git sources for
|
# github.com organizations to allow git sources for
|
||||||
github = ["encounter"]
|
github = ["notify-rs"]
|
||||||
# gitlab.com organizations to allow git sources for
|
# gitlab.com organizations to allow git sources for
|
||||||
gitlab = []
|
gitlab = []
|
||||||
# bitbucket.org organizations to allow git sources for
|
# bitbucket.org organizations to allow git sources for
|
||||||
|
|
|
@ -83,7 +83,7 @@ impl ObjArch for ObjArchMips {
|
||||||
&self,
|
&self,
|
||||||
address: u64,
|
address: u64,
|
||||||
code: &[u8],
|
code: &[u8],
|
||||||
_section_index: usize,
|
section_index: usize,
|
||||||
relocations: &[ObjReloc],
|
relocations: &[ObjReloc],
|
||||||
line_info: &BTreeMap<u64, u32>,
|
line_info: &BTreeMap<u64, u32>,
|
||||||
config: &DiffObjConfig,
|
config: &DiffObjConfig,
|
||||||
|
@ -140,11 +140,18 @@ impl ObjArch for ObjArchMips {
|
||||||
| OperandType::cpu_label
|
| OperandType::cpu_label
|
||||||
| OperandType::cpu_branch_target_label => {
|
| OperandType::cpu_branch_target_label => {
|
||||||
if let Some(reloc) = reloc {
|
if let Some(reloc) = reloc {
|
||||||
if matches!(&reloc.target_section, Some(s) if s == ".text")
|
// If the relocation target is within the current function, we can
|
||||||
&& reloc.target.address > start_address
|
// convert it into a relative branch target. Note that we check
|
||||||
&& reloc.target.address < end_address
|
// target_address > start_address instead of >= so that recursive
|
||||||
|
// tail calls are not considered branch targets.
|
||||||
|
let target_address =
|
||||||
|
reloc.target.address.checked_add_signed(reloc.addend);
|
||||||
|
if reloc.target.orig_section_index == Some(section_index)
|
||||||
|
&& matches!(target_address, Some(addr) if addr > start_address && addr < end_address)
|
||||||
{
|
{
|
||||||
args.push(ObjInsArg::BranchDest(reloc.target.address));
|
let target_address = target_address.unwrap();
|
||||||
|
args.push(ObjInsArg::BranchDest(target_address));
|
||||||
|
branch_dest = Some(target_address);
|
||||||
} else {
|
} else {
|
||||||
push_reloc(&mut args, reloc)?;
|
push_reloc(&mut args, reloc)?;
|
||||||
branch_dest = None;
|
branch_dest = None;
|
||||||
|
|
|
@ -70,9 +70,13 @@ impl FunctionDiff {
|
||||||
// let (_section, symbol) = object.section_symbol(symbol_ref);
|
// let (_section, symbol) = object.section_symbol(symbol_ref);
|
||||||
// Symbol::from(symbol)
|
// Symbol::from(symbol)
|
||||||
// });
|
// });
|
||||||
let instructions = symbol_diff.instructions.iter().map(InstructionDiff::from).collect();
|
let instructions = symbol_diff
|
||||||
|
.instructions
|
||||||
|
.iter()
|
||||||
|
.map(|ins_diff| InstructionDiff::new(object, ins_diff))
|
||||||
|
.collect();
|
||||||
Self {
|
Self {
|
||||||
symbol: Some(Symbol::from(symbol)),
|
symbol: Some(Symbol::new(symbol)),
|
||||||
// diff_symbol,
|
// diff_symbol,
|
||||||
instructions,
|
instructions,
|
||||||
match_percent: symbol_diff.match_percent,
|
match_percent: symbol_diff.match_percent,
|
||||||
|
@ -90,8 +94,8 @@ impl DataDiff {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a ObjSymbol> for Symbol {
|
impl Symbol {
|
||||||
fn from(value: &'a ObjSymbol) -> Self {
|
pub fn new(value: &ObjSymbol) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: value.name.to_string(),
|
name: value.name.to_string(),
|
||||||
demangled_name: value.demangled_name.clone(),
|
demangled_name: value.demangled_name.clone(),
|
||||||
|
@ -122,29 +126,29 @@ fn symbol_flags(value: ObjSymbolFlagSet) -> u32 {
|
||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a ObjIns> for Instruction {
|
impl Instruction {
|
||||||
fn from(value: &'a ObjIns) -> Self {
|
pub fn new(object: &ObjInfo, instruction: &ObjIns) -> Self {
|
||||||
Self {
|
Self {
|
||||||
address: value.address,
|
address: instruction.address,
|
||||||
size: value.size as u32,
|
size: instruction.size as u32,
|
||||||
opcode: value.op as u32,
|
opcode: instruction.op as u32,
|
||||||
mnemonic: value.mnemonic.clone(),
|
mnemonic: instruction.mnemonic.clone(),
|
||||||
formatted: value.formatted.clone(),
|
formatted: instruction.formatted.clone(),
|
||||||
arguments: value.args.iter().map(Argument::from).collect(),
|
arguments: instruction.args.iter().map(Argument::new).collect(),
|
||||||
relocation: value.reloc.as_ref().map(Relocation::from),
|
relocation: instruction.reloc.as_ref().map(|reloc| Relocation::new(object, reloc)),
|
||||||
branch_dest: value.branch_dest,
|
branch_dest: instruction.branch_dest,
|
||||||
line_number: value.line,
|
line_number: instruction.line,
|
||||||
original: value.orig.clone(),
|
original: instruction.orig.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a ObjInsArg> for Argument {
|
impl Argument {
|
||||||
fn from(value: &'a ObjInsArg) -> Self {
|
pub fn new(value: &ObjInsArg) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: Some(match value {
|
value: Some(match value {
|
||||||
ObjInsArg::PlainText(s) => argument::Value::PlainText(s.to_string()),
|
ObjInsArg::PlainText(s) => argument::Value::PlainText(s.to_string()),
|
||||||
ObjInsArg::Arg(v) => argument::Value::Argument(ArgumentValue::from(v)),
|
ObjInsArg::Arg(v) => argument::Value::Argument(ArgumentValue::new(v)),
|
||||||
ObjInsArg::Reloc => argument::Value::Relocation(ArgumentRelocation {}),
|
ObjInsArg::Reloc => argument::Value::Relocation(ArgumentRelocation {}),
|
||||||
ObjInsArg::BranchDest(dest) => argument::Value::BranchDest(*dest),
|
ObjInsArg::BranchDest(dest) => argument::Value::BranchDest(*dest),
|
||||||
}),
|
}),
|
||||||
|
@ -152,8 +156,8 @@ impl<'a> From<&'a ObjInsArg> for Argument {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&ObjInsArgValue> for ArgumentValue {
|
impl ArgumentValue {
|
||||||
fn from(value: &ObjInsArgValue) -> Self {
|
pub fn new(value: &ObjInsArgValue) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: Some(match value {
|
value: Some(match value {
|
||||||
ObjInsArgValue::Signed(v) => argument_value::Value::Signed(*v),
|
ObjInsArgValue::Signed(v) => argument_value::Value::Signed(*v),
|
||||||
|
@ -164,42 +168,39 @@ impl From<&ObjInsArgValue> for ArgumentValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a ObjReloc> for Relocation {
|
impl Relocation {
|
||||||
fn from(value: &ObjReloc) -> Self {
|
pub fn new(object: &ObjInfo, reloc: &ObjReloc) -> Self {
|
||||||
Self {
|
Self {
|
||||||
r#type: match value.flags {
|
r#type: match reloc.flags {
|
||||||
object::RelocationFlags::Elf { r_type } => r_type,
|
object::RelocationFlags::Elf { r_type } => r_type,
|
||||||
object::RelocationFlags::MachO { r_type, .. } => r_type as u32,
|
object::RelocationFlags::MachO { r_type, .. } => r_type as u32,
|
||||||
object::RelocationFlags::Coff { typ } => typ as u32,
|
object::RelocationFlags::Coff { typ } => typ as u32,
|
||||||
object::RelocationFlags::Xcoff { r_rtype, .. } => r_rtype as u32,
|
object::RelocationFlags::Xcoff { r_rtype, .. } => r_rtype as u32,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
type_name: String::new(), // TODO
|
type_name: object.arch.display_reloc(reloc.flags).into_owned(),
|
||||||
target: Some(RelocationTarget::from(&value.target)),
|
target: Some(RelocationTarget {
|
||||||
|
symbol: Some(Symbol::new(&reloc.target)),
|
||||||
|
addend: reloc.addend,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a ObjSymbol> for RelocationTarget {
|
impl InstructionDiff {
|
||||||
fn from(value: &'a ObjSymbol) -> Self {
|
pub fn new(object: &ObjInfo, instruction_diff: &ObjInsDiff) -> Self {
|
||||||
Self { symbol: Some(Symbol::from(value)), addend: value.addend }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a ObjInsDiff> for InstructionDiff {
|
|
||||||
fn from(value: &'a ObjInsDiff) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
instruction: value.ins.as_ref().map(Instruction::from),
|
instruction: instruction_diff.ins.as_ref().map(|ins| Instruction::new(object, ins)),
|
||||||
diff_kind: DiffKind::from(value.kind) as i32,
|
diff_kind: DiffKind::from(instruction_diff.kind) as i32,
|
||||||
branch_from: value.branch_from.as_ref().map(InstructionBranchFrom::from),
|
branch_from: instruction_diff.branch_from.as_ref().map(InstructionBranchFrom::new),
|
||||||
branch_to: value.branch_to.as_ref().map(InstructionBranchTo::from),
|
branch_to: instruction_diff.branch_to.as_ref().map(InstructionBranchTo::new),
|
||||||
arg_diff: value.arg_diff.iter().map(ArgumentDiff::from).collect(),
|
arg_diff: instruction_diff.arg_diff.iter().map(ArgumentDiff::new).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Option<ObjInsArgDiff>> for ArgumentDiff {
|
impl ArgumentDiff {
|
||||||
fn from(value: &Option<ObjInsArgDiff>) -> Self {
|
pub fn new(value: &Option<ObjInsArgDiff>) -> Self {
|
||||||
Self { diff_index: value.as_ref().map(|v| v.idx as u32) }
|
Self { diff_index: value.as_ref().map(|v| v.idx as u32) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,8 +229,8 @@ impl From<ObjDataDiffKind> for DiffKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a ObjInsBranchFrom> for InstructionBranchFrom {
|
impl InstructionBranchFrom {
|
||||||
fn from(value: &'a ObjInsBranchFrom) -> Self {
|
pub fn new(value: &ObjInsBranchFrom) -> Self {
|
||||||
Self {
|
Self {
|
||||||
instruction_index: value.ins_idx.iter().map(|&x| x as u32).collect(),
|
instruction_index: value.ins_idx.iter().map(|&x| x as u32).collect(),
|
||||||
branch_index: value.branch_idx as u32,
|
branch_index: value.branch_idx as u32,
|
||||||
|
@ -237,8 +238,8 @@ impl<'a> From<&'a ObjInsBranchFrom> for InstructionBranchFrom {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a ObjInsBranchTo> for InstructionBranchTo {
|
impl InstructionBranchTo {
|
||||||
fn from(value: &'a ObjInsBranchTo) -> Self {
|
pub fn new(value: &ObjInsBranchTo) -> Self {
|
||||||
Self { instruction_index: value.ins_idx as u32, branch_index: value.branch_idx as u32 }
|
Self { instruction_index: value.ins_idx as u32, branch_index: value.branch_idx as u32 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::{
|
||||||
DiffObjConfig, ObjInsArgDiff, ObjInsBranchFrom, ObjInsBranchTo, ObjInsDiff, ObjInsDiffKind,
|
DiffObjConfig, ObjInsArgDiff, ObjInsBranchFrom, ObjInsBranchTo, ObjInsDiff, ObjInsDiffKind,
|
||||||
ObjSymbolDiff,
|
ObjSymbolDiff,
|
||||||
},
|
},
|
||||||
obj::{ObjInfo, ObjInsArg, ObjReloc, ObjSymbol, ObjSymbolFlags, SymbolRef},
|
obj::{ObjInfo, ObjInsArg, ObjReloc, ObjSymbolFlags, SymbolRef},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn process_code_symbol(
|
pub fn process_code_symbol(
|
||||||
|
@ -45,6 +45,8 @@ pub fn no_diff_code(out: &ProcessCodeResult, symbol_ref: SymbolRef) -> Result<Ob
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn diff_code(
|
pub fn diff_code(
|
||||||
|
left_obj: &ObjInfo,
|
||||||
|
right_obj: &ObjInfo,
|
||||||
left_out: &ProcessCodeResult,
|
left_out: &ProcessCodeResult,
|
||||||
right_out: &ProcessCodeResult,
|
right_out: &ProcessCodeResult,
|
||||||
left_symbol_ref: SymbolRef,
|
left_symbol_ref: SymbolRef,
|
||||||
|
@ -60,7 +62,7 @@ pub fn diff_code(
|
||||||
|
|
||||||
let mut diff_state = InsDiffState::default();
|
let mut diff_state = InsDiffState::default();
|
||||||
for (left, right) in left_diff.iter_mut().zip(right_diff.iter_mut()) {
|
for (left, right) in left_diff.iter_mut().zip(right_diff.iter_mut()) {
|
||||||
let result = compare_ins(config, left, right, &mut diff_state)?;
|
let result = compare_ins(config, left_obj, right_obj, left, right, &mut diff_state)?;
|
||||||
left.kind = result.kind;
|
left.kind = result.kind;
|
||||||
right.kind = result.kind;
|
right.kind = result.kind;
|
||||||
left.arg_diff = result.left_args_diff;
|
left.arg_diff = result.left_args_diff;
|
||||||
|
@ -170,12 +172,33 @@ fn resolve_branches(vec: &mut [ObjInsDiff]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn address_eq(left: &ObjSymbol, right: &ObjSymbol) -> bool {
|
fn address_eq(left: &ObjReloc, right: &ObjReloc) -> bool {
|
||||||
left.address as i64 + left.addend == right.address as i64 + right.addend
|
left.target.address as i64 + left.addend == right.target.address as i64 + right.addend
|
||||||
|
}
|
||||||
|
|
||||||
|
fn section_name_eq(
|
||||||
|
left_obj: &ObjInfo,
|
||||||
|
right_obj: &ObjInfo,
|
||||||
|
left_orig_section_index: usize,
|
||||||
|
right_orig_section_index: usize,
|
||||||
|
) -> bool {
|
||||||
|
let Some(left_section) =
|
||||||
|
left_obj.sections.iter().find(|s| s.orig_index == left_orig_section_index)
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let Some(right_section) =
|
||||||
|
right_obj.sections.iter().find(|s| s.orig_index == right_orig_section_index)
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
left_section.name == right_section.name
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reloc_eq(
|
fn reloc_eq(
|
||||||
config: &DiffObjConfig,
|
config: &DiffObjConfig,
|
||||||
|
left_obj: &ObjInfo,
|
||||||
|
right_obj: &ObjInfo,
|
||||||
left_reloc: Option<&ObjReloc>,
|
left_reloc: Option<&ObjReloc>,
|
||||||
right_reloc: Option<&ObjReloc>,
|
right_reloc: Option<&ObjReloc>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
@ -189,23 +212,26 @@ fn reloc_eq(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let name_matches = left.target.name == right.target.name;
|
let symbol_name_matches = left.target.name == right.target.name;
|
||||||
match (&left.target_section, &right.target_section) {
|
match (&left.target.orig_section_index, &right.target.orig_section_index) {
|
||||||
(Some(sl), Some(sr)) => {
|
(Some(sl), Some(sr)) => {
|
||||||
// Match if section and name or address match
|
// Match if section and name or address match
|
||||||
sl == sr && (name_matches || address_eq(&left.target, &right.target))
|
section_name_eq(left_obj, right_obj, *sl, *sr)
|
||||||
|
&& (symbol_name_matches || address_eq(left, right))
|
||||||
}
|
}
|
||||||
(Some(_), None) => false,
|
(Some(_), None) => false,
|
||||||
(None, Some(_)) => {
|
(None, Some(_)) => {
|
||||||
// Match if possibly stripped weak symbol
|
// Match if possibly stripped weak symbol
|
||||||
name_matches && right.target.flags.0.contains(ObjSymbolFlags::Weak)
|
symbol_name_matches && right.target.flags.0.contains(ObjSymbolFlags::Weak)
|
||||||
}
|
}
|
||||||
(None, None) => name_matches,
|
(None, None) => symbol_name_matches,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn arg_eq(
|
fn arg_eq(
|
||||||
config: &DiffObjConfig,
|
config: &DiffObjConfig,
|
||||||
|
left_obj: &ObjInfo,
|
||||||
|
right_obj: &ObjInfo,
|
||||||
left: &ObjInsArg,
|
left: &ObjInsArg,
|
||||||
right: &ObjInsArg,
|
right: &ObjInsArg,
|
||||||
left_diff: &ObjInsDiff,
|
left_diff: &ObjInsDiff,
|
||||||
|
@ -227,6 +253,8 @@ fn arg_eq(
|
||||||
matches!(right, ObjInsArg::Reloc)
|
matches!(right, ObjInsArg::Reloc)
|
||||||
&& reloc_eq(
|
&& reloc_eq(
|
||||||
config,
|
config,
|
||||||
|
left_obj,
|
||||||
|
right_obj,
|
||||||
left_diff.ins.as_ref().and_then(|i| i.reloc.as_ref()),
|
left_diff.ins.as_ref().and_then(|i| i.reloc.as_ref()),
|
||||||
right_diff.ins.as_ref().and_then(|i| i.reloc.as_ref()),
|
right_diff.ins.as_ref().and_then(|i| i.reloc.as_ref()),
|
||||||
)
|
)
|
||||||
|
@ -257,6 +285,8 @@ struct InsDiffResult {
|
||||||
|
|
||||||
fn compare_ins(
|
fn compare_ins(
|
||||||
config: &DiffObjConfig,
|
config: &DiffObjConfig,
|
||||||
|
left_obj: &ObjInfo,
|
||||||
|
right_obj: &ObjInfo,
|
||||||
left: &ObjInsDiff,
|
left: &ObjInsDiff,
|
||||||
right: &ObjInsDiff,
|
right: &ObjInsDiff,
|
||||||
state: &mut InsDiffState,
|
state: &mut InsDiffState,
|
||||||
|
@ -283,7 +313,7 @@ fn compare_ins(
|
||||||
state.diff_count += 1;
|
state.diff_count += 1;
|
||||||
}
|
}
|
||||||
for (a, b) in left_ins.args.iter().zip(&right_ins.args) {
|
for (a, b) in left_ins.args.iter().zip(&right_ins.args) {
|
||||||
if arg_eq(config, a, b, left, right) {
|
if arg_eq(config, left_obj, right_obj, a, b, left, right) {
|
||||||
result.left_args_diff.push(None);
|
result.left_args_diff.push(None);
|
||||||
result.right_args_diff.push(None);
|
result.right_args_diff.push(None);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -94,9 +94,9 @@ fn display_reloc_name<E>(
|
||||||
mut cb: impl FnMut(DiffText) -> Result<(), E>,
|
mut cb: impl FnMut(DiffText) -> Result<(), E>,
|
||||||
) -> Result<(), E> {
|
) -> Result<(), E> {
|
||||||
cb(DiffText::Symbol(&reloc.target))?;
|
cb(DiffText::Symbol(&reloc.target))?;
|
||||||
match reloc.target.addend.cmp(&0i64) {
|
match reloc.addend.cmp(&0i64) {
|
||||||
Ordering::Greater => cb(DiffText::Basic(&format!("+{:#x}", reloc.target.addend))),
|
Ordering::Greater => cb(DiffText::Basic(&format!("+{:#x}", reloc.addend))),
|
||||||
Ordering::Less => cb(DiffText::Basic(&format!("-{:#x}", -reloc.target.addend))),
|
Ordering::Less => cb(DiffText::Basic(&format!("-{:#x}", -reloc.addend))),
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -411,6 +411,8 @@ pub fn diff_objs(
|
||||||
let left_code = process_code_symbol(left_obj, left_symbol_ref, config)?;
|
let left_code = process_code_symbol(left_obj, left_symbol_ref, config)?;
|
||||||
let right_code = process_code_symbol(right_obj, right_symbol_ref, config)?;
|
let right_code = process_code_symbol(right_obj, right_symbol_ref, config)?;
|
||||||
let (left_diff, right_diff) = diff_code(
|
let (left_diff, right_diff) = diff_code(
|
||||||
|
left_obj,
|
||||||
|
right_obj,
|
||||||
&left_code,
|
&left_code,
|
||||||
&right_code,
|
&right_code,
|
||||||
left_symbol_ref,
|
left_symbol_ref,
|
||||||
|
@ -424,6 +426,8 @@ pub fn diff_objs(
|
||||||
let (prev_obj, prev_out) = prev.as_mut().unwrap();
|
let (prev_obj, prev_out) = prev.as_mut().unwrap();
|
||||||
let prev_code = process_code_symbol(prev_obj, prev_symbol_ref, config)?;
|
let prev_code = process_code_symbol(prev_obj, prev_symbol_ref, config)?;
|
||||||
let (_, prev_diff) = diff_code(
|
let (_, prev_diff) = diff_code(
|
||||||
|
left_obj,
|
||||||
|
right_obj,
|
||||||
&right_code,
|
&right_code,
|
||||||
&prev_code,
|
&prev_code,
|
||||||
right_symbol_ref,
|
right_symbol_ref,
|
||||||
|
@ -592,6 +596,8 @@ fn generate_mapping_symbols(
|
||||||
ObjSectionKind::Code => {
|
ObjSectionKind::Code => {
|
||||||
let target_code = process_code_symbol(target_obj, target_symbol_ref, config)?;
|
let target_code = process_code_symbol(target_obj, target_symbol_ref, config)?;
|
||||||
let (left_diff, _right_diff) = diff_code(
|
let (left_diff, _right_diff) = diff_code(
|
||||||
|
target_obj,
|
||||||
|
base_obj,
|
||||||
&target_code,
|
&target_code,
|
||||||
base_code.as_ref().unwrap(),
|
base_code.as_ref().unwrap(),
|
||||||
target_symbol_ref,
|
target_symbol_ref,
|
||||||
|
|
|
@ -131,7 +131,7 @@ pub struct ObjSymbol {
|
||||||
pub size_known: bool,
|
pub size_known: bool,
|
||||||
pub kind: ObjSymbolKind,
|
pub kind: ObjSymbolKind,
|
||||||
pub flags: ObjSymbolFlagSet,
|
pub flags: ObjSymbolFlagSet,
|
||||||
pub addend: i64,
|
pub orig_section_index: Option<usize>,
|
||||||
/// Original virtual address (from .note.split section)
|
/// Original virtual address (from .note.split section)
|
||||||
pub virtual_address: Option<u64>,
|
pub virtual_address: Option<u64>,
|
||||||
/// Original index in object symbol table
|
/// Original index in object symbol table
|
||||||
|
@ -155,7 +155,7 @@ pub struct ObjReloc {
|
||||||
pub flags: RelocationFlags,
|
pub flags: RelocationFlags,
|
||||||
pub address: u64,
|
pub address: u64,
|
||||||
pub target: ObjSymbol,
|
pub target: ObjSymbol,
|
||||||
pub target_section: Option<String>,
|
pub addend: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
|
|
|
@ -13,8 +13,8 @@ use object::{
|
||||||
endian::LittleEndian as LE,
|
endian::LittleEndian as LE,
|
||||||
pe::{ImageAuxSymbolFunctionBeginEnd, ImageLinenumber},
|
pe::{ImageAuxSymbolFunctionBeginEnd, ImageLinenumber},
|
||||||
read::coff::{CoffFile, CoffHeader, ImageSymbol},
|
read::coff::{CoffFile, CoffHeader, ImageSymbol},
|
||||||
BinaryFormat, File, Object, ObjectSection, ObjectSymbol, RelocationTarget, SectionIndex,
|
BinaryFormat, File, Object, ObjectSection, ObjectSymbol, RelocationTarget, Section,
|
||||||
SectionKind, Symbol, SymbolIndex, SymbolKind, SymbolScope, SymbolSection,
|
SectionIndex, SectionKind, Symbol, SymbolIndex, SymbolKind, SymbolScope,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -41,7 +41,6 @@ fn to_obj_symbol(
|
||||||
arch: &dyn ObjArch,
|
arch: &dyn ObjArch,
|
||||||
obj_file: &File<'_>,
|
obj_file: &File<'_>,
|
||||||
symbol: &Symbol<'_, '_>,
|
symbol: &Symbol<'_, '_>,
|
||||||
addend: i64,
|
|
||||||
split_meta: Option<&SplitMeta>,
|
split_meta: Option<&SplitMeta>,
|
||||||
) -> Result<ObjSymbol> {
|
) -> Result<ObjSymbol> {
|
||||||
let mut name = symbol.name().context("Failed to process symbol name")?;
|
let mut name = symbol.name().context("Failed to process symbol name")?;
|
||||||
|
@ -111,7 +110,7 @@ fn to_obj_symbol(
|
||||||
size_known: symbol.size() != 0,
|
size_known: symbol.size() != 0,
|
||||||
kind,
|
kind,
|
||||||
flags,
|
flags,
|
||||||
addend,
|
orig_section_index: symbol.section_index().map(|i| i.0),
|
||||||
virtual_address,
|
virtual_address,
|
||||||
original_index: Some(symbol.index().0),
|
original_index: Some(symbol.index().0),
|
||||||
bytes: bytes.to_vec(),
|
bytes: bytes.to_vec(),
|
||||||
|
@ -177,7 +176,7 @@ fn symbols_by_section(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.push(to_obj_symbol(arch, obj_file, symbol, 0, split_meta)?);
|
result.push(to_obj_symbol(arch, obj_file, symbol, split_meta)?);
|
||||||
}
|
}
|
||||||
result.sort_by(|a, b| a.address.cmp(&b.address).then(a.size.cmp(&b.size)));
|
result.sort_by(|a, b| a.address.cmp(&b.address).then(a.size.cmp(&b.size)));
|
||||||
let mut iter = result.iter_mut().peekable();
|
let mut iter = result.iter_mut().peekable();
|
||||||
|
@ -217,7 +216,7 @@ fn symbols_by_section(
|
||||||
ObjSectionKind::Data | ObjSectionKind::Bss => ObjSymbolKind::Object,
|
ObjSectionKind::Data | ObjSectionKind::Bss => ObjSymbolKind::Object,
|
||||||
},
|
},
|
||||||
flags: Default::default(),
|
flags: Default::default(),
|
||||||
addend: 0,
|
orig_section_index: Some(section.orig_index),
|
||||||
virtual_address: None,
|
virtual_address: None,
|
||||||
original_index: None,
|
original_index: None,
|
||||||
bytes: Vec::new(),
|
bytes: Vec::new(),
|
||||||
|
@ -234,7 +233,7 @@ fn common_symbols(
|
||||||
obj_file
|
obj_file
|
||||||
.symbols()
|
.symbols()
|
||||||
.filter(Symbol::is_common)
|
.filter(Symbol::is_common)
|
||||||
.map(|symbol| to_obj_symbol(arch, obj_file, &symbol, 0, split_meta))
|
.map(|symbol| to_obj_symbol(arch, obj_file, &symbol, split_meta))
|
||||||
.collect::<Result<Vec<ObjSymbol>>>()
|
.collect::<Result<Vec<ObjSymbol>>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,10 +244,18 @@ fn best_symbol<'r, 'data, 'file>(
|
||||||
symbols: &'r [Symbol<'data, 'file>],
|
symbols: &'r [Symbol<'data, 'file>],
|
||||||
address: u64,
|
address: u64,
|
||||||
) -> Option<&'r Symbol<'data, 'file>> {
|
) -> Option<&'r Symbol<'data, 'file>> {
|
||||||
let closest_symbol_index = match symbols.binary_search_by_key(&address, |s| s.address()) {
|
let mut closest_symbol_index = match symbols.binary_search_by_key(&address, |s| s.address()) {
|
||||||
Ok(index) => Some(index),
|
Ok(index) => Some(index),
|
||||||
Err(index) => index.checked_sub(1),
|
Err(index) => index.checked_sub(1),
|
||||||
}?;
|
}?;
|
||||||
|
// The binary search may not find the first symbol at the address, so work backwards
|
||||||
|
let target_address = symbols[closest_symbol_index].address();
|
||||||
|
while let Some(prev_index) = closest_symbol_index.checked_sub(1) {
|
||||||
|
if symbols[prev_index].address() != target_address {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
closest_symbol_index = prev_index;
|
||||||
|
}
|
||||||
let mut best_symbol: Option<&'r Symbol<'data, 'file>> = None;
|
let mut best_symbol: Option<&'r Symbol<'data, 'file>> = None;
|
||||||
for symbol in symbols.iter().skip(closest_symbol_index) {
|
for symbol in symbols.iter().skip(closest_symbol_index) {
|
||||||
if symbol.address() > address {
|
if symbol.address() > address {
|
||||||
|
@ -276,24 +283,15 @@ fn best_symbol<'r, 'data, 'file>(
|
||||||
fn find_section_symbol(
|
fn find_section_symbol(
|
||||||
arch: &dyn ObjArch,
|
arch: &dyn ObjArch,
|
||||||
obj_file: &File<'_>,
|
obj_file: &File<'_>,
|
||||||
|
section: &Section,
|
||||||
section_symbols: &[Symbol<'_, '_>],
|
section_symbols: &[Symbol<'_, '_>],
|
||||||
target: &Symbol<'_, '_>,
|
|
||||||
address: u64,
|
address: u64,
|
||||||
split_meta: Option<&SplitMeta>,
|
split_meta: Option<&SplitMeta>,
|
||||||
) -> Result<ObjSymbol> {
|
) -> Result<ObjSymbol> {
|
||||||
if let Some(symbol) = best_symbol(section_symbols, address) {
|
if let Some(symbol) = best_symbol(section_symbols, address) {
|
||||||
return to_obj_symbol(
|
return to_obj_symbol(arch, obj_file, symbol, split_meta);
|
||||||
arch,
|
|
||||||
obj_file,
|
|
||||||
symbol,
|
|
||||||
address as i64 - symbol.address() as i64,
|
|
||||||
split_meta,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// Fallback to section symbol
|
// Fallback to section symbol
|
||||||
let section_index =
|
|
||||||
target.section_index().ok_or_else(|| anyhow::Error::msg("Unknown section index"))?;
|
|
||||||
let section = obj_file.section_by_index(section_index)?;
|
|
||||||
Ok(ObjSymbol {
|
Ok(ObjSymbol {
|
||||||
name: section.name()?.to_string(),
|
name: section.name()?.to_string(),
|
||||||
demangled_name: None,
|
demangled_name: None,
|
||||||
|
@ -303,7 +301,7 @@ fn find_section_symbol(
|
||||||
size_known: false,
|
size_known: false,
|
||||||
kind: ObjSymbolKind::Section,
|
kind: ObjSymbolKind::Section,
|
||||||
flags: Default::default(),
|
flags: Default::default(),
|
||||||
addend: address as i64 - section.address() as i64,
|
orig_section_index: Some(section.index().0),
|
||||||
virtual_address: None,
|
virtual_address: None,
|
||||||
original_index: None,
|
original_index: None,
|
||||||
bytes: Vec::new(),
|
bytes: Vec::new(),
|
||||||
|
@ -314,7 +312,7 @@ fn relocations_by_section(
|
||||||
arch: &dyn ObjArch,
|
arch: &dyn ObjArch,
|
||||||
obj_file: &File<'_>,
|
obj_file: &File<'_>,
|
||||||
section: &ObjSection,
|
section: &ObjSection,
|
||||||
section_symbols: &[Symbol<'_, '_>],
|
section_symbols: &[Vec<Symbol<'_, '_>>],
|
||||||
split_meta: Option<&SplitMeta>,
|
split_meta: Option<&SplitMeta>,
|
||||||
) -> Result<Vec<ObjReloc>> {
|
) -> Result<Vec<ObjReloc>> {
|
||||||
let obj_section = obj_file.section_by_index(SectionIndex(section.orig_index))?;
|
let obj_section = obj_file.section_by_index(SectionIndex(section.orig_index))?;
|
||||||
|
@ -339,37 +337,36 @@ fn relocations_by_section(
|
||||||
_ => bail!("Unhandled relocation target: {:?}", reloc.target()),
|
_ => bail!("Unhandled relocation target: {:?}", reloc.target()),
|
||||||
};
|
};
|
||||||
let flags = reloc.flags(); // TODO validate reloc here?
|
let flags = reloc.flags(); // TODO validate reloc here?
|
||||||
let target_section = match symbol.section() {
|
let mut addend = if reloc.has_implicit_addend() {
|
||||||
SymbolSection::Common => Some(".comm".to_string()),
|
|
||||||
SymbolSection::Section(idx) => {
|
|
||||||
obj_file.section_by_index(idx).and_then(|s| s.name().map(|s| s.to_string())).ok()
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
let addend = if reloc.has_implicit_addend() {
|
|
||||||
arch.implcit_addend(obj_file, section, address, &reloc)?
|
arch.implcit_addend(obj_file, section, address, &reloc)?
|
||||||
} else {
|
} else {
|
||||||
reloc.addend()
|
reloc.addend()
|
||||||
};
|
};
|
||||||
// println!("Reloc: {reloc:?}, symbol: {symbol:?}, addend: {addend:#x}");
|
|
||||||
let target = match symbol.kind() {
|
let target = match symbol.kind() {
|
||||||
SymbolKind::Text | SymbolKind::Data | SymbolKind::Label | SymbolKind::Unknown => {
|
SymbolKind::Text | SymbolKind::Data | SymbolKind::Label | SymbolKind::Unknown => {
|
||||||
to_obj_symbol(arch, obj_file, &symbol, addend, split_meta)
|
to_obj_symbol(arch, obj_file, &symbol, split_meta)?
|
||||||
}
|
}
|
||||||
SymbolKind::Section => {
|
SymbolKind::Section => {
|
||||||
ensure!(addend >= 0, "Negative addend in reloc: {addend}");
|
ensure!(addend >= 0, "Negative addend in section reloc: {addend}");
|
||||||
find_section_symbol(
|
let section_index = symbol
|
||||||
|
.section_index()
|
||||||
|
.ok_or_else(|| anyhow!("Section symbol {symbol:?} has no section index"))?;
|
||||||
|
let section = obj_file.section_by_index(section_index)?;
|
||||||
|
let symbol = find_section_symbol(
|
||||||
arch,
|
arch,
|
||||||
obj_file,
|
obj_file,
|
||||||
section_symbols,
|
§ion,
|
||||||
&symbol,
|
§ion_symbols[section_index.0],
|
||||||
addend as u64,
|
addend as u64,
|
||||||
split_meta,
|
split_meta,
|
||||||
)
|
)?;
|
||||||
|
// Adjust addend to be relative to the selected symbol
|
||||||
|
addend = (symbol.address - section.address()) as i64;
|
||||||
|
symbol
|
||||||
}
|
}
|
||||||
kind => Err(anyhow!("Unhandled relocation symbol type {kind:?}")),
|
kind => bail!("Unhandled relocation symbol type {kind:?}"),
|
||||||
}?;
|
};
|
||||||
relocations.push(ObjReloc { flags, address, target, target_section });
|
relocations.push(ObjReloc { flags, address, target, addend });
|
||||||
}
|
}
|
||||||
Ok(relocations)
|
Ok(relocations)
|
||||||
}
|
}
|
||||||
|
@ -591,7 +588,7 @@ fn update_combined_symbol(symbol: ObjSymbol, address_change: i64) -> Result<ObjS
|
||||||
size_known: symbol.size_known,
|
size_known: symbol.size_known,
|
||||||
kind: symbol.kind,
|
kind: symbol.kind,
|
||||||
flags: symbol.flags,
|
flags: symbol.flags,
|
||||||
addend: symbol.addend,
|
orig_section_index: symbol.orig_section_index,
|
||||||
virtual_address: if let Some(virtual_address) = symbol.virtual_address {
|
virtual_address: if let Some(virtual_address) = symbol.virtual_address {
|
||||||
Some((virtual_address as i64 + address_change).try_into()?)
|
Some((virtual_address as i64 + address_change).try_into()?)
|
||||||
} else {
|
} else {
|
||||||
|
@ -617,8 +614,8 @@ fn combine_sections(section: ObjSection, combine: ObjSection) -> Result<ObjSecti
|
||||||
relocations.push(ObjReloc {
|
relocations.push(ObjReloc {
|
||||||
flags: reloc.flags,
|
flags: reloc.flags,
|
||||||
address: (reloc.address as i64 + address_change).try_into()?,
|
address: (reloc.address as i64 + address_change).try_into()?,
|
||||||
target: reloc.target, // TODO: Should be updated?
|
target: reloc.target, // TODO: Should be updated?
|
||||||
target_section: reloc.target_section, // TODO: Same as above
|
addend: reloc.addend,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,27 +695,38 @@ pub fn parse(data: &[u8], config: &DiffObjConfig) -> Result<ObjInfo> {
|
||||||
let obj_file = File::parse(data)?;
|
let obj_file = File::parse(data)?;
|
||||||
let arch = new_arch(&obj_file)?;
|
let arch = new_arch(&obj_file)?;
|
||||||
let split_meta = split_meta(&obj_file)?;
|
let split_meta = split_meta(&obj_file)?;
|
||||||
let mut sections = filter_sections(&obj_file, split_meta.as_ref())?;
|
|
||||||
let mut name_counts: HashMap<String, u32> = HashMap::new();
|
// Create sorted symbol list for each section
|
||||||
for section in &mut sections {
|
let mut section_symbols = Vec::with_capacity(obj_file.sections().count());
|
||||||
|
for section in obj_file.sections() {
|
||||||
let mut symbols = obj_file
|
let mut symbols = obj_file
|
||||||
.symbols()
|
.symbols()
|
||||||
.filter(|s| s.section_index() == Some(SectionIndex(section.orig_index)))
|
.filter(|s| s.section_index() == Some(section.index()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
symbols.sort_by_key(|s| s.address());
|
symbols.sort_by_key(|s| s.address());
|
||||||
|
let section_index = section.index().0;
|
||||||
|
if section_index >= section_symbols.len() {
|
||||||
|
section_symbols.resize_with(section_index + 1, Vec::new);
|
||||||
|
}
|
||||||
|
section_symbols[section_index] = symbols;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut sections = filter_sections(&obj_file, split_meta.as_ref())?;
|
||||||
|
let mut section_name_counts: HashMap<String, u32> = HashMap::new();
|
||||||
|
for section in &mut sections {
|
||||||
section.symbols = symbols_by_section(
|
section.symbols = symbols_by_section(
|
||||||
arch.as_ref(),
|
arch.as_ref(),
|
||||||
&obj_file,
|
&obj_file,
|
||||||
section,
|
section,
|
||||||
&symbols,
|
§ion_symbols[section.orig_index],
|
||||||
split_meta.as_ref(),
|
split_meta.as_ref(),
|
||||||
&mut name_counts,
|
&mut section_name_counts,
|
||||||
)?;
|
)?;
|
||||||
section.relocations = relocations_by_section(
|
section.relocations = relocations_by_section(
|
||||||
arch.as_ref(),
|
arch.as_ref(),
|
||||||
&obj_file,
|
&obj_file,
|
||||||
section,
|
section,
|
||||||
&symbols,
|
§ion_symbols,
|
||||||
split_meta.as_ref(),
|
split_meta.as_ref(),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ use std::default::Default;
|
||||||
use egui::{text::LayoutJob, Id, Label, Response, RichText, Sense, Widget};
|
use egui::{text::LayoutJob, Id, Label, Response, RichText, Sense, Widget};
|
||||||
use egui_extras::TableRow;
|
use egui_extras::TableRow;
|
||||||
use objdiff_core::{
|
use objdiff_core::{
|
||||||
arch::ObjArch,
|
|
||||||
diff::{
|
diff::{
|
||||||
display::{display_diff, DiffText, HighlightKind},
|
display::{display_diff, DiffText, HighlightKind},
|
||||||
ObjDiff, ObjInsDiff, ObjInsDiffKind,
|
ObjDiff, ObjInsDiff, ObjInsDiffKind,
|
||||||
|
@ -77,7 +76,7 @@ impl FunctionViewState {
|
||||||
|
|
||||||
fn ins_hover_ui(
|
fn ins_hover_ui(
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
arch: &dyn ObjArch,
|
obj: &ObjInfo,
|
||||||
section: &ObjSection,
|
section: &ObjSection,
|
||||||
ins: &ObjIns,
|
ins: &ObjIns,
|
||||||
symbol: &ObjSymbol,
|
symbol: &ObjSymbol,
|
||||||
|
@ -120,10 +119,17 @@ fn ins_hover_ui(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(reloc) = &ins.reloc {
|
if let Some(reloc) = &ins.reloc {
|
||||||
ui.label(format!("Relocation type: {}", arch.display_reloc(reloc.flags)));
|
ui.label(format!("Relocation type: {}", obj.arch.display_reloc(reloc.flags)));
|
||||||
ui.colored_label(appearance.highlight_color, format!("Name: {}", reloc.target.name));
|
ui.colored_label(appearance.highlight_color, format!("Name: {}", reloc.target.name));
|
||||||
if let Some(section) = &reloc.target_section {
|
if let Some(orig_section_index) = reloc.target.orig_section_index {
|
||||||
ui.colored_label(appearance.highlight_color, format!("Section: {section}"));
|
if let Some(section) =
|
||||||
|
obj.sections.iter().find(|s| s.orig_index == orig_section_index)
|
||||||
|
{
|
||||||
|
ui.colored_label(
|
||||||
|
appearance.highlight_color,
|
||||||
|
format!("Section: {}", section.name),
|
||||||
|
);
|
||||||
|
}
|
||||||
ui.colored_label(
|
ui.colored_label(
|
||||||
appearance.highlight_color,
|
appearance.highlight_color,
|
||||||
format!("Address: {:x}", reloc.target.address),
|
format!("Address: {:x}", reloc.target.address),
|
||||||
|
@ -132,9 +138,10 @@ fn ins_hover_ui(
|
||||||
appearance.highlight_color,
|
appearance.highlight_color,
|
||||||
format!("Size: {:x}", reloc.target.size),
|
format!("Size: {:x}", reloc.target.size),
|
||||||
);
|
);
|
||||||
if let Some(s) = arch
|
if let Some(s) = obj
|
||||||
|
.arch
|
||||||
.guess_data_type(ins)
|
.guess_data_type(ins)
|
||||||
.and_then(|ty| arch.display_data_type(ty, &reloc.target.bytes))
|
.and_then(|ty| obj.arch.display_data_type(ty, &reloc.target.bytes))
|
||||||
{
|
{
|
||||||
ui.colored_label(appearance.highlight_color, s);
|
ui.colored_label(appearance.highlight_color, s);
|
||||||
}
|
}
|
||||||
|
@ -370,7 +377,7 @@ fn asm_col_ui(
|
||||||
if let Some(ins) = &ins_diff.ins {
|
if let Some(ins) = &ins_diff.ins {
|
||||||
response.context_menu(|ui| ins_context_menu(ui, section, ins, symbol));
|
response.context_menu(|ui| ins_context_menu(ui, section, ins, symbol));
|
||||||
response.on_hover_ui_at_pointer(|ui| {
|
response.on_hover_ui_at_pointer(|ui| {
|
||||||
ins_hover_ui(ui, ctx.obj.arch.as_ref(), section, ins, symbol, appearance)
|
ins_hover_ui(ui, ctx.obj, section, ins, symbol, appearance)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
response
|
response
|
||||||
|
|
Loading…
Reference in New Issue