]> git.saurik.com Git - apple/dyld.git/blob - dyld3/APIs_macOS.cpp
dyld-851.27.tar.gz
[apple/dyld.git] / dyld3 / APIs_macOS.cpp
1 /*
2 * Copyright (c) 2017 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
24
25 #include <string.h>
26 #include <stdio.h>
27 #include <stdint.h>
28 #include <_simple.h>
29 #include <sys/errno.h>
30 #include <sys/mman.h>
31 #include <sys/stat.h>
32 #include <dirent.h>
33 #include <fcntl.h>
34 #include <TargetConditionals.h>
35 #include <malloc/malloc.h>
36 #include <mach-o/dyld_priv.h>
37 #include <mach-o/dyld_images.h>
38
39 #include <algorithm>
40
41 #if __has_feature(ptrauth_calls)
42 #include <ptrauth.h>
43 #endif
44
45 #include "dlfcn.h"
46
47 #include "AllImages.h"
48 #include "Loading.h"
49 #include "Logging.h"
50 #include "Diagnostics.h"
51 #include "DyldSharedCache.h"
52 #include "APIs.h"
53
54
55 namespace dyld3 {
56
57 // from APIs.cpp
58 void parseDlHandle(void* h, const MachOLoaded** mh, bool* dontContinue);
59
60
61 // only in macOS and deprecated
62 #if TARGET_OS_OSX
63
64 // macOS needs to support an old API that only works with fileype==MH_BUNDLE.
65 // In this deprecated API (unlike dlopen), loading and linking are separate steps.
66 // NSCreateObjectFileImageFrom*() just maps in the bundle mach-o file.
67 // NSLinkModule() does the load of dependent modules and rebasing/binding.
68 // To unload one of these, you must call NSUnLinkModule() and NSDestroyObjectFileImage() in any order!
69 //
70
71 NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(const char* path, NSObjectFileImage* ofi)
72 {
73 log_apis("NSCreateObjectFileImageFromFile(\"%s\", %p)\n", path, ofi);
74
75 // verify path exists
76 struct stat statbuf;
77 if ( dyld3::stat(path, &statbuf) == -1 )
78 return NSObjectFileImageFailure;
79
80 // create ofi that just contains path. NSLinkModule does all the work
81 OFIInfo result;
82 result.path = strdup(path);
83 result.memSource = nullptr;
84 result.memLength = 0;
85 result.loadAddress = nullptr;
86 result.imageNum = 0;
87 *ofi = gAllImages.addNSObjectFileImage(result);
88
89 log_apis("NSCreateObjectFileImageFromFile() => %p\n", *ofi);
90
91 return NSObjectFileImageSuccess;
92 }
93
94 NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(const void* memImage, size_t memImageSize, NSObjectFileImage *ofi)
95 {
96 log_apis("NSCreateObjectFileImageFromMemory(%p, 0x%0lX, %p)\n", memImage, memImageSize, ofi);
97
98 // sanity check the buffer is a mach-o file
99 __block Diagnostics diag;
100
101 // check if it is current arch mach-o or fat with slice for current arch
102 bool usable = false;
103 const MachOFile* mf = (MachOFile*)memImage;
104 if ( mf->hasMachOMagic() && mf->isMachO(diag, memImageSize) ) {
105 usable = (gAllImages.archs().grade(mf->cputype, mf->cpusubtype, false) != 0);
106 }
107 else if ( const FatFile* ff = FatFile::isFatFile(memImage) ) {
108 uint64_t sliceOffset;
109 uint64_t sliceLen;
110 bool missingSlice;
111 if ( ff->isFatFileWithSlice(diag, memImageSize, gAllImages.archs(), false, sliceOffset, sliceLen, missingSlice) ) {
112 mf = (MachOFile*)((long)memImage+sliceOffset);
113 if ( mf->isMachO(diag, sliceLen) ) {
114 usable = true;
115 }
116 }
117 }
118 if ( usable ) {
119 if ( !mf->builtForPlatform(Platform::macOS) )
120 usable = false;
121 }
122 if ( !usable ) {
123 log_apis("NSCreateObjectFileImageFromMemory() not mach-o\n");
124 return NSObjectFileImageFailure;
125 }
126
127 // this API can only be used with bundles
128 if ( !mf->isBundle() ) {
129 log_apis("NSCreateObjectFileImageFromMemory() not a bundle\n");
130 return NSObjectFileImageInappropriateFile;
131 }
132
133 // allocate ofi that just lists the memory range
134 OFIInfo result;
135 result.path = nullptr;
136 result.memSource = memImage;
137 result.memLength = memImageSize;
138 result.loadAddress = nullptr;
139 result.imageNum = 0;
140 *ofi = gAllImages.addNSObjectFileImage(result);
141
142 log_apis("NSCreateObjectFileImageFromMemory() => %p\n", *ofi);
143
144 return NSObjectFileImageSuccess;
145 }
146
147 NSModule NSLinkModule(NSObjectFileImage ofi, const char* moduleName, uint32_t options)
148 {
149 DYLD_LOAD_LOCK_THIS_BLOCK
150 log_apis("NSLinkModule(%p, \"%s\", 0x%08X)\n", ofi, moduleName, options);
151
152 __block const char* path = nullptr;
153 bool foundImage = gAllImages.forNSObjectFileImage(ofi, ^(OFIInfo &image) {
154 // if this is memory based image, write to temp file, then use file based loading
155 if ( image.memSource != nullptr ) {
156 // make temp file with content of memory buffer
157 image.path = nullptr;
158 char tempFileName[PATH_MAX];
159 const char* tmpDir = getenv("TMPDIR");
160 if ( (tmpDir != nullptr) && (strlen(tmpDir) > 2) ) {
161 strlcpy(tempFileName, tmpDir, PATH_MAX);
162 if ( tmpDir[strlen(tmpDir)-1] != '/' )
163 strlcat(tempFileName, "/", PATH_MAX);
164 }
165 else
166 strlcpy(tempFileName,"/tmp/", PATH_MAX);
167 strlcat(tempFileName, "NSCreateObjectFileImageFromMemory-XXXXXXXX", PATH_MAX);
168 int fd = ::mkstemp(tempFileName);
169 if ( fd != -1 ) {
170 ssize_t writtenSize = ::pwrite(fd, image.memSource, image.memLength, 0);
171 if ( writtenSize == image.memLength ) {
172 image.path = strdup(tempFileName);
173 }
174 else {
175 log_apis("NSLinkModule() => NULL (could not save memory image to temp file)\n");
176 }
177 ::close(fd);
178 }
179 }
180 path = image.path;
181 });
182
183 if (!foundImage) {
184 // ofi is invalid if not in list
185 log_apis("NSLinkModule() => NULL (invalid NSObjectFileImage)\n");
186 return nullptr;
187 }
188
189 if (!path)
190 return nullptr;
191
192 // dlopen the binary outside of the read lock as we don't want to risk deadlock
193 Diagnostics diag;
194 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
195 const MachOLoaded* loadAddress = gAllImages.dlopen(diag, path, false, false, false, false, true, callerAddress);
196 if ( diag.hasError() ) {
197 log_apis(" NSLinkModule: failed: %s\n", diag.errorMessage());
198 return nullptr;
199 }
200
201 // Now update the load address of this object
202 gAllImages.forNSObjectFileImage(ofi, ^(OFIInfo &image) {
203 image.loadAddress = loadAddress;
204
205 // if memory based load, delete temp file
206 if ( image.memSource != nullptr ) {
207 log_apis(" NSLinkModule: delete temp file: %s\n", image.path);
208 ::unlink(image.path);
209 }
210 });
211
212 log_apis("NSLinkModule() => %p\n", loadAddress);
213 return (NSModule)loadAddress;
214 }
215
216 // NSUnLinkModule unmaps the image, but does not release the NSObjectFileImage
217 bool NSUnLinkModule(NSModule module, uint32_t options)
218 {
219 DYLD_LOAD_LOCK_THIS_BLOCK
220 log_apis("NSUnLinkModule(%p, 0x%08X)\n", module, options);
221
222 __block const mach_header* mh = nullptr;
223 gAllImages.infoForImageMappedAt(module, ^(const LoadedImage& foundImage, uint8_t permissions) {
224 mh = foundImage.loadedAddress();
225 });
226
227 if ( mh != nullptr )
228 gAllImages.decRefCount(mh); // removes image if reference count went to zero
229
230 log_apis("NSUnLinkModule() => %d\n", mh != nullptr);
231
232 return mh != nullptr;
233 }
234
235 // NSDestroyObjectFileImage releases the NSObjectFileImage, but the mapped image may remain in use
236 bool NSDestroyObjectFileImage(NSObjectFileImage imageHandle)
237 {
238 log_apis("NSDestroyObjectFileImage(%p)\n", imageHandle);
239
240 __block const void* memSource = nullptr;
241 __block size_t memLength = 0;
242 __block const char* path = nullptr;
243 bool foundImage = gAllImages.forNSObjectFileImage(imageHandle, ^(OFIInfo &image) {
244 // keep copy of info
245 memSource = image.memSource;
246 memLength = image.memLength;
247 path = image.path;
248 });
249
250 if (!foundImage)
251 return false;
252
253 // remove from list
254 gAllImages.removeNSObjectFileImage(imageHandle);
255
256 // if object was created from a memory, release that memory
257 // NOTE: this is the way dyld has always done this. NSCreateObjectFileImageFromMemory() hands ownership of the memory to dyld
258 if ( memSource != nullptr ) {
259 // we don't know if memory came from malloc or vm_allocate, so ask malloc
260 if ( malloc_size(memSource) != 0 )
261 free((void*)(memSource));
262 else
263 vm_deallocate(mach_task_self(), (vm_address_t)memSource, memLength);
264 }
265 free((void*)path);
266
267 return true;
268 }
269
270 uint32_t NSSymbolDefinitionCountInObjectFileImage(NSObjectFileImage objectFileImage)
271 {
272 halt("NSSymbolDefinitionCountInObjectFileImage() is obsolete");
273 }
274
275 const char* NSSymbolDefinitionNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal)
276 {
277 halt("NSSymbolDefinitionNameInObjectFileImage() is obsolete");
278 }
279
280 uint32_t NSSymbolReferenceCountInObjectFileImage(NSObjectFileImage objectFileImage)
281 {
282 halt("NSSymbolReferenceCountInObjectFileImage() is obsolete");
283 }
284
285 const char* NSSymbolReferenceNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal, bool *tentative_definition)
286 {
287 halt("NSSymbolReferenceNameInObjectFileImage() is obsolete");
288 }
289
290 bool NSIsSymbolDefinedInObjectFileImage(NSObjectFileImage imageHandle, const char* symbolName)
291 {
292 log_apis("NSIsSymbolDefinedInObjectFileImage(%p, %s)\n", imageHandle, symbolName);
293
294 __block bool hasSymbol = false;
295 bool foundImage = gAllImages.forNSObjectFileImage(imageHandle, ^(OFIInfo &image) {
296 void* addr;
297 bool resultPointsToInstructions = false;
298 hasSymbol = image.loadAddress->hasExportedSymbol(symbolName, nullptr, &addr, &resultPointsToInstructions);
299 });
300
301 // ofi is invalid if not in list
302 if (!foundImage)
303 return false;
304
305 return hasSymbol;
306 }
307
308 void* NSGetSectionDataInObjectFileImage(NSObjectFileImage imageHandle, const char* segmentName, const char* sectionName, size_t* size)
309 {
310 __block const void* result = nullptr;
311 bool foundImage = gAllImages.forNSObjectFileImage(imageHandle, ^(OFIInfo &image) {
312 uint64_t sz;
313 result = image.loadAddress->findSectionContent(segmentName, sectionName, sz);
314 *size = (size_t)sz;
315 });
316
317 // ofi is invalid if not in list
318 if (!foundImage)
319 return nullptr;
320
321 return (void*)result;
322 }
323
324 const char* NSNameOfModule(NSModule m)
325 {
326 log_apis("NSNameOfModule(%p)\n", m);
327
328 __block const char* result = nullptr;
329 gAllImages.infoForImageMappedAt(m, ^(const LoadedImage& foundImage, uint8_t permissions) {
330 result = gAllImages.imagePath(foundImage.image());
331 });
332
333 return result;
334 }
335
336 const char* NSLibraryNameForModule(NSModule m)
337 {
338 log_apis("NSLibraryNameForModule(%p)\n", m);
339
340 __block const char* result = nullptr;
341 gAllImages.infoForImageMappedAt(m, ^(const LoadedImage& foundImage, uint8_t permissions) {
342 result = gAllImages.imagePath(foundImage.image());
343 });
344 return result;
345 }
346
347
348 static bool flatFindSymbol(const char* symbolName, void** symbolAddress, const mach_header** foundInImageAtLoadAddress)
349 {
350 // <rdar://problem/59265987> allow flat lookup to find "_memcpy" even though it is not implemented as that name in any dylib
351 MachOLoaded::DependentToMachOLoaded finder = ^(const MachOLoaded* mh, uint32_t depIndex) {
352 return gAllImages.findDependent(mh, depIndex);
353 };
354
355 __block bool result = false;
356 gAllImages.forEachImage(^(const LoadedImage& loadedImage, bool& stop) {
357 bool resultPointsToInstructions = false;
358 if ( loadedImage.loadedAddress()->hasExportedSymbol(symbolName, finder, symbolAddress, &resultPointsToInstructions) ) {
359 *foundInImageAtLoadAddress = loadedImage.loadedAddress();
360 stop = true;
361 result = true;
362 }
363 });
364 return result;
365 }
366
367 bool NSIsSymbolNameDefined(const char* symbolName)
368 {
369 log_apis("NSIsSymbolNameDefined(%s)\n", symbolName);
370
371 const mach_header* foundInImageAtLoadAddress;
372 void* address;
373 return flatFindSymbol(symbolName, &address, &foundInImageAtLoadAddress);
374 }
375
376 bool NSIsSymbolNameDefinedWithHint(const char* symbolName, const char* libraryNameHint)
377 {
378 log_apis("NSIsSymbolNameDefinedWithHint(%s, %s)\n", symbolName, libraryNameHint);
379
380 const mach_header* foundInImageAtLoadAddress;
381 void* address;
382 return flatFindSymbol(symbolName, &address, &foundInImageAtLoadAddress);
383 }
384
385 bool NSIsSymbolNameDefinedInImage(const struct mach_header* mh, const char* symbolName)
386 {
387 log_apis("NSIsSymbolNameDefinedInImage(%p, %s)\n", mh, symbolName);
388
389 void* addr;
390 bool resultPointsToInstructions = false;
391 return ((MachOLoaded*)mh)->hasExportedSymbol(symbolName, nullptr, &addr, &resultPointsToInstructions);
392 }
393
394 NSSymbol NSLookupAndBindSymbol(const char* symbolName)
395 {
396 log_apis("NSLookupAndBindSymbol(%s)\n", symbolName);
397
398 const mach_header* foundInImageAtLoadAddress;
399 void* symbolAddress;
400 if ( flatFindSymbol(symbolName, &symbolAddress, &foundInImageAtLoadAddress) ) {
401 return (NSSymbol)symbolAddress;
402 }
403 return nullptr;
404 }
405
406 NSSymbol NSLookupAndBindSymbolWithHint(const char* symbolName, const char* libraryNameHint)
407 {
408 log_apis("NSLookupAndBindSymbolWithHint(%s, %s)\n", symbolName, libraryNameHint);
409
410 const mach_header* foundInImageAtLoadAddress;
411 void* symbolAddress;
412 if ( flatFindSymbol(symbolName, &symbolAddress, &foundInImageAtLoadAddress) ) {
413 return (NSSymbol)symbolAddress;
414 }
415 return nullptr;
416 }
417
418 NSSymbol NSLookupSymbolInModule(NSModule module, const char* symbolName)
419 {
420 log_apis("NSLookupSymbolInModule(%p. %s)\n", module, symbolName);
421
422 const MachOLoaded* mh = (const MachOLoaded*)module;
423 void* addr;
424 bool resultPointsToInstructions = false;
425 if ( mh->hasExportedSymbol(symbolName, nullptr, &addr, &resultPointsToInstructions) ) {
426 return (NSSymbol)addr;
427 }
428 return nullptr;
429 }
430
431 NSSymbol NSLookupSymbolInImage(const mach_header* mh, const char* symbolName, uint32_t options)
432 {
433 log_apis("NSLookupSymbolInImage(%p, \"%s\", 0x%08X)\n", mh, symbolName, options);
434
435 void* addr;
436 bool resultPointsToInstructions = false;
437 if ( ((MachOLoaded*)mh)->hasExportedSymbol(symbolName, nullptr, &addr, &resultPointsToInstructions) ) {
438 log_apis(" NSLookupSymbolInImage() => %p\n", addr);
439 return (NSSymbol)addr;
440 }
441 if ( options & NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR ) {
442 log_apis(" NSLookupSymbolInImage() => NULL\n");
443 return nullptr;
444 }
445 // FIXME: abort();
446 return nullptr;
447 }
448
449 const char* NSNameOfSymbol(NSSymbol symbol)
450 {
451 halt("NSNameOfSymbol() is obsolete");
452 }
453
454 void* NSAddressOfSymbol(NSSymbol symbol)
455 {
456 log_apis("NSAddressOfSymbol(%p)\n", symbol);
457
458 if ( symbol == nullptr )
459 return nullptr;
460
461 // in dyld 1.0, NSSymbol was a pointer to the nlist entry in the symbol table
462 void *result = (void*)symbol;
463
464 #if __has_feature(ptrauth_calls)
465 __block const MachOLoaded *module = nullptr;
466 gAllImages.infoForImageMappedAt(symbol, ^(const LoadedImage& foundImage, uint8_t permissions) {
467 module = foundImage.loadedAddress();
468 });
469
470 int64_t slide = module->getSlide();
471 __block bool resultPointsToInstructions = false;
472 module->forEachSection(^(const MachOAnalyzer::SectionInfo& sectInfo, bool malformedSectionRange, bool& stop) {
473 uint64_t sectStartAddr = sectInfo.sectAddr + slide;
474 uint64_t sectEndAddr = sectStartAddr + sectInfo.sectSize;
475 if ( ((uint64_t)result >= sectStartAddr) && ((uint64_t)result < sectEndAddr) ) {
476 resultPointsToInstructions = (sectInfo.sectFlags & S_ATTR_PURE_INSTRUCTIONS) || (sectInfo.sectFlags & S_ATTR_SOME_INSTRUCTIONS);
477 stop = true;
478 }
479 });
480
481 if (resultPointsToInstructions) {
482 result = __builtin_ptrauth_sign_unauthenticated(result, ptrauth_key_asia, 0);
483 }
484 #endif
485
486 return result;
487 }
488
489 NSModule NSModuleForSymbol(NSSymbol symbol)
490 {
491 log_apis("NSModuleForSymbol(%p)\n", symbol);
492
493 __block NSModule result = nullptr;
494 gAllImages.infoForImageMappedAt(symbol, ^(const LoadedImage& foundImage, uint8_t permissions) {
495 result = (NSModule)foundImage.loadedAddress();
496 });
497
498 return result;
499 }
500
501 void NSLinkEditError(NSLinkEditErrors *c, int *errorNumber, const char** fileName, const char** errorString)
502 {
503 log_apis("NSLinkEditError(%p, %p, %p, %p)\n", c, errorNumber, fileName, errorString);
504 *c = NSLinkEditOtherError;
505 *errorNumber = 0;
506 *fileName = NULL;
507 *errorString = NULL;
508 }
509
510 bool NSAddLibrary(const char* pathName)
511 {
512 log_apis("NSAddLibrary(%s)\n", pathName);
513
514 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
515 return ( dlopen_internal(pathName, 0, callerAddress) != nullptr);
516 }
517
518 bool NSAddLibraryWithSearching(const char* pathName)
519 {
520 log_apis("NSAddLibraryWithSearching(%s)\n", pathName);
521
522 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
523 return ( dlopen_internal(pathName, 0, callerAddress) != nullptr);
524 }
525
526 const mach_header* NSAddImage(const char* imageName, uint32_t options)
527 {
528 log_apis("NSAddImage(\"%s\", 0x%08X)\n", imageName, options);
529
530 // Note: this is a quick and dirty implementation that just uses dlopen() and ignores some option flags
531 uint32_t dloptions = 0;
532 if ( (options & NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED) != 0 )
533 dloptions |= RTLD_NOLOAD;
534
535 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
536 void* h = dlopen_internal(imageName, dloptions, callerAddress);
537 if ( h != nullptr ) {
538 const MachOLoaded* mh;
539 bool dontContinue;
540 parseDlHandle(h, &mh, &dontContinue);
541 return mh;
542 }
543
544 if ( (options & (NSADDIMAGE_OPTION_RETURN_ON_ERROR|NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED)) == 0 ) {
545 halt("NSAddImage() image not found");
546 }
547 return nullptr;
548 }
549
550 void NSInstallLinkEditErrorHandlers(const NSLinkEditErrorHandlers *handlers)
551 {
552 halt("NSInstallLinkEditErrorHandlers() is obsolete");
553 }
554
555 bool _dyld_present(void)
556 {
557 log_apis("_dyld_present()\n");
558
559 return true;
560 }
561
562 bool _dyld_launched_prebound(void)
563 {
564 halt("_dyld_launched_prebound() is obsolete");
565 }
566
567 bool _dyld_all_twolevel_modules_prebound(void)
568 {
569 halt("_dyld_all_twolevel_modules_prebound() is obsolete");
570 }
571
572 bool _dyld_bind_fully_image_containing_address(const void* address)
573 {
574 log_apis("_dyld_bind_fully_image_containing_address(%p)\n", address);
575
576 // in dyld3, everything is always fully bound
577 return true;
578 }
579
580 bool _dyld_image_containing_address(const void* address)
581 {
582 log_apis("_dyld_image_containing_address(%p)\n", address);
583
584 return (dyld_image_header_containing_address(address) != nullptr);
585 }
586
587 void _dyld_lookup_and_bind(const char* symbolName, void **address, NSModule* module)
588 {
589 log_apis("_dyld_lookup_and_bind(%s, %p, %p)\n", symbolName, address, module);
590
591 const mach_header* foundInImageAtLoadAddress;
592 if ( flatFindSymbol(symbolName, address, &foundInImageAtLoadAddress) ) {
593 *module = (NSModule)foundInImageAtLoadAddress;
594 return;
595 }
596
597 *address = 0;
598 *module = 0;
599 }
600
601 void _dyld_lookup_and_bind_with_hint(const char* symbolName, const char* libraryNameHint, void** address, NSModule* module)
602 {
603 log_apis("_dyld_lookup_and_bind_with_hint(%s, %s, %p, %p)\n", symbolName, libraryNameHint, address, module);
604
605 const mach_header* foundInImageAtLoadAddress;
606 if ( flatFindSymbol(symbolName, address, &foundInImageAtLoadAddress) ) {
607 *module = (NSModule)foundInImageAtLoadAddress;
608 return;
609 }
610
611 *address = 0;
612 *module = 0;
613 }
614
615
616 void _dyld_lookup_and_bind_fully(const char* symbolName, void** address, NSModule* module)
617 {
618 log_apis("_dyld_lookup_and_bind_fully(%s, %p, %p)\n", symbolName, address, module);
619
620 const mach_header* foundInImageAtLoadAddress;
621 if ( flatFindSymbol(symbolName, address, &foundInImageAtLoadAddress) ) {
622 *module = (NSModule)foundInImageAtLoadAddress;
623 return;
624 }
625
626 *address = 0;
627 *module = 0;
628 }
629
630 const struct mach_header* _dyld_get_image_header_containing_address(const void* address)
631 {
632 log_apis("_dyld_get_image_header_containing_address(%p)\n", address);
633
634 return dyld_image_header_containing_address(address);
635 }
636
637 #endif
638
639
640 } // namespace dyld3
641