]>
Commit | Line | Data |
---|---|---|
0959b6d4 A |
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
2 | * | |
39a8cd10 | 3 | * Copyright (c) 2004-2009 Apple Inc. All rights reserved. |
0959b6d4 A |
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 <stddef.h> | |
26 | #include <stdint.h> | |
27 | #include <stdlib.h> | |
28 | #include <string.h> | |
29 | #include <mach-o/loader.h> | |
30 | ||
31 | #include <vector> | |
32 | ||
33 | #include "mach-o/dyld_gdb.h" | |
bac542e6 | 34 | #include "mach-o/dyld_images.h" |
9f83892a | 35 | #include "mach-o/dyld_process_info.h" |
39a8cd10 | 36 | #include "ImageLoader.h" |
2fd3f4e8 | 37 | #include "dyld.h" |
0959b6d4 | 38 | |
412ebb8e A |
39 | #if __IPHONE_OS_VERSION_MIN_REQUIRED |
40 | #define INITIAL_UUID_IMAGE_COUNT 4 | |
41 | #else | |
42 | #define INITIAL_UUID_IMAGE_COUNT 32 | |
43 | #endif | |
0959b6d4 | 44 | |
2fd3f4e8 A |
45 | VECTOR_NEVER_DESTRUCTED(dyld_image_info); |
46 | VECTOR_NEVER_DESTRUCTED(dyld_uuid_info); | |
47 | ||
0959b6d4 | 48 | static std::vector<dyld_image_info> sImageInfos; |
412ebb8e | 49 | static std::vector<dyld_uuid_info> sImageUUIDs; |
0959b6d4 | 50 | |
9f83892a A |
51 | size_t allImagesCount() |
52 | { | |
53 | return sImageInfos.size(); | |
54 | } | |
55 | ||
56 | const mach_header* allImagesIndexedMachHeader(uint32_t index) | |
57 | { | |
58 | if ( index < sImageInfos.size() ) | |
59 | return sImageInfos[index].imageLoadAddress; | |
60 | else | |
61 | return NULL; | |
62 | } | |
63 | ||
64 | const char* allImagesIndexedPath(uint32_t index) | |
65 | { | |
66 | if ( index < sImageInfos.size() ) | |
67 | return sImageInfos[index].imageFilePath; | |
68 | else | |
69 | return NULL; | |
70 | } | |
71 | ||
2fd3f4e8 | 72 | |
0959b6d4 A |
73 | void addImagesToAllImages(uint32_t infoCount, const dyld_image_info info[]) |
74 | { | |
412ebb8e | 75 | // make initial size large enough that we probably won't need to re-alloc it |
bac542e6 | 76 | if ( sImageInfos.size() == 0 ) |
39a8cd10 | 77 | sImageInfos.reserve(INITIAL_IMAGE_COUNT); |
412ebb8e A |
78 | if ( sImageUUIDs.capacity() == 0 ) |
79 | sImageUUIDs.reserve(4); | |
0959b6d4 | 80 | // set infoArray to NULL to denote it is in-use |
2fd3f4e8 | 81 | dyld::gProcessInfo->infoArray = NULL; |
0959b6d4 A |
82 | |
83 | // append all new images | |
84 | for (uint32_t i=0; i < infoCount; ++i) | |
85 | sImageInfos.push_back(info[i]); | |
19894a12 | 86 | dyld::gProcessInfo->infoArrayCount = (uint32_t)sImageInfos.size(); |
9f83892a A |
87 | dyld::gProcessInfo->infoArrayChangeTimestamp = mach_absolute_time(); |
88 | ||
412ebb8e | 89 | // set infoArray back to base address of vector (other process can now read) |
2fd3f4e8 | 90 | dyld::gProcessInfo->infoArray = &sImageInfos[0]; |
412ebb8e | 91 | } |
0959b6d4 | 92 | |
2fd3f4e8 A |
93 | #if TARGET_IPHONE_SIMULATOR |
94 | // called once in dyld_sim start up to copy image list from host dyld to sImageInfos | |
95 | void syncProcessInfo() | |
96 | { | |
97 | // may want to set version field of gProcessInfo if it might be different than host | |
98 | if ( sImageInfos.size() == 0 ) { | |
99 | sImageInfos.reserve(INITIAL_IMAGE_COUNT); | |
100 | if ( dyld::gProcessInfo->infoArray != NULL ) { | |
101 | for (uint32_t i=0; i < dyld::gProcessInfo->infoArrayCount; ++i) { | |
102 | sImageInfos.push_back(dyld::gProcessInfo->infoArray[i]); | |
103 | } | |
104 | dyld::gProcessInfo->infoArray = &sImageInfos[0]; | |
19894a12 | 105 | dyld::gProcessInfo->infoArrayCount = (uint32_t)sImageInfos.size(); |
2fd3f4e8 A |
106 | } |
107 | } | |
108 | dyld::gProcessInfo->notification(dyld_image_info_change, 0, NULL); | |
109 | } | |
110 | #endif | |
412ebb8e A |
111 | |
112 | const char* notifyGDB(enum dyld_image_states state, uint32_t infoCount, const dyld_image_info info[]) | |
113 | { | |
0959b6d4 | 114 | // tell gdb that about the new images |
9f83892a | 115 | uint64_t t0 = mach_absolute_time(); |
2fd3f4e8 | 116 | dyld::gProcessInfo->notification(dyld_image_adding, infoCount, info); |
9f83892a A |
117 | uint64_t t1 = mach_absolute_time(); |
118 | ImageLoader::fgTotalDebuggerPausedTime += (t1-t0); | |
119 | ||
412ebb8e A |
120 | // <rdar://problem/7739489> record initial count of images |
121 | // so CrashReporter can note which images were dynamically loaded | |
2fd3f4e8 | 122 | if ( dyld::gProcessInfo->initialImageCount == 0 ) |
9f83892a | 123 | dyld::gProcessInfo->initialImageCount = dyld::gProcessInfo->infoArrayCount; |
412ebb8e A |
124 | return NULL; |
125 | } | |
126 | ||
127 | ||
128 | ||
129 | void addNonSharedCacheImageUUID(const dyld_uuid_info& info) | |
130 | { | |
131 | // set uuidArray to NULL to denote it is in-use | |
2fd3f4e8 | 132 | dyld::gProcessInfo->uuidArray = NULL; |
412ebb8e A |
133 | |
134 | // append all new images | |
135 | sImageUUIDs.push_back(info); | |
2fd3f4e8 | 136 | dyld::gProcessInfo->uuidArrayCount = sImageUUIDs.size(); |
412ebb8e A |
137 | |
138 | // set uuidArray back to base address of vector (other process can now read) | |
2fd3f4e8 | 139 | dyld::gProcessInfo->uuidArray = &sImageUUIDs[0]; |
0959b6d4 A |
140 | } |
141 | ||
142 | void removeImageFromAllImages(const struct mach_header* loadAddress) | |
143 | { | |
144 | dyld_image_info goingAway; | |
145 | ||
146 | // set infoArray to NULL to denote it is in-use | |
2fd3f4e8 | 147 | dyld::gProcessInfo->infoArray = NULL; |
0959b6d4 A |
148 | |
149 | // remove image from infoArray | |
150 | for (std::vector<dyld_image_info>::iterator it=sImageInfos.begin(); it != sImageInfos.end(); it++) { | |
151 | if ( it->imageLoadAddress == loadAddress ) { | |
152 | goingAway = *it; | |
153 | sImageInfos.erase(it); | |
154 | break; | |
155 | } | |
156 | } | |
19894a12 | 157 | dyld::gProcessInfo->infoArrayCount = (uint32_t)sImageInfos.size(); |
0959b6d4 A |
158 | |
159 | // set infoArray back to base address of vector | |
2fd3f4e8 | 160 | dyld::gProcessInfo->infoArray = &sImageInfos[0]; |
0959b6d4 | 161 | |
412ebb8e A |
162 | |
163 | // set uuidArrayCount to NULL to denote it is in-use | |
2fd3f4e8 | 164 | dyld::gProcessInfo->uuidArray = NULL; |
412ebb8e A |
165 | |
166 | // remove image from infoArray | |
167 | for (std::vector<dyld_uuid_info>::iterator it=sImageUUIDs.begin(); it != sImageUUIDs.end(); it++) { | |
168 | if ( it->imageLoadAddress == loadAddress ) { | |
169 | sImageUUIDs.erase(it); | |
170 | break; | |
171 | } | |
172 | } | |
2fd3f4e8 | 173 | dyld::gProcessInfo->uuidArrayCount = sImageUUIDs.size(); |
9f83892a A |
174 | dyld::gProcessInfo->infoArrayChangeTimestamp = mach_absolute_time(); |
175 | ||
412ebb8e | 176 | // set infoArray back to base address of vector |
2fd3f4e8 | 177 | dyld::gProcessInfo->uuidArray = &sImageUUIDs[0]; |
412ebb8e | 178 | |
0959b6d4 | 179 | // tell gdb that about the new images |
2fd3f4e8 | 180 | dyld::gProcessInfo->notification(dyld_image_removing, 1, &goingAway); |
0959b6d4 A |
181 | } |
182 | ||
0959b6d4 | 183 | |
2fd3f4e8 A |
184 | #if TARGET_IPHONE_SIMULATOR |
185 | namespace dyld { | |
186 | struct dyld_all_image_infos* gProcessInfo = NULL; | |
187 | } | |
188 | #else | |
39a8cd10 | 189 | |
9f83892a A |
190 | static void gdb_image_notifier(enum dyld_image_mode mode, uint32_t infoCount, const dyld_image_info info[]) |
191 | { | |
192 | uint64_t machHeaders[infoCount]; | |
193 | for (uint32_t i=0; i < infoCount; ++i) { | |
194 | machHeaders[i] = (uintptr_t)(info[i].imageLoadAddress); | |
195 | } | |
196 | switch ( mode ) { | |
197 | case dyld_image_adding: | |
198 | _dyld_debugger_notification(dyld_notify_adding, infoCount, machHeaders); | |
199 | break; | |
200 | case dyld_image_removing: | |
201 | _dyld_debugger_notification(dyld_notify_removing, infoCount, machHeaders); | |
202 | break; | |
203 | default: | |
204 | break; | |
2fd3f4e8 | 205 | } |
9f83892a A |
206 | // do nothing |
207 | // gdb sets a break point here to catch notifications | |
208 | //dyld::log("dyld: gdb_image_notifier(%s, %d, ...)\n", mode ? "dyld_image_removing" : "dyld_image_adding", infoCount); | |
209 | //for (uint32_t i=0; i < infoCount; ++i) | |
210 | // dyld::log("dyld: %d loading at %p %s\n", i, info[i].imageLoadAddress, info[i].imageFilePath); | |
211 | //for (uint32_t i=0; i < dyld::gProcessInfo->infoArrayCount; ++i) | |
212 | // dyld::log("dyld: %d loading at %p %s\n", i, dyld::gProcessInfo->infoArray[i].imageLoadAddress, dyld::gProcessInfo->infoArray[i].imageFilePath); | |
213 | } | |
214 | ||
215 | // only used with accelerator tables and ASan which images need to be re-loaded | |
216 | void resetAllImages() | |
217 | { | |
218 | sImageInfos.clear(); | |
219 | sImageUUIDs.clear(); | |
220 | _dyld_debugger_notification(dyld_notify_remove_all, 0, NULL); | |
221 | } | |
2fd3f4e8 A |
222 | |
223 | extern void* __dso_handle; | |
224 | #define STR(s) # s | |
225 | #define XSTR(s) STR(s) | |
0959b6d4 | 226 | |
2fd3f4e8 A |
227 | struct dyld_all_image_infos dyld_all_image_infos __attribute__ ((section ("__DATA,__all_image_info"))) |
228 | = { | |
9f83892a | 229 | 15, 0, NULL, &gdb_image_notifier, false, false, (const mach_header*)&__dso_handle, NULL, |
2fd3f4e8 | 230 | XSTR(DYLD_VERSION), NULL, 0, NULL, 0, 0, NULL, &dyld_all_image_infos, |
9f83892a A |
231 | 0, 0, NULL, NULL, NULL, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}, |
232 | 0, 0, "/usr/lib/dyld", {0}, {0} | |
2fd3f4e8 | 233 | }; |
0959b6d4 | 234 | |
2fd3f4e8 | 235 | struct dyld_shared_cache_ranges dyld_shared_cache_ranges; |
39a8cd10 | 236 | |
2fd3f4e8 A |
237 | namespace dyld { |
238 | struct dyld_all_image_infos* gProcessInfo = &dyld_all_image_infos; | |
239 | } | |
240 | #endif | |
0959b6d4 | 241 |