1/*
2 * Copyright (c) 2006-2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#ifndef _DYLD_IMAGES_
24#define _DYLD_IMAGES_
25
26#include <stdbool.h>
27#include <uuid/uuid.h>
28#include <TargetConditionals.h>
29
30#ifndef __OPEN_SOURCE__
31#if !0
32#include <unistd.h>
33#include <mach/mach.h>
34#endif
35#endif
36
37#if defined(__cplusplus) && (BUILDING_LIBDYLD || BUILDING_DYLD)
38#include <atomic>
39#endif
40
41#ifdef __cplusplus
42extern "C" {
43#endif
44
45
46
47/*
48 * Beginning in Mac OS X 10.4, this is how gdb discovers which mach-o images are loaded in a process.
49 *
50 * gdb looks for the symbol "_dyld_all_image_infos" in dyld. It contains the fields below.
51 *
52 * For a snashot of what images are currently loaded, the infoArray fields contain a pointer
53 * to an array of all images. If infoArray is NULL, it means it is being modified, come back later.
54 *
55 * To be notified of changes, gdb sets a break point on the address pointed to by the notificationn
56 * field. The function it points to is called by dyld with an array of information about what images
57 * have been added (dyld_image_adding) or are about to be removed (dyld_image_removing).
58 *
59 * The notification is called after infoArray is updated. This means that if gdb attaches to a process
60 * and infoArray is NULL, gdb can set a break point on notification and let the proccess continue to
61 * run until the break point. Then gdb can inspect the full infoArray.
62 *
63 * The dyldVersion field always points to a C string that contains the dyld version. For instance,
64 * in dyld-127.3, dyldVersion would contain a pointer to "127.3".
65 *
66 * The errorMessage and terminationFlags fields are normally zero. If dyld terminates a process
67 * (for instance because a required dylib or symbol is missing), then the errorMessage field will
68 * be set to point to a C string message buffer containing the reason dyld terminate the process.
69 * The low bit of the terminationFlags will be set if dyld terminated the process before any user
70 * code ran, in which case there is no need for the crash log to contain the backtrace.
71 *
72 * When dyld terminates a process because some required dylib or symbol cannot be bound, in
73 * addition to the errorMessage field, it now sets the errorKind field and the corresponding
74 * fields: errorClientOfDylibPath, errorTargetDylibPath, errorSymbol.
75 *
76 */
77
78enum dyld_image_mode { dyld_image_adding=0, dyld_image_removing=1, dyld_image_info_change=2, dyld_image_dyld_moved=3 };
79
80struct dyld_image_info {
81 const struct mach_header* imageLoadAddress; /* base address image is mapped into */
82 const char* imageFilePath; /* path dyld used to load the image */
83 uintptr_t imageFileModDate; /* time_t of image file */
84 /* if stat().st_mtime of imageFilePath does not match imageFileModDate, */
85 /* then file has been modified since dyld loaded it */
86};
87
88struct dyld_uuid_info {
89 const struct mach_header* imageLoadAddress; /* base address image is mapped into */
90 uuid_t imageUUID; /* UUID of image */
91};
92
93#define DYLD_AOT_IMAGE_KEY_SIZE 32
94struct dyld_aot_image_info {
95 const struct mach_header* x86LoadAddress;
96 const struct mach_header* aotLoadAddress;
97 uint64_t aotImageSize;
98 uint8_t aotImageKey[DYLD_AOT_IMAGE_KEY_SIZE]; // uniquely identifying SHA-256 key for this aot
99};
100
101struct dyld_aot_shared_cache_info {
102 const uintptr_t cacheBaseAddress;
103 uuid_t cacheUUID;
104};
105
106typedef void (*dyld_image_notifier)(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]);
107
108/* for use in dyld_all_image_infos.errorKind field */
109enum { dyld_error_kind_none=0,
110 dyld_error_kind_dylib_missing=1,
111 dyld_error_kind_dylib_wrong_arch=2,
112 dyld_error_kind_dylib_version=3,
113 dyld_error_kind_symbol_missing=4
114 };
115
116/* internal limit */
117#define DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT 8
118
119// Must be aligned to support atomic updates
120// Note sim cannot assume alignment until all host dylds are new enough
121#if TARGET_OS_SIMULATOR
122struct dyld_all_image_infos
123#else
124struct __attribute__((aligned(16))) dyld_all_image_infos
125#endif
126{
127 uint32_t version; /* 1 in Mac OS X 10.4 and 10.5 */
128 uint32_t infoArrayCount;
129#if defined(__cplusplus) && (BUILDING_LIBDYLD || BUILDING_DYLD)
130 std::atomic<const struct dyld_image_info*> infoArray;
131#else
132 const struct dyld_image_info* infoArray;
133#endif
134 dyld_image_notifier notification;
135 bool processDetachedFromSharedRegion;
136 /* the following fields are only in version 2 (Mac OS X 10.6, iPhoneOS 2.0) and later */
137 bool libSystemInitialized;
138 const struct mach_header* dyldImageLoadAddress;
139 /* the following field is only in version 3 (Mac OS X 10.6, iPhoneOS 3.0) and later */
140 void* jitInfo;
141 /* the following fields are only in version 5 (Mac OS X 10.6, iPhoneOS 3.0) and later */
142 const char* dyldVersion;
143 const char* errorMessage;
144 uintptr_t terminationFlags;
145 /* the following field is only in version 6 (Mac OS X 10.6, iPhoneOS 3.1) and later */
146 void* coreSymbolicationShmPage;
147 /* the following field is only in version 7 (Mac OS X 10.6, iPhoneOS 3.1) and later */
148 uintptr_t systemOrderFlag;
149 /* the following field is only in version 8 (Mac OS X 10.7, iPhoneOS 3.1) and later */
150 uintptr_t uuidArrayCount;
151 const struct dyld_uuid_info* uuidArray; /* only images not in dyld shared cache */
152 /* the following field is only in version 9 (Mac OS X 10.7, iOS 4.0) and later */
153 struct dyld_all_image_infos* dyldAllImageInfosAddress;
154 /* the following field is only in version 10 (Mac OS X 10.7, iOS 4.2) and later */
155 uintptr_t initialImageCount;
156 /* the following field is only in version 11 (Mac OS X 10.7, iOS 4.2) and later */
157 uintptr_t errorKind;
158 const char* errorClientOfDylibPath;
159 const char* errorTargetDylibPath;
160 const char* errorSymbol;
161 /* the following field is only in version 12 (Mac OS X 10.7, iOS 4.3) and later */
162 uintptr_t sharedCacheSlide;
163 /* the following field is only in version 13 (Mac OS X 10.9, iOS 7.0) and later */
164 uint8_t sharedCacheUUID[16];
165 /* the following field is only in version 15 (macOS 10.12, iOS 10.0) and later */
166 uintptr_t sharedCacheBaseAddress;
167#if defined(__cplusplus) && (BUILDING_LIBDYLD || BUILDING_DYLD)
168 // We want this to be atomic in libdyld so that we can see updates when we map it shared
169 std::atomic<uint64_t> infoArrayChangeTimestamp;
170#else
171 uint64_t infoArrayChangeTimestamp;
172#endif
173 const char* dyldPath;
174
175 mach_port_t notifyPorts[DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT];
176
177#if __LP64__
178 uintptr_t reserved[11-(DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT/2)];
179#else
180 uintptr_t reserved[9-DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT];
181#endif
182 // The following fields were added in version 18 (previously they were reserved padding fields)
183 uint64_t sharedCacheFSID;
184 uint64_t sharedCacheFSObjID;
185 /* the following field is only in version 16 (macOS 10.13, iOS 11.0) and later */
186 uintptr_t compact_dyld_image_info_addr;
187 size_t compact_dyld_image_info_size;
188 uint32_t platform; // FIXME: really a dyld_platform_t, but those aren't exposed here.
189
190 /* the following field is only in version 17 (macOS 10.16) and later */
191 uint32_t aotInfoCount;
192 const struct dyld_aot_image_info* aotInfoArray;
193 uint64_t aotInfoArrayChangeTimestamp;
194 uintptr_t aotSharedCacheBaseAddress;
195 uint8_t aotSharedCacheUUID[16];
196};
197
198/*
199 * Beginning in Mac OS X 10.5, this is how gdb discovers where the shared cache is in a process.
200 * Images that are in the shared cache have their segments rearranged, so when using imageFilePath
201 * to load the file from disk, you have to know to adjust addresses based on how their segment
202 * was rearranged.
203 *
204 * gdb looks for the symbol "_dyld_shared_region_ranges" in dyld.
205 *
206 * It contains information the count of shared regions used by the process. The count is
207 * the number of start/length pairs.
208 */
209struct dyld_shared_cache_ranges {
210 uintptr_t sharedRegionsCount; /* how many ranges follow */
211 struct {
212 uintptr_t start;
213 uintptr_t length;
214 } ranges[4]; /* max regions */
215};
216extern struct dyld_shared_cache_ranges dyld_shared_cache_ranges __attribute__((visibility("hidden")));
217
218
219
220#ifdef __cplusplus
221}
222#endif
223
224#endif /* _DYLD_IMAGES_ */