@@ -213,6 +213,71 @@ bool SharedCacheController::ApplyImage(BinaryView& view, const CacheImage& image
213213 view.SetFunctionAnalysisUpdateDisabled (true );
214214 machoProcessor.ApplyHeader (*image.header );
215215 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+ }
216281
217282 // Load objective-c information.
218283 auto objcProcessor = DSCObjC::SharedCacheObjCProcessor (&view, false , image.headerAddress );
0 commit comments