]>
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" |
39a8cd10 | 35 | #include "ImageLoader.h" |
2fd3f4e8 | 36 | #include "dyld.h" |
0959b6d4 | 37 | |
412ebb8e A |
38 | #if __IPHONE_OS_VERSION_MIN_REQUIRED |
39 | #define INITIAL_UUID_IMAGE_COUNT 4 | |
40 | #else | |
41 | #define INITIAL_UUID_IMAGE_COUNT 32 | |
42 | #endif | |
0959b6d4 | 43 | |
2fd3f4e8 A |
44 | VECTOR_NEVER_DESTRUCTED(dyld_image_info); |
45 | VECTOR_NEVER_DESTRUCTED(dyld_uuid_info); | |
46 | ||
0959b6d4 | 47 | static std::vector<dyld_image_info> sImageInfos; |
412ebb8e | 48 | static std::vector<dyld_uuid_info> sImageUUIDs; |
0959b6d4 | 49 | |
2fd3f4e8 | 50 | |
0959b6d4 A |
51 | void addImagesToAllImages(uint32_t infoCount, const dyld_image_info info[]) |
52 | { | |
412ebb8e | 53 | // make initial size large enough that we probably won't need to re-alloc it |
bac542e6 | 54 | if ( sImageInfos.size() == 0 ) |
39a8cd10 | 55 | sImageInfos.reserve(INITIAL_IMAGE_COUNT); |
412ebb8e A |
56 | if ( sImageUUIDs.capacity() == 0 ) |
57 | sImageUUIDs.reserve(4); | |
0959b6d4 | 58 | // set infoArray to NULL to denote it is in-use |
2fd3f4e8 | 59 | dyld::gProcessInfo->infoArray = NULL; |
0959b6d4 A |
60 | |
61 | // append all new images | |
62 | for (uint32_t i=0; i < infoCount; ++i) | |
63 | sImageInfos.push_back(info[i]); | |
19894a12 | 64 | dyld::gProcessInfo->infoArrayCount = (uint32_t)sImageInfos.size(); |
0959b6d4 | 65 | |
412ebb8e | 66 | // set infoArray back to base address of vector (other process can now read) |
2fd3f4e8 | 67 | dyld::gProcessInfo->infoArray = &sImageInfos[0]; |
412ebb8e | 68 | } |
0959b6d4 | 69 | |
2fd3f4e8 A |
70 | #if TARGET_IPHONE_SIMULATOR |
71 | // called once in dyld_sim start up to copy image list from host dyld to sImageInfos | |
72 | void syncProcessInfo() | |
73 | { | |
74 | // may want to set version field of gProcessInfo if it might be different than host | |
75 | if ( sImageInfos.size() == 0 ) { | |
76 | sImageInfos.reserve(INITIAL_IMAGE_COUNT); | |
77 | if ( dyld::gProcessInfo->infoArray != NULL ) { | |
78 | for (uint32_t i=0; i < dyld::gProcessInfo->infoArrayCount; ++i) { | |
79 | sImageInfos.push_back(dyld::gProcessInfo->infoArray[i]); | |
80 | } | |
81 | dyld::gProcessInfo->infoArray = &sImageInfos[0]; | |
19894a12 | 82 | dyld::gProcessInfo->infoArrayCount = (uint32_t)sImageInfos.size(); |
2fd3f4e8 A |
83 | } |
84 | } | |
85 | dyld::gProcessInfo->notification(dyld_image_info_change, 0, NULL); | |
86 | } | |
87 | #endif | |
412ebb8e A |
88 | |
89 | const char* notifyGDB(enum dyld_image_states state, uint32_t infoCount, const dyld_image_info info[]) | |
90 | { | |
0959b6d4 | 91 | // tell gdb that about the new images |
2fd3f4e8 | 92 | dyld::gProcessInfo->notification(dyld_image_adding, infoCount, info); |
412ebb8e A |
93 | // <rdar://problem/7739489> record initial count of images |
94 | // so CrashReporter can note which images were dynamically loaded | |
2fd3f4e8 A |
95 | if ( dyld::gProcessInfo->initialImageCount == 0 ) |
96 | dyld::gProcessInfo->initialImageCount = infoCount; | |
412ebb8e A |
97 | return NULL; |
98 | } | |
99 | ||
100 | ||
101 | ||
102 | void addNonSharedCacheImageUUID(const dyld_uuid_info& info) | |
103 | { | |
104 | // set uuidArray to NULL to denote it is in-use | |
2fd3f4e8 | 105 | dyld::gProcessInfo->uuidArray = NULL; |
412ebb8e A |
106 | |
107 | // append all new images | |
108 | sImageUUIDs.push_back(info); | |
2fd3f4e8 | 109 | dyld::gProcessInfo->uuidArrayCount = sImageUUIDs.size(); |
412ebb8e A |
110 | |
111 | // set uuidArray back to base address of vector (other process can now read) | |
2fd3f4e8 | 112 | dyld::gProcessInfo->uuidArray = &sImageUUIDs[0]; |
0959b6d4 A |
113 | } |
114 | ||
115 | void removeImageFromAllImages(const struct mach_header* loadAddress) | |
116 | { | |
117 | dyld_image_info goingAway; | |
118 | ||
119 | // set infoArray to NULL to denote it is in-use | |
2fd3f4e8 | 120 | dyld::gProcessInfo->infoArray = NULL; |
0959b6d4 A |
121 | |
122 | // remove image from infoArray | |
123 | for (std::vector<dyld_image_info>::iterator it=sImageInfos.begin(); it != sImageInfos.end(); it++) { | |
124 | if ( it->imageLoadAddress == loadAddress ) { | |
125 | goingAway = *it; | |
126 | sImageInfos.erase(it); | |
127 | break; | |
128 | } | |
129 | } | |
19894a12 | 130 | dyld::gProcessInfo->infoArrayCount = (uint32_t)sImageInfos.size(); |
0959b6d4 A |
131 | |
132 | // set infoArray back to base address of vector | |
2fd3f4e8 | 133 | dyld::gProcessInfo->infoArray = &sImageInfos[0]; |
0959b6d4 | 134 | |
412ebb8e A |
135 | |
136 | // set uuidArrayCount to NULL to denote it is in-use | |
2fd3f4e8 | 137 | dyld::gProcessInfo->uuidArray = NULL; |
412ebb8e A |
138 | |
139 | // remove image from infoArray | |
140 | for (std::vector<dyld_uuid_info>::iterator it=sImageUUIDs.begin(); it != sImageUUIDs.end(); it++) { | |
141 | if ( it->imageLoadAddress == loadAddress ) { | |
142 | sImageUUIDs.erase(it); | |
143 | break; | |
144 | } | |
145 | } | |
2fd3f4e8 | 146 | dyld::gProcessInfo->uuidArrayCount = sImageUUIDs.size(); |
412ebb8e A |
147 | |
148 | // set infoArray back to base address of vector | |
2fd3f4e8 | 149 | dyld::gProcessInfo->uuidArray = &sImageUUIDs[0]; |
412ebb8e | 150 | |
0959b6d4 | 151 | // tell gdb that about the new images |
2fd3f4e8 | 152 | dyld::gProcessInfo->notification(dyld_image_removing, 1, &goingAway); |
0959b6d4 A |
153 | } |
154 | ||
39a8cd10 A |
155 | void setAlImageInfosHalt(const char* message, uintptr_t flags) |
156 | { | |
2fd3f4e8 A |
157 | dyld::gProcessInfo->errorMessage = message; |
158 | dyld::gProcessInfo->terminationFlags = flags; | |
39a8cd10 | 159 | } |
0959b6d4 A |
160 | |
161 | ||
2fd3f4e8 A |
162 | #if TARGET_IPHONE_SIMULATOR |
163 | namespace dyld { | |
164 | struct dyld_all_image_infos* gProcessInfo = NULL; | |
165 | } | |
166 | #else | |
39a8cd10 | 167 | |
2fd3f4e8 A |
168 | #if __arm__ |
169 | // work around for: <rdar://problem/6530727> gdb-1109: notifier in dyld does not work if it is in thumb | |
170 | extern "C" void gdb_image_notifier(enum dyld_image_mode mode, uint32_t infoCount, const dyld_image_info info[]); | |
171 | #else | |
172 | static void gdb_image_notifier(enum dyld_image_mode mode, uint32_t infoCount, const dyld_image_info info[]) | |
173 | { | |
174 | // do nothing | |
175 | // gdb sets a break point here to catch notifications | |
176 | //dyld::log("dyld: gdb_image_notifier(%s, %d, ...)\n", mode ? "dyld_image_removing" : "dyld_image_adding", infoCount); | |
177 | //for (uint32_t i=0; i < infoCount; ++i) | |
178 | // dyld::log("dyld: %d loading at %p %s\n", i, info[i].imageLoadAddress, info[i].imageFilePath); | |
179 | //for (uint32_t i=0; i < dyld::gProcessInfo->infoArrayCount; ++i) | |
180 | // dyld::log("dyld: %d loading at %p %s\n", i, dyld::gProcessInfo->infoArray[i].imageLoadAddress, dyld::gProcessInfo->infoArray[i].imageFilePath); | |
181 | } | |
182 | #endif | |
183 | ||
184 | extern void* __dso_handle; | |
185 | #define STR(s) # s | |
186 | #define XSTR(s) STR(s) | |
0959b6d4 | 187 | |
2fd3f4e8 A |
188 | struct dyld_all_image_infos dyld_all_image_infos __attribute__ ((section ("__DATA,__all_image_info"))) |
189 | = { | |
190 | 14, 0, NULL, &gdb_image_notifier, false, false, (const mach_header*)&__dso_handle, NULL, | |
191 | XSTR(DYLD_VERSION), NULL, 0, NULL, 0, 0, NULL, &dyld_all_image_infos, | |
19894a12 A |
192 | 0, dyld_error_kind_none, NULL, NULL, NULL, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}, |
193 | {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,} | |
2fd3f4e8 | 194 | }; |
0959b6d4 | 195 | |
2fd3f4e8 | 196 | struct dyld_shared_cache_ranges dyld_shared_cache_ranges; |
39a8cd10 | 197 | |
2fd3f4e8 A |
198 | namespace dyld { |
199 | struct dyld_all_image_infos* gProcessInfo = &dyld_all_image_infos; | |
200 | } | |
201 | #endif | |
0959b6d4 | 202 |