Loading...
--- dyld/dyld-132.13/launch-cache/dsc_iterator.cpp
+++ dyld/dyld-195.5/launch-cache/dsc_iterator.cpp
@@ -1,6 +1,6 @@
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
*
- * Copyright (c) 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
@@ -23,6 +23,9 @@
*/
#include <stdlib.h>
+#include <stdio.h>
+#include <Availability.h>
+
#include "dsc_iterator.h"
#include "dyld_cache_format.h"
@@ -32,7 +35,9 @@
#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>
@@ -50,7 +55,7 @@
// 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, dyld_shared_cache_iterator_t callback)
+ void walkSegments(const uint8_t* cache, const char* dylibPath, const uint8_t* machHeader, uint64_t slide, dyld_shared_cache_iterator_slide_t callback)
{
typedef typename A::P P;
typedef typename A::P::E E;
@@ -61,26 +66,47 @@
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;
- const uint8_t* segStartInCache = mappedAddress<E>(cache, segCmd->vmaddr());
- uint64_t fileOffset = segStartInCache - cache;
- callback(dylibPath, segCmd->segname(), fileOffset, segCmd->vmsize());
+ uint64_t fileOffset = segCmd->fileoff();
+ // work around until <rdar://problem/7022345> is fixed
+ if ( fileOffset == 0 ) {
+ fileOffset = (machHeader - cache);
+ }
+ 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;
+ }
+ }
+ callback(dylibPath, segCmd->segname(), fileOffset, sizem, segCmd->vmaddr()+slide, slide);
}
cmd = (const macho_load_command<P>*)(((uint8_t*)cmd)+cmd->cmdsize());
}
}
-
+
// call walkSegments on each image in the cache
template <typename A>
- int walkImages(const uint8_t* cache, dyld_shared_cache_iterator_t callback)
+ int walkImages(const uint8_t* cache, dyld_shared_cache_iterator_slide_t callback)
{
- typedef typename A::P::E E;
+ 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()];
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, callback);
+ walkSegments<A>(cache, dylibPath, machHeader, slide, callback);
}
return 0;
}
@@ -92,7 +118,7 @@
// 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(const void* shared_cache_file, dyld_shared_cache_iterator_t callback)
+int dyld_shared_cache_iterate_segments_with_slide(const void* shared_cache_file, dyld_shared_cache_iterator_slide_t callback)
{
const uint8_t* cache = (uint8_t*)shared_cache_file;
if ( strcmp((char*)cache, "dyld_v1 i386") == 0 )
@@ -101,7 +127,42 @@
return dyld::walkImages<x86_64>(cache, callback);
else if ( strcmp((char*)cache, "dyld_v1 ppc") == 0 )
return dyld::walkImages<ppc>(cache, callback);
+ else if ( strcmp((char*)cache, "dyld_v1 armv5") == 0 )
+ return dyld::walkImages<arm>(cache, callback);
+ else if ( strcmp((char*)cache, "dyld_v1 armv6") == 0 )
+ return dyld::walkImages<arm>(cache, callback);
+ else if ( strcmp((char*)cache, "dyld_v1 armv7") == 0 )
+ return dyld::walkImages<arm>(cache, callback);
else
return -1;
}
+// implement non-block version by calling block version
+int dyld_shared_cache_iterate_segments_with_slide_nb(const void* shared_cache_file, dyld_shared_cache_iterator_slide_nb_t func, void* userData)
+{
+ return dyld_shared_cache_iterate_segments_with_slide(shared_cache_file, ^(const char* dylibName, const char* segName,
+ uint64_t offset, uint64_t size, uint64_t mappedddress, uint64_t slide) {
+ (*func)(dylibName, segName, offset, size, mappedddress, slide, userData);
+ });
+}
+
+
+// implement non-slide version by wrapping slide version in block
+int dyld_shared_cache_iterate_segments(const void* shared_cache_file, dyld_shared_cache_iterator_t callback)
+{
+ dyld_shared_cache_iterator_slide_t wrapper_cb = ^(const char* dylibName, const char* segName, uint64_t offset,
+ uint64_t size, uint64_t mappedddress, uint64_t slide) {
+ callback(dylibName, segName, offset, size, mappedddress);
+ };
+ return dyld_shared_cache_iterate_segments_with_slide(shared_cache_file, wrapper_cb);
+}
+
+// implement non-slide,non-block version by wrapping slide version in block
+int dyld_shared_cache_iterate_segments_nb(const void* shared_cache_file, dyld_shared_cache_iterator_nb_t func, void* userData)
+{
+ return dyld_shared_cache_iterate_segments_with_slide(shared_cache_file, ^(const char* dylibName, const char* segName,
+ uint64_t offset, uint64_t size, uint64_t mappedddress, uint64_t slide) {
+ (*func)(dylibName, segName, offset, size, mappedddress, userData);
+ });
+}
+