Skip to content

Commit fdaff2c

Browse files
committed
wip wip
1 parent 073afca commit fdaff2c

File tree

12 files changed

+425
-46
lines changed

12 files changed

+425
-46
lines changed

view/sharedcache/core/Dyld.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,11 @@ struct dyld_chained_ptr_arm64e_shared_cache_auth_rebase
9595
auth : 1; // == 1
9696
};
9797

98-
// dyld_cache_slide_info4 is used in watchOS which we are not close to supporting right now.
98+
// TODO: dyld_cache_slide_info4 is used in watchOS which we are not close to supporting right now.
9999

100100
#define DYLD_CACHE_SLIDE_V5_PAGE_ATTR_NO_REBASE 0xFFFF // page has no rebasing
101101

102-
struct PACKED_STRUCT dyld_cache_slide_info5
102+
struct PACKED_STRUCT dyld_cache_slide_info_v5
103103
{
104104
uint32_t version; // currently 5
105105
uint32_t page_size; // currently 4096 (may also be 16384)

view/sharedcache/core/MachO.cpp

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ void SharedCacheMachOProcessor::ApplyHeader(Ref<BinaryView> view, SharedCacheMac
480480
// Mach-O View symtab processing with
481481
// a ton of stuff cut out so it can work
482482
// NOTE: This table is read relative to the link edit segment file base.
483+
// TODO: Remove this and use the m_symbols in the cache?
483484
const auto symbols = header.ReadSymbolTable(*view, *m_vm);
484485
for (const auto& sym : symbols)
485486
ApplySymbol(view, typeLib, sym.ToBNSymbol());
@@ -489,6 +490,7 @@ void SharedCacheMachOProcessor::ApplyHeader(Ref<BinaryView> view, SharedCacheMac
489490
if (header.exportTriePresent)
490491
{
491492
// NOTE: This table is read relative to the link edit segment file base.
493+
// TODO: Remove this and use the m_symbols in the cache?
492494
const auto exportSymbols = header.ReadExportSymbolTable(*view, *m_vm);
493495
for (const auto& sym : exportSymbols)
494496
ApplySymbol(view, typeLib, sym.ToBNSymbol());
@@ -811,13 +813,11 @@ std::vector<CacheSymbol> SharedCacheMachOHeader::ReadSymbolTable(BinaryView& vie
811813
uint64_t symbolsAddress = GetLinkEditFileBase() + symtab.symoff;
812814
uint64_t stringsAddress = GetLinkEditFileBase() + symtab.stroff;
813815
uint64_t link = GetLinkEditFileBase();
814-
LogInfo("link edit file base %llx", link);
815816
if (!vm.IsAddressMapped(link))
816817
{
817-
LogError("Link edit segment not mapped");
818+
LogError("Link edit segment not mapped %llx", link);
818819
return {};
819820
}
820-
auto strings = vm.ReadBuffer(stringsAddress, symtab.strsize);
821821

822822
// TODO: This needs to be passed in as an optional argument.
823823
// TODO: Sometimes symbol tables are shared and we have to offset into the table for a specific header.
@@ -857,23 +857,17 @@ std::vector<CacheSymbol> SharedCacheMachOHeader::ReadSymbolTable(BinaryView& vie
857857
continue;
858858
}
859859

860-
std::string symbolName((char*)strings.GetDataAt(nlist.n_strx));
860+
std::string symbolName = vm.ReadCString(stringsAddress + nlist.n_strx);
861861
if (symbolName == "<redacted>")
862862
continue;
863863

864864
std::optional<BNSymbolType> symbolType;
865865
if ((nlist.n_type & N_TYPE) == N_SECT && nlist.n_sect > 0 && (size_t)(nlist.n_sect - 1) < sections.size())
866-
{
867866
symbolType = DataSymbol;
868-
}
869867
else if ((nlist.n_type & N_TYPE) == N_ABS)
870-
{
871868
symbolType = DataSymbol;
872-
}
873869
else if ((nlist.n_type & N_EXT))
874-
{
875870
symbolType = ExternalSymbol;
876-
}
877871

878872
if (!symbolType.has_value())
879873
{
@@ -913,7 +907,7 @@ std::vector<CacheSymbol> SharedCacheMachOHeader::ReadSymbolTable(BinaryView& vie
913907

914908
CacheSymbol symbol;
915909
symbol.address = symbolAddress;
916-
symbol.name = symbolName;
910+
symbol.name = std::move(symbolName);
917911
symbol.type = symbolType.value();
918912
symbolList.emplace_back(symbol);
919913
}
@@ -956,10 +950,11 @@ std::optional<CacheSymbol> SharedCacheMachOHeader::AddExportTerminalSymbol(const
956950
return exportSym;
957951
}
958952

959-
void SharedCacheMachOHeader::ProcessLinkEditTrie(std::vector<CacheSymbol>& symbols, const std::string& currentText, const uint8_t* begin, const uint8_t* current, const uint8_t* end) const
953+
// TODO: This is like 90% of the runtime.
954+
bool SharedCacheMachOHeader::ProcessLinkEditTrie(std::vector<CacheSymbol>& symbols, const std::string& currentText, const uint8_t* begin, const uint8_t* current, const uint8_t* end) const
960955
{
961956
if (current >= end)
962-
throw ReadException();
957+
return false;
963958

964959
uint64_t terminalSize = readValidULEB128(current, end);
965960
const uint8_t* child = current + terminalSize;
@@ -980,18 +975,21 @@ void SharedCacheMachOHeader::ProcessLinkEditTrie(std::vector<CacheSymbol>& symbo
980975
for (uint8_t i = 0; i < childCount; ++i)
981976
{
982977
if (current >= end)
983-
throw ReadException();
978+
return false;
984979
const auto it = std::find(current, end, 0);
985980
childText.append(current, it);
986981
current = it + 1;
987982
if (current >= end)
988-
throw ReadException();
989-
auto next = readValidULEB128(current, end);
983+
return false;
984+
const auto next = readValidULEB128(current, end);
990985
if (next == 0)
991-
throw ReadException();
992-
ProcessLinkEditTrie(symbols, childText, begin, begin + next, end);
986+
return false;
987+
if (!ProcessLinkEditTrie(symbols, childText, begin, begin + next, end))
988+
return false;
993989
childText.resize(currentText.size());
994990
}
991+
992+
return true;
995993
}
996994

997995
std::vector<CacheSymbol> SharedCacheMachOHeader::ReadExportSymbolTable(BinaryView& view, VirtualMemory& vm) const

view/sharedcache/core/MachO.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct SharedCacheMachOHeader
6060
std::optional<CacheSymbol> AddExportTerminalSymbol(const std::string &symbolName, const uint8_t *current,
6161
const uint8_t *end) const;
6262

63-
void ProcessLinkEditTrie(std::vector<CacheSymbol> &symbols, const std::string &currentText, const uint8_t *begin,
63+
bool ProcessLinkEditTrie(std::vector<CacheSymbol> &symbols, const std::string &currentText, const uint8_t *begin,
6464
const uint8_t *current, const uint8_t *end) const;
6565

6666
std::vector<CacheSymbol> ReadExportSymbolTable(BinaryNinja::BinaryView& view, VirtualMemory& vm) const;

view/sharedcache/core/SharedCache.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@ void SharedCache::AddSymbol(CacheSymbol symbol)
151151
m_symbols.insert({symbol.address, std::move(symbol)});
152152
}
153153

154+
void SharedCache::AddSymbols(std::vector<CacheSymbol> symbols)
155+
{
156+
for (auto& symbol : symbols)
157+
m_symbols.insert({symbol.address, std::move(symbol)});
158+
}
159+
154160
CacheEntryId SharedCache::AddEntry(CacheEntry entry)
155161
{
156162
// TODO: Maybe check to see if we already added the file?
@@ -163,8 +169,8 @@ CacheEntryId SharedCache::AddEntry(CacheEntry entry)
163169

164170
// Populate virtual memory using the entry mappings, by doing so we can now
165171
// read the memory of the mapped regions of the cache entry file.
166-
const auto &mappings = entry.GetMappings();
167-
for (const auto &mapping: mappings)
172+
const auto& mappings = entry.GetMappings();
173+
for (const auto& mapping: mappings)
168174
m_vm->MapRegion(fileAccessor, {mapping.address, mapping.address + mapping.size}, mapping.fileOffset);
169175

170176
// We are done and can make the entry visible to the entire cache.
@@ -311,14 +317,12 @@ void SharedCache::ProcessEntry(BinaryView &view, const CacheEntry &entry)
311317
// TODO: Populating symbols here means that we have all of the symbols for the entire shared cache loaded always.
312318
// TODO: We should make this lazy (i.e. GetSymbolAt should check the symbols list then do actual work).
313319
// Populate symbols with this images symbols.
314-
std::vector<CacheSymbol> symbols = imageHeader->ReadSymbolTable(view, *m_vm);
315-
for (const CacheSymbol& symbol : symbols)
316-
AddSymbol(symbol);
320+
// std::vector<CacheSymbol> symbols = imageHeader->ReadSymbolTable(view, *m_vm);
321+
// AddSymbols(std::move(symbols));
317322

318323
// TODO: Should export symbols be put in a different bucket? How are they consumed differently?
319324
std::vector<CacheSymbol> exportSymbols = imageHeader->ReadExportSymbolTable(view, *m_vm);
320-
for (const CacheSymbol& exportSymbol : exportSymbols)
321-
AddSymbol(exportSymbol);
325+
AddSymbols(std::move(exportSymbols));
322326

323327
// This is behind a shared pointer as the header itself is very large.
324328
image.header = std::make_shared<SharedCacheMachOHeader>(*imageHeader);

view/sharedcache/core/SharedCache.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ struct CacheSymbol
1515
uint64_t address;
1616
std::string name;
1717

18+
CacheSymbol() = default;
19+
CacheSymbol(BNSymbolType type, uint64_t address, std::string name)
20+
: type(type), address(address), name(std::move(name)) {}
21+
~CacheSymbol() = default;
22+
23+
CacheSymbol(const CacheSymbol& other) = default;
24+
CacheSymbol& operator=(const CacheSymbol& other) = default;
25+
26+
CacheSymbol(CacheSymbol&& other) noexcept = default;
27+
CacheSymbol& operator=(CacheSymbol&& other) noexcept = default;
28+
1829
// NOTE: you should really only call this when adding the symbol to the view.
1930
BinaryNinja::Ref<BinaryNinja::Symbol> ToBNSymbol() const;
2031
};
@@ -39,6 +50,15 @@ struct CacheRegion
3950
std::optional<uint64_t> imageStart;
4051
BNSegmentFlag flags;
4152

53+
CacheRegion() = default;
54+
~CacheRegion() = default;
55+
56+
CacheRegion(const CacheRegion& other) = default;
57+
CacheRegion& operator=(const CacheRegion& other) = default;
58+
59+
CacheRegion(CacheRegion&& other) noexcept = default;
60+
CacheRegion& operator=(CacheRegion&& other) noexcept = default;
61+
4262
AddressRange AsAddressRange() const
4363
{
4464
return { start, start + size };
@@ -69,6 +89,15 @@ struct CacheImage
6989
std::vector<uint64_t> regionStarts;
7090
std::shared_ptr<SharedCacheMachOHeader> header;
7191

92+
CacheImage() = default;
93+
~CacheImage() = default;
94+
95+
CacheImage(const CacheImage& other) = default;
96+
CacheImage& operator=(const CacheImage& other) = default;
97+
98+
CacheImage(CacheImage&& other) noexcept = default;
99+
CacheImage& operator=(CacheImage&& other) noexcept = default;
100+
72101
// Get the file name from the path.
73102
std::string GetName() const { return ImageName(path); }
74103
};
@@ -164,6 +193,7 @@ class SharedCache {
164193
bool AddNonOverlappingRegion(CacheRegion region);
165194

166195
void AddSymbol(CacheSymbol symbol);
196+
void AddSymbols(std::vector<CacheSymbol> symbols);
167197

168198
// Adds the cache entry and populates the virtual memory using the mapping information.
169199
// After being added the entry is read only, there is nothing that can modify it.
@@ -186,6 +216,7 @@ class SharedCache {
186216

187217
std::optional<CacheImage> GetImageAt(uint64_t address) const;
188218
std::optional<CacheImage> GetImageContaining(uint64_t address) const;
219+
// TODO: Rename to GetImageWithPath and then make another one for the image name.
189220
std::optional<CacheImage> GetImageWithName(const std::string& name) const;
190221

191222
std::optional<CacheSymbol> GetSymbolAt(uint64_t address) const;

view/sharedcache/core/SharedCacheView.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -647,19 +647,19 @@ bool SharedCacheView::Init()
647647

648648
// TODO: Add up everything here blud
649649
// TODO: Run this up on a seperate thread maybe and have callback notifications?
650+
auto startTime = std::chrono::high_resolution_clock::now();
650651
sharedCache.ProcessEntries(*this);
652+
auto endTime = std::chrono::high_resolution_clock::now();
653+
std::chrono::duration<double> elapsed = endTime - startTime;
654+
LogInfo("Processing entries took %.3f seconds", elapsed.count());
651655

652656
auto cacheController = SharedCacheController::Initialize(*this, sharedCache);
653657

654658
// TODO: Load the auto loaded images.
655659
// TODO: Make this configurable, so users can select images in OwO.
656-
// TODO: This probably wont work, the image name will be the full path rn.
657-
auto autoLoadedLib = cacheController->GetCache().GetImageWithName("libsystem_c.dylib");
658-
if (autoLoadedLib.has_value())
659-
{
660-
LogInfo("Loading libsystem_c.dylib... BLAH BLAH");
661-
cacheController->LoadImage(*this, *autoLoadedLib);
662-
}
660+
for (const auto& [_, image] : sharedCache.GetImages())
661+
if (image.GetName() == "libsystem_c.dylib")
662+
cacheController->LoadImage(*this, image);
663663

664664
return true;
665665
}

0 commit comments

Comments
 (0)