Implement diffing individual data symbols (#244)

* Implement diffing individual data symbols

* Remove unused code for diffing sections

* Data diff view: Make rows show offset within the symbol, not within the section

* Remove SelectedSymbol enum as it only has a single variant now

* Create fake data section symbols to allow diffing entire sections again

* Fix text sections not having their size zeroed out

* Update test snapshots

* Clean up code for inferring section symbol size

* Fix bug where PPC pool references weren't ignoring section symbols

* Update comment

* Always add unique section symbols for data sections

* Update test snapshots

* Remove unnecessary clone in format! call

* Auto-start mapping for unpaired data symbols
This commit is contained in:
LagoLunatic
2025-09-02 21:37:17 -04:00
committed by GitHub
parent 6fb4bb8855
commit 23009bf9a3
20 changed files with 687 additions and 221 deletions

View File

@@ -21,6 +21,7 @@ use crate::{
obj::{
FlowAnalysisResult, InstructionRef, Object, Relocation, RelocationFlags,
ResolvedInstructionRef, ResolvedRelocation, Section, Symbol, SymbolFlag, SymbolFlagSet,
SymbolKind,
},
};
@@ -832,6 +833,7 @@ fn make_fake_pool_reloc(
&& s.size > 0
&& !s.flags.contains(SymbolFlag::Hidden)
&& !s.flags.contains(SymbolFlag::Ignored)
&& s.kind != SymbolKind::Section
&& (s.address..s.address + s.size).contains(&target_address)
})?;
addend = target_address.checked_sub(symbols[target_symbol].address)? as i64;

View File

@@ -41,7 +41,13 @@ pub fn no_diff_code(
instruction_rows.push(InstructionDiffRow { ins_ref: Some(*i), ..Default::default() });
}
resolve_branches(&ops, &mut instruction_rows);
Ok(SymbolDiff { target_symbol: None, match_percent: None, diff_score: None, instruction_rows })
Ok(SymbolDiff {
target_symbol: None,
match_percent: None,
diff_score: None,
instruction_rows,
..Default::default()
})
}
const PENALTY_IMM_DIFF: u64 = 1;
@@ -147,12 +153,14 @@ pub fn diff_code(
match_percent: Some(match_percent),
diff_score: Some((diff_score, max_score)),
instruction_rows: left_rows,
..Default::default()
},
SymbolDiff {
target_symbol: Some(left_symbol_idx),
match_percent: Some(match_percent),
diff_score: Some((diff_score, max_score)),
instruction_rows: right_rows,
..Default::default()
},
))
}

View File

@@ -24,13 +24,13 @@ pub fn diff_bss_symbol(
target_symbol: Some(right_symbol_ref),
match_percent: Some(percent),
diff_score: None,
instruction_rows: vec![],
..Default::default()
},
SymbolDiff {
target_symbol: Some(left_symbol_ref),
match_percent: Some(percent),
diff_score: None,
instruction_rows: vec![],
..Default::default()
},
))
}
@@ -84,7 +84,83 @@ pub fn resolve_relocation<'obj>(
ResolvedRelocation { relocation: reloc, symbol }
}
/// Compares relocations contained with a certain data range.
/// Compares the bytes within a certain data range.
fn diff_data_range(left_data: &[u8], right_data: &[u8]) -> (f32, Vec<DataDiff>, Vec<DataDiff>) {
let ops = capture_diff_slices(Algorithm::Patience, left_data, right_data);
let bytes_match_ratio = get_diff_ratio(&ops, left_data.len(), right_data.len());
let mut left_data_diff = Vec::<DataDiff>::new();
let mut right_data_diff = Vec::<DataDiff>::new();
for op in ops {
let (tag, left_range, right_range) = op.as_tag_tuple();
let left_len = left_range.len();
let right_len = right_range.len();
let mut len = left_len.max(right_len);
let kind = match tag {
similar::DiffTag::Equal => DataDiffKind::None,
similar::DiffTag::Delete => DataDiffKind::Delete,
similar::DiffTag::Insert => DataDiffKind::Insert,
similar::DiffTag::Replace => {
// Ensure replacements are equal length
len = left_len.min(right_len);
DataDiffKind::Replace
}
};
let left_data = &left_data[left_range];
let right_data = &right_data[right_range];
left_data_diff.push(DataDiff {
data: left_data[..len.min(left_data.len())].to_vec(),
kind,
len,
..Default::default()
});
right_data_diff.push(DataDiff {
data: right_data[..len.min(right_data.len())].to_vec(),
kind,
len,
..Default::default()
});
if kind == DataDiffKind::Replace {
match left_len.cmp(&right_len) {
Ordering::Less => {
let len = right_len - left_len;
left_data_diff.push(DataDiff {
data: vec![],
kind: DataDiffKind::Insert,
len,
..Default::default()
});
right_data_diff.push(DataDiff {
data: right_data[left_len..right_len].to_vec(),
kind: DataDiffKind::Insert,
len,
..Default::default()
});
}
Ordering::Greater => {
let len = left_len - right_len;
left_data_diff.push(DataDiff {
data: left_data[right_len..left_len].to_vec(),
kind: DataDiffKind::Delete,
len,
..Default::default()
});
right_data_diff.push(DataDiff {
data: vec![],
kind: DataDiffKind::Delete,
len,
..Default::default()
});
}
Ordering::Equal => {}
}
}
}
(bytes_match_ratio, left_data_diff, right_data_diff)
}
/// Compares relocations contained within a certain data range.
fn diff_data_relocs_for_range<'left, 'right>(
left_obj: &'left Object,
right_obj: &'right Object,
@@ -186,76 +262,10 @@ pub fn diff_data_section(
.min(right_section.size);
let left_data = &left_section.data[..left_max as usize];
let right_data = &right_section.data[..right_max as usize];
let ops = capture_diff_slices(Algorithm::Patience, left_data, right_data);
let match_percent = get_diff_ratio(&ops, left_data.len(), right_data.len()) * 100.0;
let mut left_data_diff = Vec::<DataDiff>::new();
let mut right_data_diff = Vec::<DataDiff>::new();
for op in ops {
let (tag, left_range, right_range) = op.as_tag_tuple();
let left_len = left_range.len();
let right_len = right_range.len();
let mut len = left_len.max(right_len);
let kind = match tag {
similar::DiffTag::Equal => DataDiffKind::None,
similar::DiffTag::Delete => DataDiffKind::Delete,
similar::DiffTag::Insert => DataDiffKind::Insert,
similar::DiffTag::Replace => {
// Ensure replacements are equal length
len = left_len.min(right_len);
DataDiffKind::Replace
}
};
let left_data = &left_section.data[left_range];
let right_data = &right_section.data[right_range];
left_data_diff.push(DataDiff {
data: left_data[..len.min(left_data.len())].to_vec(),
kind,
len,
..Default::default()
});
right_data_diff.push(DataDiff {
data: right_data[..len.min(right_data.len())].to_vec(),
kind,
len,
..Default::default()
});
if kind == DataDiffKind::Replace {
match left_len.cmp(&right_len) {
Ordering::Less => {
let len = right_len - left_len;
left_data_diff.push(DataDiff {
data: vec![],
kind: DataDiffKind::Insert,
len,
..Default::default()
});
right_data_diff.push(DataDiff {
data: right_data[left_len..right_len].to_vec(),
kind: DataDiffKind::Insert,
len,
..Default::default()
});
}
Ordering::Greater => {
let len = left_len - right_len;
left_data_diff.push(DataDiff {
data: left_data[right_len..left_len].to_vec(),
kind: DataDiffKind::Delete,
len,
..Default::default()
});
right_data_diff.push(DataDiff {
data: vec![],
kind: DataDiffKind::Delete,
len,
..Default::default()
});
}
Ordering::Equal => {}
}
}
}
let (bytes_match_ratio, left_data_diff, right_data_diff) =
diff_data_range(left_data, right_data);
let match_percent = bytes_match_ratio * 100.0;
let mut left_reloc_diffs = Vec::new();
let mut right_reloc_diffs = Vec::new();
@@ -314,6 +324,55 @@ pub fn diff_data_section(
Ok((left_section_diff, right_section_diff))
}
pub fn no_diff_data_symbol(obj: &Object, symbol_index: usize) -> Result<SymbolDiff> {
let symbol = &obj.symbols[symbol_index];
let section_idx = symbol.section.ok_or_else(|| anyhow!("Data symbol section not found"))?;
let section = &obj.sections[section_idx];
let start = symbol
.address
.checked_sub(section.address)
.ok_or_else(|| anyhow!("Symbol address out of section bounds"))?;
let end = start + symbol.size;
if end > section.size {
return Err(anyhow!(
"Symbol {} size out of section bounds ({} > {})",
symbol.name,
end,
section.size
));
}
let range = start as usize..end as usize;
let data = &section.data[range.clone()];
let len = symbol.size as usize;
let data_diff =
vec![DataDiff { data: data.to_vec(), kind: DataDiffKind::None, len, ..Default::default() }];
let mut reloc_diffs = Vec::new();
for reloc in section.relocations.iter() {
if !range.contains(&(reloc.address as usize)) {
continue;
}
let reloc_len = obj.arch.data_reloc_size(reloc.flags);
let range = reloc.address as usize..reloc.address as usize + reloc_len;
reloc_diffs.push(DataRelocationDiff {
reloc: reloc.clone(),
kind: DataDiffKind::None,
range,
});
}
Ok(SymbolDiff {
target_symbol: None,
match_percent: None,
diff_score: None,
data_diff,
data_reloc_diff: reloc_diffs,
..Default::default()
})
}
pub fn diff_data_symbol(
left_obj: &Object,
right_obj: &Object,
@@ -362,6 +421,9 @@ pub fn diff_data_symbol(
let left_data = &left_section.data[left_range.clone()];
let right_data = &right_section.data[right_range.clone()];
let (bytes_match_ratio, left_data_diff, right_data_diff) =
diff_data_range(left_data, right_data);
let reloc_diffs = diff_data_relocs_for_range(
left_obj,
right_obj,
@@ -371,10 +433,9 @@ pub fn diff_data_symbol(
right_range,
);
let ops = capture_diff_slices(Algorithm::Patience, left_data, right_data);
let bytes_match_ratio = get_diff_ratio(&ops, left_data.len(), right_data.len());
let mut match_ratio = bytes_match_ratio;
let mut left_reloc_diffs = Vec::new();
let mut right_reloc_diffs = Vec::new();
if !reloc_diffs.is_empty() {
let mut total_reloc_bytes = 0;
let mut matching_reloc_bytes = 0;
@@ -390,6 +451,27 @@ pub fn diff_data_symbol(
if diff_kind == DataDiffKind::None {
matching_reloc_bytes += reloc_diff_len;
}
if let Some(left_reloc) = left_reloc {
let len = left_obj.arch.data_reloc_size(left_reloc.relocation.flags);
let range = left_reloc.relocation.address as usize
..left_reloc.relocation.address as usize + len;
left_reloc_diffs.push(DataRelocationDiff {
reloc: left_reloc.relocation.clone(),
kind: diff_kind,
range,
});
}
if let Some(right_reloc) = right_reloc {
let len = right_obj.arch.data_reloc_size(right_reloc.relocation.flags);
let range = right_reloc.relocation.address as usize
..right_reloc.relocation.address as usize + len;
right_reloc_diffs.push(DataRelocationDiff {
reloc: right_reloc.relocation.clone(),
kind: diff_kind,
range,
});
}
}
if total_reloc_bytes > 0 {
let relocs_match_ratio = matching_reloc_bytes as f32 / total_reloc_bytes as f32;
@@ -411,13 +493,17 @@ pub fn diff_data_symbol(
target_symbol: Some(right_symbol_idx),
match_percent: Some(match_percent),
diff_score: None,
instruction_rows: vec![],
data_diff: left_data_diff,
data_reloc_diff: left_reloc_diffs,
..Default::default()
},
SymbolDiff {
target_symbol: Some(left_symbol_idx),
match_percent: Some(match_percent),
diff_score: None,
instruction_rows: vec![],
data_diff: right_data_diff,
data_reloc_diff: right_reloc_diffs,
..Default::default()
},
))
}

View File

@@ -13,7 +13,8 @@ use crate::{
code::{diff_code, no_diff_code},
data::{
diff_bss_section, diff_bss_symbol, diff_data_section, diff_data_symbol,
diff_generic_section, no_diff_bss_section, no_diff_data_section, symbol_name_matches,
diff_generic_section, no_diff_bss_section, no_diff_data_section, no_diff_data_symbol,
symbol_name_matches,
},
},
obj::{InstructionRef, Object, Relocation, SectionKind, Symbol, SymbolFlag},
@@ -44,6 +45,8 @@ pub struct SymbolDiff {
pub match_percent: Option<f32>,
pub diff_score: Option<(u64, u64)>,
pub instruction_rows: Vec<InstructionDiffRow>,
pub data_diff: Vec<DataDiff>,
pub data_reloc_diff: Vec<DataRelocationDiff>,
}
#[derive(Debug, Clone, Default)]
@@ -163,7 +166,7 @@ impl ObjectDiff {
target_symbol: None,
match_percent: None,
diff_score: None,
instruction_rows: vec![],
..Default::default()
});
}
for _ in obj.sections.iter() {
@@ -262,7 +265,11 @@ pub fn diff_objs(
left_out.symbols[left_symbol_ref] =
no_diff_code(left_obj, left_symbol_ref, diff_config)?;
}
SectionKind::Data | SectionKind::Bss | SectionKind::Common => {
SectionKind::Data => {
left_out.symbols[left_symbol_ref] =
no_diff_data_symbol(left_obj, left_symbol_ref)?;
}
SectionKind::Bss | SectionKind::Common => {
// Nothing needs to be done
}
SectionKind::Unknown => unreachable!(),
@@ -275,7 +282,11 @@ pub fn diff_objs(
right_out.symbols[right_symbol_ref] =
no_diff_code(right_obj, right_symbol_ref, diff_config)?;
}
SectionKind::Data | SectionKind::Bss | SectionKind::Common => {
SectionKind::Data => {
right_out.symbols[right_symbol_ref] =
no_diff_data_symbol(right_obj, right_symbol_ref)?;
}
SectionKind::Bss | SectionKind::Common => {
// Nothing needs to be done
}
SectionKind::Unknown => unreachable!(),

View File

@@ -15,7 +15,7 @@ use crate::{
diff::{DiffObjConfig, DiffSide},
obj::{
FlowAnalysisResult, Object, Relocation, RelocationFlags, Section, SectionData, SectionFlag,
SectionKind, Symbol, SymbolFlag, SymbolKind,
SectionKind, Symbol, SymbolFlag, SymbolFlagSet, SymbolKind,
split_meta::{SPLITMETA_SECTION, SplitMeta},
},
util::{align_data_slice_to, align_u64_to, read_u16, read_u32},
@@ -118,7 +118,7 @@ fn map_symbols(
split_meta: Option<&SplitMeta>,
) -> Result<(Vec<Symbol>, Vec<usize>)> {
let symbol_count = obj_file.symbols().count();
let mut symbols = Vec::<Symbol>::with_capacity(symbol_count);
let mut symbols = Vec::<Symbol>::with_capacity(symbol_count + obj_file.sections().count());
let mut symbol_indices = Vec::<usize>::with_capacity(symbol_count + 1);
for obj_symbol in obj_file.symbols() {
if symbol_indices.len() <= obj_symbol.index().0 {
@@ -135,6 +135,52 @@ fn map_symbols(
Ok((symbols, symbol_indices))
}
/// Add an extra fake symbol to the start of each data section in order to allow the user to diff
/// all of the data in the section at once by clicking on this fake symbol at the top of the list.
fn add_section_symbols(sections: &[Section], symbols: &mut Vec<Symbol>) {
for (section_idx, section) in sections.iter().enumerate() {
if section.kind != SectionKind::Data {
continue;
}
// Instead of naming the fake section symbol after `section.name` (e.g. ".data") we use
// `section.id` (e.g. ".data-0") so that it is unique when multiple sections with the same
// name exist and it also doesn't conflict with any real section symbols from the object.
let name = if section.flags.contains(SectionFlag::Combined) {
// For combined sections, `section.id` (e.g. ".data-combined") is inconsistent with
// uncombined section IDs, so we add the "-0" suffix to the name to enable proper
// pairing when one side had multiple sections combined and the other only had one
// section to begin with.
format!("[{}-0]", section.name)
} else {
format!("[{}]", section.id)
};
// `section.size` can include extra padding, so instead prefer using the address that the
// last symbol ends at when there are any symbols in the section.
let size = symbols
.iter()
.filter(|s| {
s.section == Some(section_idx) && s.kind == SymbolKind::Object && s.size > 0
})
.map(|s| s.address + s.size)
.max()
.unwrap_or(section.size);
symbols.push(Symbol {
name,
demangled_name: None,
address: 0,
size,
kind: SymbolKind::Section,
section: Some(section_idx),
flags: SymbolFlagSet::default() | SymbolFlag::Local,
align: None,
virtual_address: None,
});
}
}
/// 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.
fn is_local_label(symbol: &Symbol) -> bool {
@@ -216,7 +262,11 @@ fn infer_symbol_sizes(arch: &dyn Arch, symbols: &mut [Symbol], sections: &[Secti
let section = &sections[section_idx];
let next_address =
next_symbol.map(|s| s.address).unwrap_or_else(|| section.address + section.size);
let new_size = if section.kind == SectionKind::Code {
let new_size = if symbol.kind == SymbolKind::Section && section.kind == SectionKind::Data {
// Data sections already have always-visible section symbols created by objdiff to allow
// diffing them, so no need to unhide these.
0
} else if section.kind == SectionKind::Code {
arch.infer_function_size(symbol, section, next_address)?
} else {
next_address.saturating_sub(symbol.address)
@@ -954,6 +1004,7 @@ pub fn parse(data: &[u8], config: &DiffObjConfig, diff_side: DiffSide) -> Result
if config.combine_data_sections || config.combine_text_sections {
combine_sections(&mut sections, &mut symbols, config)?;
}
add_section_symbols(&sections, &mut symbols);
arch.post_init(&sections, &symbols);
let mut obj = Object {
arch,

View File

@@ -1507,6 +1507,19 @@ Object {
align: None,
virtual_address: None,
},
Symbol {
name: "[.data-0]",
demangled_name: None,
address: 0,
size: 76,
kind: Section,
section: Some(
2,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
],
sections: [
Section {

View File

@@ -449,4 +449,17 @@ expression: obj.symbols
align: None,
virtual_address: None,
},
Symbol {
name: "[.data-0]",
demangled_name: None,
address: 0,
size: 0,
kind: Section,
section: Some(
2,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
]

View File

@@ -10,10 +10,10 @@ expression: output
[(Address(20), Normal, 5), (Spacing(4), Normal, 0), (Opcode("jal", 2), Normal, 10), (Symbol(Symbol { name: "xglSleep", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Eol, Normal, 0)]
[(Address(24), Normal, 5), (Spacing(4), Normal, 0), (Opcode("nop", 113), Normal, 10), (Eol, Normal, 0)]
[(Address(28), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lw", 26), Normal, 10), (Argument(Opaque("$a1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%gp_rel("), Normal, 0), (Symbol(Symbol { name: "WorkEnd", demangled_name: None, address: 64, size: 4, kind: Object, section: Some(8), flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("$gp")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(32), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lui", 20), Normal, 10), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%hi("), Normal, 0), (Symbol(Symbol { name: "[.sdata]", demangled_name: None, address: 0, size: 64, kind: Section, section: Some(8), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(32), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lui", 20), Normal, 10), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%hi("), Normal, 0), (Symbol(Symbol { name: "[.sdata]", demangled_name: None, address: 0, size: 0, kind: Section, section: Some(8), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(36), Normal, 5), (Spacing(4), Normal, 0), (Opcode("daddu", 97), Normal, 10), (Argument(Opaque("$a2")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("$zero")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("$zero")), Normal, 0), (Eol, Normal, 0)]
[(Address(40), Normal, 5), (Spacing(4), Normal, 0), (Opcode("jal", 2), Normal, 10), (Symbol(Symbol { name: "xglSoundLoadEffect", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Eol, Normal, 0)]
[(Address(44), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addiu", 12), Normal, 10), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%lo("), Normal, 0), (Symbol(Symbol { name: "[.sdata]", demangled_name: None, address: 0, size: 64, kind: Section, section: Some(8), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(44), Normal, 5), (Spacing(4), Normal, 0), (Opcode("addiu", 12), Normal, 10), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%lo("), Normal, 0), (Symbol(Symbol { name: "[.sdata]", demangled_name: None, address: 0, size: 0, kind: Section, section: Some(8), flags: FlagSet(Local), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(48), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lui", 20), Normal, 10), (Argument(Opaque("$a0")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%hi("), Normal, 0), (Symbol(Symbol { name: "PacketBottomNewVu1DropMicroCode", demangled_name: None, address: 0, size: 12, kind: Object, section: Some(7), flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(52), Normal, 5), (Spacing(4), Normal, 0), (Opcode("lw", 26), Normal, 10), (Argument(Opaque("$a1")), Normal, 0), (Basic(", "), Normal, 0), (Basic("%gp_rel("), Normal, 0), (Symbol(Symbol { name: "WorkEnd", demangled_name: None, address: 64, size: 4, kind: Object, section: Some(8), flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Basic(")"), Normal, 0), (Basic("("), Normal, 0), (Argument(Opaque("$gp")), Normal, 0), (Basic(")"), Normal, 0), (Eol, Normal, 0)]
[(Address(56), Normal, 5), (Spacing(4), Normal, 0), (Opcode("jal", 2), Normal, 10), (Symbol(Symbol { name: "xglSoundLoadSwd", demangled_name: None, address: 0, size: 0, kind: Unknown, section: None, flags: FlagSet(Global), align: None, virtual_address: None }), Bright, 0), (Eol, Normal, 0)]

View File

@@ -112,7 +112,7 @@ Object {
name: "[.sdata]",
demangled_name: None,
address: 0,
size: 64,
size: 0,
kind: Section,
section: Some(
8,
@@ -673,6 +673,45 @@ Object {
align: None,
virtual_address: None,
},
Symbol {
name: "[.data-0]",
demangled_name: None,
address: 0,
size: 0,
kind: Section,
section: Some(
2,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.rodata-0]",
demangled_name: None,
address: 0,
size: 12,
kind: Section,
section: Some(
7,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.sdata-0]",
demangled_name: None,
address: 0,
size: 76,
kind: Section,
section: Some(
8,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
],
sections: [
Section {

View File

@@ -2645,6 +2645,8 @@ expression: "(target_symbol_diff, base_symbol_diff)"
arg_diff: [],
},
],
data_diff: [],
data_reloc_diff: [],
},
SymbolDiff {
target_symbol: Some(
@@ -5288,5 +5290,7 @@ expression: "(target_symbol_diff, base_symbol_diff)"
arg_diff: [],
},
],
data_diff: [],
data_reloc_diff: [],
},
)

View File

@@ -1,6 +1,5 @@
---
source: objdiff-core/tests/arch_ppc.rs
assertion_line: 70
expression: sections_display
---
[
@@ -37,7 +36,7 @@ expression: sections_display
),
symbols: [
SectionDisplaySymbol {
symbol: 2,
symbol: 16,
is_mapping_symbol: false,
},
],

View File

@@ -308,6 +308,32 @@ Object {
align: None,
virtual_address: None,
},
Symbol {
name: "[extab-0]",
demangled_name: None,
address: 0,
size: 40,
kind: Section,
section: Some(
1,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[extabindex-0]",
demangled_name: None,
address: 0,
size: 36,
kind: Section,
section: Some(
2,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
],
sections: [
Section {

View File

@@ -43,7 +43,7 @@ Object {
name: "[.ctors]",
demangled_name: None,
address: 0,
size: 4,
size: 0,
kind: Section,
section: Some(
1,
@@ -157,6 +157,19 @@ Object {
0,
),
},
Symbol {
name: "[.ctors-0]",
demangled_name: None,
address: 0,
size: 4,
kind: Section,
section: Some(
1,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
],
sections: [
Section {

View File

@@ -1101,6 +1101,45 @@ Object {
align: None,
virtual_address: None,
},
Symbol {
name: "[.XBLD$W-0]",
demangled_name: None,
address: 0,
size: 16,
kind: Section,
section: Some(
2,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.rdata-0]",
demangled_name: None,
address: 0,
size: 416,
kind: Section,
section: Some(
4,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.pdata-0]",
demangled_name: None,
address: 0,
size: 40,
kind: Section,
section: Some(
6,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
],
sections: [
Section {

View File

@@ -124,6 +124,19 @@ Object {
align: None,
virtual_address: None,
},
Symbol {
name: "[.data-0]",
demangled_name: None,
address: 0,
size: 10,
kind: Section,
section: Some(
1,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
],
sections: [
Section {

View File

@@ -854,6 +854,201 @@ Object {
align: None,
virtual_address: None,
},
Symbol {
name: "[.xdata-0]",
demangled_name: None,
address: 0,
size: 8,
kind: Section,
section: Some(
7,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.pdata-0]",
demangled_name: None,
address: 0,
size: 12,
kind: Section,
section: Some(
8,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.xdata-1]",
demangled_name: None,
address: 0,
size: 8,
kind: Section,
section: Some(
9,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.pdata-1]",
demangled_name: None,
address: 0,
size: 12,
kind: Section,
section: Some(
10,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.xdata-2]",
demangled_name: None,
address: 0,
size: 8,
kind: Section,
section: Some(
11,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.pdata-2]",
demangled_name: None,
address: 0,
size: 12,
kind: Section,
section: Some(
12,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.xdata-3]",
demangled_name: None,
address: 0,
size: 8,
kind: Section,
section: Some(
13,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.pdata-3]",
demangled_name: None,
address: 0,
size: 12,
kind: Section,
section: Some(
14,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.rdata-0]",
demangled_name: None,
address: 0,
size: 256,
kind: Section,
section: Some(
15,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.xdata-4]",
demangled_name: None,
address: 0,
size: 20,
kind: Section,
section: Some(
16,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.pdata-4]",
demangled_name: None,
address: 0,
size: 12,
kind: Section,
section: Some(
17,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.rtc$IMZ-0]",
demangled_name: None,
address: 0,
size: 8,
kind: Section,
section: Some(
19,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.rtc$TMZ-0]",
demangled_name: None,
address: 0,
size: 8,
kind: Section,
section: Some(
20,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.rdata-1]",
demangled_name: None,
address: 0,
size: 4,
kind: Section,
section: Some(
21,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
Symbol {
name: "[.rdata-2]",
demangled_name: None,
address: 0,
size: 4,
kind: Section,
section: Some(
22,
),
flags: FlagSet(Local),
align: None,
virtual_address: None,
},
],
sections: [
Section {