Skip to content

Commit ab2e84a

Browse files
committed
Deprioritize generated GCC symbols in find_section_symbol
Resolves #115
1 parent 9596051 commit ab2e84a

File tree

1 file changed

+80
-40
lines changed

1 file changed

+80
-40
lines changed

objdiff-core/src/obj/read.rs

Lines changed: 80 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -152,26 +152,23 @@ fn symbols_by_section(
152152
arch: &dyn ObjArch,
153153
obj_file: &File<'_>,
154154
section: &ObjSection,
155+
section_symbols: &[Symbol<'_, '_>],
155156
split_meta: Option<&SplitMeta>,
156157
name_counts: &mut HashMap<String, u32>,
157158
) -> Result<Vec<ObjSymbol>> {
158159
let mut result = Vec::<ObjSymbol>::new();
159-
for symbol in obj_file.symbols() {
160+
for symbol in section_symbols {
160161
if symbol.kind() == SymbolKind::Section {
161162
continue;
162163
}
163-
if let Some(index) = symbol.section().index() {
164-
if index.0 == section.orig_index {
165-
if symbol.is_local() && section.kind == ObjSectionKind::Code {
166-
// TODO strip local syms in diff?
167-
let name = symbol.name().context("Failed to process symbol name")?;
168-
if symbol.size() == 0 || name.starts_with("lbl_") {
169-
continue;
170-
}
171-
}
172-
result.push(to_obj_symbol(arch, obj_file, &symbol, 0, split_meta)?);
164+
if symbol.is_local() && section.kind == ObjSectionKind::Code {
165+
// TODO strip local syms in diff?
166+
let name = symbol.name().context("Failed to process symbol name")?;
167+
if symbol.size() == 0 || name.starts_with("lbl_") {
168+
continue;
173169
}
174170
}
171+
result.push(to_obj_symbol(arch, obj_file, symbol, 0, split_meta)?);
175172
}
176173
result.sort_by(|a, b| a.address.cmp(&b.address).then(a.size.cmp(&b.size)));
177174
let mut iter = result.iter_mut().peekable();
@@ -221,47 +218,71 @@ fn common_symbols(
221218
.collect::<Result<Vec<ObjSymbol>>>()
222219
}
223220

221+
const LOW_PRIORITY_SYMBOLS: &[&str] =
222+
&["__gnu_compiled_c", "__gnu_compiled_cplusplus", "gcc2_compiled."];
223+
224+
fn best_symbol<'r, 'data, 'file>(
225+
symbols: &'r [Symbol<'data, 'file>],
226+
address: u64,
227+
) -> Option<&'r Symbol<'data, 'file>> {
228+
let closest_symbol_index = match symbols.binary_search_by_key(&address, |s| s.address()) {
229+
Ok(index) => Some(index),
230+
Err(index) => index.checked_sub(1),
231+
}?;
232+
let mut best_symbol: Option<&'r Symbol<'data, 'file>> = None;
233+
for symbol in symbols.iter().skip(closest_symbol_index) {
234+
if symbol.address() > address {
235+
break;
236+
}
237+
if symbol.kind() == SymbolKind::Section
238+
|| (symbol.size() > 0 && (symbol.address() + symbol.size()) <= address)
239+
{
240+
continue;
241+
}
242+
// TODO priority ranking with visibility, etc
243+
if let Some(best) = best_symbol {
244+
if LOW_PRIORITY_SYMBOLS.contains(&best.name().unwrap_or_default())
245+
&& !LOW_PRIORITY_SYMBOLS.contains(&symbol.name().unwrap_or_default())
246+
{
247+
best_symbol = Some(symbol);
248+
}
249+
} else {
250+
best_symbol = Some(symbol);
251+
}
252+
}
253+
best_symbol
254+
}
255+
224256
fn find_section_symbol(
225257
arch: &dyn ObjArch,
226258
obj_file: &File<'_>,
259+
section_symbols: &[Symbol<'_, '_>],
227260
target: &Symbol<'_, '_>,
228261
address: u64,
229262
split_meta: Option<&SplitMeta>,
230263
) -> Result<ObjSymbol> {
264+
if let Some(symbol) = best_symbol(section_symbols, address) {
265+
return to_obj_symbol(
266+
arch,
267+
obj_file,
268+
symbol,
269+
address as i64 - symbol.address() as i64,
270+
split_meta,
271+
);
272+
}
273+
// Fallback to section symbol
231274
let section_index =
232275
target.section_index().ok_or_else(|| anyhow::Error::msg("Unknown section index"))?;
233276
let section = obj_file.section_by_index(section_index)?;
234-
let mut closest_symbol: Option<Symbol<'_, '_>> = None;
235-
for symbol in obj_file.symbols() {
236-
if !matches!(symbol.section_index(), Some(idx) if idx == section_index) {
237-
continue;
238-
}
239-
if symbol.kind() == SymbolKind::Section || symbol.address() != address {
240-
if symbol.address() < address
241-
&& symbol.size() != 0
242-
&& (closest_symbol.is_none()
243-
|| matches!(&closest_symbol, Some(s) if s.address() <= symbol.address()))
244-
{
245-
closest_symbol = Some(symbol);
246-
}
247-
continue;
248-
}
249-
return to_obj_symbol(arch, obj_file, &symbol, 0, split_meta);
250-
}
251-
let (name, offset) = closest_symbol
252-
.and_then(|s| s.name().map(|n| (n, s.address())).ok())
253-
.or_else(|| section.name().map(|n| (n, section.address())).ok())
254-
.unwrap_or(("<unknown>", 0));
255-
let offset_addr = address - offset;
256277
Ok(ObjSymbol {
257-
name: name.to_string(),
278+
name: section.name()?.to_string(),
258279
demangled_name: None,
259-
address: offset,
260-
section_address: address - section.address(),
280+
address: section.address(),
281+
section_address: 0,
261282
size: 0,
262283
size_known: false,
263284
flags: Default::default(),
264-
addend: offset_addr as i64,
285+
addend: address as i64 - section.address() as i64,
265286
virtual_address: None,
266287
original_index: None,
267288
bytes: Vec::new(),
@@ -272,6 +293,7 @@ fn relocations_by_section(
272293
arch: &dyn ObjArch,
273294
obj_file: &File<'_>,
274295
section: &ObjSection,
296+
section_symbols: &[Symbol<'_, '_>],
275297
split_meta: Option<&SplitMeta>,
276298
) -> Result<Vec<ObjReloc>> {
277299
let obj_section = obj_file.section_by_index(SectionIndex(section.orig_index))?;
@@ -315,7 +337,14 @@ fn relocations_by_section(
315337
}
316338
SymbolKind::Section => {
317339
ensure!(addend >= 0, "Negative addend in reloc: {addend}");
318-
find_section_symbol(arch, obj_file, &symbol, addend as u64, split_meta)
340+
find_section_symbol(
341+
arch,
342+
obj_file,
343+
section_symbols,
344+
&symbol,
345+
addend as u64,
346+
split_meta,
347+
)
319348
}
320349
kind => Err(anyhow!("Unhandled relocation symbol type {kind:?}")),
321350
}?;
@@ -650,15 +679,26 @@ pub fn parse(data: &[u8], config: &DiffObjConfig) -> Result<ObjInfo> {
650679
let mut sections = filter_sections(&obj_file, split_meta.as_ref())?;
651680
let mut name_counts: HashMap<String, u32> = HashMap::new();
652681
for section in &mut sections {
682+
let mut symbols = obj_file
683+
.symbols()
684+
.filter(|s| s.section_index() == Some(SectionIndex(section.orig_index)))
685+
.collect::<Vec<_>>();
686+
symbols.sort_by_key(|s| s.address());
653687
section.symbols = symbols_by_section(
654688
arch.as_ref(),
655689
&obj_file,
656690
section,
691+
&symbols,
657692
split_meta.as_ref(),
658693
&mut name_counts,
659694
)?;
660-
section.relocations =
661-
relocations_by_section(arch.as_ref(), &obj_file, section, split_meta.as_ref())?;
695+
section.relocations = relocations_by_section(
696+
arch.as_ref(),
697+
&obj_file,
698+
section,
699+
&symbols,
700+
split_meta.as_ref(),
701+
)?;
662702
}
663703
if config.combine_data_sections {
664704
combine_data_sections(&mut sections)?;

0 commit comments

Comments
 (0)