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> 
  30 #include <mach-o/dyld_images.h> 
  31 #include <mach-o/dyld_process_info.h> 
  36 #include "ImageLoader.h" 
  39 extern "C"      void _dyld_debugger_notification(enum dyld_notify_mode mode
, unsigned long count
, uint64_t machHeaders
[]); 
  41 #if __IPHONE_OS_VERSION_MIN_REQUIRED 
  42         #define INITIAL_UUID_IMAGE_COUNT 4 
  44         #define INITIAL_UUID_IMAGE_COUNT 32 
  47 VECTOR_NEVER_DESTRUCTED(dyld_image_info
); 
  48 VECTOR_NEVER_DESTRUCTED(dyld_uuid_info
); 
  50 static std::vector
<dyld_image_info
> sImageInfos
; 
  51 static std::vector
<dyld_uuid_info
>  sImageUUIDs
; 
  53 size_t allImagesCount() 
  55         return sImageInfos
.size(); 
  58 const mach_header
* allImagesIndexedMachHeader(uint32_t index
) 
  60         if ( index 
< sImageInfos
.size() ) 
  61                 return sImageInfos
[index
].imageLoadAddress
; 
  66 const char* allImagesIndexedPath(uint32_t index
) 
  68         if ( index 
< sImageInfos
.size() ) 
  69                 return sImageInfos
[index
].imageFilePath
; 
  75 void addImagesToAllImages(uint32_t infoCount
, const dyld_image_info info
[]) 
  77         // make initial size large enough that we probably won't need to re-alloc it 
  78         if ( sImageInfos
.size() == 0 ) 
  79                 sImageInfos
.reserve(INITIAL_IMAGE_COUNT
); 
  80         if ( sImageUUIDs
.capacity() == 0 ) 
  81                 sImageUUIDs
.reserve(4); 
  82         // set infoArray to NULL to denote it is in-use 
  83         dyld::gProcessInfo
->infoArray 
= NULL
; 
  85         // append all new images 
  86         for (uint32_t i
=0; i 
< infoCount
; ++i
) 
  87                 sImageInfos
.push_back(info
[i
]); 
  88         dyld::gProcessInfo
->infoArrayCount 
= (uint32_t)sImageInfos
.size(); 
  89         dyld::gProcessInfo
->infoArrayChangeTimestamp 
= mach_absolute_time(); 
  91         // set infoArray back to base address of vector (other process can now read) 
  92         dyld::gProcessInfo
->infoArray 
= &sImageInfos
[0]; 
  95 #if TARGET_OS_SIMULATOR 
  96 // called once in dyld_sim start up to copy image list from host dyld to sImageInfos 
  97 void syncProcessInfo() 
  99         // may want to set version field of gProcessInfo if it might be different than host 
 100         if ( sImageInfos
.size() == 0 ) { 
 101                 sImageInfos
.reserve(INITIAL_IMAGE_COUNT
); 
 102                 if ( dyld::gProcessInfo
->infoArray 
!= NULL 
) { 
 103                         for (uint32_t i
=0; i 
< dyld::gProcessInfo
->infoArrayCount
; ++i
) { 
 104                                 sImageInfos
.push_back(dyld::gProcessInfo
->infoArray
[i
]); 
 106                         dyld::gProcessInfo
->infoArray 
= &sImageInfos
[0]; 
 107                         dyld::gProcessInfo
->infoArrayCount 
= (uint32_t)sImageInfos
.size(); 
 110         dyld::gProcessInfo
->notification(dyld_image_info_change
, 0, NULL
); 
 114 const char* notifyGDB(enum dyld_image_states state
, uint32_t infoCount
, const dyld_image_info info
[]) 
 116         // tell gdb that about the new images 
 117         uint64_t t0 
= mach_absolute_time(); 
 118         dyld::gProcessInfo
->notification(dyld_image_adding
, infoCount
, info
); 
 119         uint64_t t1 
= mach_absolute_time(); 
 120         ImageLoader::fgTotalDebuggerPausedTime 
+= (t1
-t0
); 
 122         // <rdar://problem/7739489> record initial count of images   
 123         // so CrashReporter can note which images were dynamically loaded 
 124         if ( dyld::gProcessInfo
->initialImageCount 
== 0 ) 
 125                 dyld::gProcessInfo
->initialImageCount 
= dyld::gProcessInfo
->infoArrayCount
; 
 131 void addNonSharedCacheImageUUID(const dyld_uuid_info
& info
) 
 133         // set uuidArray to NULL to denote it is in-use 
 134         dyld::gProcessInfo
->uuidArray 
= NULL
; 
 136         // append all new images 
 137         sImageUUIDs
.push_back(info
); 
 138         dyld::gProcessInfo
->uuidArrayCount 
= sImageUUIDs
.size(); 
 140         // set uuidArray back to base address of vector (other process can now read) 
 141         dyld::gProcessInfo
->uuidArray 
= &sImageUUIDs
[0]; 
 144 void removeImageFromAllImages(const struct mach_header
* loadAddress
) 
 146         dyld_image_info goingAway
; 
 148         // set infoArray to NULL to denote it is in-use 
 149         dyld::gProcessInfo
->infoArray 
= NULL
; 
 151         // remove image from infoArray 
 152         for (std::vector
<dyld_image_info
>::iterator it
=sImageInfos
.begin(); it 
!= sImageInfos
.end(); it
++) { 
 153                 if ( it
->imageLoadAddress 
== loadAddress 
) { 
 155                         sImageInfos
.erase(it
); 
 159         dyld::gProcessInfo
->infoArrayCount 
= (uint32_t)sImageInfos
.size(); 
 161         // set infoArray back to base address of vector 
 162         dyld::gProcessInfo
->infoArray 
= &sImageInfos
[0]; 
 165         // set uuidArrayCount to NULL to denote it is in-use 
 166         dyld::gProcessInfo
->uuidArray 
= NULL
; 
 168         // remove image from infoArray 
 169         for (std::vector
<dyld_uuid_info
>::iterator it
=sImageUUIDs
.begin(); it 
!= sImageUUIDs
.end(); it
++) { 
 170                 if ( it
->imageLoadAddress 
== loadAddress 
) { 
 171                         sImageUUIDs
.erase(it
); 
 175         dyld::gProcessInfo
->uuidArrayCount 
= sImageUUIDs
.size(); 
 176         dyld::gProcessInfo
->infoArrayChangeTimestamp 
= mach_absolute_time(); 
 178         // set infoArray back to base address of vector 
 179         dyld::gProcessInfo
->uuidArray 
= &sImageUUIDs
[0]; 
 181         // tell gdb that about the new images 
 182         dyld::gProcessInfo
->notification(dyld_image_removing
, 1, &goingAway
); 
 186 #if TARGET_OS_SIMULATOR 
 188                 struct dyld_all_image_infos
* gProcessInfo 
= NULL
; 
 192         static void gdb_image_notifier(enum dyld_image_mode mode
, uint32_t infoCount
, const dyld_image_info info
[]) 
 194                 dyld3::ScopedTimer(DBG_DYLD_GDB_IMAGE_NOTIFIER
, 0, 0, 0); 
 195                 uint64_t machHeaders
[infoCount
]; 
 196                 for (uint32_t i
=0; i 
< infoCount
; ++i
) { 
 197                         machHeaders
[i
] = (uintptr_t)(info
[i
].imageLoadAddress
); 
 200                          case dyld_image_adding
: 
 201                                 _dyld_debugger_notification(dyld_notify_adding
, infoCount
, machHeaders
); 
 203                          case dyld_image_removing
: 
 204                                 _dyld_debugger_notification(dyld_notify_removing
, infoCount
, machHeaders
); 
 210                 // gdb sets a break point here to catch notifications 
 211                 //dyld::log("dyld: gdb_image_notifier(%s, %d, ...)\n", mode ? "dyld_image_removing" : "dyld_image_adding", infoCount); 
 212                 //for (uint32_t i=0; i < infoCount; ++i) 
 213                 //      dyld::log("dyld: %d loading at %p %s\n", i, info[i].imageLoadAddress, info[i].imageFilePath); 
 214                 //for (uint32_t i=0; i < dyld::gProcessInfo->infoArrayCount; ++i) 
 215                 //      dyld::log("dyld: %d loading at %p %s\n", i, dyld::gProcessInfo->infoArray[i].imageLoadAddress, dyld::gProcessInfo->infoArray[i].imageFilePath); 
 218         // only used with accelerator tables and ASan which images need to be re-loaded 
 219         void resetAllImages() 
 223                 _dyld_debugger_notification(dyld_notify_remove_all
, 0, NULL
); 
 226         extern void* __dso_handle
; 
 228         #define XSTR(s) STR(s) 
 230         struct dyld_all_image_infos  dyld_all_image_infos 
__attribute__ ((section ("__DATA,__all_image_info")))  
 232                                                                         16, 0, {NULL
}, &gdb_image_notifier
, false, false, (const mach_header
*)&__dso_handle
, NULL
, 
 233                                                                         XSTR(DYLD_VERSION
), NULL
, 0, NULL
, 0, 0, NULL
, &dyld_all_image_infos
, 
 234                                                                         0, 0, NULL
, NULL
, NULL
, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}, 
 235                                                                         0, {0}, "/usr/lib/dyld", {0}, {0}, 0 
 238         struct dyld_shared_cache_ranges dyld_shared_cache_ranges
; 
 241                 struct dyld_all_image_infos
* gProcessInfo 
= &dyld_all_image_infos
;