binaryninja-api: demangle_ms bugs/improvements
Binary Ninja Version: 2.0.2138-dev, d031c340 Platform: Windows 10 Version 1903
After using demangle_ms a lot lately, here’s a list of problems I have come across:
Vftables have type_class TypeClass.NamedTypeReferenceClass
# const Foo::`vftable'
>>> demangle_ms(arch, '??_7Foo@@6B@')
(<type: const>, ['Foo', "`vftable'"])
>>> demangle_ms(arch, '??_7Foo@@6B@')[0].type_class
<TypeClass.NamedTypeReferenceClass: 11>
Multiple inheritance vftables produce invalid types and contain the parent in the type tokens instead of the name
# const Bar::`vftable'{for `Foo'}
>>> demangle_ms(arch, '??_7Bar@@6BFoo@@@')
Traceback (most recent call last):
File "C:\Program Files\Vector35\BinaryNinja\plugins\..\python\binaryninja\types.py", line 356, in __repr__
return "<type: %s>" % str(self)
File "C:\Program Files\Vector35\BinaryNinja\plugins\..\python\binaryninja\types.py", line 367, in __str__
return core.BNGetTypeString(self._handle, platform)
File "C:\Program Files\Vector35\BinaryNinja\plugins\..\python\binaryninja\_binaryninjacore.py", line 11021, in BNGetTypeString
result = _BNGetTypeString(*args)
OSError: exception: access violation reading 0x0000000000000010
>>> demangle_ms(arch, '??_7Bar@@6BFoo@@@')[0].get_tokens_after_name()
['{', 'for', ' `', 'Foo', "'}"]
Certain symbols contain the attributes in their type
Attributes (static, virtual, access modifier, etc.) could really do with being returned separately instead of discarding them or making them part of the type string.
# protected: static bool Foo::Bar
>>> demangle_ms(arch, '?Bar@Foo@@1_NA')
(<type: protected: static bool>, ['Foo', 'Bar'])
>>> demangle_ms(arch, '?Bar@Foo@@1_NA')[0].get_tokens_before_name()
['protected:', ' ', 'static', ' ', 'bool']
Functions with no parameters have unnecessary void parameter
# void __cdecl Foo(void)
>>> demangle_ms(arch, '?Foo@@YAXXZ')
(<type: void __cdecl (void)>, ['Foo'])
>>> demangle_ms(arch, '?Foo@@YAXXZ')[0].parameters[0].type.type_class
<TypeClass.VoidTypeClass: 0>
Functions not given a calling convention (#1390)
# public: virtual void __thiscall Foo::Bar(void)
>>> demangle_ms(arch, '?Bar@Foo@@UAEXXZ')
(<type: public: virtual void __thiscall (void)>, ['Foo', 'Bar'])
>>> demangle_ms(arch, '?Bar@Foo@@UAEXXZ')[0].calling_convention is None
True
Non-static member functions are missing hidden ‘this’ parameter
Checking whether the symbol is a non static function with an access modifier (public/protected/private) seems to be the best way to determine if the parameter is needed.
>>> demangle_ms(arch, '?Bar@Foo@@UAEXXZ')
(<type: public: virtual void __thiscall (void)>, ['Foo', 'Bar'])
>>> demangle_ms(arch, '?Bar@Foo@@UAEXXZ')[0].parameters
[void ]
Cannot demangle member function pointers
Not sure how feasible it is to create types for these since the size of member function pointers varies.
# void __cdecl Bar(void (__thiscall Foo::*)(void))
>>> demangle_ms(arch, '?Bar@@YAXP8Foo@@AEXXZ@Z')
(None, '?Bar@@YAXP8Foo@@AEXXZ@Z')
Incorrect demangled names
# `eh vector destructor iterator'
>>> demangle_ms(arch, '??_M@YGXPAXIHP6EX0@Z@Z')[1]
["`eh vector vbase constructor iterator'"]
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 1
- Comments: 32 (23 by maintainers)
As of 3.6.4615, a bug in template back-references has been fixed. This has fixed the following:
Couple slight deviations from MSVC/LLVM but I think they are just thisptr insertion and lack of type system support for public/protected/static status.
I really appreciate seeing movement in this area @CouleeApps 😃
Now included, even if nobody here asked for it: bare names of the construction
.?AV<name>or.?AU<name>. I’m not sure what the difference between AV and AU is, so they’re just handled the same. Specifically you should get something like:I’ve only seen these used in RTTI TypeDescriptor name fields, so if you’re working on an RTTI plugin this may be of use 😃