@@ -213,6 +213,71 @@ bool SharedCacheController::ApplyImage(BinaryView& view, const CacheImage& image
213
213
view.SetFunctionAnalysisUpdateDisabled (true );
214
214
machoProcessor.ApplyHeader (*image.header );
215
215
view.SetFunctionAnalysisUpdateDisabled (prevDisabledState);
216
+
217
+ // Add symbols from the symbol cache files.
218
+ // This is done separate from applying the header as it constitutes knowing about other cache images.
219
+ // NOTE: If we want to move this into the `ApplyHeader` above we would need to give it some extra cache context.
220
+ const auto & cache = GetCache ();
221
+ const auto vm = cache.GetVirtualMemory ();
222
+ for (const auto & entry : cache.GetEntries ())
223
+ {
224
+ if (entry.GetType () != CacheEntryType::Symbols && vm->GetAddressSize () == 8 )
225
+ continue ;
226
+ const auto & header = entry.GetHeader ();
227
+
228
+ // This is where we get the symbol and string table information from in the .symbols file.
229
+ dyld_cache_local_symbols_info localSymbolsInfo = {};
230
+ auto localSymbolsInfoAddr = entry.GetMappedAddress (header.localSymbolsOffset );
231
+ if (!localSymbolsInfoAddr.has_value ())
232
+ continue ;
233
+ vm->Read (&localSymbolsInfo, *localSymbolsInfoAddr, sizeof (dyld_cache_local_symbols_info));
234
+
235
+ // Read each symbols entry, looking for the current image entry.
236
+ uint64_t localEntriesAddr = *localSymbolsInfoAddr + localSymbolsInfo.entriesOffset ;
237
+ uint64_t localSymbolsAddr = *localSymbolsInfoAddr + localSymbolsInfo.nlistOffset ;
238
+ uint64_t localStringsAddr = *localSymbolsInfoAddr + localSymbolsInfo.stringsOffset ;
239
+ std::vector<dyld_cache_local_symbols_entry_64> symbolEntries;
240
+ symbolEntries.reserve (localSymbolsInfo.entriesCount );
241
+ dyld_cache_local_symbols_entry_64 localSymbolsEntry = {};
242
+
243
+ // TODO: Clean this up!!!! This is taken from the macho code...
244
+ auto typeLibraryFromName = [&](const std::string& name) -> Ref<TypeLibrary> {
245
+ // Check to see if we have already loaded the type library.
246
+ if (auto typeLib = view.GetTypeLibrary (name))
247
+ return typeLib;
248
+
249
+ auto typeLibs = view.GetDefaultPlatform ()->GetTypeLibrariesByName (name);
250
+ if (!typeLibs.empty ())
251
+ return typeLibs.front ();
252
+ return nullptr ;
253
+ };
254
+
255
+ // Pull the available type library for the image we are loading, so we can apply known types.
256
+ auto typeLib = typeLibraryFromName (image.GetName ());
257
+
258
+ for (uint32_t i = 0 ; i < localSymbolsInfo.entriesCount ; i++)
259
+ {
260
+ vm->Read (&localSymbolsEntry, localEntriesAddr + i * sizeof (dyld_cache_local_symbols_entry_64),
261
+ sizeof (dyld_cache_local_symbols_entry_64));
262
+ symbolEntries.push_back (localSymbolsEntry);
263
+ auto imageAddr = cache.GetBaseAddress () + localSymbolsEntry.dylibOffset ;
264
+ if (image.headerAddress == imageAddr)
265
+ {
266
+ // We have found the entry to read!
267
+ // TODO: Support 32bit nlist
268
+ uint64_t symbolTableStart = localSymbolsAddr + (localSymbolsEntry.nlistStartIndex * sizeof (nlist_64));
269
+ TableInfo symbolInfo = { symbolTableStart, localSymbolsEntry.nlistCount };
270
+ TableInfo stringInfo = { localStringsAddr, localSymbolsInfo.stringsSize };
271
+ const auto symbols = image.header ->ReadSymbolTable (*vm, symbolInfo, stringInfo);
272
+ m_logger->LogInfoF (" Found {} symbols in .symbols for image {}" , symbols.size (), image.path .c_str ());
273
+ for (const auto & sym : symbols)
274
+ {
275
+ auto [symbol, symbolType] = sym.GetBNSymbolAndType (view);
276
+ ApplySymbol (&view, typeLib, symbol, symbolType);
277
+ }
278
+ }
279
+ }
280
+ }
216
281
217
282
// Load objective-c information.
218
283
auto objcProcessor = DSCObjC::SharedCacheObjCProcessor (&view, false , image.headerAddress );
0 commit comments