Skip to content

Commit 3632dca

Browse files
committed
Migrate Rust demangler bindings and consumers
Introduce Rust config/result types and custom-demangler callbacks for the new C contract, update examples and regression tests, migrate Rust-based plugins, remove the obsolete standalone simplifier wrapper, and fold the final rustfmt/clippy fixes into the migration.
1 parent 8c9f02c commit 3632dca

16 files changed

Lines changed: 453 additions & 385 deletions

File tree

plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ use crate::{
2121
use binaryninja::{
2222
binary_view::{BinaryView, BinaryViewBase},
2323
debuginfo::{DebugFunctionInfo, DebugInfo},
24+
demangle::simplify_demangled_template_name,
2425
platform::Platform,
2526
rc::*,
2627
symbol::SymbolType,
27-
template_simplifier::simplify_str_to_fqn,
2828
types::{FunctionParameter, Type},
2929
variable::NamedVariableWithType,
3030
};
@@ -733,9 +733,8 @@ impl DebugInfoBuilder {
733733
let symbol_full_name = symbol.full_name();
734734

735735
// If our name has fewer namespaces than the existing name, assume we lost the namespace info
736-
if simplify_str_to_fqn(func_full_name, true).items.len()
737-
< simplify_str_to_fqn(symbol_full_name.clone(), true)
738-
.items
736+
if simplify_demangled_template_name(func_full_name).len()
737+
< simplify_demangled_template_name(symbol_full_name.to_string_lossy())
739738
.len()
740739
{
741740
func.full_name = Some(symbol_full_name.to_string_lossy().to_string());

plugins/dwarf/dwarf_import/src/functions.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use crate::dwarfdebuginfo::{DebugInfoBuilder, DebugInfoBuilderContext, TypeUID};
1818
use crate::types::get_type;
1919
use crate::{helpers::*, ReaderType};
2020

21-
use binaryninja::template_simplifier::simplify_str_to_str;
2221
use cpp_demangle::DemangleOptions;
2322
use gimli::{constants, AttributeValue, DebuggingInformationEntry, Dwarf, Operation, Unit};
2423
use regex::Regex;
@@ -134,8 +133,7 @@ pub(crate) fn parse_function_entry<R: ReaderType>(
134133
if let Ok(sym) = cpp_demangle::Symbol::new(possibly_mangled_name) {
135134
if let Ok(demangled) = sym.demangle(demangle_options) {
136135
let cleaned = abi_regex.replace_all(&demangled, "");
137-
let simplified = simplify_str_to_str(&cleaned);
138-
full_name = Some(simplified.to_string_lossy().to_string());
136+
full_name = Some(cleaned.to_string());
139137
}
140138
}
141139
}

plugins/dwarf/dwarf_import/src/lib.rs

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ use binaryninja::{
3333
binary_view::BinaryView,
3434
debuginfo::{CustomDebugInfoParser, DebugInfo, DebugInfoParser},
3535
settings::Settings,
36-
template_simplifier::simplify_str_to_str,
3736
};
3837
use dwarfreader::create_section_reader_object;
3938

@@ -247,15 +246,11 @@ fn recover_names_internal<R: ReaderType>(
247246
}
248247
debug_info_builder_context.set_name(
249248
get_uid(dwarf, &unit, entry),
250-
simplify_str_to_str(
251-
namespace_qualifiers
252-
.iter()
253-
.map(|(_, namespace)| namespace.to_owned())
254-
.collect::<Vec<String>>()
255-
.join("::"),
256-
)
257-
.to_string_lossy()
258-
.to_string(),
249+
namespace_qualifiers
250+
.iter()
251+
.map(|(_, namespace)| namespace.to_owned())
252+
.collect::<Vec<String>>()
253+
.join("::"),
259254
);
260255
}
261256
constants::DW_TAG_typedef
@@ -264,16 +259,12 @@ fn recover_names_internal<R: ReaderType>(
264259
if let Some(name) = get_name(dwarf, &unit, entry, debug_info_builder_context) {
265260
debug_info_builder_context.set_name(
266261
get_uid(dwarf, &unit, entry),
267-
simplify_str_to_str(
268-
namespace_qualifiers
269-
.iter()
270-
.chain(vec![&(-1, name)].into_iter())
271-
.map(|(_, namespace)| namespace.to_owned())
272-
.collect::<Vec<String>>()
273-
.join("::"),
274-
)
275-
.to_string_lossy()
276-
.to_string(),
262+
namespace_qualifiers
263+
.iter()
264+
.chain(vec![&(-1, name)].into_iter())
265+
.map(|(_, namespace)| namespace.to_owned())
266+
.collect::<Vec<String>>()
267+
.join("::"),
277268
);
278269
}
279270
}

plugins/pdb-ng/src/symbol_parser.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use crate::PDBParserInstance;
3939
use binaryninja::architecture::{Architecture, ArchitectureExt, Register, RegisterId};
4040
use binaryninja::binary_view::BinaryViewBase;
4141
use binaryninja::confidence::{Conf, MAX_CONFIDENCE, MIN_CONFIDENCE};
42-
use binaryninja::demangle::demangle_ms_with_view;
42+
use binaryninja::demangle::demangle_ms;
4343
use binaryninja::rc::Ref;
4444
use binaryninja::types::{FunctionParameter, QualifiedName, StructureBuilder, Type, TypeClass};
4545
use binaryninja::variable::{Variable, VariableSourceType};
@@ -1813,9 +1813,15 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> {
18131813
raw_name: &String,
18141814
rva: Rva,
18151815
) -> Result<(Option<Conf<Ref<Type>>>, Option<QualifiedName>)> {
1816-
let (mut t, mut name) = match demangle_ms_with_view(&self.arch, raw_name, Some(self.bv)) {
1817-
Some((name, Some(t))) => (Some(Conf::new(t, DEMANGLE_CONFIDENCE)), name),
1818-
Some((name, _)) => (None, name),
1816+
let simplify_templates = self.settings.get_bool_with_opts(
1817+
"analysis.types.templateSimplifier",
1818+
&mut self.settings_query_opts.clone(),
1819+
);
1820+
let (mut t, mut name) = match demangle_ms(&self.arch, raw_name, simplify_templates) {
1821+
Some(result) => (
1822+
result.ty.map(|ty| Conf::new(ty, DEMANGLE_CONFIDENCE)),
1823+
result.name,
1824+
),
18191825
_ => (None, QualifiedName::new(vec![raw_name.clone()])),
18201826
};
18211827

plugins/warp/src/convert/symbol.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use binaryninja::binary_view::BinaryView;
2+
use binaryninja::demangle::{demangle_any, DemanglerConfig};
23
use binaryninja::rc::Ref as BNRef;
34
use binaryninja::symbol::Symbol as BNSymbol;
45
use binaryninja::symbol::SymbolType as BNSymbolType;
@@ -74,18 +75,19 @@ pub fn to_bn_symbol_at_address(view: &BinaryView, symbol: &Symbol, addr: u64) ->
7475
};
7576
let raw_name = symbol.name.as_str();
7677
let mut symbol_builder = BNSymbol::builder(symbol_type, &symbol.name, addr);
77-
// Demangle symbol name (short is with simplifications).
78-
if let Some(arch) = view.default_arch() {
79-
if let Some((full_name, _)) =
80-
binaryninja::demangle::demangle_generic(&arch, raw_name, Some(view), false)
81-
{
82-
symbol_builder = symbol_builder.full_name(full_name);
83-
}
84-
if let Some((short_name, _)) =
85-
binaryninja::demangle::demangle_generic(&arch, raw_name, Some(view), false)
86-
{
87-
symbol_builder = symbol_builder.short_name(short_name);
88-
}
78+
let config = DemanglerConfig::for_binary_view(view);
79+
if let Some(result) = demangle_any(raw_name, &config) {
80+
let short_name = result.name.to_string();
81+
let platform = config.get_platform();
82+
let full_name = match result.ty {
83+
Some(ty) => format!(
84+
"{}{}",
85+
short_name,
86+
ty.get_string_after_name(Some(&platform))
87+
),
88+
None => short_name.clone(),
89+
};
90+
symbol_builder = symbol_builder.short_name(short_name).full_name(full_name);
8991
}
9092
symbol_builder.create()
9193
}

plugins/warp/tests/symbol.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use binaryninja::architecture::{ArchitectureExt, CoreArchitecture};
2+
use binaryninja::binary_view::BinaryView;
3+
use binaryninja::file_metadata::FileMetadata;
4+
use binaryninja::headless::Session;
5+
use warp::symbol::{Symbol, SymbolClass, SymbolModifiers};
6+
use warp_ninja::convert::to_bn_symbol_at_address;
7+
8+
#[test]
9+
fn demangled_symbol_names_include_parameters_only_in_the_full_name() {
10+
let _session = Session::new().expect("Failed to create session");
11+
let view = BinaryView::from_data(&FileMetadata::new(), &[]);
12+
let platform = CoreArchitecture::by_name("x86_64")
13+
.expect("x86_64 exists")
14+
.standalone_platform()
15+
.expect("x86_64 standalone platform exists");
16+
view.set_default_platform(&platform);
17+
18+
let symbol = Symbol::new("_Z3fooi", SymbolClass::Function, SymbolModifiers::default());
19+
let bn_symbol = to_bn_symbol_at_address(&view, &symbol, 0);
20+
21+
assert_eq!(bn_symbol.short_name().to_string_lossy(), "foo");
22+
assert_eq!(bn_symbol.full_name().to_string_lossy(), "foo(int32_t)");
23+
}

plugins/workflow_swift/src/demangler/mod.rs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ mod function_type;
22
mod name;
33
mod type_reconstruction;
44

5-
use binaryninja::architecture::CoreArchitecture;
65
use binaryninja::binary_view::BinaryView;
7-
use binaryninja::demangle::CustomDemangler;
8-
use binaryninja::rc::Ref;
6+
use binaryninja::demangle::{CustomDemangler, DemanglerConfig, DemanglerResult};
97
use binaryninja::settings::{QueryOptions, Settings};
10-
use binaryninja::types::{QualifiedName, Type};
8+
use binaryninja::types::QualifiedName;
119

1210
fn should_extract_types(view: Option<&BinaryView>) -> bool {
1311
let mut opts = match view {
@@ -30,27 +28,25 @@ impl CustomDemangler for SwiftDemangler {
3028
|| name.starts_with("_T")
3129
}
3230

33-
fn demangle(
34-
&self,
35-
arch: &CoreArchitecture,
36-
name: &str,
37-
view: Option<Ref<BinaryView>>,
38-
) -> Option<(QualifiedName, Option<Ref<Type>>)> {
31+
fn demangle(&self, name: &str, config: &DemanglerConfig) -> Option<DemanglerResult> {
3932
let ctx = swift_demangler::Context::new();
4033
let symbol = swift_demangler::Symbol::parse(&ctx, name)?;
4134

42-
if should_extract_types(view.as_deref()) {
43-
let ty = function_type::build_function_type(&symbol, arch);
35+
if should_extract_types(config.view.as_deref()) {
36+
let ty = config
37+
.platform
38+
.as_ref()
39+
.and_then(|platform| function_type::build_function_type(&symbol, &platform.arch()));
4440
let qname = if ty.is_some() {
4541
name::build_short_name(&symbol)
4642
} else {
4743
None
4844
}
4945
.unwrap_or_else(|| QualifiedName::from(symbol.display()));
50-
Some((qname, ty))
46+
Some(DemanglerResult::new(qname, ty))
5147
} else {
5248
let qname = QualifiedName::from(symbol.display());
53-
Some((qname, None))
49+
Some(DemanglerResult::new(qname, None))
5450
}
5551
}
5652
}

plugins/workflow_swift/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,5 @@ pub extern "C" fn CorePluginInit() -> bool {
3030
}"#,
3131
);
3232

33-
Demangler::register("Swift", SwiftDemangler);
34-
35-
true
33+
Demangler::register("Swift", SwiftDemangler)
3634
}

rust/examples/demangler.rs

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
use binaryninja::architecture::CoreArchitecture;
2-
use binaryninja::binary_view::BinaryView;
3-
use binaryninja::demangle::{CustomDemangler, Demangler};
4-
use binaryninja::rc::Ref;
1+
use binaryninja::architecture::{ArchitectureExt, CoreArchitecture};
2+
use binaryninja::demangle::{CustomDemangler, Demangler, DemanglerConfig, DemanglerResult};
53
use binaryninja::tracing::TracingLogListener;
64
use binaryninja::types::{QualifiedName, Type};
75

@@ -12,15 +10,16 @@ impl CustomDemangler for TestDemangler {
1210
name == "test_name" || name == "test_name2"
1311
}
1412

15-
fn demangle(
16-
&self,
17-
_arch: &CoreArchitecture,
18-
name: &str,
19-
_view: Option<Ref<BinaryView>>,
20-
) -> Option<(QualifiedName, Option<Ref<Type>>)> {
13+
fn demangle(&self, name: &str, _config: &DemanglerConfig) -> Option<DemanglerResult> {
2114
match name {
22-
"test_name" => Some((QualifiedName::from(vec!["test_name"]), Some(Type::bool()))),
23-
"test_name2" => Some((QualifiedName::from(vec!["test_name2", "aaa"]), None)),
15+
"test_name" => Some(DemanglerResult::new(
16+
QualifiedName::from(vec!["test_name"]),
17+
Some(Type::bool()),
18+
)),
19+
"test_name2" => Some(DemanglerResult::new(
20+
QualifiedName::from(vec!["test_name2", "aaa"]),
21+
None,
22+
)),
2423
_ => None,
2524
}
2625
}
@@ -30,14 +29,18 @@ fn main() {
3029
tracing_subscriber::fmt::init();
3130
let _listener = TracingLogListener::new().register();
3231

32+
tracing::info!("Registering demangler...");
33+
assert!(Demangler::register("Test", TestDemangler));
34+
3335
// This loads all the core architecture, platform, etc plugins
3436
let _headless_session =
3537
binaryninja::headless::Session::new().expect("Failed to initialize session");
3638

37-
tracing::info!("Registering demangler...");
38-
Demangler::register("Test", TestDemangler);
39-
4039
let placeholder_arch = CoreArchitecture::by_name("x86_64").expect("x86 exists");
40+
let platform = placeholder_arch
41+
.standalone_platform()
42+
.expect("x86 standalone platform exists");
43+
let config = DemanglerConfig::for_platform(&platform, false);
4144

4245
for d in Demangler::list().iter() {
4346
tracing::info!("{}", d.name());
@@ -46,17 +49,8 @@ fn main() {
4649
" \"__ZN1AC2Ei\" is mangled? {}",
4750
d.is_mangled_string("__ZN1AC2Ei")
4851
);
49-
tracing::info!(
50-
" \"__ZN1AC2Ei\" : {:?}",
51-
d.demangle(&placeholder_arch, "__ZN1AC2Ei", None)
52-
);
53-
tracing::info!(
54-
" \"test_name\" : {:?}",
55-
d.demangle(&placeholder_arch, "test_name", None)
56-
);
57-
tracing::info!(
58-
" \"test_name2\" : {:?}",
59-
d.demangle(&placeholder_arch, "test_name2", None)
60-
);
52+
tracing::info!(" \"__ZN1AC2Ei\" : {:?}", d.demangle("__ZN1AC2Ei", &config));
53+
tracing::info!(" \"test_name\" : {:?}", d.demangle("test_name", &config));
54+
tracing::info!(" \"test_name2\" : {:?}", d.demangle("test_name2", &config));
6155
}
6256
}

rust/src/binary_view.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1468,7 +1468,10 @@ impl BinaryView {
14681468
let name_handle = unsafe {
14691469
let id_str =
14701470
BNGenerateAutoTypeId(source_str.as_ref().as_ptr() as *const _, &mut raw_name);
1471-
BNDefineAnalysisType(self.handle, id_str, &mut raw_name, type_obj.handle)
1471+
let name_handle =
1472+
BNDefineAnalysisType(self.handle, id_str, &mut raw_name, type_obj.handle);
1473+
BNFreeString(id_str);
1474+
name_handle
14721475
};
14731476
QualifiedName::free_raw(raw_name);
14741477
QualifiedName::from_owned_raw(name_handle)

0 commit comments

Comments
 (0)