|
From: | Maxthon Chan |
Subject: | __NSCF** classes and libobjc2 dependency on C++ runtime |
Date: | Tue, 04 Jun 2013 06:45:19 +0800 |
I did some research on how Apple implemented Objective-C exceptions and CoreFoundation on iOS (iOS 6.1.3 on iPhone 4S) and I found something that we can use. If you want me to test anything, please reply to this Email and I will test it for you. I have three devices to test: iOS 6.1.3 on iPhone 4S (armv7) and iPad 2 (armv7), as well as OS X 10.8.3 on my MacBook Pro (x86-64 and i386 both). I may also be able to borrow an iPad 4 for testing (iOS 6.1.2, armv7s) 1) Apple's libobjc depend on LLVM's libc++abi (in Linux, it should be libsupc++). Not only Apple did that to allow proper Objective-C++, but also something more. When an Objective-C exception is triggered and not caught in Objective-C code, it will be raised as a C++ exception. This happens no matter if your code have C++ or not. Here is an crash log explaining this: (MobileDeuterium is the app I wrote. It have zero C++ in it.) Incident Identifier: 3B2E3282-1537-4261-A77A-7931E8898F06 CrashReporter Key: 821361952184b8795bbbd7dd4b9db7b36d3a208a Hardware Model: iPhone4,1 Process: MobileDeuterium [18922] Path: /var/mobile/Applications/C9064A00-2DB5-437A-9B0C-AC055C1F70A1/MobileDeuterium.app/MobileDeuterium Identifier: MobileDeuterium Version: ??? (???) Code Type: ARM (Native) Parent Process: launchd [1] Date/Time: 2013-05-26 08:45:19.713 +0800 OS Version: iOS 6.1.2 (10B146) Report Version: 104 Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Crashed Thread: 4 --- Lines truncated --- Thread 4 name: Dispatch queue: com.apple.root.default-priority Thread 4 Crashed: 0 libsystem_kernel.dylib 0x39c5e350 __pthread_kill + 8 1 libsystem_c.dylib 0x39bd511e pthread_kill + 54 2 libsystem_c.dylib 0x39c1196e abort + 90 3 libc++abi.dylib 0x391afd4a abort_message + 70 4 libc++abi.dylib 0x391acff4 default_terminate() + 20 5 libobjc.A.dylib 0x39760a74 _objc_terminate() + 144 6 libc++abi.dylib 0x391ad078 safe_handler_caller(void (*)()) + 76 7 libc++abi.dylib 0x391ad110 std::terminate() + 16 8 libc++abi.dylib 0x391ae50e __cxa_throw + 118 9 libobjc.A.dylib 0x397609ba objc_exception_throw + 90 10 CoreFoundation 0x31a46e02 -[NSObject(NSObject) doesNotRecognizeSelector:] + 166 11 CoreFoundation 0x31a4552c ___forwarding___ + 388 12 CoreFoundation 0x3199cf64 _CF_forwarding_prep_0 + 20 13 MobileDeuterium 0x0009ba36 0x97000 + 18998 14 libdispatch.dylib 0x39b7811c _dispatch_call_block_and_release + 8 15 libdispatch.dylib 0x39b7c95c _dispatch_root_queue_drain + 248 16 libdispatch.dylib 0x39b7cabc _dispatch_worker_thread2 + 80 17 libsystem_c.dylib 0x39baca0e _pthread_wqthread + 358 18 libsystem_c.dylib 0x39bac8a0 start_wqthread + 4 --- Lines truncated --- Note: iPhone4,1 is the internal identifier of iPhone 4S. 2) Toll-Free Bridging is a cross-effort of both Foundation and CoreFoundation. Try compile this code on OS X: #import <Foundation/Foundation.h> #import <CoreFoundation/CoreFoundation.h> int main(void) { @autoreleasepool { CFStringRef string = CFSTR("hello, world"); NSString *string_objc = (__bridge NSStirng *)string; NSLog("Class: %@", NSStringFromClass([string_objc class])); CFRelease(string); } return 0; } To compile: xcrun clang test.m -o test -framework Foundation -framework CoreFoundation -Wall -fobjc-arc The output will be: "Class: __NSCFString" and one explanation of that: it is a CoreFoundation object toll-free bridged over into Foundation. I saw this in my original ohttpd (on OS X) so here is my guess on how that worked: 1) All CoreFoundation objects have a complete Objective-C object structure, and its isa pointer is assigned to its Objective-C companion class. Given that Apple does not put retain counts in the object itself, this structure is only an isa pointer. 2) All CoreFoundation objects have a more or less functional Objective-C companion class. 3) For toll-free bridged objects, this companion class is a subclass of its public class cluster and have at least all important methods overridden with glue code that call into CoreFoundation functions. 4) For non-toll-free bridged objects, this companion class is a subclass of NSObject or NSProxy and implements only memory management methods. 5) CFRetain and CFRelease are stubs that call -[id<NSObject> retain] and -[id<NSObject> release]. CoreFoundation does not manage its memory directly using its own functions. Instead, all clean-ups are done by implementing a -[id<NSObject> dealloc] method in its companion Objective-C class. 6) When a Foundation object is passed into a CoreFoundation function as a parameter and the object is not subject to changes in the procedure, it is converted into its CoreFoundation counterpart, probably using -[id<NSCopying> copy] method. 7) When a Foundation object is passed into a CoreFoundation function as a parameter that will change the object itself, the function will call corresponding Foundation method(s) directly or via other CoreFoundation functions. |
signature.asc
Description: Message signed with OpenPGP using GPGMail
[Prev in Thread] | Current Thread | [Next in Thread] |