threatflux_binary_analysis/analysis/
symbols.rs

1use crate::types::Symbol;
2#[cfg(feature = "symbol-resolution")]
3use addr2line::demangle_auto;
4#[cfg(feature = "symbol-resolution")]
5use gimli::DW_LANG_C_plus_plus;
6#[cfg(feature = "symbol-resolution")]
7use std::borrow::Cow;
8
9/// Demangle symbol names using DWARF demangling facilities.
10///
11/// This function populates the `demangled_name` field for each provided
12/// [`Symbol`], leaving existing values intact.
13#[cfg(feature = "symbol-resolution")]
14pub fn demangle_symbols(symbols: &mut [Symbol]) {
15    for symbol in symbols.iter_mut() {
16        if symbol.demangled_name.is_none() {
17            let demangled = demangle_auto(Cow::Borrowed(&symbol.name), Some(DW_LANG_C_plus_plus));
18            let demangled = demangled.to_string();
19            if demangled != symbol.name {
20                symbol.demangled_name = Some(demangled);
21            }
22        }
23    }
24}
25
26#[cfg(test)]
27mod tests {
28    use super::*;
29    use crate::types::{SymbolBinding, SymbolType, SymbolVisibility};
30
31    #[cfg(feature = "symbol-resolution")]
32    #[test]
33    fn test_demangle_symbols() {
34        let mut symbols = vec![
35            Symbol {
36                name: "_ZN3foo3barEv".into(),
37                demangled_name: None,
38                address: 0,
39                size: 0,
40                symbol_type: SymbolType::Function,
41                binding: SymbolBinding::Global,
42                visibility: SymbolVisibility::Default,
43                section_index: None,
44            },
45            Symbol {
46                name: "plain_symbol".into(),
47                demangled_name: None,
48                address: 0,
49                size: 0,
50                symbol_type: SymbolType::Object,
51                binding: SymbolBinding::Global,
52                visibility: SymbolVisibility::Default,
53                section_index: None,
54            },
55        ];
56
57        demangle_symbols(&mut symbols);
58
59        assert_eq!(symbols[0].demangled_name.as_deref(), Some("foo::bar()"));
60        assert!(symbols[1].demangled_name.is_none());
61    }
62}