Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions view/sharedcache/core/ObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1124,13 +1124,13 @@ void DSCObjCProcessor::ApplyMethodTypes(Class& cls)
void DSCObjCProcessor::PostProcessObjCSections(VMReader* reader, std::string baseName)
{
auto ptrSize = m_data->GetAddressSize();
if (auto imageInfo = m_data->GetSectionByName(baseName + "::__objc_imageinfo"))
if (auto imageInfo = m_data->GetSectionByName(baseName + ".__objc_imageinfo"))
{
auto start = imageInfo->GetStart();
auto type = Type::NamedType(m_data, m_typeNames.imageInfo);
m_data->DefineDataVariable(start, type);
}
if (auto selrefs = m_data->GetSectionByName(baseName + "::__objc_selrefs"))
if (auto selrefs = m_data->GetSectionByName(baseName + ".__objc_selrefs"))
{
auto start = selrefs->GetStart();
auto end = selrefs->GetEnd();
Expand All @@ -1153,7 +1153,7 @@ void DSCObjCProcessor::PostProcessObjCSections(VMReader* reader, std::string bas
DefineObjCSymbol(DataSymbol, type, "selRef_" + sel, i, true);
}
}
if (auto superRefs = m_data->GetSectionByName(baseName + "::__objc_classrefs"))
if (auto superRefs = m_data->GetSectionByName(baseName + ".__objc_classrefs"))
{
auto start = superRefs->GetStart();
auto end = superRefs->GetEnd();
Expand All @@ -1171,7 +1171,7 @@ void DSCObjCProcessor::PostProcessObjCSections(VMReader* reader, std::string bas
}
}
}
if (auto superRefs = m_data->GetSectionByName(baseName + "::__objc_superrefs"))
if (auto superRefs = m_data->GetSectionByName(baseName + ".__objc_superrefs"))
{
auto start = superRefs->GetStart();
auto end = superRefs->GetEnd();
Expand All @@ -1189,7 +1189,7 @@ void DSCObjCProcessor::PostProcessObjCSections(VMReader* reader, std::string bas
}
}
}
if (auto protoRefs = m_data->GetSectionByName(baseName + "::__objc_protorefs"))
if (auto protoRefs = m_data->GetSectionByName(baseName + ".__objc_protorefs"))
{
auto start = protoRefs->GetStart();
auto end = protoRefs->GetEnd();
Expand All @@ -1207,7 +1207,7 @@ void DSCObjCProcessor::PostProcessObjCSections(VMReader* reader, std::string bas
}
}
}
if (auto ivars = m_data->GetSectionByName(baseName + "::__objc_ivar"))
if (auto ivars = m_data->GetSectionByName(baseName + ".__objc_ivar"))
{
auto start = ivars->GetStart();
auto end = ivars->GetEnd();
Expand Down Expand Up @@ -1408,23 +1408,23 @@ void DSCObjCProcessor::ProcessObjCData(std::shared_ptr<VM> vm, std::string baseN
m_typeNames.protocol = finalizeStructureBuilder(m_data, protocolBuilder, "objc_protocol_t").first;

m_data->BeginBulkModifySymbols();
if (auto classList = m_data->GetSectionByName(baseName + "::__objc_classlist"))
if (auto classList = m_data->GetSectionByName(baseName + ".__objc_classlist"))
LoadClasses(&reader, classList);
if (auto nonLazyClassList = m_data->GetSectionByName(baseName + "::__objc_nlclslist"))
if (auto nonLazyClassList = m_data->GetSectionByName(baseName + ".__objc_nlclslist"))
LoadClasses(&reader, nonLazyClassList); // See: https://stackoverflow.com/a/15318325

GenerateClassTypes();
for (auto& [_, cls] : m_classes)
ApplyMethodTypes(cls);

if (auto catList = m_data->GetSectionByName(baseName + "::__objc_catlist")) // Do this after loading class type data.
if (auto catList = m_data->GetSectionByName(baseName + ".__objc_catlist")) // Do this after loading class type data.
LoadCategories(&reader, catList);
if (auto nonLazyCatList = m_data->GetSectionByName(baseName + "::__objc_nlcatlist")) // Do this after loading class type data.
if (auto nonLazyCatList = m_data->GetSectionByName(baseName + ".__objc_nlcatlist")) // Do this after loading class type data.
LoadCategories(&reader, nonLazyCatList);
for (auto& [_, cat] : m_categories)
ApplyMethodTypes(cat);

if (auto protoList = m_data->GetSectionByName(baseName + "::__objc_protolist"))
if (auto protoList = m_data->GetSectionByName(baseName + ".__objc_protolist"))
LoadProtocols(&reader, protoList);

PostProcessObjCSections(&reader, baseName);
Expand Down Expand Up @@ -1477,7 +1477,7 @@ void DSCObjCProcessor::ProcessCFStrings(std::shared_ptr<VM> vm, std::string base
m_typeNames.cfStringUTF16 = type.first;

auto reader = VMReader(vm);
if (auto cfstrings = m_data->GetSectionByName(baseName + "::__cfstring"))
if (auto cfstrings = m_data->GetSectionByName(baseName + ".__cfstring"))
{
auto start = cfstrings->GetStart();
auto end = cfstrings->GetEnd();
Expand Down
68 changes: 44 additions & 24 deletions view/sharedcache/core/SharedCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,11 @@ bool SharedCache::LoadImageContainingAddress(uint64_t address, bool skipObjC)
return false;
}

static std::string GetNameForMemoryDataRegion(const SharedCacheMachOHeader& header, const std::string& regionName)
{
return fmt::format("{}{}", header.installName.substr(0, header.installName.size() - header.identifierPrefix.size()), regionName);
}

bool SharedCache::LoadSectionAtAddress(uint64_t address)
{
std::lock(m_mutex, m_viewSpecificState->viewOperationsThatInfluenceMetadataMutex);
Expand Down Expand Up @@ -1656,7 +1661,7 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address)

auto targetFile = vm->MappingAtAddress(targetSegment->start).first.fileAccessor->lock();
auto buff = reader.ReadBuffer(targetSegment->start, targetSegment->size);
m_dscView->GetMemoryMap()->AddDataMemoryRegion(targetSegment->prettyName, targetSegment->start, buff, targetSegment->flags);
m_dscView->GetMemoryMap()->AddDataMemoryRegion(GetNameForMemoryDataRegion(targetHeader, targetSegment->prettyName), targetSegment->start, buff, targetSegment->flags);

SetMemoryRegionIsLoaded(lock, *targetSegment);

Expand Down Expand Up @@ -1684,22 +1689,34 @@ static void GetObjCSettings(Ref<BinaryView> view, bool* processObjCMetadata, boo
*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)
static void ProcessObjCSectionsForMemoryRegion(const MemoryRegion& region, 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);
objc->ProcessObjCData(vm, region.prettyName);
if (processCFStrings)
objc->ProcessCFStrings(vm, baseName);
objc->ProcessCFStrings(vm, region.prettyName);
}
catch (const std::exception& ex)
{
logger->LogWarn("Error processing ObjC data for image %s: %s", baseName.c_str(), ex.what());
logger->LogWarn("Error processing ObjC data for memory region %s: %s", region.prettyName.c_str(), ex.what());
}
catch (...)
{
logger->LogWarn("Error processing ObjC data for image %s", baseName.c_str());
logger->LogWarn("Error processing ObjC data for memory region %s", region.prettyName.c_str());
}
}

void SharedCache::ProcessObjCSectionsForImage(std::lock_guard<std::mutex>& lock, const CacheImage& image, std::shared_ptr<VM> vm, bool processCFStrings, bool processObjCMetadata)
{
const auto objc = std::make_shared<DSCObjC::DSCObjCProcessor>(m_dscView, this, false);
for (auto regionStart : image.regionStarts)
{
const auto& region = m_cacheInfo->memoryRegions.find(regionStart)->second;
if (!MemoryRegionIsLoaded(lock, region))
continue;
ProcessObjCSectionsForMemoryRegion(region, vm, objc, processCFStrings, processObjCMetadata, m_logger);
}
}

Expand All @@ -1712,10 +1729,17 @@ void SharedCache::ProcessObjCSectionsForImageWithInstallName(std::string install
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);
for (const auto& image : this->m_cacheInfo->images)
{
if (image.installName != installName)
continue;

std::lock_guard lock(m_mutex);
ProcessObjCSectionsForImage(lock, image, vm, processCFStrings, processObjCMetadata);
break;
}
}

void SharedCache::ProcessAllObjCSections()
Expand All @@ -1736,18 +1760,9 @@ void SharedCache::ProcessAllObjCSections(std::lock_guard<std::mutex>& lock)
auto objc = std::make_shared<DSCObjC::DSCObjCProcessor>(m_dscView, this, false);
auto vm = GetVMMap();

std::set<uint64_t> processedImageHeaders;
for (auto region : GetMappedRegions())
{
// 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);
ProcessObjCSectionsForMemoryRegion(*region, vm, objc, processCFStrings, processObjCMetadata, m_logger);
}
}

Expand Down Expand Up @@ -1818,7 +1833,7 @@ bool SharedCache::LoadImageWithInstallName(std::lock_guard<std::mutex>& lock, st

auto targetFile = vm->MappingAtAddress(region.start).first.fileAccessor->lock();
auto buff = reader.ReadBuffer(region.start, region.size);
m_dscView->GetMemoryMap()->AddDataMemoryRegion(region.prettyName, region.start, buff, region.flags);
m_dscView->GetMemoryMap()->AddDataMemoryRegion(GetNameForMemoryDataRegion(header, region.prettyName), region.start, buff, region.flags);

SetMemoryRegionIsLoaded(lock, region);
regionsToLoad.push_back(&region);
Expand Down Expand Up @@ -1848,7 +1863,7 @@ bool SharedCache::LoadImageWithInstallName(std::lock_guard<std::mutex>& lock, st
bool processObjCMetadata;
GetObjCSettings(m_dscView, &processCFStrings, &processObjCMetadata);

ProcessObjCSectionsForImageWithName(h->identifierPrefix, vm, std::make_shared<DSCObjC::DSCObjCProcessor>(m_dscView, this, false), processCFStrings, processObjCMetadata, m_logger);
ProcessObjCSectionsForImage(lock, *targetImage, vm, processCFStrings, processObjCMetadata);
}

m_dscView->AddAnalysisOption("linearsweep");
Expand Down Expand Up @@ -2250,13 +2265,18 @@ std::optional<SharedCacheMachOHeader> SharedCache::LoadHeaderForAddress(std::sha

for (auto& section : header.sections)
{
char sectionName[17];
char sectionName[sizeof(section.sectname)+1];
memcpy(sectionName, section.sectname, sizeof(section.sectname));
sectionName[16] = 0;
sectionName[sizeof(sectionName)-1] = 0;

char segmentName[sizeof(section.segname)+1];
memcpy(segmentName, section.segname, sizeof(section.segname));
segmentName[sizeof(segmentName)-1] = 0;

if (header.identifierPrefix.empty())
header.sectionNames.push_back(sectionName);
header.sectionNames.push_back(fmt::format("{}.{}", segmentName, sectionName));
else
header.sectionNames.push_back(header.identifierPrefix + "::" + sectionName);
header.sectionNames.push_back(fmt::format("{}::{}.{}", header.identifierPrefix, segmentName, sectionName));
}
}
catch (ReadException&)
Expand Down
1 change: 1 addition & 0 deletions view/sharedcache/core/SharedCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,7 @@ namespace SharedCacheCore {
uint64_t stringsOffset, size_t stringsSize, uint64_t nlistEntriesOffset, uint32_t nlistCount, uint32_t nlistStartIndex = 0);
void ApplySymbol(Ref<BinaryView> view, Ref<TypeLibrary> typeLib, Ref<Symbol> symbol);

void ProcessObjCSectionsForImage(std::lock_guard<std::mutex>& lock, const CacheImage& image, std::shared_ptr<VM> vm, bool processCFStrings, bool processObjCMetadata);
void ProcessAllObjCSections(std::lock_guard<std::mutex>&);
bool LoadImageWithInstallName(std::lock_guard<std::mutex>&, std::string installName, bool skipObjC);

Expand Down
13 changes: 7 additions & 6 deletions view/sharedcache/workflow/SharedCacheWorkflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ void SharedCacheWorkflow::FixupStubs(Ref<AnalysisContext> ctx)
return;
auto section = bv->GetSectionsAt(funcStart)[0];

auto imageName = section->GetName();
const auto sectionName = section->GetName();
auto imageName = sectionName;
// remove everything after ::
auto pos = imageName.find("::");
if (pos != std::string::npos)
Expand All @@ -152,7 +153,7 @@ void SharedCacheWorkflow::FixupStubs(Ref<AnalysisContext> ctx)
}

// Processor that automatically loads the libObjC image when it encounters a stub (so we can do inlining).
if (workflowState->autoLoadObjCStubRequirements && section->GetName().find("__objc_stubs") != std::string::npos)
if (workflowState->autoLoadObjCStubRequirements && sectionName.find("__objc_stubs") != std::string::npos)
{
auto firstInstruction = mlil->GetInstruction(0);
if (firstInstruction.operation == MLIL_TAILCALL)
Expand Down Expand Up @@ -271,10 +272,10 @@ void SharedCacheWorkflow::FixupStubs(Ref<AnalysisContext> ctx)
return;
}

if (section->GetName().find("::_stubs") != std::string::npos // Branch Islands (iOS 16)
|| section->GetName().find("dyld_shared_cache_branch_islands") != std::string::npos // Branch Islands (iOS 11-?)
|| section->GetName().find("::__stubs") != std::string::npos // Stubs (non arm64e)
|| section->GetName().find("::__auth_stubs") != std::string::npos // Stubs (arm64e)
if (sectionName.find("::_stubs") != std::string::npos // Branch Islands (iOS 16)
|| sectionName.find("dyld_shared_cache_branch_islands") != std::string::npos // Branch Islands (iOS 11-?)
|| sectionName.find(".__stubs") != std::string::npos // Stubs (non arm64e)
|| sectionName.find(".__auth_stubs") != std::string::npos // Stubs (arm64e)
)
{
auto firstInstruction = mlil->GetInstruction(0);
Expand Down