mirror of
https://github.com/encounter/objdiff.git
synced 2025-12-08 21:17:59 +00:00
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:
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
@@ -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 = §ion.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()
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
@@ -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!(),
|
||||
|
||||
@@ -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 = §ions[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(§ions, &mut symbols);
|
||||
arch.post_init(§ions, &symbols);
|
||||
let mut obj = Object {
|
||||
arch,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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: [],
|
||||
},
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user