Skip to content

Commit

Permalink
Expose LLVM demangler
Browse files Browse the repository at this point in the history
  • Loading branch information
emesare committed May 3, 2024
1 parent 92a468d commit 8020109
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 1 deletion.
20 changes: 20 additions & 0 deletions binaryninjaapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions binaryninjacore.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
23 changes: 23 additions & 0 deletions demangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
33 changes: 33 additions & 0 deletions python/demangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
43 changes: 43 additions & 0 deletions rust/src/demangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion suite/api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
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
Expand Down

0 comments on commit 8020109

Please sign in to comment.