summaryrefslogtreecommitdiff
path: root/debuginfo.cpp
diff options
context:
space:
mode:
authorKyleMiles <krm504@nyu.edu>2021-05-19 20:40:24 -0400
committerKyleMiles <krm504@nyu.edu>2021-07-07 23:27:29 -0400
commitd19f5e85ee26c3d6604798d30ab821d15731cada (patch)
tree9851b7f6bf5589df69508d4489c11148515cb550 /debuginfo.cpp
parent0f58b0742e3010eee6bbd2e15f4dd4930ec0d822 (diff)
DebugInfo - plugable debug information importers - C++, Rust, and Python APIs
Diffstat (limited to 'debuginfo.cpp')
-rw-r--r--debuginfo.cpp249
1 files changed, 249 insertions, 0 deletions
diff --git a/debuginfo.cpp b/debuginfo.cpp
new file mode 100644
index 00000000..2bdc2e47
--- /dev/null
+++ b/debuginfo.cpp
@@ -0,0 +1,249 @@
+// Copyright (c) 2015-2021 Vector 35 Inc
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+
+
+// TODO : Documentation
+
+
+#include "binaryninjaapi.h"
+using namespace BinaryNinja;
+using namespace std;
+
+
+///////////////
+// DebugInfo //
+///////////////
+
+
+DebugInfo::DebugInfo(BNDebugInfo* debugInfo)
+{
+ m_object = debugInfo;
+}
+
+
+vector<NameAndType> DebugInfo::GetTypes(const string& parserName)
+{
+ size_t count;
+ BNNameAndType* nameAndTypes = BNGetDebugTypes(m_object, parserName.size() == 0 ? nullptr : parserName.c_str(), &count);
+
+ vector<NameAndType> result;
+ for (size_t i = 0; i < count; ++i)
+ {
+ result.emplace_back(nameAndTypes[i].name,
+ Confidence<Ref<Type>>(
+ new Type(BNNewTypeReference(nameAndTypes[i].type)),
+ nameAndTypes[i].typeConfidence));
+ }
+
+ BNFreeDebugTypes(nameAndTypes, count);
+ return result;
+}
+
+
+vector<DebugFunctionInfo> DebugInfo::GetFunctions(const string& parserName)
+{
+ size_t count;
+ BNDebugFunctionInfo* functions = BNGetDebugFunctions(m_object, parserName.size() == 0 ? nullptr : parserName.c_str(), &count);
+
+ vector<DebugFunctionInfo> result;
+ for (size_t i = 0; i < count; ++i)
+ {
+ vector<tuple<string, Ref<Type>>> parameters;
+ for (size_t j = 0; j < functions[i].parameterCount; ++j)
+ parameters.emplace_back(functions[i].parameterNames[j], new Type(BNNewTypeReference(functions[i].parameterTypes[j])));
+
+ result.emplace_back(functions[i].shortName ? functions[i].shortName : "",
+ functions[i].fullName ? functions[i].fullName : "",
+ functions[i].rawName ? functions[i].rawName : "",
+ functions[i].address,
+ functions[i].returnType ? new Type(BNNewTypeReference(functions[i].returnType)) : nullptr,
+ parameters,
+ functions[i].variableParameters,
+ functions[i].callingConvention ? new CoreCallingConvention(BNNewCallingConventionReference(functions[i].callingConvention)) : nullptr,
+ functions[i].platform ? new Platform(BNNewPlatformReference(functions[i].platform)) : nullptr);
+ }
+
+ BNFreeDebugFunctions(functions, count);
+ return result;
+}
+
+
+vector<DataVariableAndName> DebugInfo::GetDataVariables(const string& parserName)
+{
+ size_t count;
+ BNDataVariableAndName* variableAndNames = BNGetDebugDataVariables(m_object, parserName.size() == 0 ? nullptr : parserName.c_str(), &count);
+
+ vector<DataVariableAndName> result;
+ for (size_t i = 0; i < count; ++i)
+ {
+ result.emplace_back(variableAndNames[i].address,
+ Confidence(new Type(BNNewTypeReference(variableAndNames[i].type)), variableAndNames[i].typeConfidence),
+ variableAndNames[i].autoDiscovered,
+ variableAndNames[i].name);
+ }
+
+ BNFreeDataVariablesAndName(variableAndNames, count);
+ return result;
+}
+
+
+bool DebugInfo::AddType(const string& name, Ref<Type> type)
+{
+ return BNAddDebugType(m_object, name.c_str(), type->GetObject());
+}
+
+
+bool DebugInfo::AddFunction(const DebugFunctionInfo& function)
+{
+ BNDebugFunctionInfo* input = new BNDebugFunctionInfo();
+
+ input->shortName = function.shortName.size() ? BNAllocString(function.shortName.c_str()) : nullptr;
+ input->fullName = function.fullName.size() ? BNAllocString(function.fullName.c_str()) : nullptr;
+ input->rawName = function.rawName.size() ? BNAllocString(function.rawName.c_str()) : nullptr;
+ input->address = function.address;
+ input->returnType = function.returnType ? function.returnType->GetObject() : nullptr;
+ input->variableParameters = function.variableParameters;
+ input->callingConvention = function.callingConvention ? function.callingConvention->GetObject() : nullptr;
+ input->platform = function.platform ? function.platform->GetObject() : nullptr;
+
+ size_t parameterCount = function.parameters.size();
+ input->parameterCount = parameterCount;
+ input->parameterNames = new char*[parameterCount];
+ input->parameterTypes = new BNType*[parameterCount];
+ for (size_t i = 0; i < parameterCount; ++i)
+ {
+ input->parameterNames[i] = BNAllocString(std::get<0>(function.parameters[i]).c_str());
+ input->parameterTypes[i] = std::get<1>(function.parameters[i])->GetObject();
+ }
+
+ bool result = BNAddDebugFunction(m_object, input);
+
+ BNFreeString(input->shortName);
+ BNFreeString(input->fullName);
+ BNFreeString(input->rawName);
+
+ for (size_t i = 0; i < parameterCount; ++i)
+ BNFreeString(input->parameterNames[i]);
+
+ return result;
+}
+
+
+bool DebugInfo::AddDataVariable(uint64_t address, Ref<Type> type, const string& name)
+{
+ if (name.size() == 0)
+ return BNAddDebugDataVariable(m_object, address, type->GetObject(), nullptr);
+ return BNAddDebugDataVariable(m_object, address, type->GetObject(), name.c_str());
+}
+
+
+/////////////////////
+// DebugInfoParser //
+/////////////////////
+
+
+DebugInfoParser::DebugInfoParser(BNDebugInfoParser* parser)
+{
+ m_object = parser;
+}
+
+
+Ref<DebugInfoParser> DebugInfoParser::GetByName(const string& name)
+{
+ BNDebugInfoParser* parser = BNGetDebugInfoParserByName(name.c_str());
+ if (parser)
+ return new DebugInfoParser(BNNewDebugInfoParserReference(parser));
+ return nullptr;
+}
+
+
+vector<Ref<DebugInfoParser>> DebugInfoParser::GetList()
+{
+ size_t count = 0;
+ BNDebugInfoParser** parsers = BNGetDebugInfoParsers(&count);
+
+ vector<Ref<DebugInfoParser>> result;
+ for (size_t i = 0; i < count; ++i)
+ {
+ result.emplace_back(new DebugInfoParser(BNNewDebugInfoParserReference(parsers[i])));
+ }
+
+ BNFreeDebugInfoParserList(parsers, count);
+ return result;
+}
+
+
+vector<Ref<DebugInfoParser>> DebugInfoParser::GetListForView(const Ref<BinaryView> data)
+{
+ size_t count = 0;
+ BNDebugInfoParser** parsers = BNGetDebugInfoParsersForView(data->GetObject(), &count);
+
+ vector<Ref<DebugInfoParser>> result;
+ for (size_t i = 0; i < count; ++i)
+ {
+ result.emplace_back(new DebugInfoParser(BNNewDebugInfoParserReference(parsers[i])));
+ }
+
+ BNFreeDebugInfoParserList(parsers, count);
+ return result;
+}
+
+
+string DebugInfoParser::GetName() const
+{
+ return BNGetDebugInfoParserName(m_object);
+}
+
+
+Ref<DebugInfo> DebugInfoParser::Parse(Ref<BinaryView> view, Ref<DebugInfo> existingDebugInfo) const
+{
+ if (existingDebugInfo)
+ return new DebugInfo(BNNewDebugInfoReference(BNParseDebugInfo(m_object, view->GetObject(), existingDebugInfo->GetObject())));
+ return new DebugInfo(BNParseDebugInfo(m_object, view->GetObject(), nullptr));
+}
+
+
+bool DebugInfoParser::IsValidForView(const Ref<BinaryView> view) const
+{
+ return BNIsDebugInfoParserValidForView(m_object, view->GetObject());
+}
+
+
+//////////////////////////////
+// Plugin registration APIs //
+//////////////////////////////
+
+
+bool CustomDebugInfoParser::IsValidCallback(void* ctxt, BNBinaryView* view)
+{
+ CustomDebugInfoParser* parser = (CustomDebugInfoParser*)ctxt;
+ return parser->IsValid(new BinaryView(view));
+}
+
+
+void CustomDebugInfoParser::ParseCallback(void* ctxt, BNDebugInfo* debugInfo, BNBinaryView* view)
+{
+ CustomDebugInfoParser* parser = (CustomDebugInfoParser*)ctxt;
+ parser->ParseInfo(new DebugInfo(debugInfo), new BinaryView(view));
+}
+
+
+CustomDebugInfoParser::CustomDebugInfoParser(const string& name) :
+ DebugInfoParser(BNNewDebugInfoParserReference(BNRegisterDebugInfoParser(name.c_str(), IsValidCallback, ParseCallback, this))) {}