diff options
| author | WeiN76LQh <WeiN76LQh@github.com> | 2024-11-26 00:09:03 +0000 |
|---|---|---|
| committer | kat <kat@vector35.com> | 2024-12-26 10:42:56 -0500 |
| commit | a9245348accd81263e106896f7b98ed5bc4afe5c (patch) | |
| tree | af85e95e848bba8d84a40141e7cb321d8a123705 /view/sharedcache/core/SharedCache.cpp | |
| parent | 2cce2ab6c79879a4d64df1fc7375e2c871565f8f (diff) | |
[SharedCache] Add the ability to manually trigger Objective-C processing
A problem with processing Objective-C sections at the time a library is loaded is that some of the references within those sections may refer to unload sections. This results in things like selectors not being correctly typed and named.
This commit provides a way for users to manually trigger Objective-C parsing against sections for a specific library or all libraries, via the API. Combined with the previous commit a user can use the API to batch load a number of libraries and skip Objective-C processing for each one and then run it across the entire of the DSC once they are all loaded.
Further improvement would be to provide a way to trigger Objective-C processing through the UI.
Diffstat (limited to 'view/sharedcache/core/SharedCache.cpp')
| -rw-r--r-- | view/sharedcache/core/SharedCache.cpp | 117 |
1 files changed, 95 insertions, 22 deletions
diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp index d4ce0921..51e95bc6 100644 --- a/view/sharedcache/core/SharedCache.cpp +++ b/view/sharedcache/core/SharedCache.cpp @@ -1727,6 +1727,81 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) return true; } +static void GetObjCSettings(Ref<BinaryView> view, bool* processObjCMetadata, bool* processCFStrings) +{ + auto settings = view->GetLoadSettings(VIEW_NAME); + *processCFStrings = true; + *processObjCMetadata = true; + if (settings && settings->Contains("loader.dsc.processCFStrings")) + *processCFStrings = settings->Get<bool>("loader.dsc.processCFStrings", view); + if (settings && settings->Contains("loader.dsc.processObjC")) + *processObjCMetadata = settings->Get<bool>("loader.dsc.processObjC", view); +} + +static void ProcessObjCSectionsForImageWithName(std::string baseName, std::shared_ptr<VM> vm, std::shared_ptr<DSCObjC::DSCObjCProcessor> objc, bool processCFStrings, bool processObjCMetadata, Ref<Logger> logger) +{ + try + { + if (processObjCMetadata) + objc->ProcessObjCData(vm, baseName); + if (processCFStrings) + objc->ProcessCFStrings(vm, baseName); + } + catch (const std::exception& ex) + { + logger->LogWarn("Error processing ObjC data for image %s: %s", baseName.c_str(), ex.what()); + } + catch (...) + { + logger->LogWarn("Error processing ObjC data for image %s", baseName.c_str()); + } +} + +void SharedCache::ProcessObjCSectionsForImageWithInstallName(std::string installName) +{ + bool processCFStrings; + bool processObjCMetadata; + GetObjCSettings(m_dscView, &processCFStrings, &processObjCMetadata); + + if (!processObjCMetadata && !processCFStrings) + return; + + auto objc = std::make_shared<DSCObjC::DSCObjCProcessor>(m_dscView, this, false); + auto vm = GetVMMap(); + + ProcessObjCSectionsForImageWithName(base_name(installName), vm, objc, processCFStrings, processObjCMetadata, m_logger); +} + +void SharedCache::ProcessAllObjCSections() +{ + bool processCFStrings; + bool processObjCMetadata; + GetObjCSettings(m_dscView, &processCFStrings, &processObjCMetadata); + + if (!processObjCMetadata && !processCFStrings) + return; + + auto objc = std::make_shared<DSCObjC::DSCObjCProcessor>(m_dscView, this, false); + auto vm = GetVMMap(); + + std::set<uint64_t> processedImageHeaders; + for (auto region : GetMappedRegions()) + { + if (!region.loaded) + continue; + + // Don't repeat the same images multiple times + auto header = HeaderForAddress(region.start); + if (!header) + continue; + if (processedImageHeaders.find(header->textBase) != processedImageHeaders.end()) + continue; + processedImageHeaders.insert(header->textBase); + + ProcessObjCSectionsForImageWithName(header->identifierPrefix, vm, objc, processCFStrings, processObjCMetadata, m_logger); + } +} + bool SharedCache::LoadImageWithInstallName(std::string installName, bool skipObjC) { auto settings = m_dscView->GetLoadSettings(VIEW_NAME); @@ -1839,29 +1914,11 @@ bool SharedCache::LoadImageWithInstallName(std::string installName, bool skipObj if (!skipObjC) { - try - { - auto objc = std::make_unique<DSCObjC::DSCObjCProcessor>(m_dscView, this, false); + bool processCFStrings; + bool processObjCMetadata; + GetObjCSettings(m_dscView, &processCFStrings, &processObjCMetadata); - bool processCFStrings = true; - bool processObjCMetadata = true; - if (settings && settings->Contains("loader.dsc.processCFStrings")) - processCFStrings = settings->Get<bool>("loader.dsc.processCFStrings", m_dscView); - if (settings && settings->Contains("loader.dsc.processObjC")) - processObjCMetadata = settings->Get<bool>("loader.dsc.processObjC", m_dscView); - if (processObjCMetadata) - objc->ProcessObjCData(vm, h->identifierPrefix); - if (processCFStrings) - objc->ProcessCFStrings(vm, h->identifierPrefix); - } - catch (const std::exception& ex) - { - m_logger->LogWarn("Error processing ObjC data: %s", ex.what()); - } - catch (...) - { - m_logger->LogWarn("Error processing ObjC data"); - } + ProcessObjCSectionsForImageWithName(h->identifierPrefix, vm, std::make_shared<DSCObjC::DSCObjCProcessor>(m_dscView, this, false), processCFStrings, processObjCMetadata, m_logger); } m_dscView->AddAnalysisOption("linearsweep"); @@ -3067,6 +3124,22 @@ extern "C" return false; } + void BNDSCViewProcessObjCSectionsForImageWithInstallName(BNSharedCache* cache, char* name, bool deallocName) + { + std::string imageName = std::string(name); + if (deallocName) + BNFreeString(name); + + if (cache->object) + cache->object->ProcessObjCSectionsForImageWithInstallName(imageName); + } + + void BNDSCViewProcessAllObjCSections(BNSharedCache* cache) + { + if (cache->object) + cache->object->ProcessAllObjCSections(); + } + char** BNDSCViewGetInstallNames(BNSharedCache* cache, size_t* count) { if (cache->object) |
