]> git.saurik.com Git - apple/dyld.git/blame - src/dyldAPIsInLibSystem.cpp
dyld-360.18.tar.gz
[apple/dyld.git] / src / dyldAPIsInLibSystem.cpp
CommitLineData
0959b6d4
A
1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
2fd3f4e8 3 * Copyright (c) 2004-2012 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 <string.h>
39a8cd10 27#include <malloc/malloc.h>
2fd3f4e8 28#include <sys/mman.h>
39a8cd10 29
0959b6d4 30#include <crt_externs.h>
39a8cd10 31#include <Availability.h>
2fd3f4e8 32#include <vproc_priv.h>
0959b6d4
A
33
34#include "mach-o/dyld.h"
35#include "mach-o/dyld_priv.h"
36
19894a12 37#include "ImageLoader.h"
0959b6d4 38#include "dyldLock.h"
2fd3f4e8 39#include "start_glue.h"
0959b6d4 40
412ebb8e
A
41extern "C" int __cxa_atexit(void (*func)(void *), void *arg, void *dso);
42extern "C" void __cxa_finalize(const void *dso);
19894a12 43extern "C" void __cxa_finalize_ranges(const struct __cxa_range_t ranges[], int count);
bac542e6 44
832b6fce
A
45
46#ifndef LC_VERSION_MIN_MACOSX
47 #define LC_VERSION_MIN_MACOSX 0x24
48 struct version_min_command {
49 uint32_t cmd; /* LC_VERSION_MIN_MACOSX or
50 LC_VERSION_MIN_IPHONEOS */
51 uint32_t cmdsize; /* sizeof(struct min_version_command) */
52 uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
53 uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
54 };
55#endif
56
57#ifndef LC_VERSION_MIN_IPHONEOS
58 #define LC_VERSION_MIN_IPHONEOS 0x25
59#endif
60
df9d6cf7
A
61#ifndef LC_VERSION_MIN_TVOS
62 #define LC_VERSION_MIN_TVOS 0x2F
63#endif
64
65#ifndef LC_VERSION_MIN_WATCHOS
66 #define LC_VERSION_MIN_WATCHOS 0x30
67#endif
68
832b6fce 69
412ebb8e
A
70#ifndef LC_LOAD_UPWARD_DYLIB
71 #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */
72#endif
73
39a8cd10
A
74
75// deprecated APIs are still availble on Mac OS X, but not on iPhone OS
76#if __IPHONE_OS_VERSION_MIN_REQUIRED
77 #define DEPRECATED_APIS_SUPPORTED 0
78#else
79 #define DEPRECATED_APIS_SUPPORTED 1
80#endif
bac542e6 81
0959b6d4
A
82/*
83 * names_match() takes an install_name from an LC_LOAD_DYLIB command and a
84 * libraryName (which is -lx or -framework Foo argument passed to the static
85 * link editor for the same library) and determines if they match. This depends
86 * on conventional use of names including major versioning.
87 */
88static
89bool
90names_match(
19894a12 91const char *install_name,
0959b6d4
A
92const char* libraryName)
93{
19894a12 94 const char *basename;
0959b6d4
A
95 unsigned long n;
96
97 /*
98 * Conventional install names have these forms:
99 * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit
100 * /Local/Library/Frameworks/AppKit.framework/Appkit
101 * /lib/libsys_s.A.dylib
102 * /usr/lib/libsys_s.dylib
103 */
104 basename = strrchr(install_name, '/');
105 if(basename == NULL)
106 basename = install_name;
107 else
108 basename++;
109
110 /*
111 * By checking the base name matching the library name we take care
112 * of the -framework cases.
113 */
114 if(strcmp(basename, libraryName) == 0)
19894a12 115 return true;
0959b6d4
A
116
117 /*
118 * Now check the base name for "lib" if so proceed to check for the
119 * -lx case dealing with a possible .X.dylib and a .dylib extension.
120 */
121 if(strncmp(basename, "lib", 3) ==0){
122 n = strlen(libraryName);
123 if(strncmp(basename+3, libraryName, n) == 0){
124 if(strncmp(basename+3+n, ".dylib", 6) == 0)
19894a12 125 return true;
0959b6d4
A
126 if(basename[3+n] == '.' &&
127 basename[3+n+1] != '\0' &&
128 strncmp(basename+3+n+2, ".dylib", 6) == 0)
19894a12 129 return true;
0959b6d4
A
130 }
131 }
19894a12 132 return false;
0959b6d4
A
133}
134
39a8cd10
A
135#if DEPRECATED_APIS_SUPPORTED
136
0959b6d4
A
137void NSInstallLinkEditErrorHandlers(
138const NSLinkEditErrorHandlers* handlers)
139{
bac542e6 140 DYLD_LOCK_THIS_BLOCK;
412ebb8e
A
141 typedef void (*ucallback_t)(const char* symbol_name);
142 typedef NSModule (*mcallback_t)(NSSymbol s, NSModule old, NSModule newhandler);
143 typedef void (*lcallback_t)(NSLinkEditErrors c, int errorNumber,
144 const char* fileName, const char* errorString);
145 static void (*p)(ucallback_t undefined, mcallback_t multiple, lcallback_t linkEdit) = NULL;
0959b6d4
A
146
147 if(p == NULL)
148 _dyld_func_lookup("__dyld_install_handlers", (void**)&p);
412ebb8e
A
149 mcallback_t m = handlers->multiple;
150 p(handlers->undefined, m, handlers->linkEdit);
0959b6d4
A
151}
152
153const char*
154NSNameOfModule(
155NSModule module)
156{
bac542e6 157 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
158 static const char* (*p)(NSModule module) = NULL;
159
160 if(p == NULL)
161 _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p);
162 return(p(module));
163}
164
165const char*
166NSLibraryNameForModule(
167NSModule module)
168{
bac542e6 169 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
170 static const char* (*p)(NSModule module) = NULL;
171
172 if(p == NULL)
173 _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p);
174 return(p(module));
175}
176
177bool
178NSIsSymbolNameDefined(
179const char* symbolName)
180{
bac542e6 181 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
182 static bool (*p)(const char* symbolName) = NULL;
183
184 if(p == NULL)
185 _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p);
186 return(p(symbolName));
187}
188
189bool
190NSIsSymbolNameDefinedWithHint(
191const char* symbolName,
192const char* libraryNameHint)
193{
bac542e6 194 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
195 static bool (*p)(const char* symbolName,
196 const char* libraryNameHint) = NULL;
197
198 if(p == NULL)
199 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p);
200 return(p(symbolName, libraryNameHint));
201}
202
203bool
204NSIsSymbolNameDefinedInImage(
205const struct mach_header *image,
206const char* symbolName)
207{
bac542e6 208 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
209 static bool (*p)(const struct mach_header *image,
210 const char* symbolName) = NULL;
211
212 if(p == NULL)
213 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p);
214 return(p(image, symbolName));
215}
216
217NSSymbol
218NSLookupAndBindSymbol(
219const char* symbolName)
220{
bac542e6 221 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
222 static NSSymbol (*p)(const char* symbolName) = NULL;
223
224 if(p == NULL)
225 _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p);
226 return(p(symbolName));
227}
228
229NSSymbol
230NSLookupAndBindSymbolWithHint(
231const char* symbolName,
232const char* libraryNameHint)
233{
bac542e6 234 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
235 static NSSymbol (*p)(const char* symbolName,
236 const char* libraryNameHint) = NULL;
237
238 if(p == NULL)
239 _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p);
240 return(p(symbolName, libraryNameHint));
241}
242
243NSSymbol
244NSLookupSymbolInModule(
245NSModule module,
246const char* symbolName)
247{
bac542e6 248 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
249 static NSSymbol (*p)(NSModule module, const char* symbolName) = NULL;
250
251 if(p == NULL)
252 _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p);
253 return(p(module, symbolName));
254}
255
256NSSymbol
257NSLookupSymbolInImage(
258const struct mach_header *image,
259const char* symbolName,
260uint32_t options)
261{
bac542e6 262 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
263 static NSSymbol (*p)(const struct mach_header *image,
264 const char* symbolName,
265 uint32_t options) = NULL;
266
267 if(p == NULL)
268 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p);
269 return(p(image, symbolName, options));
270}
271
272const char*
273NSNameOfSymbol(
274NSSymbol symbol)
275{
bac542e6 276 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
277 static char * (*p)(NSSymbol symbol) = NULL;
278
279 if(p == NULL)
280 _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p);
281 return(p(symbol));
282}
283
284void *
285NSAddressOfSymbol(
286NSSymbol symbol)
287{
bac542e6 288 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
289 static void * (*p)(NSSymbol symbol) = NULL;
290
291 if(p == NULL)
292 _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p);
293 return(p(symbol));
294}
295
296NSModule
297NSModuleForSymbol(
298NSSymbol symbol)
299{
bac542e6 300 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
301 static NSModule (*p)(NSSymbol symbol) = NULL;
302
303 if(p == NULL)
304 _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p);
305 return(p(symbol));
306}
307
308bool
309NSAddLibrary(
310const char* pathName)
311{
bac542e6 312 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
313 static bool (*p)(const char* pathName) = NULL;
314
315 if(p == NULL)
316 _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p);
317 return(p(pathName));
318}
319
320bool
321NSAddLibraryWithSearching(
322const char* pathName)
323{
bac542e6 324 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
325 static bool (*p)(const char* pathName) = NULL;
326
327 if(p == NULL)
328 _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p);
329 return(p(pathName));
330}
331
332const struct mach_header *
333NSAddImage(
334const char* image_name,
335uint32_t options)
336{
bac542e6 337 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
338 static const struct mach_header * (*p)(const char* image_name,
339 uint32_t options) = NULL;
340
341 if(p == NULL)
342 _dyld_func_lookup("__dyld_NSAddImage", (void**)&p);
343 return(p(image_name, options));
344}
39a8cd10 345#endif // DEPRECATED_APIS_SUPPORTED
0959b6d4
A
346
347/*
348 * This routine returns the current version of the named shared library the
349 * executable it was built with. The libraryName parameter is the same as the
350 * -lx or -framework Foo argument passed to the static link editor when building
351 * the executable (with -lx it would be "x" and with -framework Foo it would be
352 * "Foo"). If this the executable was not built against the specified library
353 * it returns -1. It should be noted that if this only returns the value the
354 * current version of the named shared library the executable was built with
355 * and not a list of current versions that dependent libraries and bundles the
356 * program is using were built with.
357 */
19894a12 358int32_t NSVersionOfLinkTimeLibrary(const char* libraryName)
0959b6d4 359{
19894a12 360 // Lazily call _NSGetMachExecuteHeader() and cache result
bac542e6 361#if __LP64__
19894a12 362 static mach_header_64* mh = NULL;
bac542e6 363#else
19894a12 364 static mach_header* mh = NULL;
bac542e6 365#endif
19894a12 366 if ( mh == NULL )
0959b6d4 367 mh = _NSGetMachExecuteHeader();
bac542e6 368#if __LP64__
19894a12 369 const load_command* lc = (load_command*)((char*)mh + sizeof(mach_header_64));
0959b6d4 370#else
19894a12 371 const load_command* lc = (load_command*)((char*)mh + sizeof(mach_header));
0959b6d4 372#endif
19894a12 373 for(uint32_t i = 0; i < mh->ncmds; i++){
bac542e6
A
374 switch ( lc->cmd ) {
375 case LC_LOAD_DYLIB:
376 case LC_LOAD_WEAK_DYLIB:
412ebb8e 377 case LC_LOAD_UPWARD_DYLIB:
19894a12
A
378 const dylib_command* dl = (dylib_command *)lc;
379 const char* install_name = (char*)dl + dl->dylib.name.offset;
380 if ( names_match(install_name, libraryName) )
381 return dl->dylib.current_version;
bac542e6
A
382 break;
383 }
19894a12 384 lc = (load_command*)((char*)lc + lc->cmdsize);
0959b6d4 385 }
19894a12 386 return (-1);
0959b6d4
A
387}
388
389/*
390 * This routine returns the current version of the named shared library the
391 * program it is running against. The libraryName parameter is the same as
392 * would be static link editor using the -lx or -framework Foo flags (with -lx
393 * it would be "x" and with -framework Foo it would be "Foo"). If the program
394 * is not using the specified library it returns -1.
395 */
19894a12
A
396int32_t NSVersionOfRunTimeLibrary(const char* libraryName)
397{
398 uint32_t n = _dyld_image_count();
399 for(uint32_t i = 0; i < n; i++){
400 const mach_header* mh = _dyld_get_image_header(i);
401 if ( mh == NULL )
402 continue;
403 if ( mh->filetype != MH_DYLIB )
404 continue;
bac542e6 405#if __LP64__
19894a12 406 const load_command* lc = (load_command*)((char*)mh + sizeof(mach_header_64));
bac542e6 407#else
19894a12 408 const load_command* lc = (load_command*)((char*)mh + sizeof(mach_header));
bac542e6 409#endif
19894a12
A
410 for(uint32_t j = 0; j < mh->ncmds; j++){
411 if ( lc->cmd == LC_ID_DYLIB ) {
412 const dylib_command* dl = (dylib_command*)lc;
413 const char* install_name = (char *)dl + dl->dylib.name.offset;
414 if ( names_match(install_name, libraryName) )
415 return dl->dylib.current_version;
416 }
417 lc = (load_command*)((char*)lc + lc->cmdsize);
0959b6d4
A
418 }
419 }
19894a12 420 return (-1);
0959b6d4
A
421}
422
df9d6cf7 423
2fd3f4e8
A
424#define PACKED_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff))
425
832b6fce 426
df9d6cf7
A
427static bool getVersionLoadCommandInfo(const mach_header* mh, uint32_t* loadCommand, uint32_t* minOS, uint32_t* sdk)
428{
429 const load_command* startCmds = NULL;
430 if ( mh->magic == MH_MAGIC_64 )
431 startCmds = (load_command*)((char *)mh + sizeof(mach_header_64));
432 else if ( mh->magic == MH_MAGIC )
433 startCmds = (load_command*)((char *)mh + sizeof(mach_header));
434 else
435 return false; // not a mach-o file, or wrong endianness
436
437 const load_command* const cmdsEnd = (load_command*)((char*)startCmds + mh->sizeofcmds);
438 const load_command* cmd = startCmds;
439 for(uint32_t i = 0; i < mh->ncmds; ++i) {
440 const load_command* nextCmd = (load_command*)((char *)cmd + cmd->cmdsize);
441 if ( (cmd->cmdsize < 8) || (nextCmd > cmdsEnd) || (nextCmd < startCmds)) {
442 return 0;
443 }
444 const version_min_command* versCmd;
445 switch ( cmd->cmd ) {
446 case LC_VERSION_MIN_IPHONEOS:
447 case LC_VERSION_MIN_MACOSX:
448 case LC_VERSION_MIN_TVOS:
449 case LC_VERSION_MIN_WATCHOS:
450 versCmd = (version_min_command*)cmd;
451 *loadCommand = versCmd->cmd;
452 *minOS = versCmd->version;
453 *sdk = versCmd->sdk;
454 return true;
455 }
456 cmd = nextCmd;
457 }
458 return false;
459}
460
461#if !__WATCH_OS_VERSION_MIN_REQUIRED && !__TV_OS_VERSION_MIN_REQUIRED
462static uint32_t deriveSDKVersFromDylibs(const mach_header* mh)
832b6fce 463{
48479956 464 const load_command* startCmds = NULL;
2fd3f4e8 465 if ( mh->magic == MH_MAGIC_64 )
48479956 466 startCmds = (load_command*)((char *)mh + sizeof(mach_header_64));
2fd3f4e8 467 else if ( mh->magic == MH_MAGIC )
48479956 468 startCmds = (load_command*)((char *)mh + sizeof(mach_header));
2fd3f4e8
A
469 else
470 return 0; // not a mach-o file, or wrong endianness
471
48479956 472 const load_command* const cmdsEnd = (load_command*)((char*)startCmds + mh->sizeofcmds);
832b6fce 473 const dylib_command* dylibCmd;
48479956 474 const load_command* cmd = startCmds;
2fd3f4e8 475 const char* dylibName;
df9d6cf7 476 #if __IPHONE_OS_VERSION_MIN_REQUIRED
2fd3f4e8 477 uint32_t foundationVers = 0;
df9d6cf7 478 #else
832b6fce 479 uint32_t libSystemVers = 0;
df9d6cf7 480 #endif
832b6fce 481 for(uint32_t i = 0; i < mh->ncmds; ++i) {
19894a12
A
482 const load_command* nextCmd = (load_command*)((char *)cmd + cmd->cmdsize);
483 // <rdar://problem/14381579&16050962> sanity check size of command
484 if ( (cmd->cmdsize < 8) || (nextCmd > cmdsEnd) || (nextCmd < startCmds)) {
485 return 0;
486 }
487 switch ( cmd->cmd ) {
832b6fce
A
488 case LC_LOAD_DYLIB:
489 case LC_LOAD_WEAK_DYLIB:
490 case LC_LOAD_UPWARD_DYLIB:
491 dylibCmd = (dylib_command*)cmd;
19894a12
A
492 // sanity check dylib command layout
493 if ( dylibCmd->dylib.name.offset > cmd->cmdsize )
494 return 0;
2fd3f4e8 495 dylibName = (char*)dylibCmd + dylibCmd->dylib.name.offset;
df9d6cf7 496 #if __IPHONE_OS_VERSION_MIN_REQUIRED
2fd3f4e8
A
497 if ( strcmp(dylibName, "/System/Library/Frameworks/Foundation.framework/Foundation") == 0 )
498 foundationVers = dylibCmd->dylib.current_version;
df9d6cf7 499 #else
2fd3f4e8 500 if ( strcmp(dylibName, "/usr/lib/libSystem.B.dylib") == 0 )
832b6fce 501 libSystemVers = dylibCmd->dylib.current_version;
df9d6cf7 502 #endif
832b6fce
A
503 break;
504 }
19894a12 505 cmd = nextCmd;
832b6fce 506 }
2fd3f4e8
A
507
508 struct DylibToOSMapping {
509 uint32_t dylibVersion;
510 uint32_t osVersion;
511 };
832b6fce 512
df9d6cf7 513 #if __IPHONE_OS_VERSION_MIN_REQUIRED
2fd3f4e8
A
514 static const DylibToOSMapping foundationMapping[] = {
515 { PACKED_VERSION(678,24,0), DYLD_IOS_VERSION_2_0 },
516 { PACKED_VERSION(678,26,0), DYLD_IOS_VERSION_2_1 },
517 { PACKED_VERSION(678,29,0), DYLD_IOS_VERSION_2_2 },
518 { PACKED_VERSION(678,47,0), DYLD_IOS_VERSION_3_0 },
519 { PACKED_VERSION(678,51,0), DYLD_IOS_VERSION_3_1 },
520 { PACKED_VERSION(678,60,0), DYLD_IOS_VERSION_3_2 },
521 { PACKED_VERSION(751,32,0), DYLD_IOS_VERSION_4_0 },
522 { PACKED_VERSION(751,37,0), DYLD_IOS_VERSION_4_1 },
523 { PACKED_VERSION(751,49,0), DYLD_IOS_VERSION_4_2 },
524 { PACKED_VERSION(751,58,0), DYLD_IOS_VERSION_4_3 },
525 { PACKED_VERSION(881,0,0), DYLD_IOS_VERSION_5_0 },
526 { PACKED_VERSION(890,1,0), DYLD_IOS_VERSION_5_1 },
527 { PACKED_VERSION(992,0,0), DYLD_IOS_VERSION_6_0 },
528 { PACKED_VERSION(993,0,0), DYLD_IOS_VERSION_6_1 },
df9d6cf7
A
529 { PACKED_VERSION(1038,14,0),DYLD_IOS_VERSION_7_0 },
530 { PACKED_VERSION(0,0,0), DYLD_IOS_VERSION_7_0 }
531 // We don't need to expand this table because all recent
532 // binaries have LC_VERSION_MIN_ load command.
2fd3f4e8
A
533 };
534
535 if ( foundationVers != 0 ) {
536 uint32_t lastOsVersion = 0;
537 for (const DylibToOSMapping* p=foundationMapping; ; ++p) {
538 if ( p->dylibVersion == 0 )
539 return p->osVersion;
540 if ( foundationVers < p->dylibVersion )
541 return lastOsVersion;
542 lastOsVersion = p->osVersion;
543 }
544 }
545
df9d6cf7 546 #else
2fd3f4e8
A
547 // Note: versions are for the GM release. The last entry should
548 // always be zero. At the start of the next major version,
549 // a new last entry needs to be added and the previous zero
550 // updated to the GM dylib version.
551 static const DylibToOSMapping libSystemMapping[] = {
552 { PACKED_VERSION(88,1,3), DYLD_MACOSX_VERSION_10_4 },
553 { PACKED_VERSION(111,0,0), DYLD_MACOSX_VERSION_10_5 },
554 { PACKED_VERSION(123,0,0), DYLD_MACOSX_VERSION_10_6 },
555 { PACKED_VERSION(159,0,0), DYLD_MACOSX_VERSION_10_7 },
556 { PACKED_VERSION(169,3,0), DYLD_MACOSX_VERSION_10_8 },
557 { PACKED_VERSION(1197,0,0), DYLD_MACOSX_VERSION_10_9 },
558 { PACKED_VERSION(0,0,0), DYLD_MACOSX_VERSION_10_9 }
df9d6cf7
A
559 // We don't need to expand this table because all recent
560 // binaries have LC_VERSION_MIN_ load command.
2fd3f4e8
A
561 };
562
563 if ( libSystemVers != 0 ) {
564 uint32_t lastOsVersion = 0;
565 for (const DylibToOSMapping* p=libSystemMapping; ; ++p) {
566 if ( p->dylibVersion == 0 )
567 return p->osVersion;
568 if ( libSystemVers < p->dylibVersion )
569 return lastOsVersion;
570 lastOsVersion = p->osVersion;
571 }
832b6fce 572 }
df9d6cf7
A
573 #endif
574 return 0;
575}
2fd3f4e8 576#endif
df9d6cf7
A
577
578
579#if __WATCH_OS_VERSION_MIN_REQUIRED
580static uint32_t watchVersToIOSVers(uint32_t vers)
581{
582 return vers + 0x00070000;
583}
584
585uint32_t dyld_get_program_sdk_watch_os_version()
586{
587 const mach_header* mh = (mach_header*)_NSGetMachExecuteHeader();
588 uint32_t loadCommand;
589 uint32_t minOS;
590 uint32_t sdk;
591
592 if ( getVersionLoadCommandInfo(mh, &loadCommand, &minOS, &sdk) ) {
593 if ( loadCommand == LC_VERSION_MIN_WATCHOS )
594 return sdk;
595 }
596 return 0;
597}
598#endif
599
600/*
601 * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the
602 * specified binary was built against.
603 *
604 * First looks for LC_VERSION_MIN_* in binary and if sdk field is
605 * not zero, return that value.
606 * Otherwise, looks for the libSystem.B.dylib the binary linked
607 * against and uses a table to convert that to an sdk version.
608 */
609uint32_t dyld_get_sdk_version(const mach_header* mh)
610{
611 uint32_t loadCommand;
612 uint32_t minOS;
613 uint32_t sdk;
614
615 if ( getVersionLoadCommandInfo(mh, &loadCommand, &minOS, &sdk) ) {
616 switch (loadCommand) {
617#if __WATCH_OS_VERSION_MIN_REQUIRED
618 case LC_VERSION_MIN_WATCHOS:
619 // new binary. sdk version looks like "2.0" but API wants "9.0"
620 return watchVersToIOSVers(sdk);
621 case LC_VERSION_MIN_IPHONEOS:
622 // old binary. sdk matches API semantics so can return directly.
623 return sdk;
624#elif __TV_OS_VERSION_MIN_REQUIRED
625 case LC_VERSION_MIN_TVOS:
626 case LC_VERSION_MIN_IPHONEOS:
627 return sdk;
628#elif __IPHONE_OS_VERSION_MIN_REQUIRED
629 case LC_VERSION_MIN_IPHONEOS:
630 if ( sdk != 0 ) // old binaries might not have SDK set
631 return sdk;
632 break;
633#else
634 case LC_VERSION_MIN_MACOSX:
635 if ( sdk != 0 ) // old binaries might not have SDK set
636 return sdk;
637 break;
638#endif
639 }
640 }
641
642#if __WATCH_OS_VERSION_MIN_REQUIRED ||__TV_OS_VERSION_MIN_REQUIRED
643 // All WatchOS and tv OS binaries should have version load command.
832b6fce 644 return 0;
df9d6cf7
A
645#else
646 // MacOSX and iOS have old binaries without version load commmand.
647 return deriveSDKVersFromDylibs(mh);
648#endif
832b6fce
A
649}
650
651uint32_t dyld_get_program_sdk_version()
652{
653 return dyld_get_sdk_version((mach_header*)_NSGetMachExecuteHeader());
654}
655
832b6fce
A
656uint32_t dyld_get_min_os_version(const struct mach_header* mh)
657{
df9d6cf7
A
658 uint32_t loadCommand;
659 uint32_t minOS;
660 uint32_t sdk;
661
662 if ( getVersionLoadCommandInfo(mh, &loadCommand, &minOS, &sdk) ) {
663 switch (loadCommand) {
664#if __WATCH_OS_VERSION_MIN_REQUIRED
665 case LC_VERSION_MIN_WATCHOS:
666 // new binary. OS version looks like "2.0" but API wants "9.0"
667 return watchVersToIOSVers(minOS);
668 case LC_VERSION_MIN_IPHONEOS:
669 // old binary. OS matches API semantics so can return directly.
670 return minOS;
671#elif __TV_OS_VERSION_MIN_REQUIRED
672 case LC_VERSION_MIN_TVOS:
673 case LC_VERSION_MIN_IPHONEOS:
674 return minOS;
675#elif __IPHONE_OS_VERSION_MIN_REQUIRED
832b6fce 676 case LC_VERSION_MIN_IPHONEOS:
df9d6cf7 677 return minOS;
2fd3f4e8
A
678#else
679 case LC_VERSION_MIN_MACOSX:
df9d6cf7 680 return minOS;
2fd3f4e8 681#endif
832b6fce 682 }
832b6fce
A
683 }
684 return 0;
685}
686
687
688uint32_t dyld_get_program_min_os_version()
689{
690 return dyld_get_min_os_version((mach_header*)_NSGetMachExecuteHeader());
691}
692
693
39a8cd10 694#if DEPRECATED_APIS_SUPPORTED
0959b6d4
A
695/*
696 * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
697 * specified file name if the file is a correct Mach-O file that can be loaded
698 * with NSloadModule(). For return codes of NSObjectFileImageFailure and
699 * NSObjectFileImageFormat an error message is printed to stderr. All
700 * other codes cause no printing.
701 */
702NSObjectFileImageReturnCode
703NSCreateObjectFileImageFromFile(
704const char* pathName,
705NSObjectFileImage *objectFileImage)
706{
bac542e6 707 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
708 static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL;
709
710 if(p == NULL)
711 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p);
712 return p(pathName, objectFileImage);
713}
714
715
716/*
717 * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
718 * object file mapped into memory at address of size length if the object file
719 * is a correct Mach-O file that can be loaded with NSloadModule(). For return
720 * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
721 * message is printed to stderr. All other codes cause no printing.
722 */
723NSObjectFileImageReturnCode
724NSCreateObjectFileImageFromMemory(
725const void* address,
726size_t size,
727NSObjectFileImage *objectFileImage)
728{
bac542e6 729 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
730 static NSObjectFileImageReturnCode (*p)(const void*, size_t, NSObjectFileImage*) = NULL;
731
732 if(p == NULL)
733 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p);
734 return p(address, size, objectFileImage);
735}
736
bac542e6 737#if OBSOLETE_DYLD_API
0959b6d4
A
738/*
739 * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the
740 * specified core file name if the file is a correct Mach-O core file.
741 * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
742 * an error message is printed to stderr. All other codes cause no printing.
743 */
744NSObjectFileImageReturnCode
745NSCreateCoreFileImageFromFile(
746const char* pathName,
747NSObjectFileImage *objectFileImage)
748{
bac542e6 749 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
750 static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL;
751
752 if(p == NULL)
753 _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p);
754 return p(pathName, objectFileImage);
755}
bac542e6 756#endif
0959b6d4
A
757
758bool
759NSDestroyObjectFileImage(
760NSObjectFileImage objectFileImage)
761{
bac542e6 762 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
763 static bool (*p)(NSObjectFileImage) = NULL;
764
765 if(p == NULL)
766 _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p);
767 return p(objectFileImage);
768}
769
770
771NSModule
772NSLinkModule(
773NSObjectFileImage objectFileImage,
774const char* moduleName,
775uint32_t options)
776{
bac542e6 777 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
778 static NSModule (*p)(NSObjectFileImage, const char*, unsigned long) = NULL;
779
780 if(p == NULL)
781 _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p);
782
783 return p(objectFileImage, moduleName, options);
784}
785
786
0959b6d4
A
787
788
789/*
790 * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
791 * definitions in the NSObjectFileImage.
792 */
793uint32_t
794NSSymbolDefinitionCountInObjectFileImage(
795NSObjectFileImage objectFileImage)
796{
bac542e6 797 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
798 static unsigned long (*p)(NSObjectFileImage) = NULL;
799
800 if(p == NULL)
801 _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p);
802
803 return p(objectFileImage);
804}
805
806/*
807 * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
808 * symbol definitions in the NSObjectFileImage. If the ordinal specified is
809 * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
810 * be returned.
811 */
812const char*
813NSSymbolDefinitionNameInObjectFileImage(
814NSObjectFileImage objectFileImage,
815uint32_t ordinal)
816{
bac542e6 817 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
818 static const char* (*p)(NSObjectFileImage, uint32_t) = NULL;
819
820 if(p == NULL)
821 _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p);
822
823 return p(objectFileImage, ordinal);
824}
825
826/*
827 * NSSymbolReferenceCountInObjectFileImage() returns the number of references
828 * to undefined symbols the NSObjectFileImage.
829 */
830uint32_t
831NSSymbolReferenceCountInObjectFileImage(
832NSObjectFileImage objectFileImage)
833{
bac542e6 834 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
835 static unsigned long (*p)(NSObjectFileImage) = NULL;
836
837 if(p == NULL)
838 _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p);
839
840 return p(objectFileImage);
841}
842
843/*
844 * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
845 * undefined symbol in the NSObjectFileImage. If the ordinal specified is
846 * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
847 * returned.
848 */
849const char*
850NSSymbolReferenceNameInObjectFileImage(
851NSObjectFileImage objectFileImage,
852uint32_t ordinal,
853bool *tentative_definition) /* can be NULL */
854{
bac542e6 855 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
856 static const char* (*p)(NSObjectFileImage, uint32_t, bool*) = NULL;
857
858 if(p == NULL)
859 _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p);
860
861 return p(objectFileImage, ordinal, tentative_definition);
862}
863
864/*
865 * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
866 * name has a definition in the NSObjectFileImage and FALSE otherwise.
867 */
868bool
869NSIsSymbolDefinedInObjectFileImage(
870NSObjectFileImage objectFileImage,
871const char* symbolName)
872{
bac542e6 873 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
874 static bool (*p)(NSObjectFileImage, const char*) = NULL;
875
876 if(p == NULL)
877 _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p);
878
879 return p(objectFileImage, symbolName);
880}
881
882/*
883 * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
884 * in the NSObjectFileImage for the specified segmentName and sectionName if
885 * it exists and it is not a zerofill section. If not it returns NULL. If
886 * the parameter size is not NULL the size of the section is also returned
887 * indirectly through that pointer.
888 */
889void *
890NSGetSectionDataInObjectFileImage(
891NSObjectFileImage objectFileImage,
892const char* segmentName,
893const char* sectionName,
894unsigned long *size) /* can be NULL */
895{
bac542e6 896 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
897 static void* (*p)(NSObjectFileImage, const char*, const char*, unsigned long*) = NULL;
898
899 if(p == NULL)
900 _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p);
901
902 return p(objectFileImage, segmentName, sectionName, size);
903}
904
0959b6d4
A
905
906void
907NSLinkEditError(
908NSLinkEditErrors *c,
909int *errorNumber,
910const char* *fileName,
911const char* *errorString)
912{
bac542e6 913 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
914 static void (*p)(NSLinkEditErrors *c,
915 int *errorNumber,
916 const char* *fileName,
917 const char* *errorString) = NULL;
918
919 if(p == NULL)
920 _dyld_func_lookup("__dyld_link_edit_error", (void**)&p);
921 if(p != NULL)
922 p(c, errorNumber, fileName, errorString);
923}
924
925bool
926NSUnLinkModule(
927NSModule module,
928uint32_t options)
929{
bac542e6 930 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
931 static bool (*p)(NSModule module, uint32_t options) = NULL;
932
933 if(p == NULL)
934 _dyld_func_lookup("__dyld_unlink_module", (void**)&p);
935
936 return p(module, options);
937}
938
bac542e6 939#if OBSOLETE_DYLD_API
0959b6d4
A
940NSModule
941NSReplaceModule(
942NSModule moduleToReplace,
943NSObjectFileImage newObjectFileImage,
944uint32_t options)
945{
946 return(NULL);
947}
bac542e6 948#endif
0959b6d4 949
39a8cd10
A
950
951#endif // DEPRECATED_APIS_SUPPORTED
952
0959b6d4
A
953/*
954 *_NSGetExecutablePath copies the path of the executable into the buffer and
955 * returns 0 if the path was successfully copied in the provided buffer. If the
956 * buffer is not large enough, -1 is returned and the expected buffer size is
957 * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
958 * the executable not a "real path" to the executable. That is the path may be
959 * a symbolic link and not the real file. And with deep directories the total
960 * bufsize needed could be more than MAXPATHLEN.
961 */
962int
963_NSGetExecutablePath(
964char *buf,
965uint32_t *bufsize)
966{
bac542e6 967 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
968 static int (*p)(char *buf, uint32_t *bufsize) = NULL;
969
970 if(p == NULL)
971 _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p);
972 return(p(buf, bufsize));
973}
974
39a8cd10 975#if DEPRECATED_APIS_SUPPORTED
0959b6d4
A
976void
977_dyld_lookup_and_bind(
978const char* symbol_name,
979void** address,
980NSModule* module)
981{
bac542e6 982 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
983 static void (*p)(const char*, void** , NSModule*) = NULL;
984
985 if(p == NULL)
986 _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p);
987 p(symbol_name, address, module);
988}
989
990void
991_dyld_lookup_and_bind_with_hint(
992const char* symbol_name,
993const char* library_name_hint,
994void** address,
995NSModule* module)
996{
bac542e6 997 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
998 static void (*p)(const char*, const char*, void**, NSModule*) = NULL;
999
1000 if(p == NULL)
1001 _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p);
1002 p(symbol_name, library_name_hint, address, module);
1003}
1004
bac542e6 1005#if OBSOLETE_DYLD_API
0959b6d4
A
1006void
1007_dyld_lookup_and_bind_objc(
1008const char* symbol_name,
1009void** address,
1010NSModule* module)
1011{
bac542e6 1012 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1013 static void (*p)(const char* , void**, NSModule*) = NULL;
1014
1015 if(p == NULL)
1016 _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p);
1017 p(symbol_name, address, module);
1018}
bac542e6 1019#endif
0959b6d4
A
1020
1021void
1022_dyld_lookup_and_bind_fully(
1023const char* symbol_name,
1024void** address,
1025NSModule* module)
1026{
bac542e6 1027 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1028 static void (*p)(const char*, void**, NSModule*) = NULL;
1029
1030 if(p == NULL)
1031 _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p);
1032 p(symbol_name, address, module);
1033}
1034
1035bool
1036_dyld_bind_fully_image_containing_address(
1037const void* address)
1038{
bac542e6 1039 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1040 static bool (*p)(const void*) = NULL;
1041
1042 if(p == NULL)
1043 _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p);
1044 return p(address);
1045}
39a8cd10 1046#endif // DEPRECATED_APIS_SUPPORTED
0959b6d4
A
1047
1048
1049/*
1050 * _dyld_register_func_for_add_image registers the specified function to be
1051 * called when a new image is added (a bundle or a dynamic shared library) to
1052 * the program. When this function is first registered it is called for once
1053 * for each image that is currently part of the program.
1054 */
1055void
1056_dyld_register_func_for_add_image(
1057void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
1058{
bac542e6 1059 DYLD_LOCK_THIS_BLOCK;
412ebb8e
A
1060 typedef void (*callback_t)(const struct mach_header *mh, intptr_t vmaddr_slide);
1061 static void (*p)(callback_t func) = NULL;
0959b6d4
A
1062
1063 if(p == NULL)
1064 _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p);
1065 p(func);
1066}
1067
1068/*
1069 * _dyld_register_func_for_remove_image registers the specified function to be
1070 * called when an image is removed (a bundle or a dynamic shared library) from
1071 * the program.
1072 */
1073void
1074_dyld_register_func_for_remove_image(
1075void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
1076{
bac542e6 1077 DYLD_LOCK_THIS_BLOCK;
412ebb8e
A
1078 typedef void (*callback_t)(const struct mach_header *mh, intptr_t vmaddr_slide);
1079 static void (*p)(callback_t func) = NULL;
0959b6d4
A
1080
1081 if(p == NULL)
1082 _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p);
1083 p(func);
1084}
1085
bac542e6 1086#if OBSOLETE_DYLD_API
0959b6d4
A
1087/*
1088 * _dyld_register_func_for_link_module registers the specified function to be
1089 * called when a module is bound into the program. When this function is first
1090 * registered it is called for once for each module that is currently bound into
1091 * the program.
1092 */
1093void
1094_dyld_register_func_for_link_module(
1095void (*func)(NSModule module))
1096{
bac542e6 1097 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1098 static void (*p)(void (*func)(NSModule module)) = NULL;
1099
1100 if(p == NULL)
1101 _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p);
1102 p(func);
1103}
1104
1105/*
1106 * _dyld_register_func_for_unlink_module registers the specified function to be
1107 * called when a module is unbound from the program.
1108 */
1109void
1110_dyld_register_func_for_unlink_module(
1111void (*func)(NSModule module))
1112{
bac542e6 1113 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1114 static void (*p)(void (*func)(NSModule module)) = NULL;
1115
1116 if(p == NULL)
1117 _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p);
1118 p(func);
1119}
1120
1121/*
1122 * _dyld_register_func_for_replace_module registers the specified function to be
1123 * called when a module is to be replace with another module in the program.
1124 */
1125void
1126_dyld_register_func_for_replace_module(
1127void (*func)(NSModule oldmodule, NSModule newmodule))
1128{
bac542e6 1129 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1130 static void (*p)(void (*func)(NSModule oldmodule,
1131 NSModule newmodule)) = NULL;
1132
1133 if(p == NULL)
1134 _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p);
1135 p(func);
1136}
1137
1138
1139/*
1140 * _dyld_get_objc_module_sect_for_module is passed a module and sets a
1141 * pointer to the (__OBJC,__module) section and its size for the specified
1142 * module.
1143 */
1144void
1145_dyld_get_objc_module_sect_for_module(
1146NSModule module,
1147void **objc_module,
1148unsigned long *size)
1149{
bac542e6 1150 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1151 static void (*p)(NSModule module,
1152 void **objc_module,
1153 unsigned long *size) = NULL;
1154
1155 if(p == NULL)
1156 _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p);
1157 p(module, objc_module, size);
1158}
1159
1160/*
1161 * _dyld_bind_objc_module() is passed a pointer to something in an (__OBJC,
1162 * __module) section and causes the module that is associated with that address
1163 * to be bound.
1164 */
1165void
bac542e6 1166_dyld_bind_objc_module(const void* objc_module)
0959b6d4 1167{
bac542e6 1168 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1169 static void (*p)(const void *objc_module) = NULL;
1170
1171 if(p == NULL)
1172 _dyld_func_lookup("__dyld_bind_objc_module", (void**)&p);
1173 p(objc_module);
1174}
bac542e6 1175#endif
0959b6d4 1176
39a8cd10 1177#if DEPRECATED_APIS_SUPPORTED
0959b6d4 1178bool
bac542e6 1179_dyld_present(void)
0959b6d4 1180{
bac542e6 1181 // this function exists for compatiblity only
0959b6d4
A
1182 return true;
1183}
39a8cd10 1184#endif
0959b6d4
A
1185
1186uint32_t
bac542e6 1187_dyld_image_count(void)
0959b6d4
A
1188{
1189 DYLD_NO_LOCK_THIS_BLOCK;
19894a12 1190 static uint32_t (*p)(void) = NULL;
0959b6d4 1191
0959b6d4
A
1192 if(p == NULL)
1193 _dyld_func_lookup("__dyld_image_count", (void**)&p);
1194 return(p());
1195}
1196
1197const struct mach_header *
bac542e6 1198_dyld_get_image_header(uint32_t image_index)
0959b6d4
A
1199{
1200 DYLD_NO_LOCK_THIS_BLOCK;
1201 static struct mach_header * (*p)(uint32_t image_index) = NULL;
1202
1203 if(p == NULL)
1204 _dyld_func_lookup("__dyld_get_image_header", (void**)&p);
1205 return(p(image_index));
1206}
1207
1208intptr_t
bac542e6 1209_dyld_get_image_vmaddr_slide(uint32_t image_index)
0959b6d4
A
1210{
1211 DYLD_NO_LOCK_THIS_BLOCK;
1212 static unsigned long (*p)(uint32_t image_index) = NULL;
1213
1214 if(p == NULL)
1215 _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p);
1216 return(p(image_index));
1217}
1218
1219const char*
bac542e6 1220_dyld_get_image_name(uint32_t image_index)
0959b6d4
A
1221{
1222 DYLD_NO_LOCK_THIS_BLOCK;
1223 static const char* (*p)(uint32_t image_index) = NULL;
1224
1225 if(p == NULL)
1226 _dyld_func_lookup("__dyld_get_image_name", (void**)&p);
1227 return(p(image_index));
1228}
1229
39a8cd10
A
1230// SPI in Mac OS X 10.6
1231intptr_t _dyld_get_image_slide(const struct mach_header* mh)
1232{
1233 DYLD_NO_LOCK_THIS_BLOCK;
1234 static intptr_t (*p)(const struct mach_header*) = NULL;
1235
1236 if(p == NULL)
1237 _dyld_func_lookup("__dyld_get_image_slide", (void**)&p);
1238 return(p(mh));
1239}
1240
1241
0959b6d4 1242bool
bac542e6 1243_dyld_image_containing_address(const void* address)
0959b6d4 1244{
bac542e6 1245 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1246 static bool (*p)(const void*) = NULL;
1247
1248 if(p == NULL)
1249 _dyld_func_lookup("__dyld_image_containing_address", (void**)&p);
1250 return(p(address));
1251}
1252
1253const struct mach_header *
1254_dyld_get_image_header_containing_address(
1255const void* address)
1256{
bac542e6 1257 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1258 static const struct mach_header * (*p)(const void*) = NULL;
1259
1260 if(p == NULL)
1261 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p);
1262 return p(address);
1263}
1264
0959b6d4 1265
39a8cd10 1266#if DEPRECATED_APIS_SUPPORTED
bac542e6 1267bool _dyld_launched_prebound(void)
0959b6d4 1268{
bac542e6 1269 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1270 static bool (*p)(void) = NULL;
1271
1272 if(p == NULL)
1273 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p);
1274 return(p());
1275}
1276
bac542e6 1277bool _dyld_all_twolevel_modules_prebound(void)
0959b6d4 1278{
bac542e6 1279 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1280 static bool (*p)(void) = NULL;
1281
1282 if(p == NULL)
1283 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p);
1284 return(p());
1285}
39a8cd10 1286#endif // DEPRECATED_APIS_SUPPORTED
0959b6d4
A
1287
1288
1289#include <dlfcn.h>
1290#include <stddef.h>
1291#include <pthread.h>
1292#include <stdlib.h>
1293#include <mach-o/dyld.h>
bac542e6
A
1294#include <servers/bootstrap.h>
1295#include "dyldLibSystemInterface.h"
bac542e6 1296
0959b6d4
A
1297
1298// pthread key used to access per-thread dlerror message
1299static pthread_key_t dlerrorPerThreadKey;
bac542e6 1300static bool dlerrorPerThreadKeyInitialized = false;
0959b6d4
A
1301
1302// data kept per-thread
1303struct dlerrorPerThreadData
1304{
19894a12 1305 size_t sizeAllocated;
0959b6d4
A
1306 char message[1];
1307};
1308
1309// function called by dyld to get buffer to store dlerror message
19894a12 1310static char* getPerThreadBufferFor_dlerror(size_t sizeRequired)
0959b6d4 1311{
bac542e6
A
1312 // ok to create key lazily because this function is called within dyld lock, so there is no race condition
1313 if (!dlerrorPerThreadKeyInitialized ) {
1314 // create key and tell pthread package to call free() on any data associated with key if thread dies
1315 pthread_key_create(&dlerrorPerThreadKey, &free);
1316 dlerrorPerThreadKeyInitialized = true;
1317 }
1318
19894a12 1319 const size_t size = (sizeRequired < 256) ? 256 : sizeRequired;
0959b6d4
A
1320 dlerrorPerThreadData* data = (dlerrorPerThreadData*)pthread_getspecific(dlerrorPerThreadKey);
1321 if ( data == NULL ) {
1322 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
19894a12 1323 const size_t mallocSize = sizeof(dlerrorPerThreadData)+size;
0959b6d4
A
1324 data = (dlerrorPerThreadData*)malloc(mallocSize);
1325 data->sizeAllocated = size;
1326 pthread_setspecific(dlerrorPerThreadKey, data);
1327 }
1328 else if ( data->sizeAllocated < sizeRequired ) {
1329 free(data);
1330 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
19894a12 1331 const size_t mallocSize = sizeof(dlerrorPerThreadData)+size;
0959b6d4
A
1332 data = (dlerrorPerThreadData*)malloc(mallocSize);
1333 data->sizeAllocated = size;
1334 pthread_setspecific(dlerrorPerThreadKey, data);
1335 }
1336 return data->message;
1337}
1338
2fd3f4e8
A
1339// <rdar://problem/10595338> dlerror buffer leak
1340// Only allocate buffer if an actual error message needs to be set
1341static bool hasPerThreadBufferFor_dlerror()
1342{
1343 if (!dlerrorPerThreadKeyInitialized )
1344 return false;
1345
1346 return (pthread_getspecific(dlerrorPerThreadKey) != NULL);
1347}
1348
1349// use non-lazy pointer to vproc_swap_integer so that lazy binding does not recurse
1350typedef vproc_err_t (*vswapproc)(vproc_t vp, vproc_gsk_t key,int64_t *inval, int64_t *outval);
1351static vswapproc swapProc = &vproc_swap_integer;
1352
1353static bool isLaunchdOwned() {
1354 static bool first = true;
1355 static bool result;
1356 if ( first ) {
1357 int64_t val = 0;
1358 (*swapProc)(NULL, VPROC_GSK_IS_MANAGED, NULL, &val);
1359 result = ( val != 0 );
1360 first = false;
1361 }
1362 return result;
1363}
1364
bac542e6 1365
39a8cd10 1366#if DYLD_SHARED_CACHE_SUPPORT
bac542e6
A
1367static void shared_cache_missing()
1368{
39a8cd10 1369 // leave until dyld's that might call this are rare
bac542e6
A
1370}
1371
1372static void shared_cache_out_of_date()
1373{
39a8cd10 1374 // leave until dyld's that might call this are rare
bac542e6 1375}
39a8cd10 1376#endif // DYLD_SHARED_CACHE_SUPPORT
bac542e6
A
1377
1378
39a8cd10 1379// the table passed to dyld containing thread helpers
19894a12 1380static dyld::LibSystemHelpers sHelpers = { 13, &dyldGlobalLockAcquire, &dyldGlobalLockRelease,
bac542e6 1381 &getPerThreadBufferFor_dlerror, &malloc, &free, &__cxa_atexit,
39a8cd10 1382 #if DYLD_SHARED_CACHE_SUPPORT
bac542e6 1383 &shared_cache_missing, &shared_cache_out_of_date,
39a8cd10
A
1384 #else
1385 NULL, NULL,
1386 #endif
1387 NULL, NULL,
1388 &pthread_key_create, &pthread_setspecific,
412ebb8e
A
1389 &malloc_size,
1390 &pthread_getspecific,
832b6fce 1391 &__cxa_finalize,
2fd3f4e8
A
1392 address_of_start,
1393 &hasPerThreadBufferFor_dlerror,
1394 &isLaunchdOwned,
1395 &vm_allocate,
19894a12
A
1396 &mmap,
1397 &__cxa_finalize_ranges};
bac542e6 1398
0959b6d4
A
1399
1400//
1401// during initialization of libSystem this routine will run
bac542e6 1402// and call dyld, registering the helper functions.
0959b6d4 1403//
412ebb8e
A
1404extern "C" void tlv_initializer();
1405extern "C" void _dyld_initializer();
bac542e6 1406void _dyld_initializer()
2fd3f4e8 1407{
bac542e6
A
1408 void (*p)(dyld::LibSystemHelpers*);
1409
1410 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p);
0959b6d4 1411 if(p != NULL)
bac542e6 1412 p(&sHelpers);
412ebb8e
A
1413
1414 tlv_initializer();
0959b6d4
A
1415}
1416
0959b6d4
A
1417
1418char* dlerror()
1419{
bac542e6 1420 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1421 static char* (*p)() = NULL;
1422
1423 if(p == NULL)
1424 _dyld_func_lookup("__dyld_dlerror", (void**)&p);
1425 return(p());
1426}
1427
1428int dladdr(const void* addr, Dl_info* info)
1429{
bac542e6 1430 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1431 static int (*p)(const void* , Dl_info*) = NULL;
1432
1433 if(p == NULL)
1434 _dyld_func_lookup("__dyld_dladdr", (void**)&p);
1435 return(p(addr, info));
1436}
1437
1438int dlclose(void* handle)
1439{
bac542e6 1440 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1441 static int (*p)(void* handle) = NULL;
1442
1443 if(p == NULL)
1444 _dyld_func_lookup("__dyld_dlclose", (void**)&p);
1445 return(p(handle));
1446}
1447
1448void* dlopen(const char* path, int mode)
bac542e6
A
1449{
1450 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1451 DYLD_NO_LOCK_THIS_BLOCK;
1452
0959b6d4
A
1453 static void* (*p)(const char* path, int) = NULL;
1454
1455 if(p == NULL)
1456 _dyld_func_lookup("__dyld_dlopen", (void**)&p);
bac542e6
A
1457 void* result = p(path, mode);
1458 // use asm block to prevent tail call optimization
1459 // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain
1460 // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash>
1461 __asm__ volatile("");
1462
1463 return result;
1464}
1465
1466bool dlopen_preflight(const char* path)
1467{
1468 DYLD_LOCK_THIS_BLOCK;
1469 static bool (*p)(const char* path) = NULL;
1470
1471 if(p == NULL)
1472 _dyld_func_lookup("__dyld_dlopen_preflight", (void**)&p);
1473 return(p(path));
0959b6d4
A
1474}
1475
1476void* dlsym(void* handle, const char* symbol)
1477{
bac542e6 1478 DYLD_LOCK_THIS_BLOCK;
0959b6d4
A
1479 static void* (*p)(void* handle, const char* symbol) = NULL;
1480
1481 if(p == NULL)
1482 _dyld_func_lookup("__dyld_dlsym", (void**)&p);
1483 return(p(handle, symbol));
1484}
1485
bac542e6
A
1486void dyld_register_image_state_change_handler(dyld_image_states state,
1487 bool batch, dyld_image_state_change_handler handler)
1488{
1489 DYLD_LOCK_THIS_BLOCK;
1490 static void* (*p)(dyld_image_states, bool, dyld_image_state_change_handler) = NULL;
1491
1492 if(p == NULL)
1493 _dyld_func_lookup("__dyld_dyld_register_image_state_change_handler", (void**)&p);
1494 p(state, batch, handler);
1495}
1496
0959b6d4 1497
39a8cd10
A
1498const struct dyld_all_image_infos* _dyld_get_all_image_infos()
1499{
1500 DYLD_NO_LOCK_THIS_BLOCK;
1501 static struct dyld_all_image_infos* (*p)() = NULL;
1502
1503 if(p == NULL)
1504 _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p);
1505 return p();
1506}
1507
19894a12 1508#if SUPPORT_ZERO_COST_EXCEPTIONS
39a8cd10
A
1509bool _dyld_find_unwind_sections(void* addr, dyld_unwind_sections* info)
1510{
1511 DYLD_NO_LOCK_THIS_BLOCK;
1512 static void* (*p)(void*, dyld_unwind_sections*) = NULL;
1513
1514 if(p == NULL)
1515 _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p);
1516 return p(addr, info);
1517}
1518#endif
1519
1520
19894a12 1521#if __i386__ || __x86_64__ || __arm__ || __arm64__
39a8cd10
A
1522__attribute__((visibility("hidden")))
1523void* _dyld_fast_stub_entry(void* loadercache, long lazyinfo)
1524{
1525 DYLD_NO_LOCK_THIS_BLOCK;
1526 static void* (*p)(void*, long) = NULL;
1527
1528 if(p == NULL)
1529 _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p);
1530 return p(loadercache, lazyinfo);
1531}
1532#endif
1533
1534
1535const char* dyld_image_path_containing_address(const void* addr)
1536{
1537 DYLD_NO_LOCK_THIS_BLOCK;
1538 static const char* (*p)(const void*) = NULL;
0959b6d4 1539
39a8cd10
A
1540 if(p == NULL)
1541 _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p);
1542 return p(addr);
1543}
0959b6d4 1544
df9d6cf7
A
1545const struct mach_header* dyld_image_header_containing_address(const void* addr)
1546{
1547 DYLD_NO_LOCK_THIS_BLOCK;
1548 static const mach_header* (*p)(const void*) = NULL;
1549
1550 if(p == NULL)
1551 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p);
1552 return p(addr);
1553}
1554
1555
412ebb8e
A
1556bool dyld_shared_cache_some_image_overridden()
1557{
1558 DYLD_NO_LOCK_THIS_BLOCK;
1559 static bool (*p)() = NULL;
1560
1561 if(p == NULL)
1562 _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p);
1563 return p();
1564}
412ebb8e
A
1565
1566
2fd3f4e8
A
1567bool dyld_process_is_restricted()
1568{
1569 DYLD_NO_LOCK_THIS_BLOCK;
1570 static bool (*p)() = NULL;
1571
1572 if(p == NULL)
1573 _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p);
1574 return p();
1575}
1576
df9d6cf7
A
1577#if DYLD_SHARED_CACHE_SUPPORT
1578const char* dyld_shared_cache_file_path()
1579{
1580 DYLD_NO_LOCK_THIS_BLOCK;
1581 static const char* (*p)() = NULL;
1582
1583 if(p == NULL)
1584 _dyld_func_lookup("__dyld_shared_cache_file_path", (void**)&p);
1585 return p();
1586}
1587#endif
2fd3f4e8 1588
19894a12
A
1589void dyld_dynamic_interpose(const struct mach_header* mh, const struct dyld_interpose_tuple array[], size_t count)
1590{
1591 DYLD_LOCK_THIS_BLOCK;
1592 static void (*p)(const struct mach_header* mh, const struct dyld_interpose_tuple array[], size_t count) = NULL;
1593
1594 if (p == NULL)
1595 _dyld_func_lookup("__dyld_dynamic_interpose", (void**)&p);
1596 p(mh, array, count);
1597}
2fd3f4e8
A
1598
1599
412ebb8e
A
1600// SPI called __fork
1601void _dyld_fork_child()
1602{
1603 DYLD_NO_LOCK_THIS_BLOCK;
1604 static void (*p)() = NULL;
1605
1606 if(p == NULL)
1607 _dyld_func_lookup("__dyld_fork_child", (void**)&p);
1608 return p();
1609}
1610
1611
1612
0959b6d4 1613