diff options
| -rw-r--r-- | binaryninjaapi.h | 20 | ||||
| -rw-r--r-- | binaryninjacore.h | 5 | ||||
| -rw-r--r-- | demangle.cpp | 23 | ||||
| -rw-r--r-- | python/demangle.py | 33 | ||||
| -rw-r--r-- | rust/src/demangle.rs | 43 | ||||
| -rw-r--r-- | suite/api_test.py | 2 |
6 files changed, 125 insertions, 1 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 5ec190b2..9d4a3ae6 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1531,6 +1531,26 @@ namespace BinaryNinja { std::function<bool(size_t, size_t)> progress = {}, Ref<Metadata> options = new Metadata(MetadataType::KeyValueDataType), bool isDatabase = false); + /*! Demangles using LLVM's demangler + + \param[in] mangledName a mangled (msvc/itanium/rust/dlang) name + \param[out] outVarName QualifiedName reference to write the output name to. + \param[in] simplify Whether to simplify demangled names. + + \ingroup demangle + */ + bool DemangleLLVM(const std::string& mangledName, QualifiedName& outVarName, const bool simplify = false); + + /*! Demangles using LLVM's demangler + + \param[in] mangledName a mangled (msvc/itanium/rust/dlang) name + \param[out] outVarName QualifiedName reference to write the output name to. + \param[in] view View to check the analysis.types.templateSimplifier for + + \ingroup demangle + */ + bool DemangleLLVM(const std::string& mangledName, QualifiedName& outVarName, BinaryView* view); + /*! Demangles a Microsoft Visual Studio C++ name \param[in] arch Architecture for the symbol. Required for pointer and integer sizes. diff --git a/binaryninjacore.h b/binaryninjacore.h index 826ebf48..23d63acc 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -6530,6 +6530,11 @@ extern "C" char*** outVarName, size_t* outVarNameElements, const BNBinaryView* const view); BINARYNINJACOREAPI void BNFreeDemangledName(char*** name, size_t nameElements); + BINARYNINJACOREAPI bool BNDemangleLLVM(const char* mangledName, + char*** outVarName, size_t* outVarNameElements, const bool simplify); + BINARYNINJACOREAPI bool BNDemangleLLVMWithOptions(const char* mangledName, + char*** outVarName, size_t* outVarNameElements, const BNBinaryView* const view); + // Plugin repository APIs BINARYNINJACOREAPI char** BNPluginGetApis(BNRepoPlugin* p, size_t* count); BINARYNINJACOREAPI const char* BNPluginGetAuthor(BNRepoPlugin* p); diff --git a/demangle.cpp b/demangle.cpp index 56f4ba90..fbe39672 100644 --- a/demangle.cpp +++ b/demangle.cpp @@ -3,6 +3,29 @@ using namespace std; namespace BinaryNinja { + bool DemangleLLVM(const std::string& mangledName, QualifiedName& outVarName, + BinaryView* view) + { + const bool simplify = Settings::Instance()->Get<bool>("analysis.types.templateSimplifier", view); + return DemangleLLVM(mangledName, outVarName, simplify); + } + + bool DemangleLLVM(const std::string& mangledName, QualifiedName& outVarName, + const bool simplify) + { + BNType* localType = nullptr; + char** localVarName = nullptr; + size_t localSize = 0; + if (!BNDemangleLLVM(mangledName.c_str(), &localVarName, &localSize, simplify)) + return false; + for (size_t i = 0; i < localSize; i++) + { + outVarName.push_back(localVarName[i]); + } + BNFreeDemangledName(&localVarName, localSize); + return true; + } + bool DemangleMS(Architecture* arch, const std::string& mangledName, Ref<Type>& outType, QualifiedName& outVarName, BinaryView* view) { diff --git a/python/demangle.py b/python/demangle.py index 874b13cf..158880f0 100644 --- a/python/demangle.py +++ b/python/demangle.py @@ -46,6 +46,39 @@ def get_qualified_name(names): return "::".join(names) +def demangle_llvm(mangled_name: str, options=None): + """ + ``demangle_llvm`` demangles a mangled name to a Type object. + + :param str mangled_name: a mangled (msvc/itanium/rust/dlang) name + :param options: (optional) Whether to simplify demangled names : None falls back to user settings, a BinaryView uses that BinaryView's settings, or a boolean to set it directly + :type options: Tuple[bool, BinaryView, None] + :return: returns demangled name or None on error + :rtype: str + """ + outName = ctypes.POINTER(ctypes.c_char_p)() + outSize = ctypes.c_ulonglong() + names = [] + if ( + isinstance(options, binaryview.BinaryView) and core.BNDemangleLLVMWithOptions( + mangled_name, ctypes.byref(outName), ctypes.byref(outSize), options + ) + ) or ( + isinstance(options, bool) and core.BNDemangleLLVM( + mangled_name, ctypes.byref(outName), ctypes.byref(outSize), options + ) + ) or ( + options is None and core.BNDemangleLLVMWithOptions( + mangled_name, ctypes.byref(outName), ctypes.byref(outSize), None + ) + ): + for i in range(outSize.value): + names.append(outName[i].decode('utf8')) # type: ignore + core.BNFreeDemangledName(ctypes.byref(outName), outSize.value) + return names + return None + + def demangle_ms(archOrPlatform:Union[Architecture, Platform], mangled_name:str, options=False): """ ``demangle_ms`` demangles a mangled Microsoft Visual Studio C++ name to a Type object. diff --git a/rust/src/demangle.rs b/rust/src/demangle.rs index 3756ea06..1b940ff9 100644 --- a/rust/src/demangle.rs +++ b/rust/src/demangle.rs @@ -26,6 +26,49 @@ use crate::rc::*; pub type Result<R> = result::Result<R, ()>; +pub fn demangle_llvm<S: BnStrCompatible>( + mangled_name: S, + simplify: bool, +) -> Result<Vec<String>> { + let mangled_name_bwn = mangled_name.into_bytes_with_nul(); + let mangled_name_ptr = mangled_name_bwn.as_ref(); + let mut out_name: *mut *mut std::os::raw::c_char = unsafe { std::mem::zeroed() }; + let mut out_size: usize = 0; + let res = unsafe { + BNDemangleLLVM( + mangled_name_ptr.as_ptr() as *const c_char, + &mut out_name, + &mut out_size, + simplify, + ) + }; + + if !res || out_size == 0 { + let cstr = match CStr::from_bytes_with_nul(mangled_name_ptr) { + Ok(cstr) => cstr, + Err(_) => { + log::error!("demangle_llvm: failed to parse mangled name"); + return Err(()); + } + }; + return Ok(vec![cstr.to_string_lossy().into_owned()]); + } + + if out_name.is_null() { + log::error!("demangle_llvm: out_name is NULL"); + return Err(()); + } + + let names = unsafe { ArrayGuard::<BnString>::new(out_name, out_size, ()) } + .iter() + .map(str::to_string) + .collect(); + + unsafe { BNFreeDemangledName(&mut out_name, out_size) }; + + Ok(names) +} + pub fn demangle_gnu3<S: BnStrCompatible>( arch: &CoreArchitecture, mangled_name: S, diff --git a/suite/api_test.py b/suite/api_test.py index 7054008a..fb3103cb 100644 --- a/suite/api_test.py +++ b/suite/api_test.py @@ -5,7 +5,7 @@ import binaryninja as bn from binaryninja.binaryview import BinaryView, BinaryViewType from binaryninja.settings import Settings, SettingsScope from binaryninja.metadata import Metadata -from binaryninja.demangle import demangle_gnu3, demangle_ms, get_qualified_name +from binaryninja.demangle import demangle_gnu3, demangle_ms, demangle_llvm, get_qualified_name from binaryninja.architecture import Architecture from binaryninja.pluginmanager import RepositoryManager from binaryninja.platform import Platform |
