]> git.saurik.com Git - apple/dyld.git/blob - launch-cache/dsc_iterator.cpp
5110cbc751ba5aa1f36e8f2e050954396a104136
[apple/dyld.git] / launch-cache / dsc_iterator.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2009 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 #include <stdlib.h>
26
27 #include "dsc_iterator.h"
28 #include "dyld_cache_format.h"
29 #define NO_ULEB
30 #include "Architectures.hpp"
31 #include "MachOFileAbstraction.hpp"
32 #include "CacheFileAbstraction.hpp"
33
34
35 namespace dyld {
36
37 // convert an address in the shared region where the cache would normally be mapped, into an address where the cache is currently mapped
38 template <typename E>
39 const uint8_t* mappedAddress(const uint8_t* cache, uint64_t addr)
40 {
41 const dyldCacheHeader<E>* header = (dyldCacheHeader<E>*)cache;
42 const dyldCacheFileMapping<E>* mappings = (dyldCacheFileMapping<E>*)&cache[header->mappingOffset()];
43 for (uint32_t i=0; i < header->mappingCount(); ++i) {
44 if ( (mappings[i].address() <= addr) && (addr < (mappings[i].address() + mappings[i].size())) ) {
45 return &cache[mappings[i].file_offset() + addr - mappings[i].address()];
46 }
47 }
48 return NULL;
49 }
50
51 // call the callback block on each segment in this image
52 template <typename A>
53 void walkSegments(const uint8_t* cache, const char* dylibPath, const uint8_t* machHeader, dyld_shared_cache_iterator_t callback)
54 {
55 typedef typename A::P P;
56 typedef typename A::P::E E;
57 const macho_header<P>* mh = (const macho_header<P>*)machHeader;
58 const macho_load_command<P>* const cmds = (macho_load_command<P>*)(machHeader + sizeof(macho_header<P>));
59 const uint32_t cmd_count = mh->ncmds();
60 const macho_load_command<P>* cmd = cmds;
61 for (uint32_t i = 0; i < cmd_count; ++i) {
62 if ( cmd->cmd() == macho_segment_command<P>::CMD ) {
63 macho_segment_command<P>* segCmd = (macho_segment_command<P>*)cmd;
64 const uint8_t* segStartInCache = mappedAddress<E>(cache, segCmd->vmaddr());
65 uint64_t fileOffset = segStartInCache - cache;
66 callback(dylibPath, segCmd->segname(), fileOffset, segCmd->vmsize());
67 }
68 cmd = (const macho_load_command<P>*)(((uint8_t*)cmd)+cmd->cmdsize());
69 }
70 }
71
72
73 // call walkSegments on each image in the cache
74 template <typename A>
75 int walkImages(const uint8_t* cache, dyld_shared_cache_iterator_t callback)
76 {
77 typedef typename A::P::E E;
78 const dyldCacheHeader<E>* header = (dyldCacheHeader<E>*)cache;
79 const dyldCacheImageInfo<E>* dylibs = (dyldCacheImageInfo<E>*)&cache[header->imagesOffset()];
80 for (uint32_t i=0; i < header->imagesCount(); ++i) {
81 const char* dylibPath = (char*)cache + dylibs[i].pathFileOffset();
82 const uint8_t* machHeader = mappedAddress<E>(cache, dylibs[i].address());
83 walkSegments<A>(cache, dylibPath, machHeader, callback);
84 }
85 return 0;
86 }
87
88 }
89
90
91 // Given a pointer to an in-memory copy of a dyld shared cache file,
92 // this routine will call the callback block once for each segment
93 // in each dylib in the shared cache file.
94 // Returns -1 if there was an error, otherwise 0.
95 int dyld_shared_cache_iterate_segments(const void* shared_cache_file, dyld_shared_cache_iterator_t callback)
96 {
97 const uint8_t* cache = (uint8_t*)shared_cache_file;
98 if ( strcmp((char*)cache, "dyld_v1 i386") == 0 )
99 return dyld::walkImages<x86>(cache, callback);
100 else if ( strcmp((char*)cache, "dyld_v1 x86_64") == 0 )
101 return dyld::walkImages<x86_64>(cache, callback);
102 else if ( strcmp((char*)cache, "dyld_v1 ppc") == 0 )
103 return dyld::walkImages<ppc>(cache, callback);
104 else
105 return -1;
106 }
107