advanced fun with objective-c runtime

29
Objec&ve(C Ini&alisa&on before your app had its morning cup of coffee.

Upload: sash-zats

Post on 02-Jul-2015

199 views

Category:

Technology


3 download

DESCRIPTION

Objective-C runtime is a foundation for the awesomeness all iOS and Mac OS X developers love. We'll take a look at the core pieces that make the runtime dynamism possible

TRANSCRIPT

Page 1: Advanced fun with Objective-C runtime

Objec&ve(C*Ini&alisa&onbefore&your&app&had&its&morning&cup&of&coffee.

Page 2: Advanced fun with Objective-C runtime

Intro

objc4!library!is!open!sourced:h2p://opensource.apple.com/source/objc4/objc48646/

Page 3: Advanced fun with Objective-C runtime

Objec&ve(C• 1970&'&Alan&Kay&and&others&developed&Smalltalk.

• 1980&'&Cox&and&Love&developed&set&of&C&preprocessing&macros&to&support&Smalltalk&OOP&features.

• 1988&'&NeXT&licensed&ObjecKve'C,&added&support&to&GCC.

• 1996&'&Apple&(NeXT)&built&Mac&OS&using&ObjecKve'C.

• 2007&'&ObjecKve'C&2.0:&non'fragile&classes&(release&2007).

• 2014&'&SwiV:&ObjecKve'C&without&C.

Page 4: Advanced fun with Objective-C runtime

Ini$alisa$on• Dynamic)messaging,)associated)objects,)swizzling,)class)posing)and)more)8)this)is)where)it)all)begins.

• _objc_init

• Called)by)/usr/lib/libSystem.

• Encapsulates)all)ini>aliza>on)steps.

Page 5: Advanced fun with Objective-C runtime

Environment

environ_init

• Reads'environment'variables,'prints'help.

• Your'chance'to'specify'OBJC_HELP'and'other'flags.

Page 6: Advanced fun with Objective-C runtime

Locks

lock_init

• Sets&up&locks&requires&for&thread4safe&run6me&modifica6ons&of:

• Registered&selectors.

• Classes,&methods,&protocols,&caches&etc.

• Temporary&list&of&classes&and&protocols&to&call&+load&on.

Page 7: Advanced fun with Objective-C runtime

Excep&ons

exception_init

• Fairly(straigh-orward(excep5on(setup(with(std::set_terminate.

• _objc_default_uncaught_exception_handler(expected(to(be(overridden(by(Founda5on.

Page 8: Advanced fun with Objective-C runtime

dyld!handlers• unmap_image

• Registering*first*to*be*prepared*if*someone*unloads*image*during*the*+load.

• Finds*appropriate*headers*to*unload*&*removes*classes*from*loadable_classes*list.

• Frees*classes*&*their*isa.

Page 9: Advanced fun with Objective-C runtime

dyld!handlers

• map_images"&"load_images

• Process"the"given"images"which"are"being"mapped"in"by"dyld.

• All"class"registra:on"and"fixups"are"performed,"and"+load"methods"are"called.

• List"of"headers"is"in"boAomBup"order.

Page 10: Advanced fun with Objective-C runtime

Thank&you.

Page 11: Advanced fun with Objective-C runtime

One$more$thing.

Page 12: Advanced fun with Objective-C runtime

[obj message];

Page 13: Advanced fun with Objective-C runtime

objc_msgSend(obj, @selector(message));

Page 14: Advanced fun with Objective-C runtime

objc_msgSend

Any$message$passing$can$be$rewri0en$using$objc_msgSend

// safe releasewhile ([obj retainCount] > 0) { [obj release];}

Page 15: Advanced fun with Objective-C runtime

objc_msgSend

Any$message$passing$can$be$rewri0en$using$objc_msgSend

// fast safe releasewhile (objc_msgSend(obj, @selector(retainCount)) > 0) { (objc_msgSend(obj, @selector(release));}

Page 16: Advanced fun with Objective-C runtime

So#you#want#to#call#objc_msgSend#directly

// fast safe releasetypedef NSUInteger (*retain_count_t)(id, SEL);typedef NSUInteger (*release_t)(id, SEL);

while (((retain_count_t)objc_msgSend)(obj, sel_getUid("retainCount")) > 0) { ((release_t)objc_msgSend)(obj, sel_getUid("release"));}

Page 17: Advanced fun with Objective-C runtime

The$Objec)ve+C$language$defers$as$many$decisions$as$it$can$from$compile$)me$and$link$)me$to$run)me

!!"Objec(ve!C"Run(me"Reference.

Page 18: Advanced fun with Objective-C runtime

objc_msgSend

• Group'of'methods.

• Declared'in'message.h.

• Implemented'in'objc-msg-x86_64.s.'Wait,'what?

• arm,'arm64

• i386,'simulator-i386

• x86_64,'simulator-x86_64

• win32

Page 19: Advanced fun with Objective-C runtime

objc_msgSend

ENTRY objc_msgSend MESSENGER_START

cbz r0, LNilReceiver_f

ldr r9, [r0] // r9 = self->isa CacheLookup NORMAL // calls IMP or LCacheMiss

LCacheMiss: MESSENGER_END_SLOW ldr r9, [r0, #ISA] // class = receiver->isa b __objc_msgSend_uncached

LNilReceiver: mov r1, #0 MESSENGER_END_NIL bx lr

LMsgSendExit: END_ENTRY objc_msgSend

Page 20: Advanced fun with Objective-C runtime

objc_msgSend

• Tail&op)mised

• Dropped&support&for&vtable

• ????

Page 21: Advanced fun with Objective-C runtime

objc_msgSend:"fast"path.• Check'for'ignored'selectors'(GC)'and'short6circuit.

• Check'for'nil'target'&'tagged'pointer.

• Jump'to'nil'receiver'handler'or'cleanup'and'return.

• Return'nil'(or'primi?ve'equivalent).

• Search'the'class’s'method'cache'for'the'method'IMP.

Page 22: Advanced fun with Objective-C runtime

objc_msgSend:"slow"path

Used%once%per%unique%selector%per%class.

• Method(is(not(cached.(Lookup(the(method(IMP(in(the(class(itself.

• If(no(IMP(found,(try(to:

• Resolve(methods(using(+resolveClassMethod(or(+resolveInstanceMethod.

• Forward(using(forwarding(mechanism.

Page 23: Advanced fun with Objective-C runtime

!Warning:!The!Objec*ve,C!run*me!lets!you!uncover!many!private!implementa*on!details!of!system!classes.!You!must!not!use!

any!of!this!informa*on!in!your!final!product.

!!"Technical"Note"TN2239""iOS"Debugging"Magic"

Page 24: Advanced fun with Objective-C runtime

-[UIViewController attentionClassDumpUser:yesItsUsAgain:althoughSwizzlingAndOverridingPrivateMethodsIsFun:itWasntMuchFunWhenYourAppStoppedWorking:pleaseRefrainFromDoingSoInTheFutureOkayThan

ksBye:]

Page 25: Advanced fun with Objective-C runtime

libextobjc

Run$me'and'compiler'magic'at'its'best.

…extends(the(dynamism(of(the(Objec4ve6C(programming(language(to(support(addi4onal(pa=erns(present(in(other(programming(

languages((including(those(that(are(not(necessarily(object6oriented).

!!"h$ps://github.com/jspahrsummers/libextobjc.

Page 26: Advanced fun with Objective-C runtime

@keypath

Allows&compile,-me&verifica-on&of&key&paths.

@interface MyClass : NSObject+ (BOOL)classProperty;@property (nonatomic, assign) NSUInteger someUniqueProperty;@property (nonatomic, copy) NSArray /* MyClass */ *collection;@end

@keypath(MyClass, classProperty);// @"classProperty"

@collectionKeypath(obj.collection, MyClass.new, someUniqueProperty);// @"collection.someUniqueProperty"

Page 27: Advanced fun with Objective-C runtime

@onExit

Defines&some&code&to&be&executed&when&the&current&scope&exits.

__block BOOL cleanupBlockRun = NO;@try { @onExit { cleanupBlockRun = YES; }; [NSException raise:@"Wild exception" format:@"Absolutely unexpected"];} @catch (NSException *exception) { // your recovery code} @finally { // cleanupBlockRun == YES}

Page 28: Advanced fun with Objective-C runtime

EXTNil

nil!value!you!can!add!to!collec-ons.

NSDictionary *dictionary = @{@"foo":[EXTNil null]};dictionary[@"foo"];// [EXTNil null];

[(NSValue *)dictionary[@"foo"] CGRectValue];// (CGRect){{0, 0}, {0, 0}}

Page 29: Advanced fun with Objective-C runtime

Demo