diff options
| author | Mason Reed <mason@vector35.com> | 2025-04-10 00:53:06 -0400 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2025-04-10 14:38:09 -0400 |
| commit | 86019f825db516d8d5349c271f702dfe69b5fead (patch) | |
| tree | ec91007fa0c857bfd54bb3d1d78ff55daf083928 /view/sharedcache/core/SharedCacheBuilder.cpp | |
| parent | b00d315524610d8c66af27619e87648bd5d63942 (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.cpp | 104 |
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; +} |
