2727#include " SharedCache.h"
2828#include " ObjC.h"
2929#include < filesystem>
30+ #include < mutex>
31+ #include < unordered_map>
3032#include < utility>
3133#include < fcntl.h>
3234#include < memory>
@@ -78,19 +80,51 @@ struct SharedCache::State
7880 DSCViewState viewState = DSCViewStateUnloaded;
7981};
8082
81- static std::recursive_mutex viewStateMutex;
82- static std::unordered_map<uint64_t , std::shared_ptr<struct SharedCache ::State>> viewStateCache;
83+ struct SharedCache ::ViewSpecificState {
84+ std::mutex typeLibraryMutex;
85+ std::mutex viewOperationsThatInfluenceMetadataMutex;
8386
84- std::mutex progressMutex;
85- std::unordered_map<uint64_t , BNDSCViewLoadProgress> progressMap;
87+ std::atomic<BNDSCViewLoadProgress> progress;
8688
87- struct ViewSpecificMutexes {
88- std::mutex viewOperationsThatInfluenceMetadataMutex;
89- std::mutex typeLibraryLookupAndApplicationMutex;
89+ std::mutex stateMutex;
90+ std::shared_ptr<struct SharedCache ::State> cachedState;
9091};
9192
92- static std::unordered_map<uint64_t , ViewSpecificMutexes> viewSpecificMutexes;
9393
94+ std::shared_ptr<SharedCache::ViewSpecificState> ViewSpecificStateForId (uint64_t viewIdentifier, bool insertIfNeeded = true ) {
95+ static std::mutex viewSpecificStateMutex;
96+ static std::unordered_map<uint64_t , std::weak_ptr<SharedCache::ViewSpecificState>> viewSpecificState;
97+
98+ std::lock_guard lock (viewSpecificStateMutex);
99+
100+ if (auto it = viewSpecificState.find (viewIdentifier); it != viewSpecificState.end ()) {
101+ if (auto statePtr = it->second .lock ()) {
102+ return statePtr;
103+ }
104+ }
105+
106+ if (!insertIfNeeded) {
107+ return nullptr ;
108+ }
109+
110+ auto statePtr = std::make_shared<SharedCache::ViewSpecificState>();
111+ viewSpecificState[viewIdentifier] = statePtr;
112+
113+ // Prune entries for any views that are no longer in use.
114+ for (auto it = viewSpecificState.begin (); it != viewSpecificState.end (); ) {
115+ if (it->second .expired ()) {
116+ it = viewSpecificState.erase (it);
117+ } else {
118+ ++it;
119+ }
120+ }
121+
122+ return statePtr;
123+ }
124+
125+ std::shared_ptr<SharedCache::ViewSpecificState> ViewSpecificStateForView (Ref<BinaryNinja::BinaryView> view) {
126+ return ViewSpecificStateForId (view->GetFile ()->GetSessionId ());
127+ }
94128
95129std::string base_name (std::string const & path)
96130{
@@ -220,9 +254,7 @@ void SharedCache::PerformInitialLoad()
220254 auto path = m_dscView->GetFile ()->GetOriginalFilename ();
221255 auto baseFile = MMappedFileAccessor::Open (m_dscView, m_dscView->GetFile ()->GetSessionId (), path)->lock ();
222256
223- progressMutex.lock ();
224- progressMap[m_dscView->GetFile ()->GetSessionId ()] = LoadProgressLoadingCaches;
225- progressMutex.unlock ();
257+ m_viewSpecificState->progress = LoadProgressLoadingCaches;
226258
227259 WillMutateState ();
228260
@@ -737,9 +769,8 @@ void SharedCache::PerformInitialLoad()
737769 }
738770 }
739771 baseFile.reset ();
740- progressMutex.lock ();
741- progressMap[m_dscView->GetFile ()->GetSessionId ()] = LoadProgressLoadingImages;
742- progressMutex.unlock ();
772+
773+ m_viewSpecificState->progress = LoadProgressLoadingImages;
743774
744775 // We have set up enough metadata to map VM now.
745776
@@ -952,9 +983,7 @@ void SharedCache::PerformInitialLoad()
952983
953984 m_logger->LogDebug (" Finished initial load of Shared Cache" );
954985
955- progressMutex.lock ();
956- progressMap[m_dscView->GetFile ()->GetSessionId ()] = LoadProgressFinished;
957- progressMutex.unlock ();
986+ m_viewSpecificState->progress = LoadProgressFinished;
958987}
959988
960989std::shared_ptr<VM> SharedCache::GetVMMap (bool mapPages)
@@ -983,10 +1012,10 @@ void SharedCache::DeserializeFromRawView()
9831012{
9841013 if (m_dscView->QueryMetadata (SharedCacheMetadataTag))
9851014 {
986- std::unique_lock<std::recursive_mutex> viewStateCacheLock (viewStateMutex );
987- if (auto it = viewStateCache. find (m_dscView-> GetFile ()-> GetSessionId ()); it != viewStateCache. end () )
1015+ std::lock_guard lock (m_viewSpecificState-> stateMutex );
1016+ if (m_viewSpecificState-> cachedState )
9881017 {
989- m_state = it-> second ;
1018+ m_state = m_viewSpecificState-> cachedState ;
9901019 m_stateIsShared = true ;
9911020 m_metadataValid = true ;
9921021 }
@@ -1367,7 +1396,7 @@ void SharedCache::ParseAndApplySlideInfoForFile(std::shared_ptr<MMappedFileAcces
13671396}
13681397
13691398
1370- SharedCache::SharedCache (BinaryNinja::Ref<BinaryNinja::BinaryView> dscView) : m_dscView(dscView)
1399+ SharedCache::SharedCache (BinaryNinja::Ref<BinaryNinja::BinaryView> dscView) : m_dscView(dscView), m_viewSpecificState(ViewSpecificStateForView(dscView))
13711400{
13721401 if (dscView->GetTypeName () != VIEW_NAME)
13731402 {
@@ -1381,46 +1410,43 @@ SharedCache::SharedCache(BinaryNinja::Ref<BinaryNinja::BinaryView> dscView) : m_
13811410 DeserializeFromRawView ();
13821411 if (!m_metadataValid)
13831412 return ;
1384- if (State ().viewState == DSCViewStateUnloaded)
1413+
1414+ if (State ().viewState != DSCViewStateUnloaded) {
1415+ m_viewSpecificState->progress = LoadProgressFinished;
1416+ return ;
1417+ }
1418+
1419+ std::unique_lock lock (m_viewSpecificState->viewOperationsThatInfluenceMetadataMutex );
1420+ try {
1421+ PerformInitialLoad ();
1422+ }
1423+ catch (...)
13851424 {
1386- std::unique_lock<std::mutex> lock (viewSpecificMutexes[m_dscView->GetFile ()->GetSessionId ()].viewOperationsThatInfluenceMetadataMutex );
1387- try {
1388- PerformInitialLoad ();
1389- }
1390- catch (...)
1391- {
1392- m_logger->LogError (" Failed to perform initial load of Shared Cache" );
1393- }
1425+ m_logger->LogError (" Failed to perform initial load of Shared Cache" );
1426+ }
13941427
1395- auto settings = m_dscView->GetLoadSettings (VIEW_NAME);
1396- bool autoLoadLibsystem = true ;
1397- if (settings && settings->Contains (" loader.dsc.autoLoadLibSystem" ))
1398- {
1399- autoLoadLibsystem = settings->Get <bool >(" loader.dsc.autoLoadLibSystem" , m_dscView);
1400- }
1401- if (autoLoadLibsystem)
1428+ auto settings = m_dscView->GetLoadSettings (VIEW_NAME);
1429+ bool autoLoadLibsystem = true ;
1430+ if (settings && settings->Contains (" loader.dsc.autoLoadLibSystem" ))
1431+ {
1432+ autoLoadLibsystem = settings->Get <bool >(" loader.dsc.autoLoadLibSystem" , m_dscView);
1433+ }
1434+ if (autoLoadLibsystem)
1435+ {
1436+ for (const auto & [_, header] : State ().headers )
14021437 {
1403- for ( const auto & [_, header] : State (). headers )
1438+ if ( header. installName . find ( " libsystem_c.dylib " ) != std::string::npos )
14041439 {
1405- if (header.installName .find (" libsystem_c.dylib" ) != std::string::npos)
1406- {
1407- lock.unlock ();
1408- m_logger->LogInfo (" Loading core libsystem_c.dylib library" );
1409- LoadImageWithInstallName (header.installName , false );
1410- lock.lock ();
1411- break ;
1412- }
1440+ lock.unlock ();
1441+ m_logger->LogInfo (" Loading core libsystem_c.dylib library" );
1442+ LoadImageWithInstallName (header.installName , false );
1443+ break ;
14131444 }
14141445 }
1415- MutableState ().viewState = DSCViewStateLoaded;
1416- SaveToDSCView ();
1417- }
1418- else
1419- {
1420- progressMutex.lock ();
1421- progressMap[m_dscView->GetFile ()->GetSessionId ()] = LoadProgressFinished;
1422- progressMutex.unlock ();
14231446 }
1447+
1448+ MutableState ().viewState = DSCViewStateLoaded;
1449+ SaveToDSCView ();
14241450}
14251451
14261452SharedCache::~SharedCache () {
@@ -1536,7 +1562,7 @@ bool SharedCache::LoadImageContainingAddress(uint64_t address, bool skipObjC)
15361562
15371563bool SharedCache::LoadSectionAtAddress (uint64_t address)
15381564{
1539- std::unique_lock<std::mutex> lock (viewSpecificMutexes[m_dscView-> GetFile ()-> GetSessionId ()]. viewOperationsThatInfluenceMetadataMutex );
1565+ std::unique_lock lock (m_viewSpecificState-> viewOperationsThatInfluenceMetadataMutex );
15401566 DeserializeFromRawView ();
15411567 WillMutateState ();
15421568
@@ -1806,7 +1832,7 @@ bool SharedCache::LoadImageWithInstallName(std::string installName, bool skipObj
18061832{
18071833 auto settings = m_dscView->GetLoadSettings (VIEW_NAME);
18081834
1809- std::unique_lock<std::mutex> lock (viewSpecificMutexes[m_dscView-> GetFile ()-> GetSessionId ()]. viewOperationsThatInfluenceMetadataMutex );
1835+ std::unique_lock lock (m_viewSpecificState-> viewOperationsThatInfluenceMetadataMutex );
18101836
18111837 DeserializeFromRawView ();
18121838 WillMutateState ();
@@ -1880,7 +1906,7 @@ bool SharedCache::LoadImageWithInstallName(std::string installName, bool skipObj
18801906 return false ;
18811907 }
18821908
1883- std::unique_lock<std::mutex> typelibLock (viewSpecificMutexes[m_dscView-> GetFile ()-> GetSessionId ()]. typeLibraryLookupAndApplicationMutex );
1909+ std::unique_lock typelibLock (m_viewSpecificState-> typeLibraryMutex );
18841910 auto typeLib = m_dscView->GetTypeLibrary (header.installName );
18851911
18861912 if (!typeLib)
@@ -2875,7 +2901,7 @@ std::vector<std::pair<std::string, Ref<Symbol>>> SharedCache::LoadAllSymbolsAndW
28752901{
28762902 WillMutateState ();
28772903
2878- std::unique_lock<std::mutex> initialLoadBlock (viewSpecificMutexes[m_dscView-> GetFile ()-> GetSessionId ()]. viewOperationsThatInfluenceMetadataMutex );
2904+ std::lock_guard initialLoadBlock (m_viewSpecificState-> viewOperationsThatInfluenceMetadataMutex );
28792905
28802906 std::vector<std::pair<std::string, Ref<Symbol>>> symbols;
28812907 for (const auto & img : State ().images )
@@ -2973,7 +2999,7 @@ void SharedCache::FindSymbolAtAddrAndApplyToAddr(
29732999 }
29743000 auto exportList = SharedCache::ParseExportTrie (mapping, *header);
29753001 std::vector<std::pair<uint64_t , std::pair<BNSymbolType, std::string>>> exportMapping;
2976- std::unique_lock<std::mutex> lock (viewSpecificMutexes[m_dscView-> GetFile ()-> GetSessionId ()]. typeLibraryLookupAndApplicationMutex );
3002+ std::unique_lock lock (m_viewSpecificState-> typeLibraryMutex );
29773003 auto typeLib = m_dscView->GetTypeLibrary (header->installName );
29783004 if (!typeLib)
29793005 {
@@ -3020,7 +3046,7 @@ void SharedCache::FindSymbolAtAddrAndApplyToAddr(
30203046 }
30213047 }
30223048 {
3023- std::unique_lock<std::mutex> _lock (viewSpecificMutexes[m_dscView-> GetFile ()-> GetSessionId ()]. viewOperationsThatInfluenceMetadataMutex );
3049+ std::lock_guard lock (m_viewSpecificState-> viewOperationsThatInfluenceMetadataMutex );
30243050 MutableState ().exportInfos [header->textBase ] = std::move (exportMapping);
30253051 }
30263052 m_dscView->EndBulkModifySymbols ();
@@ -3044,8 +3070,8 @@ bool SharedCache::SaveToDSCView()
30443070 m_state = cachedState;
30453071 m_stateIsShared = true ;
30463072
3047- std::unique_lock<std::recursive_mutex> viewStateCacheLock (viewStateMutex );
3048- viewStateCache[m_dscView-> GetFile ()-> GetSessionId ()] = std::move (cachedState);
3073+ std::lock_guard lock (m_viewSpecificState-> stateMutex );
3074+ m_viewSpecificState-> cachedState = std::move (cachedState);
30493075
30503076 m_metadataValid = true ;
30513077
@@ -3055,7 +3081,7 @@ bool SharedCache::SaveToDSCView()
30553081}
30563082std::vector<MemoryRegion> SharedCache::GetMappedRegions () const
30573083{
3058- std::unique_lock<std::mutex> lock (viewSpecificMutexes[m_dscView-> GetFile ()-> GetSessionId ()]. viewOperationsThatInfluenceMetadataMutex );
3084+ std::lock_guard lock (m_viewSpecificState-> viewOperationsThatInfluenceMetadataMutex );
30593085 return State ().regionsMappedIntoMemory ;
30603086}
30613087
@@ -3392,15 +3418,11 @@ extern "C"
33923418
33933419 BNDSCViewLoadProgress BNDSCViewGetLoadProgress (uint64_t sessionID)
33943420 {
3395- progressMutex.lock ();
3396- if (progressMap.find (sessionID) == progressMap.end ())
3397- {
3398- progressMutex.unlock ();
3399- return LoadProgressNotStarted;
3421+ if (auto viewSpecificState = ViewSpecificStateForId (sessionID, false )) {
3422+ return viewSpecificState->progress ;
34003423 }
3401- auto progress = progressMap[sessionID];
3402- progressMutex.unlock ();
3403- return progress;
3424+
3425+ return LoadProgressNotStarted;
34043426 }
34053427
34063428 uint64_t BNDSCViewFastGetBackingCacheCount (BNBinaryView* data)
0 commit comments