summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyleMiles <krm504@nyu.edu>2022-09-22 13:43:46 -0400
committerKyleMiles <krm504@nyu.edu>2022-09-22 13:49:36 -0400
commitbdf05c261bd1c24f0440c17e10b983b50613bc20 (patch)
tree8a6ee0c5b801b60028d22bea7f31af38bd9da0eb
parente95b220ef18c9dd9e1aecab32b735ff47237f9c7 (diff)
Add new DebugInfo APIs
-rw-r--r--binaryninjaapi.h28
-rw-r--r--binaryninjacore.h47
-rw-r--r--debuginfo.cpp154
-rw-r--r--python/debuginfo.py99
-rw-r--r--rust/src/debuginfo.rs224
5 files changed, 541 insertions, 11 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 752b9c52..5c04816b 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -11933,9 +11933,31 @@ namespace BinaryNinja {
public:
DebugInfo(BNDebugInfo* debugInfo);
- std::vector<NameAndType> GetTypes(const std::string& parserName = "");
- std::vector<DebugFunctionInfo> GetFunctions(const std::string& parserName = "");
- std::vector<DataVariableAndName> GetDataVariables(const std::string& parserName = "");
+ std::vector<std::string> GetParsers() const;
+
+ std::vector<NameAndType> GetTypes(const std::string& parserName = "") const;
+ std::vector<DebugFunctionInfo> GetFunctions(const std::string& parserName = "") const;
+ std::vector<DataVariableAndName> GetDataVariables(const std::string& parserName = "") const;
+
+ Ref<Type> GetTypeByName(const std::string& parserName, const std::string& name) const;
+ std::optional<std::tuple<uint64_t, Ref<Type>>> GetDataVariableByName(
+ const std::string& parserName, const std::string& name) const;
+ std::optional<std::tuple<std::string, Ref<Type>>> GetDataVariableByAddress(
+ const std::string& parserName, const uint64_t address) const;
+
+ std::vector<std::tuple<std::string, Ref<Type>>> GetTypesByName(const std::string& name) const;
+ std::vector<std::tuple<std::string, uint64_t, Ref<Type>>> GetDataVariablesByName(const std::string& name) const;
+ std::vector<std::tuple<std::string, std::string, Ref<Type>>> GetDataVariablesByAddress(
+ const uint64_t address) const;
+
+ bool RemoveParserInfo(const std::string& parserName);
+ bool RemoveParserTypes(const std::string& parserName);
+ bool RemoveParserFunctions(const std::string& parserName);
+ bool RemoveParserDataVariables(const std::string& parserName);
+
+ bool RemoveTypeByName(const std::string& parserName, const std::string& name);
+ bool RemoveFunctionByIndex(const std::string& parserName, const size_t index);
+ bool RemoveDataVariableByAddress(const std::string& parserName, const uint64_t address);
bool AddType(const std::string& name, Ref<Type> type);
bool AddFunction(const DebugFunctionInfo& function);
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 12c1b277..416f9574 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -994,6 +994,16 @@ extern "C"
uint8_t typeConfidence;
};
+ struct BNDataVariableAndNameAndDebugParser
+ {
+ uint64_t address;
+ BNType* type;
+ char* name;
+ char* parser;
+ bool autoDiscovered;
+ uint8_t typeConfidence;
+ };
+
enum BNMediumLevelILOperation
{
MLIL_NOP,
@@ -4231,7 +4241,10 @@ extern "C"
BINARYNINJACOREAPI void BNUndefineUserDataVariable(BNBinaryView* view, uint64_t addr);
BINARYNINJACOREAPI BNDataVariable* BNGetDataVariables(BNBinaryView* view, size_t* count);
BINARYNINJACOREAPI void BNFreeDataVariables(BNDataVariable* vars, size_t count);
+ BINARYNINJACOREAPI void BNFreeDataVariableAndName(BNDataVariableAndName* var);
BINARYNINJACOREAPI void BNFreeDataVariablesAndName(BNDataVariableAndName* vars, size_t count);
+ BINARYNINJACOREAPI void BNFreeDataVariableAndNameAndDebugParserList(
+ BNDataVariableAndNameAndDebugParser* vars, size_t count);
BINARYNINJACOREAPI bool BNGetDataVariableAtAddress(BNBinaryView* view, uint64_t addr, BNDataVariable* var);
BINARYNINJACOREAPI bool BNParseTypeString(BNBinaryView* view, const char* text, BNQualifiedNameAndType* result,
@@ -6255,19 +6268,43 @@ extern "C"
BINARYNINJACOREAPI BNDebugInfo* BNNewDebugInfoReference(BNDebugInfo* debugInfo);
BINARYNINJACOREAPI void BNFreeDebugInfoReference(BNDebugInfo* debugInfo);
+ BINARYNINJACOREAPI char** BNGetDebugParserNames(BNDebugInfo* const debugInfo, size_t* count);
+ BINARYNINJACOREAPI bool BNRemoveDebugParserInfo(BNDebugInfo* const debugInfo, const char* const parserName);
+ BINARYNINJACOREAPI bool BNRemoveDebugParserTypes(BNDebugInfo* const debugInfo, const char* const parserName);
+ BINARYNINJACOREAPI bool BNRemoveDebugParserFunctions(BNDebugInfo* const debugInfo, const char* const parserName);
+ BINARYNINJACOREAPI bool BNRemoveDebugParserDataVariables(
+ BNDebugInfo* const debugInfo, const char* const parserName);
BINARYNINJACOREAPI bool BNAddDebugType(
- BNDebugInfo* const debugInfo, const char* const name, const BNType* const type);
+ BNDebugInfo* const debugInfo, const char* const name, const BNType* const type);
BINARYNINJACOREAPI BNNameAndType* BNGetDebugTypes(
- BNDebugInfo* const debugInfo, const char* const name, size_t* count);
+ BNDebugInfo* const debugInfo, const char* const name, size_t* count);
+ BINARYNINJACOREAPI BNType* BNGetDebugTypeByName(
+ BNDebugInfo* const debugInfo, const char* const parserName, const char* const typeName);
+ BINARYNINJACOREAPI BNNameAndType* BNGetDebugTypesByName(
+ BNDebugInfo* const debugInfo, const char* const typeName, size_t* count);
+ BINARYNINJACOREAPI bool BNRemoveDebugTypeByName(
+ BNDebugInfo* const debugInfo, const char* const parserName, const char* typeName);
BINARYNINJACOREAPI void BNFreeDebugTypes(BNNameAndType* types, size_t count);
BINARYNINJACOREAPI bool BNAddDebugFunction(BNDebugInfo* const debugInfo, BNDebugFunctionInfo* func);
BINARYNINJACOREAPI BNDebugFunctionInfo* BNGetDebugFunctions(
- BNDebugInfo* const debugInfo, const char* const name, size_t* count);
+ BNDebugInfo* const debugInfo, const char* const name, size_t* count);
+ BINARYNINJACOREAPI bool BNRemoveDebugFunctionByIndex(
+ BNDebugInfo* const debugInfo, const char* const parserName, const size_t index);
BINARYNINJACOREAPI void BNFreeDebugFunctions(BNDebugFunctionInfo* functions, size_t count);
BINARYNINJACOREAPI bool BNAddDebugDataVariable(
- BNDebugInfo* const debugInfo, uint64_t address, const BNType* const type, const char* name);
+ BNDebugInfo* const debugInfo, uint64_t address, const BNType* const type, const char* name);
BINARYNINJACOREAPI BNDataVariableAndName* BNGetDebugDataVariables(
- BNDebugInfo* const debugInfo, const char* const name, size_t* count);
+ BNDebugInfo* const debugInfo, const char* const name, size_t* count);
+ BINARYNINJACOREAPI BNDataVariableAndName* BNGetDebugDataVariableByName(
+ BNDebugInfo* const debugInfo, const char* const parserName, const char* const variableName);
+ BINARYNINJACOREAPI BNDataVariableAndName* BNGetDebugDataVariableByAddress(
+ BNDebugInfo* const debugInfo, const char* const parserName, const uint64_t address);
+ BINARYNINJACOREAPI BNDataVariableAndName* BNGetDebugDataVariablesByName(
+ BNDebugInfo* const debugInfo, const char* const variableName, size_t* count);
+ BINARYNINJACOREAPI BNDataVariableAndNameAndDebugParser* BNGetDebugDataVariablesByAddress(
+ BNDebugInfo* const debugInfo, const uint64_t address, size_t* count);
+ BINARYNINJACOREAPI bool BNRemoveDebugDataVariableByAddress(
+ BNDebugInfo* const debugInfo, const char* const parserName, const uint64_t address);
// Secrets providers
BINARYNINJACOREAPI BNSecretsProvider* BNRegisterSecretsProvider(
diff --git a/debuginfo.cpp b/debuginfo.cpp
index e8450399..fb10039e 100644
--- a/debuginfo.cpp
+++ b/debuginfo.cpp
@@ -38,7 +38,23 @@ DebugInfo::DebugInfo(BNDebugInfo* debugInfo)
}
-vector<NameAndType> DebugInfo::GetTypes(const string& parserName)
+vector<string> DebugInfo::GetParsers() const
+{
+ size_t count;
+ char** parsers = BNGetDebugParserNames(m_object, &count);
+
+ vector<string> result;
+ for (size_t i = 0; i < count; ++i)
+ {
+ result.emplace_back(parsers[i]);
+ }
+ BNFreeStringList(parsers, count);
+
+ return result;
+}
+
+
+vector<NameAndType> DebugInfo::GetTypes(const string& parserName) const
{
size_t count;
BNNameAndType* nameAndTypes =
@@ -56,7 +72,7 @@ vector<NameAndType> DebugInfo::GetTypes(const string& parserName)
}
-vector<DebugFunctionInfo> DebugInfo::GetFunctions(const string& parserName)
+vector<DebugFunctionInfo> DebugInfo::GetFunctions(const string& parserName) const
{
size_t count;
BNDebugFunctionInfo* functions =
@@ -86,7 +102,7 @@ vector<DebugFunctionInfo> DebugInfo::GetFunctions(const string& parserName)
}
-vector<DataVariableAndName> DebugInfo::GetDataVariables(const string& parserName)
+vector<DataVariableAndName> DebugInfo::GetDataVariables(const string& parserName) const
{
size_t count;
BNDataVariableAndName* variableAndNames =
@@ -105,6 +121,138 @@ vector<DataVariableAndName> DebugInfo::GetDataVariables(const string& parserName
}
+// May return nullptr
+Ref<Type> DebugInfo::GetTypeByName(const string& parserName, const string& name) const
+{
+ BNType* result = BNGetDebugTypeByName(m_object, parserName.c_str(), name.c_str());
+ if (result)
+ return Ref<Type>(new Type(result));
+ return nullptr;
+}
+
+
+optional<tuple<uint64_t, Ref<Type>>> DebugInfo::GetDataVariableByName(
+ const string& parserName, const string& name) const
+{
+ BNDataVariableAndName* result = BNGetDebugDataVariableByName(m_object, parserName.c_str(), name.c_str());
+ if (result)
+ {
+ BNFreeString(result->name);
+ return {{result->address, Ref<Type>(new Type(result->type))}};
+ }
+ return {};
+}
+
+
+optional<tuple<string, Ref<Type>>> DebugInfo::GetDataVariableByAddress(
+ const string& parserName, const uint64_t address) const
+{
+ BNDataVariableAndName* nameAndVar = BNGetDebugDataVariableByAddress(m_object, parserName.c_str(), address);
+ if (nameAndVar)
+ {
+ const tuple<string, Ref<Type>> result = {nameAndVar->name, Ref<Type>(new Type(nameAndVar->type))};
+ BNFreeString(nameAndVar->name);
+ return {result};
+ }
+ return {};
+}
+
+
+// The tuple is (DebugInfoParserName, type)
+vector<tuple<string, Ref<Type>>> DebugInfo::GetTypesByName(const string& name) const
+{
+ size_t count;
+ BNNameAndType* namesAndTypes = BNGetDebugTypesByName(m_object, name.c_str(), &count);
+
+ vector<tuple<string, Ref<Type>>> result;
+ for (size_t i = 0; i < count; ++i)
+ {
+ result.emplace_back(namesAndTypes[i].name, Ref<Type>(new Type(BNNewTypeReference(namesAndTypes[i].type))));
+ }
+
+ BNFreeNameAndTypeList(namesAndTypes, count);
+ return result;
+}
+
+
+// The tuple is (DebugInfoParserName, address, type)
+vector<tuple<string, uint64_t, Ref<Type>>> DebugInfo::GetDataVariablesByName(const string& name) const
+{
+ size_t count;
+ BNDataVariableAndName* variablesAndName = BNGetDebugDataVariablesByName(m_object, name.c_str(), &count);
+
+ vector<tuple<string, uint64_t, Ref<Type>>> result;
+ for (size_t i = 0; i < count; ++i)
+ {
+ result.emplace_back(variablesAndName[i].name, variablesAndName[i].address,
+ Ref<Type>(new Type(BNNewTypeReference(variablesAndName[i].type))));
+ }
+
+ BNFreeDataVariablesAndName(variablesAndName, count);
+ return result;
+}
+
+
+// The tuple is (DebugInfoParserName, TypeName, type)
+vector<tuple<string, string, Ref<Type>>> DebugInfo::GetDataVariablesByAddress(const uint64_t address) const
+{
+ size_t count;
+ BNDataVariableAndNameAndDebugParser* variablesAndName = BNGetDebugDataVariablesByAddress(m_object, address, &count);
+
+ vector<tuple<string, string, Ref<Type>>> result;
+ for (size_t i = 0; i < count; ++i)
+ {
+ result.emplace_back(variablesAndName[i].parser, variablesAndName[i].name,
+ Ref<Type>(new Type(BNNewTypeReference(variablesAndName[i].type))));
+ }
+
+ BNFreeDataVariableAndNameAndDebugParserList(variablesAndName, count);
+ return result;
+}
+
+
+bool DebugInfo::RemoveParserInfo(const string& parserName)
+{
+ return BNRemoveDebugParserInfo(m_object, parserName.c_str());
+}
+
+
+bool DebugInfo::RemoveParserTypes(const string& parserName)
+{
+ return BNRemoveDebugParserTypes(m_object, parserName.c_str());
+}
+
+
+bool DebugInfo::RemoveParserFunctions(const string& parserName)
+{
+ return BNRemoveDebugParserFunctions(m_object, parserName.c_str());
+}
+
+
+bool DebugInfo::RemoveParserDataVariables(const string& parserName)
+{
+ return BNRemoveDebugParserDataVariables(m_object, parserName.c_str());
+}
+
+
+bool DebugInfo::RemoveTypeByName(const string& parserName, const string& name)
+{
+ return BNRemoveDebugTypeByName(m_object, parserName.c_str(), name.c_str());
+}
+
+
+bool DebugInfo::RemoveFunctionByIndex(const string& parserName, const size_t index)
+{
+ return BNRemoveDebugFunctionByIndex(m_object, parserName.c_str(), index);
+}
+
+
+bool DebugInfo::RemoveDataVariableByAddress(const string& parserName, const uint64_t address)
+{
+ return BNRemoveDebugDataVariableByAddress(m_object, parserName.c_str(), address);
+}
+
+
bool DebugInfo::AddType(const string& name, Ref<Type> type)
{
return BNAddDebugType(m_object, name.c_str(), type->GetObject());
diff --git a/python/debuginfo.py b/python/debuginfo.py
index 46f9e959..7b5a6dbc 100644
--- a/python/debuginfo.py
+++ b/python/debuginfo.py
@@ -283,6 +283,18 @@ class DebugInfo(object):
def __del__(self) -> None:
core.BNFreeDebugInfoReference(self.handle)
+ def get_parsers(self):
+ count = ctypes.c_ulonglong()
+ parsers = core.BNGetDebugParserNames(self.handle, count)
+
+ result = []
+ for i in range(count.value):
+ assert parsers is not None, "core.BNGetDebugParserNames returned None"
+ result.append(parsers[i])
+ core.BNFreeStringList(parsers, count.value)
+
+ return result
+
def types_from_parser(self, name: Optional[str] = None) -> Iterator[Tuple[str, _types.Type]]:
"""Returns a generator of all types provided by a named DebugInfoParser"""
count = ctypes.c_ulonglong(0)
@@ -364,6 +376,93 @@ class DebugInfo(object):
"""A generator of all data variables provided by DebugInfoParsers"""
return self.data_variables_from_parser()
+ def get_type_by_name(self, parser_name: str, name: str) -> Optional[_types.Type]:
+ result = core.BNGetDebugTypeByName(self.handle, parser_name, name)
+ if result is not None:
+ return _types.Type(core.BNNewTypeReference(result))
+ return None
+
+ def get_data_variable_by_name(self, parser_name: str, name: str) -> Optional[Tuple[int, _types.Type]]:
+ result = core.BNGetDebugDataVariableByName(self.handle, parser_name, name)
+ if result is not None:
+ core.BNFreeString(result.name)
+ return (result.address, _types.Type(result.type))
+ return None
+
+ def get_data_variable_by_address(self, parser_name: str, address: int) -> Optional[Tuple[str, _types.Type]]:
+ name_and_var = core.BNGetDebugDataVariableByAddress(self.handle, parser_name, address)
+ if name_and_var is not None:
+ result = (str(name_and_var.name), _types.Type(name_and_var.type))
+ core.BNFreeString(name_and_var.name)
+ return result
+ return None
+
+ def get_types_by_name(self, name: str) -> List[Tuple[str, _types.Type]]:
+ """ The first element in the Tuple returned in the list is the name of the debug info parser the type came from """
+ count = ctypes.c_ulonglong()
+ names_and_types = core.BNGetDebugTypesByName(self.handle, name, count)
+
+ result = []
+ for i in range(count.value):
+ assert names_and_types is not None, "core.BNGetDebugTypesByName returned None"
+ result.append((names_and_types[i].name, _types.Type(core.BNNewTypeReference(names_and_types[i].type))))
+
+ core.BNFreeNameAndTypeList(names_and_types, count.value)
+ return result
+
+ def get_data_variables_by_name(self, name: str) -> List[Tuple[str, _types.Type]]:
+ """ The values in the tuples returned in the list is (DebugInfoParserName, address, type) """
+ count = ctypes.c_ulonglong()
+ variables_and_name = core.BNGetDebugDataVariablesByName(self.handle, name, count)
+
+ result = []
+ for i in range(count.value):
+ assert variables_and_name is not None, "core.BNGetDebugDataVariablesByName returned None"
+ result.append((
+ variables_and_name[i].name, variables_and_name[i].address,
+ _types.Type(core.BNNewTypeReference(variables_and_name[i].type))
+ ))
+
+ core.BNFreeDataVariablesAndName(variables_and_name, count.value)
+ return result
+
+ def get_data_variables_by_address(self, address: int) -> List[Tuple[str, _types.Type]]:
+ """ The values in the tuples returned in the list is (DebugInfoParserName, TypeName, type) """
+ count = ctypes.c_ulonglong()
+ variables_and_name = core.BNGetDebugDataVariablesByAddress(self.handle, address, count)
+
+ result = []
+ for i in range(count.value):
+ assert variables_and_name is not None, "core.BNGetDebugDataVariablesByAddress returned None"
+ result.append((
+ variables_and_name[i].parser, variables_and_name[i].name,
+ _types.Type(core.BNNewTypeReference(variables_and_name[i].type))
+ ))
+
+ core.BNFreeDataVariableAndNameAndDebugParserList(variables_and_name, count.value)
+ return result
+
+ def remove_parser_info(self, parser_name: str):
+ return core.BNRemoveDebugParserInfo(self.handle, parser_name)
+
+ def remove_parser_types(self, parser_name: str):
+ return core.BNRemoveDebugParserTypes(self.handle, parser_name)
+
+ def remove_parser_functions(self, parser_name: str):
+ return core.BNRemoveDebugParserFunctions(self.handle, parser_name)
+
+ def remove_parser_data_variables(self, parser_name: str):
+ return core.BNRemoveDebugParserDataVariables(self.handle, parser_name)
+
+ def remove_type_by_name(self, parser_name: str, name: str):
+ return core.BNRemoveDebugTypeByName(self.handle, parser_name, name)
+
+ def remove_function_by_index(self, parser_name: str, index: int):
+ return core.BNRemoveDebugFunctionByIndex(self.handle, parser_name, index)
+
+ def remove_data_variable_by_address(self, parser_name: str, address: int):
+ return core.BNRemoveDebugDataVariableByAddress(self.handle, parser_name, address)
+
def add_type(self, name: str, new_type: '_types.Type') -> bool:
"""Adds a type scoped under the current parser's name to the debug info"""
if isinstance(new_type, _types.Type):
diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs
index aad0f996..f780973c 100644
--- a/rust/src/debuginfo.rs
+++ b/rust/src/debuginfo.rs
@@ -494,6 +494,230 @@ impl DebugInfo {
result
}
+ /// May return nullptr
+ pub fn type_by_name<S: BnStrCompatible>(&self, parser_name: S, name: S) -> Option<Ref<Type>> {
+ let parser_name = parser_name.as_bytes_with_nul();
+ let name = name.as_bytes_with_nul();
+
+ let result = unsafe {
+ BNGetDebugTypeByName(
+ self.handle,
+ parser_name.as_ref().as_ptr() as *mut _,
+ name.as_ref().as_ptr() as *mut _,
+ )
+ };
+ if !result.is_null() {
+ Some(unsafe { Type::ref_from_raw(result) })
+ } else {
+ None
+ }
+ }
+
+ pub fn get_data_variable_by_name<S: BnStrCompatible>(
+ &self,
+ parser_name: S,
+ name: S,
+ ) -> Option<(u64, Ref<Type>)> {
+ let parser_name = parser_name.as_bytes_with_nul();
+ let name = name.as_bytes_with_nul();
+
+ let result = unsafe {
+ BNGetDebugDataVariableByName(
+ self.handle,
+ parser_name.as_ref().as_ptr() as *mut _,
+ name.as_ref().as_ptr() as *mut _,
+ )
+ };
+
+ if !result.is_null() {
+ unsafe { BNFreeString((*result).name) };
+ Some(unsafe { ((*result).address, Type::ref_from_raw((*result).type_)) })
+ } else {
+ None
+ }
+ }
+
+ pub fn get_data_variable_by_address<S: BnStrCompatible>(
+ &self,
+ parser_name: S,
+ address: u64,
+ ) -> Option<(String, Ref<Type>)> {
+ let parser_name = parser_name.as_bytes_with_nul();
+ let name_and_var = unsafe {
+ BNGetDebugDataVariableByAddress(
+ self.handle,
+ parser_name.as_ref().as_ptr() as *mut _,
+ address,
+ )
+ };
+
+ if !name_and_var.is_null() {
+ let result = unsafe {
+ (
+ raw_to_string((*name_and_var).name).unwrap(),
+ Type::ref_from_raw((*name_and_var).type_),
+ )
+ };
+ unsafe { BNFreeString((*name_and_var).name) };
+ Some(result)
+ } else {
+ None
+ }
+ }
+
+ // The tuple is (DebugInfoParserName, type)
+ pub fn get_types_by_name<S: BnStrCompatible>(&self, name: S) -> Vec<(String, Ref<Type>)> {
+ let name = name.as_bytes_with_nul();
+
+ let mut count: usize = 0;
+ let raw_names_and_types = unsafe {
+ BNGetDebugTypesByName(self.handle, name.as_ref().as_ptr() as *mut _, &mut count)
+ };
+
+ let names_and_types: &[*mut BNNameAndType] =
+ unsafe { slice::from_raw_parts(raw_names_and_types as *mut _, count) };
+
+ let mut result = Vec::with_capacity(count);
+ for i in 0..count {
+ unsafe {
+ result.push((
+ raw_to_string((*names_and_types[i]).name).unwrap(),
+ Type::ref_from_raw(BNNewTypeReference((*names_and_types[i]).type_)),
+ ))
+ };
+ }
+
+ unsafe { BNFreeNameAndTypeList(raw_names_and_types, count) };
+ result
+ }
+
+ // The tuple is (DebugInfoParserName, address, type)
+ pub fn get_data_variables_by_name<S: BnStrCompatible>(
+ &self,
+ name: S,
+ ) -> Vec<(String, u64, Ref<Type>)> {
+ let name = name.as_bytes_with_nul();
+
+ let mut count: usize = 0;
+ let raw_variables_and_names = unsafe {
+ BNGetDebugDataVariablesByName(self.handle, name.as_ref().as_ptr() as *mut _, &mut count)
+ };
+
+ let variables_and_names: &[*mut BNDataVariableAndName] =
+ unsafe { slice::from_raw_parts(raw_variables_and_names as *mut _, count) };
+
+ let mut result = Vec::with_capacity(count);
+ for i in 0..count {
+ unsafe {
+ result.push((
+ raw_to_string((*variables_and_names[i]).name).unwrap(),
+ (*variables_and_names[i]).address,
+ Type::ref_from_raw(BNNewTypeReference((*variables_and_names[i]).type_)),
+ ))
+ };
+ }
+
+ unsafe { BNFreeDataVariablesAndName(raw_variables_and_names, count) };
+ result
+ }
+
+ /// The tuple is (DebugInfoParserName, TypeName, type)
+ pub fn get_data_variables_by_address(&self, address: u64) -> Vec<(String, String, Ref<Type>)> {
+ let mut count: usize = 0;
+ let raw_variables_and_names =
+ unsafe { BNGetDebugDataVariablesByAddress(self.handle, address, &mut count) };
+
+ let variables_and_names: &[*mut BNDataVariableAndNameAndDebugParser] =
+ unsafe { slice::from_raw_parts(raw_variables_and_names as *mut _, count) };
+
+ let mut result = Vec::with_capacity(count);
+ for i in 0..count {
+ unsafe {
+ result.push((
+ raw_to_string((*variables_and_names[i]).parser).unwrap(),
+ raw_to_string((*variables_and_names[i]).name).unwrap(),
+ Type::ref_from_raw(BNNewTypeReference((*variables_and_names[i]).type_)),
+ ))
+ };
+ }
+
+ unsafe { BNFreeDataVariableAndNameAndDebugParserList(raw_variables_and_names, count) };
+ result
+ }
+
+ pub fn remove_parser_info<S: BnStrCompatible>(&self, parser_name: S) -> bool {
+ let parser_name = parser_name.as_bytes_with_nul();
+
+ unsafe { BNRemoveDebugParserInfo(self.handle, parser_name.as_ref().as_ptr() as *mut _) }
+ }
+
+ pub fn remove_parser_types<S: BnStrCompatible>(&self, parser_name: S) -> bool {
+ let parser_name = parser_name.as_bytes_with_nul();
+
+ unsafe { BNRemoveDebugParserTypes(self.handle, parser_name.as_ref().as_ptr() as *mut _) }
+ }
+
+ pub fn remove_parser_functions<S: BnStrCompatible>(&self, parser_name: S) -> bool {
+ let parser_name = parser_name.as_bytes_with_nul();
+
+ unsafe {
+ BNRemoveDebugParserFunctions(self.handle, parser_name.as_ref().as_ptr() as *mut _)
+ }
+ }
+
+ pub fn remove_parser_data_variables<S: BnStrCompatible>(&self, parser_name: S) -> bool {
+ let parser_name = parser_name.as_bytes_with_nul();
+
+ unsafe {
+ BNRemoveDebugParserDataVariables(self.handle, parser_name.as_ref().as_ptr() as *mut _)
+ }
+ }
+
+ pub fn remove_type_by_name<S: BnStrCompatible>(&self, parser_name: S, name: S) -> bool {
+ let parser_name = parser_name.as_bytes_with_nul();
+ let name = name.as_bytes_with_nul();
+
+ unsafe {
+ BNRemoveDebugTypeByName(
+ self.handle,
+ parser_name.as_ref().as_ptr() as *mut _,
+ name.as_ref().as_ptr() as *mut _,
+ )
+ }
+ }
+
+ pub fn remove_function_by_index<S: BnStrCompatible>(
+ &self,
+ parser_name: S,
+ index: usize,
+ ) -> bool {
+ let parser_name = parser_name.as_bytes_with_nul();
+
+ unsafe {
+ BNRemoveDebugFunctionByIndex(
+ self.handle,
+ parser_name.as_ref().as_ptr() as *mut _,
+ index,
+ )
+ }
+ }
+
+ pub fn remove_data_variable_by_address<S: BnStrCompatible>(
+ &self,
+ parser_name: S,
+ address: u64,
+ ) -> bool {
+ let parser_name = parser_name.as_bytes_with_nul();
+
+ unsafe {
+ BNRemoveDebugDataVariableByAddress(
+ self.handle,
+ parser_name.as_ref().as_ptr() as *mut _,
+ address,
+ )
+ }
+ }
+
/// Adds a type scoped under the current parser's name to the debug info
pub fn add_type<S: BnStrCompatible>(&mut self, name: S, new_type: &Type) -> bool {
let name = name.as_bytes_with_nul();