2 * Copyright (c) 2007 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 /***********************************************************************
26 * OS portability layer.
27 **********************************************************************/
30 #include "objc-private.h"
31 #include "objc-loadmethod.h"
35 #include "objc-runtime-old.h"
38 malloc_zone_t *_objc_internal_zone(void)
43 int monitor_init(monitor_t *c)
45 // fixme error checking
46 HANDLE mutex = CreateMutex(NULL, TRUE, NULL);
48 // fixme memory barrier here?
49 if (0 == InterlockedCompareExchangePointer(&c->mutex, mutex, 0)) {
50 // we win - finish construction
51 c->waiters = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
52 c->waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL);
53 InitializeCriticalSection(&c->waitCountLock);
56 ReleaseMutex(c->mutex);
61 // someone else allocated the mutex and constructed the monitor
67 void mutex_init(mutex_t *m)
70 CRITICAL_SECTION *newlock = malloc(sizeof(CRITICAL_SECTION));
71 InitializeCriticalSection(newlock);
72 // fixme memory barrier here?
73 if (0 == InterlockedCompareExchangePointer(&m->lock, newlock, 0)) {
76 // someone else installed their lock first
77 DeleteCriticalSection(newlock);
83 void recursive_mutex_init(recursive_mutex_t *m)
85 // fixme error checking
86 HANDLE newmutex = CreateMutex(NULL, FALSE, NULL);
88 // fixme memory barrier here?
89 if (0 == InterlockedCompareExchangePointer(&m->mutex, newmutex, 0)) {
95 // someone else installed their lock first
96 CloseHandle(newmutex);
100 WINBOOL APIENTRY DllMain( HMODULE hModule,
101 DWORD ul_reason_for_call,
105 switch (ul_reason_for_call) {
106 case DLL_PROCESS_ATTACH:
114 case DLL_THREAD_ATTACH:
117 case DLL_THREAD_DETACH:
118 case DLL_PROCESS_DETACH:
124 OBJC_EXPORT void *_objc_init_image(HMODULE image, const objc_sections *sects)
126 header_info *hi = _malloc_internal(sizeof(header_info));
129 hi->mhdr = (const headerType *)image;
130 hi->info = sects->iiStart;
131 hi->allClassesRealized = NO;
132 hi->os.modules = sects->modStart ? (Module *)((void **)sects->modStart+1) : 0;
133 hi->os.moduleCount = (Module *)sects->modEnd - hi->os.modules;
134 hi->os.protocols = sects->protoStart ? (struct old_protocol **)((void **)sects->protoStart+1) : 0;
135 hi->os.protocolCount = (struct old_protocol **)sects->protoEnd - hi->os.protocols;
136 hi->os.imageinfo = NULL;
137 hi->os.imageinfoBytes = 0;
138 // hi->os.imageinfo = sects->iiStart ? (uint8_t *)((void **)sects->iiStart+1) : 0;;
139 // hi->os.imageinfoBytes = (uint8_t *)sects->iiEnd - hi->os.imageinfo;
140 hi->os.selrefs = sects->selrefsStart ? (SEL *)((void **)sects->selrefsStart+1) : 0;
141 hi->os.selrefCount = (SEL *)sects->selrefsEnd - hi->os.selrefs;
142 hi->os.clsrefs = sects->clsrefsStart ? (Class *)((void **)sects->clsrefsStart+1) : 0;
143 hi->os.clsrefCount = (Class *)sects->clsrefsEnd - hi->os.clsrefs;
146 for (i = 0; i < hi->os.moduleCount; i++) {
147 if (hi->os.modules[i]) count++;
152 hi->mod_ptr = malloc(count * sizeof(struct objc_module));
153 for (i = 0; i < hi->os.moduleCount; i++) {
154 if (hi->os.modules[i]) memcpy(&hi->mod_ptr[hi->mod_count++], hi->os.modules[i], sizeof(struct objc_module));
158 hi->os.moduleName = malloc(MAX_PATH * sizeof(TCHAR));
159 GetModuleFileName((HMODULE)(hi->mhdr), hi->os.moduleName, MAX_PATH * sizeof(TCHAR));
161 _objc_appendHeader(hi);
164 _objc_inform("IMAGES: loading image for %s%s%s\n",
165 _nameForHeader(hi->mhdr),
166 headerIsBundle(hi) ? " (bundle)" : "",
167 _objcHeaderIsReplacement(hi) ? " (replacement)":"");
170 _read_images(&hi, 1);
175 OBJC_EXPORT void _objc_load_image(HMODULE image, header_info *hinfo)
177 prepare_load_methods(hinfo);
181 OBJC_EXPORT void _objc_unload_image(HMODULE image, header_info *hinfo)
183 _objc_fatal("image unload not supported");
187 PRIVATE_EXTERN bool crashlog_header_name(header_info *hi)
197 #include "objc-file-old.h"
200 PRIVATE_EXTERN void mutex_init(mutex_t *m)
202 pthread_mutex_init(m, NULL);
206 PRIVATE_EXTERN void recursive_mutex_init(recursive_mutex_t *m)
208 // fixme error checking
209 pthread_mutex_t *newmutex;
211 // Build recursive mutex attributes, if needed
212 static pthread_mutexattr_t *attr;
214 pthread_mutexattr_t *newattr =
215 _malloc_internal(sizeof(pthread_mutexattr_t));
216 pthread_mutexattr_init(newattr);
217 pthread_mutexattr_settype(newattr, PTHREAD_MUTEX_RECURSIVE);
219 if (OSAtomicCompareAndSwapPtrBarrier(0, newattr, (void**)&attr)) {
224 // someone else built the attr first
225 _free_internal(newattr);
229 // Build the mutex itself
230 newmutex = _malloc_internal(sizeof(pthread_mutex_t));
231 pthread_mutex_init(newmutex, attr);
233 if (OSAtomicCompareAndSwapPtrBarrier(0, newmutex, (void**)&m->mutex)) {
239 // someone else installed their mutex first
240 pthread_mutex_destroy(newmutex);
244 /***********************************************************************
246 * Return YES if the header has invalid Mach-o magic.
247 **********************************************************************/
248 PRIVATE_EXTERN BOOL bad_magic(const headerType *mhdr)
250 return (mhdr->magic != MH_MAGIC && mhdr->magic != MH_MAGIC_64 &&
251 mhdr->magic != MH_CIGAM && mhdr->magic != MH_CIGAM_64);
255 static header_info * _objc_addHeader(const headerType *mhdr)
257 size_t info_size = 0;
258 unsigned long seg_size;
259 const uint8_t *objc_segment;
260 const objc_image_info *image_info;
263 if (bad_magic(mhdr)) return NULL;
265 // Weed out duplicates
266 for (result = FirstHeader; result; result = result->next) {
267 if (mhdr == result->mhdr) return NULL;
270 // Locate the __OBJC segment
271 image_info = _getObjcImageInfo(mhdr, &info_size);
272 objc_segment = getsegmentdata(mhdr, SEG_OBJC, &seg_size);
273 if (!objc_segment && !image_info) return NULL;
275 // Allocate a header_info entry.
276 result = _calloc_internal(sizeof(header_info), 1);
278 // Set up the new header_info entry.
281 // mhdr must already be set
282 result->mod_count = 0;
283 result->mod_ptr = _getObjcModules(result, &result->mod_count);
285 result->info = image_info;
286 dladdr(result->mhdr, &result->os.dl_info);
287 result->allClassesRealized = NO;
289 // dylibs are not allowed to unload
290 // ...except those with image_info and nothing else (5359412)
291 if (result->mhdr->filetype == MH_DYLIB && _hasObjcContents(result)) {
292 dlopen(result->os.dl_info.dli_fname, RTLD_NOLOAD);
295 // Make sure every copy of objc_image_info in this image is the same.
296 // This means same version and same bitwise contents.
298 const objc_image_info *start = result->info;
299 const objc_image_info *end =
300 (objc_image_info *)(info_size + (uint8_t *)start);
301 const objc_image_info *info = start;
303 // version is byte size, except for version 0
304 size_t struct_size = info->version;
305 if (struct_size == 0) struct_size = 2 * sizeof(uint32_t);
306 if (info->version != start->version ||
307 0 != memcmp(info, start, struct_size))
309 _objc_inform("'%s' has inconsistently-compiled Objective-C "
310 "code. Please recompile all code in it.",
311 _nameForHeader(mhdr));
313 info = (objc_image_info *)(struct_size + (uint8_t *)info);
317 _objc_appendHeader(result);
325 PRIVATE_EXTERN const char *_gcForHInfo(const header_info *hinfo)
329 PRIVATE_EXTERN const char *_gcForHInfo2(const header_info *hinfo)
336 /***********************************************************************
338 **********************************************************************/
339 PRIVATE_EXTERN const char *_gcForHInfo(const header_info *hinfo)
341 if (_objcHeaderRequiresGC(hinfo)) {
342 if (_objcHeaderSupportsCompaction(hinfo))
343 return "requires GC, supports compaction";
345 return "requires GC";
346 } else if (_objcHeaderSupportsGC(hinfo)) {
347 if (_objcHeaderSupportsCompaction(hinfo))
348 return "supports GC, supports compaction";
350 return "supports GC";
352 return "does not support GC";
355 PRIVATE_EXTERN const char *_gcForHInfo2(const header_info *hinfo)
357 if (_objcHeaderRequiresGC(hinfo)) {
358 if (_objcHeaderSupportsCompaction(hinfo))
359 return "(requires GC) (supports compaction)";
361 return "(requires GC)";
362 } else if (_objcHeaderSupportsGC(hinfo)) {
363 if (_objcHeaderSupportsCompaction(hinfo))
364 return "(supports GC) (supports compaction)";
366 return "(supports GC)";
372 /***********************************************************************
374 * Check whether the executable supports or requires GC, and make sure
375 * all already-loaded libraries support the executable's GC mode.
376 * Returns TRUE if the executable wants GC on.
377 **********************************************************************/
378 static void check_wants_gc(BOOL *appWantsGC, BOOL *appSupportsCompaction)
380 const header_info *hi;
382 // Environment variables can override the following.
384 _objc_inform("GC: forcing GC OFF because OBJC_DISABLE_GC is set");
386 *appSupportsCompaction = NO;
389 // Find the executable and check its GC bits.
390 // If the executable cannot be found, default to NO.
391 // (The executable will not be found if the executable contains
392 // no Objective-C code.)
394 *appSupportsCompaction = NO;
395 for (hi = FirstHeader; hi != NULL; hi = hi->next) {
396 if (hi->mhdr->filetype == MH_EXECUTE) {
397 *appWantsGC = _objcHeaderSupportsGC(hi) ? YES : NO;
398 *appSupportsCompaction = (*appWantsGC && _objcHeaderSupportsCompaction(hi)) ? YES : NO;
400 _objc_inform("GC: executable '%s' %s",
401 _nameForHeader(hi->mhdr), _gcForHInfo(hi));
409 /***********************************************************************
410 * verify_gc_readiness
411 * if we want gc, verify that every header describes files compiled
412 * and presumably ready for gc.
413 ************************************************************************/
414 static void verify_gc_readiness(BOOL wantsGC, BOOL *wantsCompaction,
415 header_info **hList, uint32_t hCount)
420 // Find the libraries and check their GC bits against the app's request
421 for (i = 0; i < hCount; i++) {
422 header_info *hi = hList[i];
423 if (hi->mhdr->filetype == MH_EXECUTE) {
426 else if (hi->mhdr == &_mh_dylib_header) {
427 // libobjc itself works with anything even though it is not
428 // compiled with -fobjc-gc (fixme should it be?)
430 else if (wantsGC && ! _objcHeaderSupportsGC(hi)) {
431 // App wants GC but library does not support it - bad
432 _objc_inform_now_and_on_crash
433 ("'%s' was not compiled with -fobjc-gc or -fobjc-gc-only, "
434 "but the application requires GC",
435 _nameForHeader(hi->mhdr));
438 else if (!wantsGC && _objcHeaderRequiresGC(hi)) {
439 // App doesn't want GC but library requires it - bad
440 _objc_inform_now_and_on_crash
441 ("'%s' was compiled with -fobjc-gc-only, "
442 "but the application does not support GC",
443 _nameForHeader(hi->mhdr));
447 if (*wantsCompaction && !_objcHeaderSupportsCompaction(hi)) {
448 // App supports compaction, but library doesn't.
449 _objc_inform_now_and_on_crash
450 ("'%s' was not linked with -Xlinker -objc_gc_compaction, "
451 "but the application wants compaction.",
452 _nameForHeader(hi->mhdr));
453 // Simply warn for now until radars are filed. Eventually,
454 // objc_disableCompaction() will block until any current compaction completes.
455 objc_disableCompaction();
456 *wantsCompaction = NO;
460 _objc_inform("GC: library '%s' %s",
461 _nameForHeader(hi->mhdr), _gcForHInfo(hi));
466 // GC state is not consistent.
467 // Kill the process unless one of the forcing flags is set.
469 _objc_fatal("*** GC capability of application and some libraries did not match");
475 /***********************************************************************
477 * Make sure that images about to be loaded by dyld are GC-acceptable.
478 * Images linked to the executable are always permitted; they are
479 * enforced inside map_images() itself.
480 **********************************************************************/
481 static BOOL InitialDyldRegistration = NO;
482 static const char *gc_enforcer(enum dyld_image_states state,
484 const struct dyld_image_info info[])
488 // Linked images get a free pass
489 if (InitialDyldRegistration) return NULL;
492 _objc_inform("IMAGES: checking %d images for compatibility...",
496 for (i = 0; i < infoCount; i++) {
497 crashlog_header_name_string(info[i].imageFilePath);
499 const headerType *mhdr = (const headerType *)info[i].imageLoadAddress;
500 if (bad_magic(mhdr)) continue;
502 objc_image_info *image_info;
505 if (mhdr == &_mh_dylib_header) {
506 // libobjc itself - OK
511 unsigned long seg_size;
512 // 32-bit: __OBJC seg but no image_info means no GC support
513 if (!getsegmentdata(mhdr, "__OBJC", &seg_size)) {
514 // not objc - assume OK
517 image_info = _getObjcImageInfo(mhdr, &size);
519 // No image_info - assume GC unsupported
525 if (PrintImages || PrintGC) {
526 _objc_inform("IMAGES: rejecting %d images because %s doesn't support GC (no image_info)", infoCount, info[i].imageFilePath);
532 // 64-bit: no image_info means no objc at all
533 image_info = _getObjcImageInfo(mhdr, &size);
535 // not objc - assume OK
540 if (UseGC && !_objcInfoSupportsGC(image_info)) {
541 // GC is ON, but image does not support GC
542 if (PrintImages || PrintGC) {
543 _objc_inform("IMAGES: rejecting %d images because %s doesn't support GC", infoCount, info[i].imageFilePath);
547 if (!UseGC && _objcInfoRequiresGC(image_info)) {
548 // GC is OFF, but image requires GC
549 if (PrintImages || PrintGC) {
550 _objc_inform("IMAGES: rejecting %d images because %s requires GC", infoCount, info[i].imageFilePath);
556 crashlog_header_name_string(NULL);
560 crashlog_header_name_string(NULL);
561 return "GC capability mismatch";
568 /***********************************************************************
570 * Process the given images which are being mapped in by dyld.
571 * All class registration and fixups are performed (or deferred pending
572 * discovery of missing superclasses etc), and +load methods are called.
574 * info[] is in bottom-up order i.e. libobjc will be earlier in the
575 * array than any library that links to libobjc.
577 * Locking: loadMethodLock(old) or runtimeLock(new) acquired by map_images.
578 **********************************************************************/
579 PRIVATE_EXTERN const char *
580 map_images_nolock(enum dyld_image_states state, uint32_t infoCount,
581 const struct dyld_image_info infoList[])
583 static BOOL firstTime = YES;
584 static BOOL wantsGC = NO;
585 static BOOL wantsCompaction = NO;
588 header_info *hList[infoCount];
591 // Perform first-time initialization if necessary.
592 // This function is called before ordinary library initializers.
593 // fixme defer initialization until an objc-using image is found?
596 InitialDyldRegistration = YES;
597 dyld_register_image_state_change_handler(dyld_image_state_mapped, 0 /* batch */, &gc_enforcer);
598 InitialDyldRegistration = NO;
603 _objc_inform("IMAGES: processing %u newly-mapped images...\n", infoCount);
607 // Find all images with Objective-C metadata.
611 const headerType *mhdr = (headerType *)infoList[i].imageLoadAddress;
613 hi = _objc_addHeader(mhdr);
615 // no objc data in this entry
619 hList[hCount++] = hi;
623 _objc_inform("IMAGES: loading image for %s%s%s%s%s\n",
624 _nameForHeader(mhdr),
625 mhdr->filetype == MH_BUNDLE ? " (bundle)" : "",
626 _objcHeaderIsReplacement(hi) ? " (replacement)" : "",
627 _objcHeaderOptimizedByDyld(hi)?" (preoptimized)" : "",
632 // Perform one-time runtime initialization that must be deferred until
633 // the executable itself is found. This needs to be done before
634 // further initialization.
635 // (The executable may not be present in this infoList if the
636 // executable does not contain Objective-C code but Objective-C
637 // is dynamically loaded later. In that case, check_wants_gc()
638 // will do the right thing.)
641 check_wants_gc(&wantsGC, &wantsCompaction);
643 verify_gc_readiness(wantsGC, &wantsCompaction, hList, hCount);
645 gc_init(wantsGC, wantsCompaction); // needs executable for GC decision
646 rtp_init(); // needs GC decision first
648 verify_gc_readiness(wantsGC, &wantsCompaction, hList, hCount);
652 // tell the collector about the data segment ranges.
653 for (i = 0; i < hCount; ++i) {
655 unsigned long seg_size;
658 seg = getsegmentdata(hi->mhdr, "__DATA", &seg_size);
659 if (seg) gc_register_datasegment((uintptr_t)seg, seg_size);
661 seg = getsegmentdata(hi->mhdr, "__OBJC", &seg_size);
662 if (seg) gc_register_datasegment((uintptr_t)seg, seg_size);
663 // __OBJC contains no GC data, but pointers to it are
664 // used as associated reference values (rdar://6953570)
668 // Need to fixup barriers in all libraries that call into libobjc, whether GC is on or not.
669 for (i = 0; i < infoCount; ++i) {
670 gc_fixup_barrier_stubs(&infoList[i]);
675 extern SEL FwdSel; // in objc-msg-*.s
677 FwdSel = sel_registerName("forward::");
682 _read_images(hList, hCount);
690 /***********************************************************************
692 * Prepares +load in the given images which are being mapped in by dyld.
693 * Returns YES if there are now +load methods to be called by call_load_methods.
695 * Locking: loadMethodLock(both) and runtimeLock(new) acquired by load_images
696 **********************************************************************/
698 load_images_nolock(enum dyld_image_states state,uint32_t infoCount,
699 const struct dyld_image_info infoList[])
707 for (hi = FirstHeader; hi != NULL; hi = hi->next) {
708 const headerType *mhdr = (headerType*)infoList[i].imageLoadAddress;
709 if (hi->mhdr == mhdr) {
710 prepare_load_methods(hi);
720 /***********************************************************************
722 * Process the given image which is about to be unmapped by dyld.
723 * mh is mach_header instead of headerType because that's what
724 * dyld_priv.h says even for 64-bit.
726 * Locking: loadMethodLock(both) and runtimeLock(new) acquired by unmap_image.
727 **********************************************************************/
729 unmap_image_nolock(const struct mach_header *mh)
732 _objc_inform("IMAGES: processing 1 newly-unmapped image...\n");
737 // Find the runtime's header_info struct for the image
738 for (hi = FirstHeader; hi != NULL; hi = hi->next) {
739 if (hi->mhdr == (const headerType *)mh) {
747 _objc_inform("IMAGES: unloading image for %s%s%s%s\n",
748 _nameForHeader(hi->mhdr),
749 hi->mhdr->filetype == MH_BUNDLE ? " (bundle)" : "",
750 _objcHeaderIsReplacement(hi) ? " (replacement)" : "",
757 unsigned long seg_size;
759 seg = getsegmentdata(hi->mhdr, "__DATA", &seg_size);
760 if (seg) gc_unregister_datasegment((uintptr_t)seg, seg_size);
762 seg = getsegmentdata(hi->mhdr, "__OBJC", &seg_size);
763 if (seg) gc_unregister_datasegment((uintptr_t)seg, seg_size);
769 // Remove header_info from header list
770 _objc_removeHeader(hi);
775 /***********************************************************************
777 * Static initializer. Registers our image notifier with dyld.
778 **********************************************************************/
779 static __attribute__((constructor))
780 void _objc_init(void)
782 // fixme defer initialization until an objc-using image is found?
788 // Register for unmap first, in case some +load unmaps something
789 _dyld_register_func_for_remove_image(&unmap_image);
790 dyld_register_image_state_change_handler(dyld_image_state_bound,
791 1/*batch*/, &map_images);
792 dyld_register_image_state_change_handler(dyld_image_state_dependents_initialized, 0/*not batch*/, &load_images);
796 /***********************************************************************
798 * addr can be a class or a category
799 **********************************************************************/
800 static const header_info *_headerForAddress(void *addr)
803 const char *segname = "__DATA";
805 const char *segname = "__OBJC";
809 // Check all headers in the vector
810 for (hi = FirstHeader; hi != NULL; hi = hi->next)
813 unsigned long seg_size;
815 seg = getsegmentdata(hi->mhdr, segname, &seg_size);
818 // Is the class in this header?
819 if ((uint8_t *)addr >= seg && (uint8_t *)addr < seg + seg_size)
828 /***********************************************************************
830 * Return the image header containing this class, or NULL.
831 * Returns NULL on runtime-constructed classes, and the NSCF classes.
832 **********************************************************************/
833 PRIVATE_EXTERN const header_info *_headerForClass(Class cls)
835 return _headerForAddress(cls);
839 /**********************************************************************
841 * Securely open a file from a world-writable directory (like /tmp)
842 * If the file does not exist, it will be atomically created with mode 0600
843 * If the file exists, it must be, and remain after opening:
844 * 1. a regular file (in particular, not a symlink)
846 * 3. permissions 0600
848 * Returns a file descriptor or -1. Errno may or may not be set on error.
849 **********************************************************************/
850 PRIVATE_EXTERN int secure_open(const char *filename, int flags, uid_t euid)
857 if (flags & O_TRUNC) {
858 // Don't truncate the file until after it is open and verified.
862 if (flags & O_CREAT) {
863 // Don't create except when we're ready for it
869 if (lstat(filename, &ls) < 0) {
870 if (errno == ENOENT && create) {
871 // No such file - create it
872 fd = open(filename, flags | O_CREAT | O_EXCL, 0600);
874 // File was created successfully.
875 // New file does not need to be truncated.
878 // File creation failed.
882 // lstat failed, or user doesn't want to create the file
886 // lstat succeeded - verify attributes and open
887 if (S_ISREG(ls.st_mode) && // regular file?
888 ls.st_nlink == 1 && // link count == 1?
889 ls.st_uid == euid && // owned by euid?
890 (ls.st_mode & ALLPERMS) == (S_IRUSR | S_IWUSR)) // mode 0600?
892 // Attributes look ok - open it and check attributes again
893 fd = open(filename, flags, 0000);
895 // File is open - double-check attributes
896 if (0 == fstat(fd, &fs) &&
897 fs.st_nlink == ls.st_nlink && // link count == 1?
898 fs.st_uid == ls.st_uid && // owned by euid?
899 fs.st_mode == ls.st_mode && // regular file, 0600?
900 fs.st_ino == ls.st_ino && // same inode as before?
901 fs.st_dev == ls.st_dev) // same device as before?
903 // File is open and OK
904 if (truncate) ftruncate(fd, 0);
907 // Opened file looks funny - close it
916 // Unopened file looks funny - don't open it
923 /***********************************************************************
924 * _objc_internal_zone.
925 * Malloc zone for internal runtime data.
926 * By default this is the default malloc zone, but a dedicated zone is
927 * used if environment variable OBJC_USE_INTERNAL_ZONE is set.
928 **********************************************************************/
929 PRIVATE_EXTERN malloc_zone_t *_objc_internal_zone(void)
931 static malloc_zone_t *z = (malloc_zone_t *)-1;
932 if (z == (malloc_zone_t *)-1) {
933 if (UseInternalZone) {
934 z = malloc_create_zone(vm_page_size, 0);
935 malloc_set_zone_name(z, "ObjC");
937 z = malloc_default_zone();
944 PRIVATE_EXTERN const char *
945 _getObjcHeaderName(const headerType *header)
949 if (dladdr(header, &info)) {
950 return info.dli_fname;
953 return (*_NSGetArgv())[0];
958 PRIVATE_EXTERN bool crashlog_header_name(header_info *hi)
960 return crashlog_header_name_string(hi ? hi->os.dl_info.dli_fname : NULL);
963 PRIVATE_EXTERN bool crashlog_header_name_string(const char *name)
965 CRSetCrashLogMessage2(name);
972 PRIVATE_EXTERN const char *__crashreporter_info__ = NULL;
974 PRIVATE_EXTERN const char *CRSetCrashLogMessage(const char *msg)
976 __crashreporter_info__ = msg;
979 PRIVATE_EXTERN const char *CRGetCrashLogMessage(void)
981 return __crashreporter_info__;
984 PRIVATE_EXTERN const char *CRSetCrashLogMessage2(const char *msg)