1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
   3  * Copyright (c) 2004-2009 Apple Inc. All rights reserved. 
   5  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  22  * @APPLE_LICENSE_HEADER_END@ 
  29 #include <mach-o/loader.h> 
  33 #include "mach-o/dyld_gdb.h" 
  34 #include "mach-o/dyld_images.h" 
  35 #include "mach-o/dyld_process_info.h" 
  36 #include "ImageLoader.h" 
  39 #if __IPHONE_OS_VERSION_MIN_REQUIRED 
  40         #define INITIAL_UUID_IMAGE_COUNT 4 
  42         #define INITIAL_UUID_IMAGE_COUNT 32 
  45 VECTOR_NEVER_DESTRUCTED(dyld_image_info
); 
  46 VECTOR_NEVER_DESTRUCTED(dyld_uuid_info
); 
  48 static std::vector
<dyld_image_info
> sImageInfos
; 
  49 static std::vector
<dyld_uuid_info
>  sImageUUIDs
; 
  51 size_t allImagesCount() 
  53         return sImageInfos
.size(); 
  56 const mach_header
* allImagesIndexedMachHeader(uint32_t index
) 
  58         if ( index 
< sImageInfos
.size() ) 
  59                 return sImageInfos
[index
].imageLoadAddress
; 
  64 const char* allImagesIndexedPath(uint32_t index
) 
  66         if ( index 
< sImageInfos
.size() ) 
  67                 return sImageInfos
[index
].imageFilePath
; 
  73 void addImagesToAllImages(uint32_t infoCount
, const dyld_image_info info
[]) 
  75         // make initial size large enough that we probably won't need to re-alloc it 
  76         if ( sImageInfos
.size() == 0 ) 
  77                 sImageInfos
.reserve(INITIAL_IMAGE_COUNT
); 
  78         if ( sImageUUIDs
.capacity() == 0 ) 
  79                 sImageUUIDs
.reserve(4); 
  80         // set infoArray to NULL to denote it is in-use 
  81         dyld::gProcessInfo
->infoArray 
= NULL
; 
  83         // append all new images 
  84         for (uint32_t i
=0; i 
< infoCount
; ++i
) 
  85                 sImageInfos
.push_back(info
[i
]); 
  86         dyld::gProcessInfo
->infoArrayCount 
= (uint32_t)sImageInfos
.size(); 
  87         dyld::gProcessInfo
->infoArrayChangeTimestamp 
= mach_absolute_time(); 
  89         // set infoArray back to base address of vector (other process can now read) 
  90         dyld::gProcessInfo
->infoArray 
= &sImageInfos
[0]; 
  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() 
  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
]); 
 104                         dyld::gProcessInfo
->infoArray 
= &sImageInfos
[0]; 
 105                         dyld::gProcessInfo
->infoArrayCount 
= (uint32_t)sImageInfos
.size(); 
 108         dyld::gProcessInfo
->notification(dyld_image_info_change
, 0, NULL
); 
 112 const char* notifyGDB(enum dyld_image_states state
, uint32_t infoCount
, const dyld_image_info info
[]) 
 114         // tell gdb that about the new images 
 115         uint64_t t0 
= mach_absolute_time(); 
 116         dyld::gProcessInfo
->notification(dyld_image_adding
, infoCount
, info
); 
 117         uint64_t t1 
= mach_absolute_time(); 
 118         ImageLoader::fgTotalDebuggerPausedTime 
+= (t1
-t0
); 
 120         // <rdar://problem/7739489> record initial count of images   
 121         // so CrashReporter can note which images were dynamically loaded 
 122         if ( dyld::gProcessInfo
->initialImageCount 
== 0 ) 
 123                 dyld::gProcessInfo
->initialImageCount 
= dyld::gProcessInfo
->infoArrayCount
; 
 129 void addNonSharedCacheImageUUID(const dyld_uuid_info
& info
) 
 131         // set uuidArray to NULL to denote it is in-use 
 132         dyld::gProcessInfo
->uuidArray 
= NULL
; 
 134         // append all new images 
 135         sImageUUIDs
.push_back(info
); 
 136         dyld::gProcessInfo
->uuidArrayCount 
= sImageUUIDs
.size(); 
 138         // set uuidArray back to base address of vector (other process can now read) 
 139         dyld::gProcessInfo
->uuidArray 
= &sImageUUIDs
[0]; 
 142 void removeImageFromAllImages(const struct mach_header
* loadAddress
) 
 144         dyld_image_info goingAway
; 
 146         // set infoArray to NULL to denote it is in-use 
 147         dyld::gProcessInfo
->infoArray 
= NULL
; 
 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 
) { 
 153                         sImageInfos
.erase(it
); 
 157         dyld::gProcessInfo
->infoArrayCount 
= (uint32_t)sImageInfos
.size(); 
 159         // set infoArray back to base address of vector 
 160         dyld::gProcessInfo
->infoArray 
= &sImageInfos
[0]; 
 163         // set uuidArrayCount to NULL to denote it is in-use 
 164         dyld::gProcessInfo
->uuidArray 
= NULL
; 
 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
); 
 173         dyld::gProcessInfo
->uuidArrayCount 
= sImageUUIDs
.size(); 
 174         dyld::gProcessInfo
->infoArrayChangeTimestamp 
= mach_absolute_time(); 
 176         // set infoArray back to base address of vector 
 177         dyld::gProcessInfo
->uuidArray 
= &sImageUUIDs
[0]; 
 179         // tell gdb that about the new images 
 180         dyld::gProcessInfo
->notification(dyld_image_removing
, 1, &goingAway
); 
 184 #if TARGET_IPHONE_SIMULATOR 
 186                 struct dyld_all_image_infos
* gProcessInfo 
= NULL
; 
 190         static void gdb_image_notifier(enum dyld_image_mode mode
, uint32_t infoCount
, const dyld_image_info info
[]) 
 192                 uint64_t machHeaders
[infoCount
]; 
 193                 for (uint32_t i
=0; i 
< infoCount
; ++i
) { 
 194                         machHeaders
[i
] = (uintptr_t)(info
[i
].imageLoadAddress
); 
 197                          case dyld_image_adding
: 
 198                                 _dyld_debugger_notification(dyld_notify_adding
, infoCount
, machHeaders
); 
 200                          case dyld_image_removing
: 
 201                                 _dyld_debugger_notification(dyld_notify_removing
, infoCount
, machHeaders
); 
 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); 
 215         // only used with accelerator tables and ASan which images need to be re-loaded 
 216         void resetAllImages() 
 220                 _dyld_debugger_notification(dyld_notify_remove_all
, 0, NULL
); 
 223         extern void* __dso_handle
; 
 225         #define XSTR(s) STR(s) 
 227         struct dyld_all_image_infos  dyld_all_image_infos 
__attribute__ ((section ("__DATA,__all_image_info")))  
 229                                                                         15, 0, NULL
, &gdb_image_notifier
, false, false, (const mach_header
*)&__dso_handle
, NULL
, 
 230                                                                         XSTR(DYLD_VERSION
), NULL
, 0, NULL
, 0, 0, NULL
, &dyld_all_image_infos
,  
 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} 
 235         struct dyld_shared_cache_ranges dyld_shared_cache_ranges
; 
 238                 struct dyld_all_image_infos
* gProcessInfo 
= &dyld_all_image_infos
;