@@ -2665,33 +2665,34 @@ void SharedCache::InitializeHeader(
26652665
26662666 if (header.exportTriePresent && header.linkeditPresent && vm->AddressIsMapped (header.linkeditSegment .vmaddr ))
26672667 {
2668- auto symbols = SharedCache::ParseExportTrie (vm->MappingAtAddress (header.linkeditSegment .vmaddr ).first .fileAccessor ->lock (), header);
2669- std::vector<std::pair<uint64_t , std::pair<BNSymbolType, std::string>>> exportMapping;
2668+ auto symbols = GetExportListForHeader (header, [&]() {
2669+ return vm->MappingAtAddress (header.linkeditSegment .vmaddr ).first .fileAccessor ->lock ();
2670+ });
26702671 for (const auto & symbol : symbols)
26712672 {
2672- exportMapping. push_back ({ symbol-> GetAddress (), { symbol-> GetType () , symbol-> GetRawName ()}} );
2673+ auto bnSymbol = new Symbol ( symbol. second . first , symbol. second . second , symbol. first );
26732674 if (typeLib)
26742675 {
2675- auto type = m_dscView->ImportTypeLibraryObject (typeLib, {symbol-> GetFullName () });
2676+ auto type = m_dscView->ImportTypeLibraryObject (typeLib, {symbol. second . second });
26762677
26772678 if (type)
26782679 {
2679- view->DefineAutoSymbolAndVariableOrFunction (view->GetDefaultPlatform (), symbol , type);
2680+ view->DefineAutoSymbolAndVariableOrFunction (view->GetDefaultPlatform (), bnSymbol , type);
26802681 }
26812682 else
2682- view->DefineAutoSymbol (symbol );
2683+ view->DefineAutoSymbol (bnSymbol );
26832684
2684- if (view->GetAnalysisFunction (view->GetDefaultPlatform (), symbol-> GetAddress () ))
2685+ if (view->GetAnalysisFunction (view->GetDefaultPlatform (), symbol. first ))
26852686 {
2686- auto func = view->GetAnalysisFunction (view->GetDefaultPlatform (), symbol-> GetAddress () );
2687- if (symbol-> GetFullName () == " _objc_msgSend" )
2687+ auto func = view->GetAnalysisFunction (view->GetDefaultPlatform (), symbol. first );
2688+ if (symbol. second . second == " _objc_msgSend" )
26882689 {
26892690 func->SetHasVariableArguments (false );
26902691 }
2691- else if (symbol-> GetFullName (). find (" _objc_retain_x" ) != std::string::npos || symbol-> GetFullName () .find (" _objc_release_x" ) != std::string::npos)
2692+ else if (symbol. second . second . find (" _objc_retain_x" ) != std::string::npos || symbol. second . second .find (" _objc_release_x" ) != std::string::npos)
26922693 {
2693- auto x = symbol-> GetFullName () .rfind (" x" );
2694- auto num = symbol-> GetFullName () .substr (x + 1 );
2694+ auto x = symbol. second . second .rfind (" x" );
2695+ auto num = symbol. second . second .substr (x + 1 );
26952696
26962697 std::vector<BinaryNinja::FunctionParameter> callTypeParams;
26972698 auto cc = m_dscView->GetDefaultArchitecture ()->GetCallingConventionByName (" apple-arm64-objc-fast-arc-" + num);
@@ -2704,9 +2705,8 @@ void SharedCache::InitializeHeader(
27042705 }
27052706 }
27062707 else
2707- view->DefineAutoSymbol (symbol );
2708+ view->DefineAutoSymbol (bnSymbol );
27082709 }
2709- MutableState ().exportInfos [header.textBase ] = std::move (exportMapping);
27102710 }
27112711 view->EndBulkModifySymbols ();
27122712
@@ -2794,6 +2794,7 @@ std::vector<Ref<Symbol>> SharedCache::ParseExportTrie(std::shared_ptr<MMappedFil
27942794
27952795 try
27962796 {
2797+ // FIXME we can absolutely predict this size
27972798 std::vector<Ref<Symbol>> symbols;
27982799 auto [begin, end] = linkeditFile->ReadSpan (header.exportTrie .dataoff , header.exportTrie .datasize );
27992800 ReadExportNode (symbols, header, begin, end, begin, header.textBase , " " );
@@ -2806,6 +2807,32 @@ std::vector<Ref<Symbol>> SharedCache::ParseExportTrie(std::shared_ptr<MMappedFil
28062807 }
28072808}
28082809
2810+
2811+ std::vector<std::pair<uint64_t , std::pair<BNSymbolType, std::string>>> SharedCache::GetExportListForHeader (SharedCacheMachOHeader header, std::function<std::shared_ptr<MMappedFileAccessor>()> provideLinkeditFile)
2812+ {
2813+ if (auto it = m_state->exportInfos .find (header.textBase ); it != m_state->exportInfos .end ())
2814+ {
2815+ return it->second ;
2816+ }
2817+ else
2818+ {
2819+ // TODO does this have to be a functor? can't we just pass the accessor? if not, why?
2820+ std::shared_ptr<MMappedFileAccessor> linkeditFile = provideLinkeditFile ();
2821+ if (!linkeditFile)
2822+ return std::vector<std::pair<uint64_t , std::pair<BNSymbolType, std::string>>>();
2823+
2824+ auto exportList = SharedCache::ParseExportTrie (linkeditFile, header);
2825+ std::vector<std::pair<uint64_t , std::pair<BNSymbolType, std::string>>> exportMapping (exportList.size ());
2826+ for (const auto & sym : exportList)
2827+ {
2828+ exportMapping.push_back ({sym->GetAddress (), {sym->GetType (), sym->GetRawName ()}});
2829+ }
2830+ m_state->exportInfos [header.textBase ] = exportMapping;
2831+ return exportMapping;
2832+ }
2833+ }
2834+
2835+
28092836std::vector<std::string> SharedCache::GetAvailableImages ()
28102837{
28112838 std::vector<std::string> installNames;
@@ -2823,30 +2850,32 @@ std::vector<std::pair<std::string, Ref<Symbol>>> SharedCache::LoadAllSymbolsAndW
28232850
28242851 std::lock_guard initialLoadBlock (m_viewSpecificState->viewOperationsThatInfluenceMetadataMutex );
28252852
2853+ bool doSave = false ;
28262854 std::vector<std::pair<std::string, Ref<Symbol>>> symbols;
28272855 for (const auto & img : State ().images )
28282856 {
28292857 auto header = HeaderForAddress (img.headerLocation );
2830- std::shared_ptr<MMappedFileAccessor> mapping;
2831- try {
2832- mapping = MMappedFileAccessor::Open (m_dscView, m_dscView->GetFile ()->GetSessionId (), header->exportTriePath )->lock ();
2833- }
2834- catch (...)
2835- {
2836- m_logger->LogWarn (" Serious Error: Failed to open export trie %s for %s" , header->exportTriePath .c_str (), header->installName .c_str ());
2837- continue ;
2838- }
2839- auto exportList = SharedCache::ParseExportTrie (mapping, *header);
2840- std::vector<std::pair<uint64_t , std::pair<BNSymbolType, std::string>>> exportMapping;
2858+ auto exportList = GetExportListForHeader (*header, [&]() {
2859+ try {
2860+ auto mapping = MMappedFileAccessor::Open (m_dscView, m_dscView->GetFile ()->GetSessionId (), header->exportTriePath )->lock ();
2861+ doSave = true ;
2862+ return mapping;
2863+ }
2864+ catch (...)
2865+ {
2866+ m_logger->LogWarn (" Serious Error: Failed to open export trie %s for %s" , header->exportTriePath .c_str (), header->installName .c_str ());
2867+ return std::shared_ptr<MMappedFileAccessor>(nullptr );
2868+ }
2869+ });
28412870 for (const auto & sym : exportList)
28422871 {
2843- exportMapping.push_back ({sym->GetAddress (), {sym->GetType (), sym->GetRawName ()}});
2844- symbols.push_back ({img.installName , sym});
2872+ symbols.push_back ({img.installName , new Symbol (sym.second .first , sym.second .second , sym.first )});
28452873 }
2846- MutableState ().exportInfos [header->textBase ] = std::move (exportMapping);
28472874 }
28482875
2849- SaveToDSCView ();
2876+ // Only save to DSC view if a header was actually loaded
2877+ if (doSave)
2878+ SaveToDSCView ();
28502879
28512880 return symbols;
28522881}
@@ -2926,41 +2955,42 @@ void SharedCache::FindSymbolAtAddrAndApplyToAddr(
29262955 auto header = HeaderForAddress (symbolLocation);
29272956 if (header)
29282957 {
2929- std::shared_ptr<MMappedFileAccessor> mapping;
2930- try {
2931- mapping = MMappedFileAccessor::Open (m_dscView, m_dscView->GetFile ()->GetSessionId (), header->exportTriePath )->lock ();
2932- }
2933- catch (...)
2934- {
2935- m_logger->LogWarn (" Serious Error: Failed to open export trie for %s" , header->installName .c_str ());
2936- return ;
2937- }
2938- auto exportList = SharedCache::ParseExportTrie (mapping, *header);
2958+
2959+ auto exportList = GetExportListForHeader (*header, [&]() {
2960+ try {
2961+ return MMappedFileAccessor::Open (m_dscView, m_dscView->GetFile ()->GetSessionId (), header->exportTriePath )->lock ();
2962+ }
2963+ catch (...)
2964+ {
2965+ m_logger->LogWarn (" Serious Error: Failed to open export trie %s for %s" , header->exportTriePath .c_str (), header->installName .c_str ());
2966+ return std::shared_ptr<MMappedFileAccessor>(nullptr );
2967+ }
2968+ });
2969+
29392970 std::vector<std::pair<uint64_t , std::pair<BNSymbolType, std::string>>> exportMapping;
29402971 auto typeLib = TypeLibraryForImage (header->installName );
29412972 id = m_dscView->BeginUndoActions ();
29422973 m_dscView->BeginBulkModifySymbols ();
29432974 for (const auto & sym : exportList)
29442975 {
2945- exportMapping.push_back ({sym->GetAddress (), {sym->GetType (), sym->GetRawName ()}});
2946- if (sym->GetAddress () == symbolLocation)
2976+ if (sym.first == symbolLocation)
29472977 {
29482978 if (auto func = m_dscView->GetAnalysisFunction (m_dscView->GetDefaultPlatform (), targetLocation))
29492979 {
29502980 m_dscView->DefineUserSymbol (
2951- new Symbol (FunctionSymbol, prefix + sym-> GetFullName () , targetLocation));
2981+ new Symbol (FunctionSymbol, prefix + sym. second . second , targetLocation));
29522982
29532983 if (typeLib)
2954- if (auto type = m_dscView->ImportTypeLibraryObject (typeLib, {sym-> GetFullName () }))
2984+ if (auto type = m_dscView->ImportTypeLibraryObject (typeLib, {sym. second . second }))
29552985 func->SetUserType (type);
29562986 }
29572987 else
29582988 {
29592989 m_dscView->DefineUserSymbol (
2960- new Symbol (sym-> GetType () , prefix + sym-> GetFullName () , targetLocation));
2990+ new Symbol (sym. second . first , prefix + sym. second . second , targetLocation));
29612991
29622992 if (typeLib)
2963- if (auto type = m_dscView->ImportTypeLibraryObject (typeLib, {sym-> GetFullName () }))
2993+ if (auto type = m_dscView->ImportTypeLibraryObject (typeLib, {sym. second . second }))
29642994 m_dscView->DefineUserDataVariable (targetLocation, type);
29652995 }
29662996 if (triggerReanalysis)
@@ -2972,10 +3002,6 @@ void SharedCache::FindSymbolAtAddrAndApplyToAddr(
29723002 break ;
29733003 }
29743004 }
2975- {
2976- std::lock_guard lock (m_viewSpecificState->viewOperationsThatInfluenceMetadataMutex );
2977- MutableState ().exportInfos [header->textBase ] = std::move (exportMapping);
2978- }
29793005 m_dscView->EndBulkModifySymbols ();
29803006 m_dscView->ForgetUndoActions (id);
29813007 }
0 commit comments