summaryrefslogtreecommitdiff
path: root/view/sharedcache
diff options
context:
space:
mode:
Diffstat (limited to 'view/sharedcache')
-rw-r--r--view/sharedcache/core/MachOProcessor.cpp84
-rw-r--r--view/sharedcache/core/MachOProcessor.h2
-rw-r--r--view/sharedcache/core/SharedCache.cpp17
-rw-r--r--view/sharedcache/core/SharedCache.h8
4 files changed, 69 insertions, 42 deletions
diff --git a/view/sharedcache/core/MachOProcessor.cpp b/view/sharedcache/core/MachOProcessor.cpp
index df2fcfde..281f40c2 100644
--- a/view/sharedcache/core/MachOProcessor.cpp
+++ b/view/sharedcache/core/MachOProcessor.cpp
@@ -84,50 +84,58 @@ void SharedCacheMachOProcessor::ApplyHeader(const SharedCache& cache, SharedCach
}
// Apply symbols from the .symbols cache files.
- for (const auto &entry: cache.GetEntries())
- {
- // NOTE: We check addr size as we only support 64bit .symbols files currently.
- if (entry.GetType() != CacheEntryType::Symbols && m_vm->GetAddressSize() == 8)
- continue;
- const auto& entryHeader = entry.GetHeader();
+ ApplyUnmappedLocalSymbols(cache, header, std::move(typeLib));
+}
- // This is where we get the symbol and string table information from in the .symbols file.
- dyld_cache_local_symbols_info localSymbolsInfo = {};
- auto localSymbolsInfoAddr = entry.GetMappedAddress(entryHeader.localSymbolsOffset);
- if (!localSymbolsInfoAddr.has_value())
- continue;
- m_vm->Read(&localSymbolsInfo, *localSymbolsInfoAddr, sizeof(dyld_cache_local_symbols_info));
+void SharedCacheMachOProcessor::ApplyUnmappedLocalSymbols(const SharedCache& cache, const SharedCacheMachOHeader& header, Ref<TypeLibrary> typeLib)
+{
+ const auto& localSymbolsCacheEntry = cache.GetLocalSymbolsEntry();
+ auto localSymbolsVM = cache.GetLocalSymbolsVM();
+ if (!localSymbolsCacheEntry || !localSymbolsVM)
+ return;
+
+ // NOTE: We check addr size as we only support 64bit .symbols files currently.
+ // TODO: Support 32-bit nlist
+ if (localSymbolsVM->GetAddressSize() != 8)
+ return;
+
+ const auto& entryHeader = localSymbolsCacheEntry->GetHeader();
+
+ // This is where we get the symbol and string table information from in the .symbols file.
+ dyld_cache_local_symbols_info localSymbolsInfo = {};
+ auto localSymbolsInfoAddr = entryHeader.localSymbolsOffset;
+
+ localSymbolsVM->Read(&localSymbolsInfo, localSymbolsInfoAddr, sizeof(dyld_cache_local_symbols_info));
- // Read each symbols entry, looking for the current image entry.
- uint64_t localEntriesAddr = *localSymbolsInfoAddr + localSymbolsInfo.entriesOffset;
- uint64_t localSymbolsAddr = *localSymbolsInfoAddr + localSymbolsInfo.nlistOffset;
- uint64_t localStringsAddr = *localSymbolsInfoAddr + localSymbolsInfo.stringsOffset;
+ // Read each symbols entry, looking for the current image entry.
+ uint64_t localEntriesAddr = localSymbolsInfoAddr + localSymbolsInfo.entriesOffset;
+ uint64_t localSymbolsAddr = localSymbolsInfoAddr + localSymbolsInfo.nlistOffset;
+ uint64_t localStringsAddr = localSymbolsInfoAddr + localSymbolsInfo.stringsOffset;
+ for (uint32_t i = 0; i < localSymbolsInfo.entriesCount; i++)
+ {
dyld_cache_local_symbols_entry_64 localSymbolsEntry = {};
- for (uint32_t i = 0; i < localSymbolsInfo.entriesCount; i++)
+ localSymbolsVM->Read(&localSymbolsEntry, localEntriesAddr + i * sizeof(dyld_cache_local_symbols_entry_64),
+ sizeof(dyld_cache_local_symbols_entry_64));
+
+ // The dylibOffset is the offset from the cache base address to the image header.
+ const auto imageAddr = cache.GetBaseAddress() + localSymbolsEntry.dylibOffset;
+ if (imageAddr != header.textBase)
+ continue;
+
+ // We have found the entry to read!
+ uint64_t symbolTableStart = localSymbolsAddr + (localSymbolsEntry.nlistStartIndex * sizeof(nlist_64));
+ TableInfo symbolInfo = {symbolTableStart, localSymbolsEntry.nlistCount};
+ TableInfo stringInfo = {localStringsAddr, localSymbolsInfo.stringsSize};
+ m_view->BeginBulkModifySymbols();
+ const auto symbols = header.ReadSymbolTable(*localSymbolsVM, symbolInfo, stringInfo);
+ for (const auto &sym: symbols)
{
- m_vm->Read(&localSymbolsEntry, localEntriesAddr + i * sizeof(dyld_cache_local_symbols_entry_64),
- sizeof(dyld_cache_local_symbols_entry_64));
- // The dylibOffset is the offset from the cache base address to the image header.
- const auto imageAddr = cache.GetBaseAddress() + localSymbolsEntry.dylibOffset;
- if (imageAddr == header.textBase)
- {
- // We have found the entry to read!
- // TODO: Support 32bit nlist
- uint64_t symbolTableStart = localSymbolsAddr + (localSymbolsEntry.nlistStartIndex * sizeof(nlist_64));
- TableInfo symbolInfo = {symbolTableStart, localSymbolsEntry.nlistCount};
- TableInfo stringInfo = {localStringsAddr, localSymbolsInfo.stringsSize};
- m_view->BeginBulkModifySymbols();
- const auto symbols = header.ReadSymbolTable(*m_vm, symbolInfo, stringInfo);
- for (const auto &sym: symbols)
- {
- auto [symbol, symbolType] = sym.GetBNSymbolAndType(*m_view);
- ApplySymbol(m_view, typeLib, symbol, symbolType);
- }
- m_view->EndBulkModifySymbols();
- break;
- }
+ auto [symbol, symbolType] = sym.GetBNSymbolAndType(*m_view);
+ ApplySymbol(m_view, typeLib, std::move(symbol), std::move(symbolType));
}
+ m_view->EndBulkModifySymbols();
+ return;
}
}
diff --git a/view/sharedcache/core/MachOProcessor.h b/view/sharedcache/core/MachOProcessor.h
index 4b014f4e..86772c99 100644
--- a/view/sharedcache/core/MachOProcessor.h
+++ b/view/sharedcache/core/MachOProcessor.h
@@ -21,4 +21,6 @@ public:
uint64_t ApplyHeaderSections(SharedCacheMachOHeader& header);
void ApplyHeaderDataVariables(SharedCacheMachOHeader& header);
+
+ void ApplyUnmappedLocalSymbols(const SharedCache& cache, const SharedCacheMachOHeader& header, BinaryNinja::Ref<BinaryNinja::TypeLibrary> typeLib);
};
diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp
index 0a14cfaf..c084c692 100644
--- a/view/sharedcache/core/SharedCache.cpp
+++ b/view/sharedcache/core/SharedCache.cpp
@@ -91,10 +91,8 @@ CacheEntry CacheEntry::FromFile(const std::string& filePath, const std::string&
{
// We found a single symbols cache entry file. Mark it as such!
type = CacheEntryType::Symbols;
- // Adjust the mapping for the symbol file, they seem to be only for the header.
- // If we do not adjust the mapping than we will not be able to read the symbol table through the virtual memory.
- mappings[0].fileOffset = 0;
- mappings[0].size = file->Length();
+ // Symbol files are not mapped into the address space.
+ mappings.clear();
}
else if (mappings.size() == 1 && header.imagesCountOld == 0 && header.imagesCount == 0
&& header.imagesTextOffset == 0)
@@ -231,6 +229,17 @@ void SharedCache::AddEntry(CacheEntry entry)
// Get the file accessor to associate with the virtual memory region.
auto fileAccessor = FileAccessorCache::Global().Open(entry.GetFilePath());
+ if (entry.GetType() == CacheEntryType::Symbols)
+ {
+ m_localSymbolsEntry = std::move(entry);
+ // Map the entire file into its own virtual memory space.
+ // This is necessary due to code that processes symbols being written in terms of a `VirtualMemory`
+ // rather than something more generic.
+ m_localSymbolsVM = std::make_shared<VirtualMemory>(m_vm->GetAddressSize());
+ m_localSymbolsVM->MapRegion(fileAccessor, {0, fileAccessor.lock()->Length()}, 0);
+ return;
+ }
+
// Populate virtual memory using the entry mappings, by doing so we can now
// read the memory of the mapped regions of the cache entry file.
const auto& mappings = entry.GetMappings();
diff --git a/view/sharedcache/core/SharedCache.h b/view/sharedcache/core/SharedCache.h
index efef394c..58f1f38c 100644
--- a/view/sharedcache/core/SharedCache.h
+++ b/view/sharedcache/core/SharedCache.h
@@ -188,6 +188,11 @@ class SharedCache
// NOTE: Wrapped in unique_ptr to keep SharedCache movable.
std::unique_ptr<std::shared_mutex> m_namedSymMutex;
+ // Local symbols entry and its mapping, used to read symbol tables from the .symbols file.
+ // These are handled separately as they are not mapped into the main virtual memory of the cache.
+ std::optional<CacheEntry> m_localSymbolsEntry;
+ std::shared_ptr<VirtualMemory> m_localSymbolsVM;
+
bool ProcessEntryImage(const std::string& path, const dyld_cache_image_info& info);
// Add a region known not to overlap with another, otherwise use AddRegion.
@@ -211,6 +216,9 @@ public:
const std::unordered_map<uint64_t, CacheImage>& GetImages() const { return m_images; }
const std::unordered_map<uint64_t, CacheSymbol>& GetSymbols() const { return m_symbols; }
+ const std::optional<CacheEntry>& GetLocalSymbolsEntry() const { return m_localSymbolsEntry; }
+ std::shared_ptr<VirtualMemory> GetLocalSymbolsVM() const { return m_localSymbolsVM; }
+
void AddImage(CacheImage&& image);
// Add a region that may overlap with another.