mirror of
https://github.com/encounter/objdiff.git
synced 2025-08-24 04:32:13 +00:00
Compare commits
No commits in common. "main" and "v3.0.0" have entirely different histories.
@ -90,23 +90,17 @@ file as well. You can then add `objdiff.json` to your `.gitignore` to prevent it
|
|||||||
"build_base": true,
|
"build_base": true,
|
||||||
"watch_patterns": [
|
"watch_patterns": [
|
||||||
"*.c",
|
"*.c",
|
||||||
"*.cc",
|
|
||||||
"*.cp",
|
"*.cp",
|
||||||
"*.cpp",
|
"*.cpp",
|
||||||
"*.cxx",
|
"*.cxx",
|
||||||
"*.c++",
|
|
||||||
"*.h",
|
"*.h",
|
||||||
"*.hh",
|
|
||||||
"*.hp",
|
"*.hp",
|
||||||
"*.hpp",
|
"*.hpp",
|
||||||
"*.hxx",
|
"*.hxx",
|
||||||
"*.h++",
|
|
||||||
"*.pch",
|
|
||||||
"*.pch++",
|
|
||||||
"*.inc",
|
|
||||||
"*.s",
|
"*.s",
|
||||||
"*.S",
|
"*.S",
|
||||||
"*.asm",
|
"*.asm",
|
||||||
|
"*.inc",
|
||||||
"*.py",
|
"*.py",
|
||||||
"*.yml",
|
"*.yml",
|
||||||
"*.txt",
|
"*.txt",
|
||||||
|
@ -57,23 +57,17 @@
|
|||||||
},
|
},
|
||||||
"default": [
|
"default": [
|
||||||
"*.c",
|
"*.c",
|
||||||
"*.cc",
|
|
||||||
"*.cp",
|
"*.cp",
|
||||||
"*.cpp",
|
"*.cpp",
|
||||||
"*.cxx",
|
"*.cxx",
|
||||||
"*.c++",
|
|
||||||
"*.h",
|
"*.h",
|
||||||
"*.hh",
|
|
||||||
"*.hp",
|
"*.hp",
|
||||||
"*.hpp",
|
"*.hpp",
|
||||||
"*.hxx",
|
"*.hxx",
|
||||||
"*.h++",
|
|
||||||
"*.pch",
|
|
||||||
"*.pch++",
|
|
||||||
"*.inc",
|
|
||||||
"*.s",
|
"*.s",
|
||||||
"*.S",
|
"*.S",
|
||||||
"*.asm",
|
"*.asm",
|
||||||
|
"*.inc",
|
||||||
"*.py",
|
"*.py",
|
||||||
"*.yml",
|
"*.yml",
|
||||||
"*.txt",
|
"*.txt",
|
||||||
|
@ -675,7 +675,7 @@ fn make_symbol_ref(symbol: &object::Symbol) -> Result<ExtabSymbolRef> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct PoolReference {
|
struct PoolReference {
|
||||||
addr_src_gpr: powerpc::GPR,
|
addr_src_gpr: powerpc::GPR,
|
||||||
addr_offset: i64,
|
addr_offset: i16,
|
||||||
addr_dst_gpr: Option<powerpc::GPR>,
|
addr_dst_gpr: Option<powerpc::GPR>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,20 +683,16 @@ struct PoolReference {
|
|||||||
// If so, return information pertaining to where the instruction is getting that address from and
|
// If so, return information pertaining to where the instruction is getting that address from and
|
||||||
// what it's doing with the address (e.g. copying it into another register, adding an offset, etc).
|
// what it's doing with the address (e.g. copying it into another register, adding an offset, etc).
|
||||||
fn get_pool_reference_for_inst(
|
fn get_pool_reference_for_inst(
|
||||||
ins: powerpc::Ins,
|
opcode: powerpc::Opcode,
|
||||||
simplified: &powerpc::ParsedIns,
|
simplified: &powerpc::ParsedIns,
|
||||||
) -> Option<PoolReference> {
|
) -> Option<PoolReference> {
|
||||||
use powerpc::{Argument, Opcode};
|
use powerpc::{Argument, Opcode};
|
||||||
let args = &simplified.args;
|
let args = &simplified.args;
|
||||||
if flow_analysis::guess_data_type_from_load_store_inst_op(ins.op).is_some() {
|
if flow_analysis::guess_data_type_from_load_store_inst_op(opcode).is_some() {
|
||||||
match (args[1], args[2]) {
|
match (args[1], args[2]) {
|
||||||
(Argument::Offset(offset), Argument::GPR(addr_src_gpr)) => {
|
(Argument::Offset(offset), Argument::GPR(addr_src_gpr)) => {
|
||||||
// e.g. lwz. Immediate offset.
|
// e.g. lwz. Immediate offset.
|
||||||
Some(PoolReference {
|
Some(PoolReference { addr_src_gpr, addr_offset: offset.0, addr_dst_gpr: None })
|
||||||
addr_src_gpr,
|
|
||||||
addr_offset: offset.0 as i64,
|
|
||||||
addr_dst_gpr: None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
(Argument::GPR(addr_src_gpr), Argument::GPR(_offset_gpr)) => {
|
(Argument::GPR(addr_src_gpr), Argument::GPR(_offset_gpr)) => {
|
||||||
// e.g. lwzx. The offset is in a register and was likely calculated from an index.
|
// e.g. lwzx. The offset is in a register and was likely calculated from an index.
|
||||||
@ -716,51 +712,17 @@ fn get_pool_reference_for_inst(
|
|||||||
// If either of these match, we also want to return the destination register that the
|
// If either of these match, we also want to return the destination register that the
|
||||||
// address is being copied into so that we can detect any future references to that new
|
// address is being copied into so that we can detect any future references to that new
|
||||||
// register as well.
|
// register as well.
|
||||||
match (ins.op, args[0], args[1], args[2]) {
|
match (opcode, args[0], args[1], args[2]) {
|
||||||
(
|
(
|
||||||
// `addi` or `subi`
|
|
||||||
Opcode::Addi,
|
Opcode::Addi,
|
||||||
Argument::GPR(addr_dst_gpr),
|
Argument::GPR(addr_dst_gpr),
|
||||||
Argument::GPR(addr_src_gpr),
|
Argument::GPR(addr_src_gpr),
|
||||||
Argument::Simm(simm),
|
Argument::Simm(simm),
|
||||||
) => {
|
) => Some(PoolReference {
|
||||||
let offset = if simplified.mnemonic == "addi" { simm.0 } else { -simm.0 };
|
addr_src_gpr,
|
||||||
Some(PoolReference {
|
addr_offset: simm.0,
|
||||||
addr_src_gpr,
|
addr_dst_gpr: Some(addr_dst_gpr),
|
||||||
addr_offset: offset as i64,
|
}),
|
||||||
addr_dst_gpr: Some(addr_dst_gpr),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
(
|
|
||||||
// `addis`
|
|
||||||
Opcode::Addis,
|
|
||||||
Argument::GPR(addr_dst_gpr),
|
|
||||||
Argument::GPR(addr_src_gpr),
|
|
||||||
Argument::Uimm(uimm), // Note: `addis` uses UIMM, unlike `addi`, `subi`, and `subis`
|
|
||||||
) => {
|
|
||||||
assert_eq!(simplified.mnemonic, "addis");
|
|
||||||
let offset = (uimm.0 as i64) << 16;
|
|
||||||
Some(PoolReference {
|
|
||||||
addr_src_gpr,
|
|
||||||
addr_offset: offset,
|
|
||||||
addr_dst_gpr: Some(addr_dst_gpr),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
(
|
|
||||||
// `subis`
|
|
||||||
Opcode::Addis,
|
|
||||||
Argument::GPR(addr_dst_gpr),
|
|
||||||
Argument::GPR(addr_src_gpr),
|
|
||||||
Argument::Simm(simm),
|
|
||||||
) => {
|
|
||||||
assert_eq!(simplified.mnemonic, "subis");
|
|
||||||
let offset = (simm.0 as i64) << 16;
|
|
||||||
Some(PoolReference {
|
|
||||||
addr_src_gpr,
|
|
||||||
addr_offset: offset,
|
|
||||||
addr_dst_gpr: Some(addr_dst_gpr),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
(
|
(
|
||||||
// `mr` or `mr.`
|
// `mr` or `mr.`
|
||||||
Opcode::Or,
|
Opcode::Or,
|
||||||
@ -815,13 +777,13 @@ fn clear_overwritten_gprs(ins: powerpc::Ins, gpr_pool_relocs: &mut BTreeMap<u8,
|
|||||||
// Also, if this instruction is accessing the middle of a symbol instead of the start, we add an
|
// Also, if this instruction is accessing the middle of a symbol instead of the start, we add an
|
||||||
// addend to indicate that.
|
// addend to indicate that.
|
||||||
fn make_fake_pool_reloc(
|
fn make_fake_pool_reloc(
|
||||||
offset: i64,
|
offset: i16,
|
||||||
cur_addr: u32,
|
cur_addr: u32,
|
||||||
pool_reloc: &Relocation,
|
pool_reloc: &Relocation,
|
||||||
symbols: &[Symbol],
|
symbols: &[Symbol],
|
||||||
) -> Option<Relocation> {
|
) -> Option<Relocation> {
|
||||||
let pool_reloc = resolve_relocation(symbols, pool_reloc);
|
let pool_reloc = resolve_relocation(symbols, pool_reloc);
|
||||||
let offset_from_pool = pool_reloc.relocation.addend + offset;
|
let offset_from_pool = pool_reloc.relocation.addend + offset as i64;
|
||||||
let target_address = pool_reloc.symbol.address.checked_add_signed(offset_from_pool)?;
|
let target_address = pool_reloc.symbol.address.checked_add_signed(offset_from_pool)?;
|
||||||
let target_symbol;
|
let target_symbol;
|
||||||
let addend;
|
let addend;
|
||||||
@ -984,7 +946,7 @@ fn generate_fake_pool_relocations_for_function(
|
|||||||
clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
|
clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(pool_ref) = get_pool_reference_for_inst(ins, &simplified) {
|
} else if let Some(pool_ref) = get_pool_reference_for_inst(ins.op, &simplified) {
|
||||||
// This instruction doesn't have a real relocation, so it may be a reference to one of
|
// This instruction doesn't have a real relocation, so it may be a reference to one of
|
||||||
// the already-loaded pools.
|
// the already-loaded pools.
|
||||||
if let Some(pool_reloc) = gpr_pool_relocs.get(&pool_ref.addr_src_gpr.0) {
|
if let Some(pool_reloc) = gpr_pool_relocs.get(&pool_ref.addr_src_gpr.0) {
|
||||||
@ -1003,7 +965,7 @@ fn generate_fake_pool_relocations_for_function(
|
|||||||
// with the offset within the .data section of an array variable into r21.
|
// with the offset within the .data section of an array variable into r21.
|
||||||
// Then the body of the loop will `lwzx` one of the array elements from r21.
|
// Then the body of the loop will `lwzx` one of the array elements from r21.
|
||||||
let mut new_reloc = pool_reloc.clone();
|
let mut new_reloc = pool_reloc.clone();
|
||||||
new_reloc.addend += pool_ref.addr_offset;
|
new_reloc.addend += pool_ref.addr_offset as i64;
|
||||||
gpr_pool_relocs.insert(addr_dst_gpr.0, new_reloc);
|
gpr_pool_relocs.insert(addr_dst_gpr.0, new_reloc);
|
||||||
} else {
|
} else {
|
||||||
clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
|
clear_overwritten_gprs(ins, &mut gpr_pool_relocs);
|
||||||
|
@ -204,9 +204,8 @@ pub struct ScratchConfig {
|
|||||||
pub const CONFIG_FILENAMES: [&str; 3] = ["objdiff.json", "objdiff.yml", "objdiff.yaml"];
|
pub const CONFIG_FILENAMES: [&str; 3] = ["objdiff.json", "objdiff.yml", "objdiff.yaml"];
|
||||||
|
|
||||||
pub const DEFAULT_WATCH_PATTERNS: &[&str] = &[
|
pub const DEFAULT_WATCH_PATTERNS: &[&str] = &[
|
||||||
"*.c", "*.cc", "*.cp", "*.cpp", "*.cxx", "*.c++", "*.h", "*.hh", "*.hp", "*.hpp", "*.hxx",
|
"*.c", "*.cp", "*.cpp", "*.cxx", "*.h", "*.hp", "*.hpp", "*.hxx", "*.s", "*.S", "*.asm",
|
||||||
"*.h++", "*.pch", "*.pch++", "*.inc", "*.s", "*.S", "*.asm", "*.py", "*.yml", "*.txt",
|
"*.inc", "*.py", "*.yml", "*.txt", "*.json",
|
||||||
"*.json",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const DEFAULT_IGNORE_PATTERNS: &[&str] = &["build/**/*"];
|
pub const DEFAULT_IGNORE_PATTERNS: &[&str] = &["build/**/*"];
|
||||||
|
@ -130,7 +130,7 @@ fn map_symbols(
|
|||||||
/// When inferring a symbol's size, we ignore symbols that start with specific prefixes. They are
|
/// When inferring a symbol's size, we ignore symbols that start with specific prefixes. They are
|
||||||
/// usually emitted as branch targets and do not represent the start of a function or object.
|
/// usually emitted as branch targets and do not represent the start of a function or object.
|
||||||
fn is_local_label(symbol: &Symbol) -> bool {
|
fn is_local_label(symbol: &Symbol) -> bool {
|
||||||
const LABEL_PREFIXES: &[&str] = &[".L", "LAB_", "switchD_"];
|
const LABEL_PREFIXES: &[&str] = &[".L", "LAB_"];
|
||||||
symbol.size == 0
|
symbol.size == 0
|
||||||
&& symbol.flags.contains(SymbolFlag::Local)
|
&& symbol.flags.contains(SymbolFlag::Local)
|
||||||
&& LABEL_PREFIXES.iter().any(|p| symbol.name.starts_with(p))
|
&& LABEL_PREFIXES.iter().any(|p| symbol.name.starts_with(p))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user