summaryrefslogtreecommitdiff
path: root/view/sharedcache/core/SharedCacheBuilder.cpp
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-04-10 00:53:06 -0400
committerMason Reed <mason@vector35.com>2025-04-10 14:38:09 -0400
commit86019f825db516d8d5349c271f702dfe69b5fead (patch)
treeec91007fa0c857bfd54bb3d1d78ff55daf083928 /view/sharedcache/core/SharedCacheBuilder.cpp
parentb00d315524610d8c66af27619e87648bd5d63942 (diff)
[SharedCache] Make the shared cache file lookup more straightforward
We already had separated this part out into the `CacheProcessor` but its more like a builder than anything, so this refactors that out into a `SharedCacheBuilder`. - Separate out the `CacheProcessor` and simplify its implementation - Move more implementation specific stuff to the shared cache view - Prepare for more validation of the shared cache to detect irregular or incomplete shared cache information - Deduplicate a lot of file vs. project file lookup stuff - Stop copying all images when getting the number of images to log - Allow user to select another directory to scan for shared cache files, might make this a warning instead to prevent users from relying on this behavior We will likely follow this commit up soon with better open behavior, maybe open with options can specify a list of cache entry files? Shouldn't be too much effort aside from making the UI modal for that.
Diffstat (limited to 'view/sharedcache/core/SharedCacheBuilder.cpp')
-rw-r--r--view/sharedcache/core/SharedCacheBuilder.cpp104
1 files changed, 104 insertions, 0 deletions
diff --git a/view/sharedcache/core/SharedCacheBuilder.cpp b/view/sharedcache/core/SharedCacheBuilder.cpp
new file mode 100644
index 00000000..5c3ea0d8
--- /dev/null
+++ b/view/sharedcache/core/SharedCacheBuilder.cpp
@@ -0,0 +1,104 @@
+#include <filesystem>
+#include "SharedCacheBuilder.h"
+
+using namespace BinaryNinja;
+
+SharedCacheBuilder::SharedCacheBuilder(Ref<BinaryView> view)
+{
+ m_view = std::move(view);
+ m_logger = new Logger("SharedCache.Builder", m_view->GetFile()->GetSessionId());
+ m_primaryFileName = BaseFileName(m_view->GetFile()->GetOriginalFilename());
+ m_cache = SharedCache(m_view->GetAddressSize());
+ m_processedFiles = {};
+}
+
+SharedCache SharedCacheBuilder::Finalize()
+{
+ // Reset the state to the builder to reuse.
+ m_processedFiles = {};
+ return std::move(m_cache);
+}
+
+bool SharedCacheBuilder::AddFile(
+ const std::string& filePath, const std::string& fileName, const CacheEntryType cacheType)
+{
+ // Skip already processed files.
+ if (auto [_, inserted] = m_processedFiles.insert(filePath); !inserted)
+ return false;
+ // We only want to process files containing the base file name.
+ if (fileName.find(m_primaryFileName) == std::string::npos)
+ return false;
+ // Skip map files, they contain some nice information... we don't use.
+ if (fileName.find(".map") != std::string::npos)
+ return false;
+ // Skip bndb files!
+ if (fileName.find(".bndb") != std::string::npos)
+ return false;
+
+ try
+ {
+ if (auto entry = CacheEntry::FromFile(filePath, fileName, cacheType))
+ {
+ m_cache.AddEntry(std::move(*entry));
+ return true;
+ }
+ }
+ catch (const std::exception& e)
+ {
+ // Just return false so the view init can continue.
+ m_logger->LogErrorF("Failed to add file {}... {}", fileName, e.what());
+ }
+
+ return false;
+}
+
+size_t SharedCacheBuilder::AddDirectory(const std::string& directoryPath)
+{
+ // Filters then attempts to process a single directory entry as a shared cache file.
+ auto processDirEntry = [&](const std::filesystem::directory_entry& entry) {
+ const auto currentFilePath = entry.path().string();
+ const auto currentFileName = BaseFileName(currentFilePath);
+
+ // Skip non-files.
+ if (!entry.is_regular_file())
+ return false;
+
+ // Ok, we are now _sure_ that this file _might_ be a part of the cache, lets try and process it!
+ return AddFile(currentFilePath, currentFileName, CacheEntryType::Secondary);
+ };
+
+ // TODO: This is ugly.
+ size_t added = 0;
+ // Locate all possible related entry files and add them to the cache.
+ for (const auto& entry : std::filesystem::directory_iterator(directoryPath))
+ if (processDirEntry(entry))
+ added++;
+ return added;
+}
+
+size_t SharedCacheBuilder::AddProjectFolder(Ref<ProjectFolder> folder)
+{
+ auto processProjectFile = [&](const ProjectFile& file) {
+ const auto currentFilePath = file.GetPathOnDisk();
+ const auto currentFileName = file.GetName();
+
+ // Skip files not in the folder.
+ if (const auto currentFolder = file.GetFolder(); folder)
+ if (currentFolder->GetId() != folder->GetId())
+ return false;
+
+ // Ok, we are now _sure_ that this file _might_ be a part of the cache, lets try and process it!
+ return AddFile(currentFilePath, currentFileName, CacheEntryType::Secondary);
+ };
+
+ auto viewProjectFile = m_view->GetFile()->GetProjectFile();
+ if (!viewProjectFile)
+ return 0;
+
+ auto project = viewProjectFile->GetProject();
+ size_t added = 0;
+ for (const auto& projectFile : project->GetFiles())
+ if (processProjectFile(*projectFile))
+ added++;
+ return added;
+}