]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-os.mm
objc4-723.tar.gz
[apple/objc4.git] / runtime / objc-os.mm
1 /*
2 * Copyright (c) 2007 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 * objc-os.m
26 * OS portability layer.
27 **********************************************************************/
28
29 #include "objc-private.h"
30 #include "objc-loadmethod.h"
31
32 #if TARGET_OS_WIN32
33
34 #include "objc-runtime-old.h"
35 #include "objcrt.h"
36
37 const fork_unsafe_lock_t fork_unsafe_lock;
38
39 int monitor_init(monitor_t *c)
40 {
41 // fixme error checking
42 HANDLE mutex = CreateMutex(NULL, TRUE, NULL);
43 while (!c->mutex) {
44 // fixme memory barrier here?
45 if (0 == InterlockedCompareExchangePointer(&c->mutex, mutex, 0)) {
46 // we win - finish construction
47 c->waiters = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
48 c->waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL);
49 InitializeCriticalSection(&c->waitCountLock);
50 c->waitCount = 0;
51 c->didBroadcast = 0;
52 ReleaseMutex(c->mutex);
53 return 0;
54 }
55 }
56
57 // someone else allocated the mutex and constructed the monitor
58 ReleaseMutex(mutex);
59 CloseHandle(mutex);
60 return 0;
61 }
62
63 void mutex_init(mutex_t *m)
64 {
65 while (!m->lock) {
66 CRITICAL_SECTION *newlock = malloc(sizeof(CRITICAL_SECTION));
67 InitializeCriticalSection(newlock);
68 // fixme memory barrier here?
69 if (0 == InterlockedCompareExchangePointer(&m->lock, newlock, 0)) {
70 return;
71 }
72 // someone else installed their lock first
73 DeleteCriticalSection(newlock);
74 free(newlock);
75 }
76 }
77
78
79 void recursive_mutex_init(recursive_mutex_t *m)
80 {
81 // fixme error checking
82 HANDLE newmutex = CreateMutex(NULL, FALSE, NULL);
83 while (!m->mutex) {
84 // fixme memory barrier here?
85 if (0 == InterlockedCompareExchangePointer(&m->mutex, newmutex, 0)) {
86 // we win
87 return;
88 }
89 }
90
91 // someone else installed their lock first
92 CloseHandle(newmutex);
93 }
94
95
96 WINBOOL APIENTRY DllMain( HMODULE hModule,
97 DWORD ul_reason_for_call,
98 LPVOID lpReserved
99 )
100 {
101 switch (ul_reason_for_call) {
102 case DLL_PROCESS_ATTACH:
103 environ_init();
104 tls_init();
105 lock_init();
106 sel_init(3500); // old selector heuristic
107 exception_init();
108 break;
109
110 case DLL_THREAD_ATTACH:
111 break;
112
113 case DLL_THREAD_DETACH:
114 case DLL_PROCESS_DETACH:
115 break;
116 }
117 return TRUE;
118 }
119
120 OBJC_EXPORT void *_objc_init_image(HMODULE image, const objc_sections *sects)
121 {
122 header_info *hi = malloc(sizeof(header_info));
123 size_t count, i;
124
125 hi->mhdr = (const headerType *)image;
126 hi->info = sects->iiStart;
127 hi->allClassesRealized = NO;
128 hi->modules = sects->modStart ? (Module *)((void **)sects->modStart+1) : 0;
129 hi->moduleCount = (Module *)sects->modEnd - hi->modules;
130 hi->protocols = sects->protoStart ? (struct old_protocol **)((void **)sects->protoStart+1) : 0;
131 hi->protocolCount = (struct old_protocol **)sects->protoEnd - hi->protocols;
132 hi->imageinfo = NULL;
133 hi->imageinfoBytes = 0;
134 // hi->imageinfo = sects->iiStart ? (uint8_t *)((void **)sects->iiStart+1) : 0;;
135 // hi->imageinfoBytes = (uint8_t *)sects->iiEnd - hi->imageinfo;
136 hi->selrefs = sects->selrefsStart ? (SEL *)((void **)sects->selrefsStart+1) : 0;
137 hi->selrefCount = (SEL *)sects->selrefsEnd - hi->selrefs;
138 hi->clsrefs = sects->clsrefsStart ? (Class *)((void **)sects->clsrefsStart+1) : 0;
139 hi->clsrefCount = (Class *)sects->clsrefsEnd - hi->clsrefs;
140
141 count = 0;
142 for (i = 0; i < hi->moduleCount; i++) {
143 if (hi->modules[i]) count++;
144 }
145 hi->mod_count = 0;
146 hi->mod_ptr = 0;
147 if (count > 0) {
148 hi->mod_ptr = malloc(count * sizeof(struct objc_module));
149 for (i = 0; i < hi->moduleCount; i++) {
150 if (hi->modules[i]) memcpy(&hi->mod_ptr[hi->mod_count++], hi->modules[i], sizeof(struct objc_module));
151 }
152 }
153
154 hi->moduleName = malloc(MAX_PATH * sizeof(TCHAR));
155 GetModuleFileName((HMODULE)(hi->mhdr), hi->moduleName, MAX_PATH * sizeof(TCHAR));
156
157 appendHeader(hi);
158
159 if (PrintImages) {
160 _objc_inform("IMAGES: loading image for %s%s%s%s\n",
161 hi->fname,
162 headerIsBundle(hi) ? " (bundle)" : "",
163 hi->info->isReplacement() ? " (replacement)":"",
164 hi->info->hasCategoryClassProperties() ? " (has class properties)":"");
165 }
166
167 // Count classes. Size various table based on the total.
168 int total = 0;
169 int unoptimizedTotal = 0;
170 {
171 if (_getObjc2ClassList(hi, &count)) {
172 total += (int)count;
173 if (!hi->getInSharedCache()) unoptimizedTotal += count;
174 }
175 }
176
177 _read_images(&hi, 1, total, unoptimizedTotal);
178
179 return hi;
180 }
181
182 OBJC_EXPORT void _objc_load_image(HMODULE image, header_info *hinfo)
183 {
184 prepare_load_methods(hinfo);
185 call_load_methods();
186 }
187
188 OBJC_EXPORT void _objc_unload_image(HMODULE image, header_info *hinfo)
189 {
190 _objc_fatal("image unload not supported");
191 }
192
193
194 // TARGET_OS_WIN32
195 #elif TARGET_OS_MAC
196
197 #include "objc-file-old.h"
198 #include "objc-file.h"
199
200
201 /***********************************************************************
202 * libobjc must never run static destructors.
203 * Cover libc's __cxa_atexit with our own definition that runs nothing.
204 * rdar://21734598 ER: Compiler option to suppress C++ static destructors
205 **********************************************************************/
206 extern "C" int __cxa_atexit();
207 extern "C" int __cxa_atexit() { return 0; }
208
209
210 /***********************************************************************
211 * bad_magic.
212 * Return YES if the header has invalid Mach-o magic.
213 **********************************************************************/
214 bool bad_magic(const headerType *mhdr)
215 {
216 return (mhdr->magic != MH_MAGIC && mhdr->magic != MH_MAGIC_64 &&
217 mhdr->magic != MH_CIGAM && mhdr->magic != MH_CIGAM_64);
218 }
219
220
221 static header_info * addHeader(const headerType *mhdr, const char *path, int &totalClasses, int &unoptimizedTotalClasses)
222 {
223 header_info *hi;
224
225 if (bad_magic(mhdr)) return NULL;
226
227 bool inSharedCache = false;
228
229 // Look for hinfo from the dyld shared cache.
230 hi = preoptimizedHinfoForHeader(mhdr);
231 if (hi) {
232 // Found an hinfo in the dyld shared cache.
233
234 // Weed out duplicates.
235 if (hi->isLoaded()) {
236 return NULL;
237 }
238
239 inSharedCache = true;
240
241 // Initialize fields not set by the shared cache
242 // hi->next is set by appendHeader
243 hi->setLoaded(true);
244
245 if (PrintPreopt) {
246 _objc_inform("PREOPTIMIZATION: honoring preoptimized header info at %p for %s", hi, hi->fname());
247 }
248
249 #if !__OBJC2__
250 _objc_fatal("shouldn't be here");
251 #endif
252 #if DEBUG
253 // Verify image_info
254 size_t info_size = 0;
255 const objc_image_info *image_info = _getObjcImageInfo(mhdr,&info_size);
256 assert(image_info == hi->info());
257 #endif
258 }
259 else
260 {
261 // Didn't find an hinfo in the dyld shared cache.
262
263 // Weed out duplicates
264 for (hi = FirstHeader; hi; hi = hi->getNext()) {
265 if (mhdr == hi->mhdr()) return NULL;
266 }
267
268 // Locate the __OBJC segment
269 size_t info_size = 0;
270 unsigned long seg_size;
271 const objc_image_info *image_info = _getObjcImageInfo(mhdr,&info_size);
272 const uint8_t *objc_segment = getsegmentdata(mhdr,SEG_OBJC,&seg_size);
273 if (!objc_segment && !image_info) return NULL;
274
275 // Allocate a header_info entry.
276 // Note we also allocate space for a single header_info_rw in the
277 // rw_data[] inside header_info.
278 hi = (header_info *)calloc(sizeof(header_info) + sizeof(header_info_rw), 1);
279
280 // Set up the new header_info entry.
281 hi->setmhdr(mhdr);
282 #if !__OBJC2__
283 // mhdr must already be set
284 hi->mod_count = 0;
285 hi->mod_ptr = _getObjcModules(hi, &hi->mod_count);
286 #endif
287 // Install a placeholder image_info if absent to simplify code elsewhere
288 static const objc_image_info emptyInfo = {0, 0};
289 hi->setinfo(image_info ?: &emptyInfo);
290
291 hi->setLoaded(true);
292 hi->setAllClassesRealized(NO);
293 }
294
295 #if __OBJC2__
296 {
297 size_t count = 0;
298 if (_getObjc2ClassList(hi, &count)) {
299 totalClasses += (int)count;
300 if (!inSharedCache) unoptimizedTotalClasses += count;
301 }
302 }
303 #endif
304
305 appendHeader(hi);
306
307 return hi;
308 }
309
310
311 /***********************************************************************
312 * linksToLibrary
313 * Returns true if the image links directly to a dylib whose install name
314 * is exactly the given name.
315 **********************************************************************/
316 bool
317 linksToLibrary(const header_info *hi, const char *name)
318 {
319 const struct dylib_command *cmd;
320 unsigned long i;
321
322 cmd = (const struct dylib_command *) (hi->mhdr() + 1);
323 for (i = 0; i < hi->mhdr()->ncmds; i++) {
324 if (cmd->cmd == LC_LOAD_DYLIB || cmd->cmd == LC_LOAD_UPWARD_DYLIB ||
325 cmd->cmd == LC_LOAD_WEAK_DYLIB || cmd->cmd == LC_REEXPORT_DYLIB)
326 {
327 const char *dylib = cmd->dylib.name.offset + (const char *)cmd;
328 if (0 == strcmp(dylib, name)) return true;
329 }
330 cmd = (const struct dylib_command *)((char *)cmd + cmd->cmdsize);
331 }
332
333 return false;
334 }
335
336
337 #if SUPPORT_GC_COMPAT
338
339 /***********************************************************************
340 * shouldRejectGCApp
341 * Return YES if the executable requires GC.
342 **********************************************************************/
343 static bool shouldRejectGCApp(const header_info *hi)
344 {
345 assert(hi->mhdr()->filetype == MH_EXECUTE);
346
347 if (!hi->info()->supportsGC()) {
348 // App does not use GC. Don't reject it.
349 return NO;
350 }
351
352 // Exception: Trivial AppleScriptObjC apps can run without GC.
353 // 1. executable defines no classes
354 // 2. executable references NSBundle only
355 // 3. executable links to AppleScriptObjC.framework
356 // Note that objc_appRequiresGC() also knows about this.
357 size_t classcount = 0;
358 size_t refcount = 0;
359 #if __OBJC2__
360 _getObjc2ClassList(hi, &classcount);
361 _getObjc2ClassRefs(hi, &refcount);
362 #else
363 if (hi->mod_count == 0 || (hi->mod_count == 1 && !hi->mod_ptr[0].symtab)) classcount = 0;
364 else classcount = 1;
365 _getObjcClassRefs(hi, &refcount);
366 #endif
367 if (classcount == 0 && refcount == 1 &&
368 linksToLibrary(hi, "/System/Library/Frameworks"
369 "/AppleScriptObjC.framework/Versions/A"
370 "/AppleScriptObjC"))
371 {
372 // It's AppleScriptObjC. Don't reject it.
373 return NO;
374 }
375 else {
376 // GC and not trivial AppleScriptObjC. Reject it.
377 return YES;
378 }
379 }
380
381
382 /***********************************************************************
383 * rejectGCImage
384 * Halt if an image requires GC.
385 * Testing of the main executable should use rejectGCApp() instead.
386 **********************************************************************/
387 static bool shouldRejectGCImage(const headerType *mhdr)
388 {
389 assert(mhdr->filetype != MH_EXECUTE);
390
391 objc_image_info *image_info;
392 size_t size;
393
394 #if !__OBJC2__
395 unsigned long seg_size;
396 // 32-bit: __OBJC seg but no image_info means no GC support
397 if (!getsegmentdata(mhdr, "__OBJC", &seg_size)) {
398 // Not objc, therefore not GC. Don't reject it.
399 return NO;
400 }
401 image_info = _getObjcImageInfo(mhdr, &size);
402 if (!image_info) {
403 // No image_info, therefore not GC. Don't reject it.
404 return NO;
405 }
406 #else
407 // 64-bit: no image_info means no objc at all
408 image_info = _getObjcImageInfo(mhdr, &size);
409 if (!image_info) {
410 // Not objc, therefore not GC. Don't reject it.
411 return NO;
412 }
413 #endif
414
415 return image_info->requiresGC();
416 }
417
418 // SUPPORT_GC_COMPAT
419 #endif
420
421
422 /***********************************************************************
423 * map_images_nolock
424 * Process the given images which are being mapped in by dyld.
425 * All class registration and fixups are performed (or deferred pending
426 * discovery of missing superclasses etc), and +load methods are called.
427 *
428 * info[] is in bottom-up order i.e. libobjc will be earlier in the
429 * array than any library that links to libobjc.
430 *
431 * Locking: loadMethodLock(old) or runtimeLock(new) acquired by map_images.
432 **********************************************************************/
433 #if __OBJC2__
434 #include "objc-file.h"
435 #else
436 #include "objc-file-old.h"
437 #endif
438
439 void
440 map_images_nolock(unsigned mhCount, const char * const mhPaths[],
441 const struct mach_header * const mhdrs[])
442 {
443 static bool firstTime = YES;
444 header_info *hList[mhCount];
445 uint32_t hCount;
446 size_t selrefCount = 0;
447
448 // Perform first-time initialization if necessary.
449 // This function is called before ordinary library initializers.
450 // fixme defer initialization until an objc-using image is found?
451 if (firstTime) {
452 preopt_init();
453 }
454
455 if (PrintImages) {
456 _objc_inform("IMAGES: processing %u newly-mapped images...\n", mhCount);
457 }
458
459
460 // Find all images with Objective-C metadata.
461 hCount = 0;
462
463 // Count classes. Size various table based on the total.
464 int totalClasses = 0;
465 int unoptimizedTotalClasses = 0;
466 {
467 uint32_t i = mhCount;
468 while (i--) {
469 const headerType *mhdr = (const headerType *)mhdrs[i];
470
471 auto hi = addHeader(mhdr, mhPaths[i], totalClasses, unoptimizedTotalClasses);
472 if (!hi) {
473 // no objc data in this entry
474 continue;
475 }
476
477 if (mhdr->filetype == MH_EXECUTE) {
478 // Size some data structures based on main executable's size
479 #if __OBJC2__
480 size_t count;
481 _getObjc2SelectorRefs(hi, &count);
482 selrefCount += count;
483 _getObjc2MessageRefs(hi, &count);
484 selrefCount += count;
485 #else
486 _getObjcSelectorRefs(hi, &selrefCount);
487 #endif
488
489 #if SUPPORT_GC_COMPAT
490 // Halt if this is a GC app.
491 if (shouldRejectGCApp(hi)) {
492 _objc_fatal_with_reason
493 (OBJC_EXIT_REASON_GC_NOT_SUPPORTED,
494 OS_REASON_FLAG_CONSISTENT_FAILURE,
495 "Objective-C garbage collection "
496 "is no longer supported.");
497 }
498 #endif
499 }
500
501 hList[hCount++] = hi;
502
503 if (PrintImages) {
504 _objc_inform("IMAGES: loading image for %s%s%s%s%s\n",
505 hi->fname(),
506 mhdr->filetype == MH_BUNDLE ? " (bundle)" : "",
507 hi->info()->isReplacement() ? " (replacement)" : "",
508 hi->info()->hasCategoryClassProperties() ? " (has class properties)" : "",
509 hi->info()->optimizedByDyld()?" (preoptimized)":"");
510 }
511 }
512 }
513
514 // Perform one-time runtime initialization that must be deferred until
515 // the executable itself is found. This needs to be done before
516 // further initialization.
517 // (The executable may not be present in this infoList if the
518 // executable does not contain Objective-C code but Objective-C
519 // is dynamically loaded later.
520 if (firstTime) {
521 sel_init(selrefCount);
522 arr_init();
523
524 #if SUPPORT_GC_COMPAT
525 // Reject any GC images linked to the main executable.
526 // We already rejected the app itself above.
527 // Images loaded after launch will be rejected by dyld.
528
529 for (uint32_t i = 0; i < hCount; i++) {
530 auto hi = hList[i];
531 auto mh = hi->mhdr();
532 if (mh->filetype != MH_EXECUTE && shouldRejectGCImage(mh)) {
533 _objc_fatal_with_reason
534 (OBJC_EXIT_REASON_GC_NOT_SUPPORTED,
535 OS_REASON_FLAG_CONSISTENT_FAILURE,
536 "%s requires Objective-C garbage collection "
537 "which is no longer supported.", hi->fname());
538 }
539 }
540 #endif
541
542 #if TARGET_OS_OSX
543 // Disable +initialize fork safety if the app is too old (< 10.13).
544 // Disable +initialize fork safety if the app has a
545 // __DATA,__objc_fork_ok section.
546
547 if (dyld_get_program_sdk_version() < DYLD_MACOSX_VERSION_10_13) {
548 DisableInitializeForkSafety = true;
549 if (PrintInitializing) {
550 _objc_inform("INITIALIZE: disabling +initialize fork "
551 "safety enforcement because the app is "
552 "too old (SDK version " SDK_FORMAT ")",
553 FORMAT_SDK(dyld_get_program_sdk_version()));
554 }
555 }
556
557 for (uint32_t i = 0; i < hCount; i++) {
558 auto hi = hList[i];
559 auto mh = hi->mhdr();
560 if (mh->filetype != MH_EXECUTE) continue;
561 unsigned long size;
562 if (getsectiondata(hi->mhdr(), "__DATA", "__objc_fork_ok", &size)) {
563 DisableInitializeForkSafety = true;
564 if (PrintInitializing) {
565 _objc_inform("INITIALIZE: disabling +initialize fork "
566 "safety enforcement because the app has "
567 "a __DATA,__objc_fork_ok section");
568 }
569 }
570 break; // assume only one MH_EXECUTE image
571 }
572 #endif
573
574 }
575
576 if (hCount > 0) {
577 _read_images(hList, hCount, totalClasses, unoptimizedTotalClasses);
578 }
579
580 firstTime = NO;
581 }
582
583
584 /***********************************************************************
585 * unmap_image_nolock
586 * Process the given image which is about to be unmapped by dyld.
587 * mh is mach_header instead of headerType because that's what
588 * dyld_priv.h says even for 64-bit.
589 *
590 * Locking: loadMethodLock(both) and runtimeLock(new) acquired by unmap_image.
591 **********************************************************************/
592 void
593 unmap_image_nolock(const struct mach_header *mh)
594 {
595 if (PrintImages) {
596 _objc_inform("IMAGES: processing 1 newly-unmapped image...\n");
597 }
598
599 header_info *hi;
600
601 // Find the runtime's header_info struct for the image
602 for (hi = FirstHeader; hi != NULL; hi = hi->getNext()) {
603 if (hi->mhdr() == (const headerType *)mh) {
604 break;
605 }
606 }
607
608 if (!hi) return;
609
610 if (PrintImages) {
611 _objc_inform("IMAGES: unloading image for %s%s%s\n",
612 hi->fname(),
613 hi->mhdr()->filetype == MH_BUNDLE ? " (bundle)" : "",
614 hi->info()->isReplacement() ? " (replacement)" : "");
615 }
616
617 _unload_image(hi);
618
619 // Remove header_info from header list
620 removeHeader(hi);
621 free(hi);
622 }
623
624
625 /***********************************************************************
626 * static_init
627 * Run C++ static constructor functions.
628 * libc calls _objc_init() before dyld would call our static constructors,
629 * so we have to do it ourselves.
630 **********************************************************************/
631 static void static_init()
632 {
633 size_t count;
634 Initializer *inits = getLibobjcInitializers(&_mh_dylib_header, &count);
635 for (size_t i = 0; i < count; i++) {
636 inits[i]();
637 }
638 }
639
640
641 /***********************************************************************
642 * _objc_atfork_prepare
643 * _objc_atfork_parent
644 * _objc_atfork_child
645 * Allow ObjC to be used between fork() and exec().
646 * libc requires this because it has fork-safe functions that use os_objects.
647 *
648 * _objc_atfork_prepare() acquires all locks.
649 * _objc_atfork_parent() releases the locks again.
650 * _objc_atfork_child() forcibly resets the locks.
651 **********************************************************************/
652
653 // Declare lock ordering.
654 #if LOCKDEBUG
655 __attribute__((constructor))
656 static void defineLockOrder()
657 {
658 // Every lock precedes crashlog_lock
659 // on the assumption that fatal errors could be anywhere.
660 lockdebug_lock_precedes_lock(&loadMethodLock, &crashlog_lock);
661 lockdebug_lock_precedes_lock(&classInitLock, &crashlog_lock);
662 #if __OBJC2__
663 lockdebug_lock_precedes_lock(&runtimeLock, &crashlog_lock);
664 lockdebug_lock_precedes_lock(&DemangleCacheLock, &crashlog_lock);
665 #else
666 lockdebug_lock_precedes_lock(&classLock, &crashlog_lock);
667 lockdebug_lock_precedes_lock(&methodListLock, &crashlog_lock);
668 lockdebug_lock_precedes_lock(&NXUniqueStringLock, &crashlog_lock);
669 lockdebug_lock_precedes_lock(&impLock, &crashlog_lock);
670 #endif
671 lockdebug_lock_precedes_lock(&selLock, &crashlog_lock);
672 lockdebug_lock_precedes_lock(&cacheUpdateLock, &crashlog_lock);
673 lockdebug_lock_precedes_lock(&objcMsgLogLock, &crashlog_lock);
674 lockdebug_lock_precedes_lock(&AltHandlerDebugLock, &crashlog_lock);
675 lockdebug_lock_precedes_lock(&AssociationsManagerLock, &crashlog_lock);
676 SideTableLocksPrecedeLock(&crashlog_lock);
677 PropertyLocks.precedeLock(&crashlog_lock);
678 StructLocks.precedeLock(&crashlog_lock);
679 CppObjectLocks.precedeLock(&crashlog_lock);
680
681 // loadMethodLock precedes everything
682 // because it is held while +load methods run
683 lockdebug_lock_precedes_lock(&loadMethodLock, &classInitLock);
684 #if __OBJC2__
685 lockdebug_lock_precedes_lock(&loadMethodLock, &runtimeLock);
686 lockdebug_lock_precedes_lock(&loadMethodLock, &DemangleCacheLock);
687 #else
688 lockdebug_lock_precedes_lock(&loadMethodLock, &methodListLock);
689 lockdebug_lock_precedes_lock(&loadMethodLock, &classLock);
690 lockdebug_lock_precedes_lock(&loadMethodLock, &NXUniqueStringLock);
691 lockdebug_lock_precedes_lock(&loadMethodLock, &impLock);
692 #endif
693 lockdebug_lock_precedes_lock(&loadMethodLock, &selLock);
694 lockdebug_lock_precedes_lock(&loadMethodLock, &cacheUpdateLock);
695 lockdebug_lock_precedes_lock(&loadMethodLock, &objcMsgLogLock);
696 lockdebug_lock_precedes_lock(&loadMethodLock, &AltHandlerDebugLock);
697 lockdebug_lock_precedes_lock(&loadMethodLock, &AssociationsManagerLock);
698 SideTableLocksSucceedLock(&loadMethodLock);
699 PropertyLocks.succeedLock(&loadMethodLock);
700 StructLocks.succeedLock(&loadMethodLock);
701 CppObjectLocks.succeedLock(&loadMethodLock);
702
703 // PropertyLocks and CppObjectLocks and AssociationManagerLock
704 // precede everything because they are held while objc_retain()
705 // or C++ copy are called.
706 // (StructLocks do not precede everything because it calls memmove only.)
707 auto PropertyAndCppObjectAndAssocLocksPrecedeLock = [&](const void *lock) {
708 PropertyLocks.precedeLock(lock);
709 CppObjectLocks.precedeLock(lock);
710 lockdebug_lock_precedes_lock(&AssociationsManagerLock, lock);
711 };
712 #if __OBJC2__
713 PropertyAndCppObjectAndAssocLocksPrecedeLock(&runtimeLock);
714 PropertyAndCppObjectAndAssocLocksPrecedeLock(&DemangleCacheLock);
715 #else
716 PropertyAndCppObjectAndAssocLocksPrecedeLock(&methodListLock);
717 PropertyAndCppObjectAndAssocLocksPrecedeLock(&classLock);
718 PropertyAndCppObjectAndAssocLocksPrecedeLock(&NXUniqueStringLock);
719 PropertyAndCppObjectAndAssocLocksPrecedeLock(&impLock);
720 #endif
721 PropertyAndCppObjectAndAssocLocksPrecedeLock(&classInitLock);
722 PropertyAndCppObjectAndAssocLocksPrecedeLock(&selLock);
723 PropertyAndCppObjectAndAssocLocksPrecedeLock(&cacheUpdateLock);
724 PropertyAndCppObjectAndAssocLocksPrecedeLock(&objcMsgLogLock);
725 PropertyAndCppObjectAndAssocLocksPrecedeLock(&AltHandlerDebugLock);
726
727 SideTableLocksSucceedLocks(PropertyLocks);
728 SideTableLocksSucceedLocks(CppObjectLocks);
729 SideTableLocksSucceedLock(&AssociationsManagerLock);
730
731 PropertyLocks.precedeLock(&AssociationsManagerLock);
732 CppObjectLocks.precedeLock(&AssociationsManagerLock);
733
734 #if __OBJC2__
735 lockdebug_lock_precedes_lock(&classInitLock, &runtimeLock);
736 #endif
737
738 #if __OBJC2__
739 // Runtime operations may occur inside SideTable locks
740 // (such as storeWeak calling getMethodImplementation)
741 SideTableLocksPrecedeLock(&runtimeLock);
742 SideTableLocksPrecedeLock(&classInitLock);
743 // Some operations may occur inside runtimeLock.
744 lockdebug_lock_precedes_lock(&runtimeLock, &selLock);
745 lockdebug_lock_precedes_lock(&runtimeLock, &cacheUpdateLock);
746 lockdebug_lock_precedes_lock(&runtimeLock, &DemangleCacheLock);
747 #else
748 // Runtime operations may occur inside SideTable locks
749 // (such as storeWeak calling getMethodImplementation)
750 SideTableLocksPrecedeLock(&methodListLock);
751 SideTableLocksPrecedeLock(&classInitLock);
752 // Method lookup and fixup.
753 lockdebug_lock_precedes_lock(&methodListLock, &classLock);
754 lockdebug_lock_precedes_lock(&methodListLock, &selLock);
755 lockdebug_lock_precedes_lock(&methodListLock, &cacheUpdateLock);
756 lockdebug_lock_precedes_lock(&methodListLock, &impLock);
757 lockdebug_lock_precedes_lock(&classLock, &selLock);
758 lockdebug_lock_precedes_lock(&classLock, &cacheUpdateLock);
759 #endif
760
761 // Striped locks use address order internally.
762 SideTableDefineLockOrder();
763 PropertyLocks.defineLockOrder();
764 StructLocks.defineLockOrder();
765 CppObjectLocks.defineLockOrder();
766 }
767 // LOCKDEBUG
768 #endif
769
770 static bool ForkIsMultithreaded;
771 void _objc_atfork_prepare()
772 {
773 // Save threaded-ness for the child's use.
774 ForkIsMultithreaded = pthread_is_threaded_np();
775
776 lockdebug_assert_no_locks_locked();
777 lockdebug_setInForkPrepare(true);
778
779 loadMethodLock.lock();
780 PropertyLocks.lockAll();
781 CppObjectLocks.lockAll();
782 AssociationsManagerLock.lock();
783 SideTableLockAll();
784 classInitLock.enter();
785 #if __OBJC2__
786 runtimeLock.write();
787 DemangleCacheLock.lock();
788 #else
789 methodListLock.lock();
790 classLock.lock();
791 NXUniqueStringLock.lock();
792 impLock.lock();
793 #endif
794 selLock.write();
795 cacheUpdateLock.lock();
796 objcMsgLogLock.lock();
797 AltHandlerDebugLock.lock();
798 StructLocks.lockAll();
799 crashlog_lock.lock();
800
801 lockdebug_assert_all_locks_locked();
802 lockdebug_setInForkPrepare(false);
803 }
804
805 void _objc_atfork_parent()
806 {
807 lockdebug_assert_all_locks_locked();
808
809 CppObjectLocks.unlockAll();
810 StructLocks.unlockAll();
811 PropertyLocks.unlockAll();
812 AssociationsManagerLock.unlock();
813 AltHandlerDebugLock.unlock();
814 objcMsgLogLock.unlock();
815 crashlog_lock.unlock();
816 loadMethodLock.unlock();
817 cacheUpdateLock.unlock();
818 selLock.unlockWrite();
819 SideTableUnlockAll();
820 #if __OBJC2__
821 DemangleCacheLock.unlock();
822 runtimeLock.unlockWrite();
823 #else
824 impLock.unlock();
825 NXUniqueStringLock.unlock();
826 methodListLock.unlock();
827 classLock.unlock();
828 #endif
829 classInitLock.leave();
830
831 lockdebug_assert_no_locks_locked();
832 }
833
834 void _objc_atfork_child()
835 {
836 // Turn on +initialize fork safety enforcement if applicable.
837 if (ForkIsMultithreaded && !DisableInitializeForkSafety) {
838 MultithreadedForkChild = true;
839 }
840
841 lockdebug_assert_all_locks_locked();
842
843 CppObjectLocks.forceResetAll();
844 StructLocks.forceResetAll();
845 PropertyLocks.forceResetAll();
846 AssociationsManagerLock.forceReset();
847 AltHandlerDebugLock.forceReset();
848 objcMsgLogLock.forceReset();
849 crashlog_lock.forceReset();
850 loadMethodLock.forceReset();
851 cacheUpdateLock.forceReset();
852 selLock.forceReset();
853 SideTableForceResetAll();
854 #if __OBJC2__
855 DemangleCacheLock.forceReset();
856 runtimeLock.forceReset();
857 #else
858 impLock.forceReset();
859 NXUniqueStringLock.forceReset();
860 methodListLock.forceReset();
861 classLock.forceReset();
862 #endif
863 classInitLock.forceReset();
864
865 lockdebug_assert_no_locks_locked();
866 }
867
868
869 /***********************************************************************
870 * _objc_init
871 * Bootstrap initialization. Registers our image notifier with dyld.
872 * Called by libSystem BEFORE library initialization time
873 **********************************************************************/
874
875 void _objc_init(void)
876 {
877 static bool initialized = false;
878 if (initialized) return;
879 initialized = true;
880
881 // fixme defer initialization until an objc-using image is found?
882 environ_init();
883 tls_init();
884 static_init();
885 lock_init();
886 exception_init();
887
888 _dyld_objc_notify_register(&map_images, load_images, unmap_image);
889 }
890
891
892 /***********************************************************************
893 * _headerForAddress.
894 * addr can be a class or a category
895 **********************************************************************/
896 static const header_info *_headerForAddress(void *addr)
897 {
898 #if __OBJC2__
899 const char *segnames[] = { "__DATA", "__DATA_CONST", "__DATA_DIRTY" };
900 #else
901 const char *segnames[] = { "__OBJC" };
902 #endif
903 header_info *hi;
904
905 for (hi = FirstHeader; hi != NULL; hi = hi->getNext()) {
906 for (size_t i = 0; i < sizeof(segnames)/sizeof(segnames[0]); i++) {
907 unsigned long seg_size;
908 uint8_t *seg = getsegmentdata(hi->mhdr(), segnames[i], &seg_size);
909 if (!seg) continue;
910
911 // Is the class in this header?
912 if ((uint8_t *)addr >= seg && (uint8_t *)addr < seg + seg_size) {
913 return hi;
914 }
915 }
916 }
917
918 // Not found
919 return 0;
920 }
921
922
923 /***********************************************************************
924 * _headerForClass
925 * Return the image header containing this class, or NULL.
926 * Returns NULL on runtime-constructed classes, and the NSCF classes.
927 **********************************************************************/
928 const header_info *_headerForClass(Class cls)
929 {
930 return _headerForAddress(cls);
931 }
932
933
934 /**********************************************************************
935 * secure_open
936 * Securely open a file from a world-writable directory (like /tmp)
937 * If the file does not exist, it will be atomically created with mode 0600
938 * If the file exists, it must be, and remain after opening:
939 * 1. a regular file (in particular, not a symlink)
940 * 2. owned by euid
941 * 3. permissions 0600
942 * 4. link count == 1
943 * Returns a file descriptor or -1. Errno may or may not be set on error.
944 **********************************************************************/
945 int secure_open(const char *filename, int flags, uid_t euid)
946 {
947 struct stat fs, ls;
948 int fd = -1;
949 bool truncate = NO;
950 bool create = NO;
951
952 if (flags & O_TRUNC) {
953 // Don't truncate the file until after it is open and verified.
954 truncate = YES;
955 flags &= ~O_TRUNC;
956 }
957 if (flags & O_CREAT) {
958 // Don't create except when we're ready for it
959 create = YES;
960 flags &= ~O_CREAT;
961 flags &= ~O_EXCL;
962 }
963
964 if (lstat(filename, &ls) < 0) {
965 if (errno == ENOENT && create) {
966 // No such file - create it
967 fd = open(filename, flags | O_CREAT | O_EXCL, 0600);
968 if (fd >= 0) {
969 // File was created successfully.
970 // New file does not need to be truncated.
971 return fd;
972 } else {
973 // File creation failed.
974 return -1;
975 }
976 } else {
977 // lstat failed, or user doesn't want to create the file
978 return -1;
979 }
980 } else {
981 // lstat succeeded - verify attributes and open
982 if (S_ISREG(ls.st_mode) && // regular file?
983 ls.st_nlink == 1 && // link count == 1?
984 ls.st_uid == euid && // owned by euid?
985 (ls.st_mode & ALLPERMS) == (S_IRUSR | S_IWUSR)) // mode 0600?
986 {
987 // Attributes look ok - open it and check attributes again
988 fd = open(filename, flags, 0000);
989 if (fd >= 0) {
990 // File is open - double-check attributes
991 if (0 == fstat(fd, &fs) &&
992 fs.st_nlink == ls.st_nlink && // link count == 1?
993 fs.st_uid == ls.st_uid && // owned by euid?
994 fs.st_mode == ls.st_mode && // regular file, 0600?
995 fs.st_ino == ls.st_ino && // same inode as before?
996 fs.st_dev == ls.st_dev) // same device as before?
997 {
998 // File is open and OK
999 if (truncate) ftruncate(fd, 0);
1000 return fd;
1001 } else {
1002 // Opened file looks funny - close it
1003 close(fd);
1004 return -1;
1005 }
1006 } else {
1007 // File didn't open
1008 return -1;
1009 }
1010 } else {
1011 // Unopened file looks funny - don't open it
1012 return -1;
1013 }
1014 }
1015 }
1016
1017
1018 #if TARGET_OS_IPHONE
1019
1020 const char *__crashreporter_info__ = NULL;
1021
1022 const char *CRSetCrashLogMessage(const char *msg)
1023 {
1024 __crashreporter_info__ = msg;
1025 return msg;
1026 }
1027 const char *CRGetCrashLogMessage(void)
1028 {
1029 return __crashreporter_info__;
1030 }
1031
1032 #endif
1033
1034 // TARGET_OS_MAC
1035 #else
1036
1037
1038 #error unknown OS
1039
1040
1041 #endif