Skip to content

Commit e691b44

Browse files
committed
wip
1 parent 8eb1b5e commit e691b44

File tree

5 files changed

+73
-50
lines changed

5 files changed

+73
-50
lines changed

view/sharedcache/core/MachO.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -629,11 +629,8 @@ uint64_t SharedCacheMachOHeader::ApplyHeaderSections(Ref<BinaryView> view)
629629
};
630630

631631
uint64_t addedSections = 0;
632-
for (size_t i = 0; i < sections.size(); i++)
632+
for (size_t i = 0; i < sections.size() && i < sectionNames.size(); i++)
633633
{
634-
// We only add sections with a name!
635-
if (i >= sectionNames.size())
636-
continue;
637634
if (initSection(sections[i], sectionNames[i]))
638635
addedSections++;
639636
}

view/sharedcache/core/ObjC.cpp

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,100 @@
11
#include "ObjC.h"
22

3+
#include "SharedCacheController.h"
4+
35
using namespace BinaryNinja;
46
using namespace DSCObjC;
57

6-
DSCObjCReader::DSCObjCReader(VirtualMemoryReader reader, size_t addressSize) : m_reader(reader), m_addressSize(addressSize)
8+
SharedCacheObjCReader::SharedCacheObjCReader(VirtualMemoryReader reader, size_t addressSize) : m_reader(reader), m_addressSize(addressSize)
79
{
810
}
911

10-
void DSCObjCReader::Read(void* dest, size_t len)
12+
void SharedCacheObjCReader::Read(void* dest, size_t len)
1113
{
1214
m_reader.Read(dest, len);
1315
}
1416

15-
std::string DSCObjCReader::ReadCString()
17+
std::string SharedCacheObjCReader::ReadCString()
1618
{
1719
return m_reader.ReadCString(m_reader.GetOffset());
1820
}
1921

20-
uint8_t DSCObjCReader::Read8()
22+
uint8_t SharedCacheObjCReader::Read8()
2123
{
2224
return m_reader.ReadUInt8();
2325
}
2426

25-
uint16_t DSCObjCReader::Read16()
27+
uint16_t SharedCacheObjCReader::Read16()
2628
{
2729
return m_reader.ReadUInt16();
2830
}
2931

30-
uint32_t DSCObjCReader::Read32()
32+
uint32_t SharedCacheObjCReader::Read32()
3133
{
3234
return m_reader.ReadUInt32();
3335
}
3436

35-
uint64_t DSCObjCReader::Read64()
37+
uint64_t SharedCacheObjCReader::Read64()
3638
{
3739
return m_reader.ReadUInt64();
3840
}
3941

40-
int8_t DSCObjCReader::ReadS8()
42+
int8_t SharedCacheObjCReader::ReadS8()
4143
{
4244
return m_reader.ReadInt8();
4345
}
4446

45-
int16_t DSCObjCReader::ReadS16()
47+
int16_t SharedCacheObjCReader::ReadS16()
4648
{
4749
return m_reader.ReadInt16();
4850
}
4951

50-
int32_t DSCObjCReader::ReadS32()
52+
int32_t SharedCacheObjCReader::ReadS32()
5153
{
5254
return m_reader.ReadInt32();
5355
}
5456

55-
int64_t DSCObjCReader::ReadS64()
57+
int64_t SharedCacheObjCReader::ReadS64()
5658
{
5759
return m_reader.ReadInt64();
5860
}
5961

60-
uint64_t DSCObjCReader::ReadPointer()
62+
uint64_t SharedCacheObjCReader::ReadPointer()
6163
{
6264
return m_reader.ReadPointer();
6365
}
6466

65-
uint64_t DSCObjCReader::GetOffset() const
67+
uint64_t SharedCacheObjCReader::GetOffset() const
6668
{
6769
return m_reader.GetOffset();
6870
}
6971

70-
void DSCObjCReader::Seek(uint64_t offset)
72+
void SharedCacheObjCReader::Seek(uint64_t offset)
7173
{
7274
m_reader.Seek(offset);
7375
}
7476

75-
void DSCObjCReader::SeekRelative(int64_t offset)
77+
void SharedCacheObjCReader::SeekRelative(int64_t offset)
7678
{
7779
m_reader.SeekRelative(offset);
7880
}
7981

80-
VirtualMemoryReader& DSCObjCReader::GetVMReader()
82+
VirtualMemoryReader& SharedCacheObjCReader::GetVMReader()
8183
{
8284
return m_reader;
8385
}
8486

85-
std::shared_ptr<ObjCReader> DSCObjCProcessor::GetReader()
87+
std::shared_ptr<ObjCReader> SharedCacheObjCProcessor::GetReader()
8688
{
87-
auto reader = VirtualMemoryReader(m_cache->GetVirtualMemory());
88-
return std::make_shared<DSCObjCReader>(reader, m_data->GetAddressSize());
89+
const auto controller = DSC::SharedCacheController::FromView(*m_data);
90+
// TODO: This should never happen.
91+
if (!controller)
92+
throw std::runtime_error("SharedCacheController not found for SharedCacheObjCProcessor::GetReader!");
93+
auto reader = VirtualMemoryReader(controller->GetCache().GetVirtualMemory());
94+
return std::make_shared<SharedCacheObjCReader>(reader, m_data->GetAddressSize());
8995
}
9096

91-
void DSCObjCProcessor::GetRelativeMethod(ObjCReader* reader, method_t& meth)
97+
void SharedCacheObjCProcessor::GetRelativeMethod(ObjCReader* reader, method_t& meth)
9298
{
9399
if (m_customRelativeMethodSelectorBase.has_value())
94100
{
@@ -102,12 +108,12 @@ void DSCObjCProcessor::GetRelativeMethod(ObjCReader* reader, method_t& meth)
102108
}
103109
}
104110

105-
std::optional<ObjCOptimizationHeader> DSCObjCProcessor::GetObjCOptimizationHeader(VirtualMemoryReader &reader) const
111+
std::optional<ObjCOptimizationHeader> GetObjCOptimizationHeader(SharedCache& cache, VirtualMemoryReader &reader)
106112
{
107113
// Find the first primary entry and use that header to read the obj opt header.
108114
// Don't ask me why this is done like this...
109115
std::optional<dyld_cache_header> primaryCacheHeader = std::nullopt;
110-
for (const auto& [_, entry] : m_cache->GetEntries())
116+
for (const auto& [_, entry] : cache.GetEntries())
111117
{
112118
if (entry.GetType() == CacheEntryType::Primary)
113119
{
@@ -122,21 +128,28 @@ std::optional<ObjCOptimizationHeader> DSCObjCProcessor::GetObjCOptimizationHeade
122128

123129
ObjCOptimizationHeader header = {};
124130
// Ignoring `objcOptsSize` in favor of `sizeof(ObjCOptimizationHeader)` matches dyld's behavior.
125-
reader.Read(&header, m_cache->GetBaseAddress() + primaryCacheHeader->objcOptsOffset, sizeof(ObjCOptimizationHeader));
131+
reader.Read(&header, cache.GetBaseAddress() + primaryCacheHeader->objcOptsOffset, sizeof(ObjCOptimizationHeader));
126132

127133
return header;
128134
}
129135

130-
uint64_t DSCObjCProcessor::GetObjCRelativeMethodBaseAddress(ObjCReader* reader)
136+
uint64_t SharedCacheObjCProcessor::GetObjCRelativeMethodBaseAddress(ObjCReader* reader)
131137
{
132-
// TODO: This is a silly.
133-
auto dangerReader = dynamic_cast<DSCObjCReader*>(reader)->GetVMReader();
134-
if (const auto header = GetObjCOptimizationHeader(dangerReader); header.has_value())
135-
m_customRelativeMethodSelectorBase = m_cache->GetBaseAddress() + header->relativeMethodSelectorBaseAddressOffset;
138+
// Try and retrieve the base address of the selector stuff.
139+
if (const auto controller = DSC::SharedCacheController::FromView(*m_data))
140+
{
141+
auto baseAddress = controller->GetCache().GetBaseAddress();
142+
auto dangerReader = dynamic_cast<SharedCacheObjCReader*>(reader)->GetVMReader();
143+
if (const auto header = GetObjCOptimizationHeader(controller->GetCache(), dangerReader); header.has_value())
144+
{
145+
m_customRelativeMethodSelectorBase = baseAddress + header->relativeMethodSelectorBaseAddressOffset;
146+
}
147+
}
148+
136149
return m_customRelativeMethodSelectorBase.value_or(0);
137150
}
138151

139-
DSCObjCProcessor::DSCObjCProcessor(BinaryView* data, SharedCache* cache, bool isBackedByDatabase) :
140-
ObjCProcessor(data, "SharedCache.ObjC", isBackedByDatabase, true), m_cache(cache)
152+
SharedCacheObjCProcessor::SharedCacheObjCProcessor(BinaryView* data, bool isBackedByDatabase) :
153+
ObjCProcessor(data, "SharedCache.ObjC", isBackedByDatabase, true)
141154
{
142155
}

view/sharedcache/core/ObjC.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ struct ObjCOptimizationHeader
1717
};
1818

1919
namespace DSCObjC {
20-
class DSCObjCReader : public BinaryNinja::ObjCReader {
20+
class SharedCacheObjCReader : public BinaryNinja::ObjCReader {
2121
VirtualMemoryReader m_reader;
2222
size_t m_addressSize;
2323

@@ -39,22 +39,17 @@ namespace DSCObjC {
3939

4040
VirtualMemoryReader& GetVMReader();
4141

42-
DSCObjCReader(VirtualMemoryReader reader, size_t addressSize);
42+
SharedCacheObjCReader(VirtualMemoryReader reader, size_t addressSize);
4343
};
4444

45-
class DSCObjCProcessor : public BinaryNinja::ObjCProcessor {
45+
class SharedCacheObjCProcessor : public BinaryNinja::ObjCProcessor {
4646
std::optional<uint64_t> m_customRelativeMethodSelectorBase = std::nullopt;
47-
// TODO: Nuh uh.
48-
SharedCache* m_cache;
4947

5048
std::shared_ptr<BinaryNinja::ObjCReader> GetReader() override;
5149
void GetRelativeMethod(BinaryNinja::ObjCReader* reader, BinaryNinja::method_t& meth) override;
5250

53-
// Intentionally takes a copy to avoid modifying the cursor position in the original reader.
54-
std::optional<ObjCOptimizationHeader> GetObjCOptimizationHeader(VirtualMemoryReader& reader) const;
55-
5651
public:
57-
DSCObjCProcessor(BinaryNinja::BinaryView* data, SharedCache* cache, bool isBackedByDatabase);
52+
SharedCacheObjCProcessor(BinaryNinja::BinaryView* data, bool isBackedByDatabase);
5853

5954
// TODO: Do we really need this???
6055
uint64_t GetObjCRelativeMethodBaseAddress(BinaryNinja::ObjCReader* reader) override;

view/sharedcache/core/SharedCache.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,11 @@ void SharedCache::AddRegion(CacheRegion region)
126126
}
127127

128128
// First region past the end of the region.
129-
auto end = m_regions.lower_bound(region.AsAddressRange().end);
129+
const auto end = m_regions.lower_bound(region.AsAddressRange().end);
130130

131131
for (auto it = begin; it != end; ++it)
132132
{
133-
uint64_t newRegionSize = it->second.start - region.start;
133+
const uint64_t newRegionSize = it->second.start - region.start;
134134
if (newRegionSize)
135135
{
136136
CacheRegion newRegion(region);
@@ -293,15 +293,17 @@ void SharedCache::ProcessEntry(BinaryView &view, const CacheEntry &entry)
293293
memcpy(segName, segment.segname, 16);
294294
segName[16] = 0;
295295

296-
// TODO: Limit this to link edit regions only? Duplicate for other region types?
297296
// Many images include a __LINKEDIT segment that share a single region in the shared cache.
298297
// Reuse the same `MemoryRegion` to represent all of these link edit regions.
299298
// Check to see if we have a shared region, if so skip it.
300-
auto existingRegion = m_regions.find(AddressRange(segment.vmaddr, segment.vmaddr + segment.vmsize));
301-
if (existingRegion != m_regions.end())
299+
if (std::string(segName) == "__LINKEDIT")
302300
{
303-
image.regionStarts.push_back(existingRegion->second.start);
304-
continue;
301+
auto existingRegion = m_regions.find(AddressRange(segment.vmaddr, segment.vmaddr + segment.vmsize));
302+
if (existingRegion != m_regions.end())
303+
{
304+
image.regionStarts.push_back(existingRegion->second.start);
305+
continue;
306+
}
305307
}
306308

307309
CacheRegion sectionRegion;

view/sharedcache/core/SharedCacheController.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "SharedCacheController.h"
22

33
#include "MachO.h"
4+
#include "ObjC.h"
45
#include "SlideInfo.h"
56

67
using namespace BinaryNinja;
@@ -68,6 +69,14 @@ bool SharedCacheController::LoadRegion(BinaryView& view, const CacheRegion& regi
6869
if (!view.GetSectionsAt(region.start).empty())
6970
return false;
7071

72+
// Skip LINKEDIT region, it is like 300mb.
73+
// TODO: Make this configurable.
74+
if (region.name.find("LINKEDIT") != std::string::npos)
75+
{
76+
LogDebug("Skipping LINKEDIT region at %llx", region.start);
77+
return false;
78+
}
79+
7180
auto vm = m_cache.GetVirtualMemory();
7281
auto reader = VirtualMemoryReader(vm);
7382
DataBuffer buffer = {};
@@ -121,6 +130,13 @@ bool SharedCacheController::LoadImage(BinaryView& view, const CacheImage& image)
121130
// Header information is applied to the view here, such as sections.
122131
auto machoProcessor = SharedCacheMachOProcessor(m_cache.GetVirtualMemory());
123132
machoProcessor.ApplyHeader(&view, *image.header);
133+
134+
// Load objective-c information
135+
auto objcProcessor = DSCObjC::SharedCacheObjCProcessor(&view, false);
136+
// TODO: Passing in an image name here is weird considering this is shared with the MACHO view.
137+
// TODO: We should abstract out the "image" into an objc image type that represents what is required, which ig is the name?
138+
objcProcessor.ProcessObjCData(image.GetName());
139+
objcProcessor.ProcessCFStrings(image.GetName());
124140
}
125141

126142
m_loadedImages.insert(image.headerAddress);

0 commit comments

Comments
 (0)