summaryrefslogtreecommitdiff
path: root/view/sharedcache/core/ObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'view/sharedcache/core/ObjC.cpp')
-rw-r--r--view/sharedcache/core/ObjC.cpp113
1 files changed, 75 insertions, 38 deletions
diff --git a/view/sharedcache/core/ObjC.cpp b/view/sharedcache/core/ObjC.cpp
index c763b321..bb483542 100644
--- a/view/sharedcache/core/ObjC.cpp
+++ b/view/sharedcache/core/ObjC.cpp
@@ -1,95 +1,98 @@
#include "ObjC.h"
+#include "SharedCacheController.h"
+
using namespace BinaryNinja;
using namespace DSCObjC;
-using namespace SharedCacheCore;
-DSCObjCReader::DSCObjCReader(SharedCache* cache, size_t addressSize) :
- m_reader(VMReader(cache->GetVMMap())), m_addressSize(addressSize)
-{
-}
+SharedCacheObjCReader::SharedCacheObjCReader(VirtualMemoryReader reader) : m_reader(reader) {}
-void DSCObjCReader::Read(void* dest, size_t len)
+void SharedCacheObjCReader::Read(void* dest, size_t len)
{
m_reader.Read(dest, len);
}
-std::string DSCObjCReader::ReadCString()
+std::string SharedCacheObjCReader::ReadCString(size_t maxLength)
{
- return m_reader.ReadCString(m_reader.GetOffset());
+ return m_reader.ReadCString(m_reader.GetOffset(), maxLength);
}
-uint8_t DSCObjCReader::Read8()
+uint8_t SharedCacheObjCReader::Read8()
{
- return m_reader.Read8();
+ return m_reader.ReadUInt8();
}
-uint16_t DSCObjCReader::Read16()
+uint16_t SharedCacheObjCReader::Read16()
{
- return m_reader.Read16();
+ return m_reader.ReadUInt16();
}
-uint32_t DSCObjCReader::Read32()
+uint32_t SharedCacheObjCReader::Read32()
{
- return m_reader.Read32();
+ return m_reader.ReadUInt32();
}
-uint64_t DSCObjCReader::Read64()
+uint64_t SharedCacheObjCReader::Read64()
{
- return m_reader.Read64();
+ return m_reader.ReadUInt64();
}
-int8_t DSCObjCReader::ReadS8()
+int8_t SharedCacheObjCReader::ReadS8()
{
- return m_reader.ReadS8();
+ return m_reader.ReadInt8();
}
-int16_t DSCObjCReader::ReadS16()
+int16_t SharedCacheObjCReader::ReadS16()
{
- return m_reader.ReadS16();
+ return m_reader.ReadInt16();
}
-int32_t DSCObjCReader::ReadS32()
+int32_t SharedCacheObjCReader::ReadS32()
{
- return m_reader.ReadS32();
+ return m_reader.ReadInt32();
}
-int64_t DSCObjCReader::ReadS64()
+int64_t SharedCacheObjCReader::ReadS64()
{
- return m_reader.ReadS64();
+ return m_reader.ReadInt64();
}
-uint64_t DSCObjCReader::ReadPointer()
+uint64_t SharedCacheObjCReader::ReadPointer()
{
return m_reader.ReadPointer();
}
-uint64_t DSCObjCReader::GetOffset() const
+uint64_t SharedCacheObjCReader::GetOffset() const
{
return m_reader.GetOffset();
}
-void DSCObjCReader::Seek(uint64_t offset)
+void SharedCacheObjCReader::Seek(uint64_t offset)
{
m_reader.Seek(offset);
}
-void DSCObjCReader::SeekRelative(int64_t offset)
+void SharedCacheObjCReader::SeekRelative(int64_t offset)
{
m_reader.SeekRelative(offset);
}
-VMReader& DSCObjCReader::GetVMReader()
+VirtualMemoryReader& SharedCacheObjCReader::GetVMReader()
{
return m_reader;
}
-std::shared_ptr<ObjCReader> DSCObjCProcessor::GetReader()
+std::shared_ptr<ObjCReader> SharedCacheObjCProcessor::GetReader()
{
- return std::make_shared<DSCObjCReader>(m_cache, m_data->GetAddressSize());
+ const auto controller = DSC::SharedCacheController::FromView(*m_data);
+ // TODO: This should never happen.
+ if (!controller)
+ throw std::runtime_error("SharedCacheController not found for SharedCacheObjCProcessor::GetReader!");
+ auto reader = VirtualMemoryReader(controller->GetCache().GetVirtualMemory(), m_data->GetAddressSize());
+ return std::make_shared<SharedCacheObjCReader>(reader);
}
-void DSCObjCProcessor::GetRelativeMethod(ObjCReader* reader, method_t& meth)
+void SharedCacheObjCProcessor::GetRelativeMethod(ObjCReader* reader, method_t& meth)
{
if (m_customRelativeMethodSelectorBase.has_value())
{
@@ -103,14 +106,48 @@ void DSCObjCProcessor::GetRelativeMethod(ObjCReader* reader, method_t& meth)
}
}
-uint64_t DSCObjCProcessor::GetObjCRelativeMethodBaseAddress(ObjCReader* reader)
+std::optional<ObjCOptimizationHeader> GetObjCOptimizationHeader(SharedCache& cache, VirtualMemoryReader& reader)
{
- auto objCRelativeMethodsBaseAddr = m_cache->GetObjCRelativeMethodBaseAddress(static_cast<DSCObjCReader*>(reader)->GetVMReader());
- m_customRelativeMethodSelectorBase = objCRelativeMethodsBaseAddr;
- return objCRelativeMethodsBaseAddr;
+ // Find the first primary entry and use that header to read the obj opt header.
+ // Don't ask me why this is done like this...
+ std::optional<dyld_cache_header> primaryCacheHeader = std::nullopt;
+ for (const auto& [_, entry] : cache.GetEntries())
+ {
+ if (entry.GetType() == CacheEntryType::Primary)
+ {
+ primaryCacheHeader = entry.GetHeader();
+ break;
+ }
+ }
+
+ // Check if we even have the obj opt stuff.
+ if (!primaryCacheHeader || !primaryCacheHeader->objcOptsOffset || !primaryCacheHeader->objcOptsSize)
+ return std::nullopt;
+
+ ObjCOptimizationHeader header = {};
+ // Ignoring `objcOptsSize` in favor of `sizeof(ObjCOptimizationHeader)` matches dyld's behavior.
+ // TODO: The base address is the lowest region, however is that going to be where the primary cache header resides?
+ reader.Read(&header, cache.GetBaseAddress() + primaryCacheHeader->objcOptsOffset, sizeof(ObjCOptimizationHeader));
+
+ return header;
}
-DSCObjCProcessor::DSCObjCProcessor(BinaryView* data, SharedCache* cache, bool isBackedByDatabase) :
- ObjCProcessor(data, "SharedCache.ObjC", isBackedByDatabase, true), m_cache(cache)
+uint64_t SharedCacheObjCProcessor::GetObjCRelativeMethodBaseAddress(ObjCReader* reader)
{
+ // Try and retrieve the base address of the selector stuff.
+ if (const auto controller = DSC::SharedCacheController::FromView(*m_data))
+ {
+ auto baseAddress = controller->GetCache().GetBaseAddress();
+ auto dangerReader = dynamic_cast<SharedCacheObjCReader*>(reader)->GetVMReader();
+ if (const auto header = GetObjCOptimizationHeader(controller->GetCache(), dangerReader); header.has_value())
+ {
+ m_customRelativeMethodSelectorBase = baseAddress + header->relativeMethodSelectorBaseAddressOffset;
+ }
+ }
+
+ return m_customRelativeMethodSelectorBase.value_or(0);
}
+
+SharedCacheObjCProcessor::SharedCacheObjCProcessor(BinaryView* data, bool isBackedByDatabase) :
+ ObjCProcessor(data, "SharedCache.ObjC", isBackedByDatabase, true)
+{}