Loading...
--- dyld/dyld-195.5/launch-cache/dsc_iterator.cpp
+++ dyld/dyld-360.14/launch-cache/dsc_iterator.cpp
@@ -1,6 +1,6 @@
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
*
- * Copyright (c) 2009-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2012 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
@@ -35,19 +35,23 @@
#include "CacheFileAbstraction.hpp"
-
namespace dyld {
// convert an address in the shared region where the cache would normally be mapped, into an address where the cache is currently mapped
template <typename E>
- const uint8_t* mappedAddress(const uint8_t* cache, uint64_t addr)
+ const uint8_t* mappedAddress(const uint8_t* cache, const uint8_t* cacheEnd, uint64_t addr)
{
const dyldCacheHeader<E>* header = (dyldCacheHeader<E>*)cache;
const dyldCacheFileMapping<E>* mappings = (dyldCacheFileMapping<E>*)&cache[header->mappingOffset()];
for (uint32_t i=0; i < header->mappingCount(); ++i) {
if ( (mappings[i].address() <= addr) && (addr < (mappings[i].address() + mappings[i].size())) ) {
- return &cache[mappings[i].file_offset() + addr - mappings[i].address()];
+ uint64_t cacheOffset = mappings[i].file_offset() + addr - mappings[i].address();
+ const uint8_t* result = &cache[cacheOffset];
+ if ( result < cacheEnd )
+ return result;
+ else
+ return NULL;
}
}
return NULL;
@@ -55,14 +59,37 @@
// call the callback block on each segment in this image
template <typename A>
- void walkSegments(const uint8_t* cache, const char* dylibPath, const uint8_t* machHeader, uint64_t slide, dyld_shared_cache_iterator_slide_t callback)
+ int walkSegments(const uint8_t* cache, const uint8_t* cacheEnd, const uint8_t* firstSeg, const char* dylibPath, uint64_t inode,uint64_t modTime, const uint8_t* machHeader,
+ void (^callback)(const dyld_shared_cache_dylib_info* dylibInfo, const dyld_shared_cache_segment_info* segInfo))
{
typedef typename A::P P;
typedef typename A::P::E E;
+ dyld_shared_cache_dylib_info dylibInfo;
+ dyld_shared_cache_segment_info segInfo;
+ dylibInfo.version = 2;
+ dylibInfo.isAlias = (dylibPath < (char*)firstSeg); // paths for aliases are store between cache header and first segment
+ dylibInfo.machHeader = machHeader;
+ dylibInfo.path = dylibPath;
+ dylibInfo.inode = inode;
+ dylibInfo.modTime = modTime;
const macho_header<P>* mh = (const macho_header<P>*)machHeader;
const macho_load_command<P>* const cmds = (macho_load_command<P>*)(machHeader + sizeof(macho_header<P>));
+ if ( (machHeader+ mh->sizeofcmds()) > cacheEnd )
+ return -1;
const uint32_t cmd_count = mh->ncmds();
const macho_load_command<P>* cmd = cmds;
+ // scan for LC_UUID
+ dylibInfo.uuid = NULL;
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ if ( cmd->cmd() == LC_UUID ) {
+ const uuid_command* uc = (const uuid_command*)cmd;
+ dylibInfo.uuid = &uc->uuid;
+ break;
+ }
+ cmd = (const macho_load_command<P>*)(((uint8_t*)cmd)+cmd->cmdsize());
+ }
+ // callback for each LC_SEGMENT
+ cmd = cmds;
for (uint32_t i = 0; i < cmd_count; ++i) {
if ( cmd->cmd() == macho_segment_command<P>::CMD ) {
macho_segment_command<P>* segCmd = (macho_segment_command<P>*)cmd;
@@ -74,39 +101,76 @@
uint64_t sizem = segCmd->vmsize();
if ( strcmp(segCmd->segname(), "__LINKEDIT") == 0 ) {
// clip LINKEDIT size if bigger than cache file
- const dyldCacheHeader<E>* header = (dyldCacheHeader<E>*)cache;
- const dyldCacheFileMapping<E>* mappings = (dyldCacheFileMapping<E>*)&cache[header->mappingOffset()];
- if ( mappings[2].file_offset() <= fileOffset ) {
- if ( sizem > mappings[2].size() )
- sizem = mappings[2].file_offset() + mappings[2].size() - fileOffset;
- }
+ if ( (fileOffset+sizem) > (uint64_t)(cacheEnd-cache) )
+ sizem = (cacheEnd-cache)-fileOffset;
}
- callback(dylibPath, segCmd->segname(), fileOffset, sizem, segCmd->vmaddr()+slide, slide);
+ segInfo.version = 1;
+ segInfo.name = segCmd->segname();
+ segInfo.fileOffset = fileOffset;
+ segInfo.fileSize = sizem;
+ if ( segCmd->filesize() > segCmd->vmsize() )
+ return -1;
+ segInfo.address = segCmd->vmaddr();
+ callback(&dylibInfo, &segInfo);
}
cmd = (const macho_load_command<P>*)(((uint8_t*)cmd)+cmd->cmdsize());
}
+ return 0;
}
// call walkSegments on each image in the cache
template <typename A>
- int walkImages(const uint8_t* cache, dyld_shared_cache_iterator_slide_t callback)
+ int walkImages(const uint8_t* cache, uint32_t size, void (^callback)(const dyld_shared_cache_dylib_info* dylibInfo, const dyld_shared_cache_segment_info* segInfo))
{
+ // Sanity check there is at least a header
+ if ( (size > 0) && (size < 0x7000) )
+ return -1;
typedef typename A::P::E E;
typedef typename A::P P;
- typedef typename A::P::uint_t pint_t;
- const dyldCacheHeader<E>* header = (dyldCacheHeader<E>*)cache;
- uint64_t slide = 0;
- if ( header->mappingOffset() >= 0x48 ) {
- const dyldCacheFileMapping<E>* mappings = (dyldCacheFileMapping<E>*)&cache[header->mappingOffset()];
- uint64_t storedPointerToHeader = P::getP(*((pint_t*)&cache[mappings[1].file_offset()]));
- slide = storedPointerToHeader - mappings[0].address();
- }
- const dyldCacheImageInfo<E>* dylibs = (dyldCacheImageInfo<E>*)&cache[header->imagesOffset()];
+ const dyldCacheHeader<E>* header = (dyldCacheHeader<E>*)cache;
+ const dyldCacheImageInfo<E>* dylibs = (dyldCacheImageInfo<E>*)&cache[header->imagesOffset()];
+ const dyldCacheFileMapping<E>* mappings = (dyldCacheFileMapping<E>*)&cache[header->mappingOffset()];
+ uint64_t greatestMappingOffset = 0;
+ for (uint32_t i=0; i < header->mappingCount(); ++i) {
+ if ( (size != 0) && (mappings[i].file_offset() > size) )
+ return -1;
+ uint64_t endOffset = mappings[i].file_offset()+mappings[i].size();
+ if ( (size != 0) && (endOffset > size) )
+ return -1;
+ if ( endOffset > greatestMappingOffset )
+ greatestMappingOffset = endOffset;
+ }
+ const uint8_t* cacheEnd = &cache[size];
+ if ( size == 0 ) {
+ // Zero size means old API is being used, assume all mapped
+ cacheEnd = &cache[greatestMappingOffset];
+ }
+ else {
+ // verifiy mappings are not bigger than size
+ if ( size < greatestMappingOffset )
+ return -1;
+ }
+ // verify all image infos are mapped
+ if ( (const uint8_t*)&dylibs[header->imagesCount()] > cacheEnd )
+ return -1;
+ const uint8_t* firstSeg = NULL;
for (uint32_t i=0; i < header->imagesCount(); ++i) {
const char* dylibPath = (char*)cache + dylibs[i].pathFileOffset();
- const uint8_t* machHeader = mappedAddress<E>(cache, dylibs[i].address());
- walkSegments<A>(cache, dylibPath, machHeader, slide, callback);
+ uint64_t inode = dylibs[i].inode();
+ uint64_t modTime = dylibs[i].modTime();
+ if ( (const uint8_t*)dylibPath > cacheEnd )
+ return -1;
+ const uint8_t* machHeader = mappedAddress<E>(cache, cacheEnd, dylibs[i].address());
+ if ( machHeader == NULL )
+ return -1;
+ if ( machHeader > cacheEnd )
+ return -1;
+ if ( firstSeg == NULL )
+ firstSeg = machHeader;
+ int result = walkSegments<A>(cache, cacheEnd, firstSeg, dylibPath, inode, modTime, machHeader, callback);
+ if ( result != 0 )
+ return result;
}
return 0;
}
@@ -118,23 +182,36 @@
// this routine will call the callback block once for each segment
// in each dylib in the shared cache file.
// Returns -1 if there was an error, otherwise 0.
-int dyld_shared_cache_iterate_segments_with_slide(const void* shared_cache_file, dyld_shared_cache_iterator_slide_t callback)
-{
+extern int dyld_shared_cache_iterate(const void* shared_cache_file, uint32_t shared_cache_size,
+ void (^callback)(const dyld_shared_cache_dylib_info* dylibInfo, const dyld_shared_cache_segment_info* segInfo)) {
const uint8_t* cache = (uint8_t*)shared_cache_file;
if ( strcmp((char*)cache, "dyld_v1 i386") == 0 )
- return dyld::walkImages<x86>(cache, callback);
+ return dyld::walkImages<x86>(cache, shared_cache_size, callback);
else if ( strcmp((char*)cache, "dyld_v1 x86_64") == 0 )
- return dyld::walkImages<x86_64>(cache, callback);
- else if ( strcmp((char*)cache, "dyld_v1 ppc") == 0 )
- return dyld::walkImages<ppc>(cache, callback);
+ return dyld::walkImages<x86_64>(cache, shared_cache_size, callback);
+ else if ( strcmp((char*)cache, "dyld_v1 x86_64h") == 0 )
+ return dyld::walkImages<x86_64>(cache, shared_cache_size, callback);
else if ( strcmp((char*)cache, "dyld_v1 armv5") == 0 )
- return dyld::walkImages<arm>(cache, callback);
+ return dyld::walkImages<arm>(cache, shared_cache_size, callback);
else if ( strcmp((char*)cache, "dyld_v1 armv6") == 0 )
- return dyld::walkImages<arm>(cache, callback);
+ return dyld::walkImages<arm>(cache, shared_cache_size, callback);
else if ( strcmp((char*)cache, "dyld_v1 armv7") == 0 )
- return dyld::walkImages<arm>(cache, callback);
+ return dyld::walkImages<arm>(cache, shared_cache_size, callback);
+ else if ( strncmp((char*)cache, "dyld_v1 armv7", 14) == 0 )
+ return dyld::walkImages<arm>(cache, shared_cache_size, callback);
+ else if ( strcmp((char*)cache, "dyld_v1 arm64") == 0 )
+ return dyld::walkImages<arm64>(cache, shared_cache_size, callback);
else
return -1;
+}
+
+
+// implement old version by calling new version
+int dyld_shared_cache_iterate_segments_with_slide(const void* shared_cache_file, dyld_shared_cache_iterator_slide_t callback)
+{
+ return dyld_shared_cache_iterate(shared_cache_file, 0, ^(const dyld_shared_cache_dylib_info* dylibInfo, const dyld_shared_cache_segment_info* segInfo) {
+ callback(dylibInfo->path, segInfo->name, segInfo->fileOffset, segInfo->fileSize, segInfo->address, 0);
+ });
}
// implement non-block version by calling block version