Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | /* * Copyright (c) 2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifndef _DYLD_PROCESS_INFO_ #define _DYLD_PROCESS_INFO_ #include <TargetConditionals.h> #if !TARGET_OS_EXCLAVEKIT #include <dispatch/dispatch.h> #include <mach/mach.h> #include <stdint.h> #include <unistd.h> #endif #include <stdbool.h> #include <uuid/uuid.h> //FIXME we should include dyld_priv.h, but we need to do this to workaround a header search path bug in tapi typedef uint32_t dyld_platform_t; #ifdef __cplusplus extern "C" { #endif // // Beginning in iOS 10.0 and Mac OS X 10.12, this is how lldb figures out mach-o binaries are in a process: // // When attaching to an existing process, lldb uses _dyld_process_info_create() to get the current list of images // in a process, then falls into the start up case. // // When starting a process, lldb starts the process suspended, finds the "_dyld_debugger_notification" symbol in // dyld, sets a break point on it, then resumes the process. Dyld will call _dyld_debugger_notification() with // a list of images that were just added or removed from the process. Dyld calls this function before running // any initializers in the image, so the debugger will have a chance to set break points in the image. // // enum dyld_notify_mode { dyld_notify_adding=0, dyld_notify_removing=1, dyld_notify_remove_all=2, dyld_notify_dyld_moved=3 }; // void _dyld_debugger_notification(enum dyld_notify_mode, unsigned long count, uint64_t machHeaders[]); struct dyld_process_cache_info { uuid_t cacheUUID; // UUID of cache used by process uint64_t cacheBaseAddress; // load address of dyld shared cache bool noCache; // process is running without a dyld cache bool privateCache; // process is using a private copy of its dyld cache }; typedef struct dyld_process_cache_info dyld_process_cache_info; struct dyld_process_aot_cache_info { uuid_t cacheUUID; uint64_t cacheBaseAddress; }; typedef struct dyld_process_aot_cache_info dyld_process_aot_cache_info; enum { dyld_process_state_not_started = 0x00, // process is suspended, dyld has not started running yet dyld_process_state_dyld_initialized = 0x10, // dyld has initialzed itself dyld_process_state_terminated_before_inits = 0x20, // process was terminated due missing library or symbol before it got to main() dyld_process_state_libSystem_initialized = 0x30, // dyld has run libSystem's initializer dyld_process_state_running_initializers = 0x40, // dyld is running other initializers dyld_process_state_program_running = 0x50, // dyld has finished and jumped into main() dyld_process_state_dyld_terminated = 0x60 // process was terminated by dyld post-main (e.g. bad lazying binding info) }; struct dyld_process_state_info { uint64_t timestamp; // mach_absolute_time of last time dyld change to image list uint32_t imageCount; // number of images currently loaded into process uint32_t initialImageCount; // number of images statically loaded into process (before any dlopen() calls) uint8_t dyldState; // one of dyld_process_state_* values }; typedef struct dyld_process_state_info dyld_process_state_info; typedef const struct dyld_process_info_base* dyld_process_info; #if !TARGET_OS_EXCLAVEKIT // // Generate a dyld_process_info object for specified task. // // The timestamp parameter is an optimization to not spend the time to gather all the image information // if the process image list has not changed since the last call. If timestamp is zero, this function // always gathers the full process info. If timestamp is non-zero, this function will check if the target // task's image list has changed since that time. If is has not changed, the function returns NULL and // kern_return_t is KERN_SUCCESS. If it has changed, the function gathers the full image info. // The kernelError parameter can be NULL for clients that don't care why it failed. // extern dyld_process_info _dyld_process_info_create(task_t task, uint64_t timestamp, kern_return_t* kernelError); // retain/release dyld_process_info for specified task extern void _dyld_process_info_release(dyld_process_info info); extern void _dyld_process_info_retain(dyld_process_info info); // fill in struct with basic info about dyld in the process extern void _dyld_process_info_get_state(dyld_process_info info, dyld_process_state_info* stateInfo); // fill in struct with info about dyld cache in use by process extern void _dyld_process_info_get_cache(dyld_process_info info, dyld_process_cache_info* cacheInfo); // fill in struct with info about aot cache in use by process extern void _dyld_process_info_get_aot_cache(dyld_process_info info, dyld_process_aot_cache_info* aotCacheInfo); // iterate all images in process extern void _dyld_process_info_for_each_image(dyld_process_info info, void (^callback)(uint64_t machHeaderAddress, const uuid_t uuid, const char* path)); // iterate all aot images in process extern void _dyld_process_info_for_each_aot_image(dyld_process_info info, bool (^callback)(uint64_t x86Address, uint64_t aotAddress, uint64_t aotSize, uint8_t* aotImageKey, size_t aotImageKeySize)) __API_UNAVAILABLE(ios, tvos, watchos) __API_UNAVAILABLE(bridgeos); // iterate all segments in an image extern void _dyld_process_info_for_each_segment(dyld_process_info info, uint64_t machHeaderAddress, void (^callback)(uint64_t segmentAddress, uint64_t segmentSize, const char* segmentName)); // returns 0 if the platform cannot be determined, otherwise returns the platform of the remote process extern dyld_platform_t _dyld_process_info_get_platform(dyld_process_info info) SPI_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0), watchos(6.0), bridgeos(4.0)); typedef const struct dyld_process_info_notify_base* dyld_process_info_notify; // // Request notifications if image list changes in target process. Each time a load or unload happens in the target taks, // the notify block will be called in this process. If the process exits, the notifyExit block will be called. // If the notifications cannot be set up, this function will return NULL, and the reason in the kernError parameter. // The kernelError parameter can be NULL for clients that don't care why it failed. // If you want to stop receiving notifications, call _dyld_process_info_notify_release(). // extern dyld_process_info_notify _dyld_process_info_notify(task_t task, dispatch_queue_t queue, void (^notify)(bool unload, uint64_t timestamp, uint64_t machHeader, const uuid_t uuid, const char* path), void (^notifyExit)(void), kern_return_t* kernelError); // add block to call right before main() is entered. // does nothing if process is already in main(). extern void _dyld_process_info_notify_main(dyld_process_info_notify objc, void (^notifyMain)(void)); // stop notifications and invalid dyld_process_info_notify object extern void _dyld_process_info_notify_release(dyld_process_info_notify object); extern void _dyld_process_info_notify_retain(dyld_process_info_notify object); #endif // !TARGET_OS_EXCLAVEKIT #ifdef __cplusplus } #endif #endif /* _DYLD_PROCESS_INFO_ */ |