summaryrefslogtreecommitdiff
path: root/rust/tests/demangler.rs
blob: 3c1d021600cc62456dcd71c11428042916435d0c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use binaryninja::architecture::CoreArchitecture;
use binaryninja::binary_view::BinaryView;
use binaryninja::demangle::{
    demangle_generic, demangle_gnu3, demangle_llvm, demangle_ms, CustomDemangler, Demangler,
};
use binaryninja::headless::Session;
use binaryninja::rc::Ref;
use binaryninja::types::{QualifiedName, Type};

#[test]
fn test_demangler_simple() {
    let _session = Session::new().expect("Failed to initialize session");
    let placeholder_arch = CoreArchitecture::by_name("x86").expect("x86 exists");
    // Example LLVM-style mangled name
    let llvm_mangled = "_Z3fooi"; // "foo(int)" in LLVM mangling
    let llvm_demangled = demangle_llvm(llvm_mangled, true).unwrap();
    assert_eq!(llvm_demangled, "foo(int)".into());

    // Example GNU-style mangled name
    let gnu_mangled = "_Z3bari"; // "bar(int)" in GNU mangling
    let (gnu_demangled_name, gnu_demangled_type) =
        demangle_gnu3(&placeholder_arch, gnu_mangled, true).unwrap();
    assert_eq!(gnu_demangled_name, "bar".into());
    // TODO: We check the type display because other means include things such as confidence which is hard to get 1:1
    assert_eq!(
        gnu_demangled_type.unwrap().to_string(),
        "int32_t(int32_t)".to_string()
    );

    // Example MSVC-style mangled name
    let msvc_mangled = "?baz@@YAHH@Z"; // "int __cdecl baz(int)" in MSVC mangling
    let (msvc_demangled_name, msvc_demangled_type) =
        demangle_ms(&placeholder_arch, msvc_mangled, true).unwrap();
    assert_eq!(msvc_demangled_name, "baz".into());
    // TODO: We check the type display because other means include things such as confidence which is hard to get 1:1
    assert_eq!(
        msvc_demangled_type.unwrap().to_string(),
        "int32_t __cdecl(int32_t)".to_string()
    );
}

#[test]
fn test_custom_demangler() {
    let _session = Session::new().expect("Failed to initialize session");
    struct TestDemangler;

    impl CustomDemangler for TestDemangler {
        fn is_mangled_string(&self, name: &str) -> bool {
            name == "test_name" || name == "test_name2"
        }

        fn demangle(
            &self,
            _arch: &CoreArchitecture,
            name: &str,
            _view: Option<Ref<BinaryView>>,
        ) -> Option<(QualifiedName, Option<Ref<Type>>)> {
            match name {
                "test_name" => Some((QualifiedName::from(vec!["test_name"]), Some(Type::bool()))),
                "test_name2" => Some((QualifiedName::from(vec!["test_name2", "aaa"]), None)),
                _ => None,
            }
        }
    }

    Demangler::register("Test", TestDemangler);

    let placeholder_arch = CoreArchitecture::by_name("x86_64").expect("x86_64 exists");

    let demangled = demangle_generic(&placeholder_arch, "test_name", None, true).unwrap();
    assert_eq!(
        demangled,
        (QualifiedName::from(vec!["test_name"]), Some(Type::bool()))
    );
    let demangled2 = demangle_generic(&placeholder_arch, "test_name2", None, true).unwrap();
    assert_eq!(
        demangled2,
        (QualifiedName::from(vec!["test_name2", "aaa"]), None)
    );
}