summaryrefslogtreecommitdiff
path: root/view/kernelcache/core/Utility.cpp
diff options
context:
space:
mode:
authorkat <kat@vector35.com>2025-07-06 15:05:01 -0400
committerkat <kat@vector35.com>2025-07-07 07:37:23 -0400
commit768f7c78465fb93936e5ca50a0ca712664fe54e7 (patch)
tree78c73e0022d6006882e365a257595a5b55a37432 /view/kernelcache/core/Utility.cpp
parent8f3e251c42169fb4fe8db9403d900571434d88ff (diff)
KernelCache rewrite
Diffstat (limited to 'view/kernelcache/core/Utility.cpp')
-rw-r--r--view/kernelcache/core/Utility.cpp159
1 files changed, 159 insertions, 0 deletions
diff --git a/view/kernelcache/core/Utility.cpp b/view/kernelcache/core/Utility.cpp
new file mode 100644
index 00000000..6f8323bf
--- /dev/null
+++ b/view/kernelcache/core/Utility.cpp
@@ -0,0 +1,159 @@
+#include "Utility.h"
+#include "binaryninjaapi.h"
+#include "view/macho/machoview.h"
+
+using namespace BinaryNinja;
+
+BNSegmentFlag SegmentFlagsFromMachOProtections(int initProt, int maxProt)
+{
+ uint32_t flags = 0;
+ if (initProt & MACHO_VM_PROT_READ)
+ flags |= SegmentReadable;
+ if (initProt & MACHO_VM_PROT_WRITE)
+ flags |= SegmentWritable;
+ if (initProt & MACHO_VM_PROT_EXECUTE)
+ flags |= SegmentExecutable;
+ if (((initProt & MACHO_VM_PROT_WRITE) == 0) && ((maxProt & MACHO_VM_PROT_WRITE) == 0))
+ flags |= SegmentDenyWrite;
+ if (((initProt & MACHO_VM_PROT_EXECUTE) == 0) && ((maxProt & MACHO_VM_PROT_EXECUTE) == 0))
+ flags |= SegmentDenyExecute;
+ return static_cast<BNSegmentFlag>(flags);
+}
+
+int64_t readSLEB128(const uint8_t*& current, const uint8_t* end)
+{
+ uint8_t cur;
+ int64_t value = 0;
+ size_t shift = 0;
+ while (current != end)
+ {
+ cur = *current++;
+ value |= (cur & 0x7f) << shift;
+ shift += 7;
+ if ((cur & 0x80) == 0)
+ break;
+ }
+ value = (value << (64 - shift)) >> (64 - shift);
+ return value;
+}
+
+uint64_t readLEB128(const uint8_t*& current, const uint8_t* end)
+{
+ uint64_t result = 0;
+ int bit = 0;
+ do
+ {
+ if (current >= end)
+ return -1;
+
+ uint64_t slice = *current & 0x7f;
+
+ if (bit > 63)
+ return -1;
+ result |= (slice << bit);
+ bit += 7;
+ } while (*current++ & 0x80);
+ return result;
+}
+
+
+uint64_t readValidULEB128(const uint8_t*& current, const uint8_t* end)
+{
+ uint64_t value = readLEB128(current, end);
+ if ((int64_t)value == -1)
+ throw ReadException();
+ return value;
+}
+
+void ApplySymbol(Ref<BinaryView> view, Ref<TypeLibrary> typeLib, Ref<Symbol> symbol, Ref<Type> type)
+{
+ auto symbolAddress = symbol->GetAddress();
+ auto symbolName = symbol->GetFullName();
+
+ // Sometimes the symbol will be duplicated, so lets not do this work again.
+ if (view->GetSymbolByAddress(symbolAddress))
+ return;
+
+ // Define the symbol!
+ view->DefineAutoSymbol(symbol);
+
+ // Try and pull a type from a type library to apply at the symbol location.
+ // The type library type will take precedence over the passed in type.
+ Ref<Type> selectedType = type;
+ if (typeLib)
+ selectedType = view->ImportTypeLibraryObject(typeLib, {symbolName});
+
+ Ref<Function> func = nullptr;
+ if (symbol->GetType() == FunctionSymbol)
+ {
+ Ref<Platform> targetPlatform = view->GetDefaultPlatform();
+ // Make sure to check for already added function from the function table.
+ // Unless we have retrieved a type here we don't need to make a new function.
+ func = view->GetAnalysisFunction(targetPlatform, symbolAddress);
+ if (!func || selectedType != nullptr)
+ func = view->AddFunctionForAnalysis(targetPlatform, symbolAddress, false, selectedType);
+ // The above function might be overwritten so we also want to apply the type here.
+ if (func && selectedType != nullptr)
+ func->ApplyAutoDiscoveredType(selectedType);
+ }
+ else
+ {
+ // Other symbol types can just use this, they don't need to worry about linear sweep removing them.
+ view->DefineAutoSymbolAndVariableOrFunction(view->GetDefaultPlatform(), symbol, selectedType);
+ }
+
+ if (func)
+ {
+ // objective c type adjustment stuff.
+ if (symbolName == "_objc_msgSend")
+ {
+ func->SetHasVariableArguments(false);
+ }
+ else if (symbolName.find("_objc_retain_x") != std::string::npos
+ || symbolName.find("_objc_release_x") != std::string::npos)
+ {
+ auto x = symbolName.rfind('x');
+ auto num = symbolName.substr(x + 1);
+
+ std::vector<FunctionParameter> callTypeParams;
+ auto cc = view->GetDefaultArchitecture()->GetCallingConventionByName("apple-arm64-objc-fast-arc-" + num);
+
+ if (auto idType = view->GetTypeByName({"id"}))
+ {
+ callTypeParams.emplace_back("obj", idType, true, Variable());
+ auto funcType = Type::FunctionType(idType, cc, callTypeParams);
+ func->SetUserType(funcType);
+ }
+ else
+ {
+ LogWarn("Failed to find id type for %llx, objective-c processor not ran?", func->GetStart());
+ }
+ }
+ }
+}
+
+std::string BaseFileName(const std::string& path)
+{
+ auto lastSlashPos = path.find_last_of("/\\");
+ if (lastSlashPos != std::string::npos)
+ return path.substr(lastSlashPos + 1);
+ return path;
+}
+
+bool IsSameFolderForFile(Ref<ProjectFile> a, Ref<ProjectFile> b)
+{
+ if (!a && !b)
+ return true;
+ if (a && b)
+ return IsSameFolder(a->GetFolder(), b->GetFolder());
+ return false;
+}
+
+bool IsSameFolder(Ref<ProjectFolder> a, Ref<ProjectFolder> b)
+{
+ if (!a && !b)
+ return true;
+ if (a && b)
+ return a->GetId() == b->GetId();
+ return false;
+}