6

Swift ASM at a glance

A quick glance at Swift ASM

Swift ASM at a glance

giving a function like:

 fileprivate func createAndLoadInterstitial() {
    interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
}

What does it looks like in ASM? (ignoring those name mangling)

__text:0000000100008008                 SUB             SP, SP, #0xA0
__text:000000010000800C                 STP             X29, X30, [SP,#0x90]
__text:0000000100008010                 ADD             X29, SP, #0x90
__text:0000000100008014                 STUR            X0, [X29,#self]
__text:0000000100008018                 STUR            X0, [X29,#-0x18]
__text:000000010000801C                 BL              __TMaCSo15GADInterstitial ; type metadata accessor for __ObjC.GADInterstitial
__text:0000000100008020                 ADRP            X30, #aCaAppPub394025@PAGE ; "ca-app-pub-3940256099942544/4411468910"
__text:0000000100008024                 ADD             X30, X30, #aCaAppPub394025@PAGEOFF ; "ca-app-pub-3940256099942544/4411468910"
__text:0000000100008028                 MOV             W8, #0x26
__text:000000010000802C                 MOV             X1, X8
__text:0000000100008030                 MOV             W2, #1
__text:0000000100008034                 STUR            X0, [X29,#-0x20]
__text:0000000100008038                 MOV             X0, X30
__text:000000010000803C                 BL              __TFSSCfT21_builtinStringLiteralBp17utf8CodeUnitCountBw7isASCIIBi1__SS ; String.init(_builtinStringLiteral:Builtin.RawPointer,utf8CodeUnitCount:Builtin.Word,isASCII:Builtin.Int1)
__text:0000000100008040                 LDUR            X3, [X29,#-0x20]
__text:0000000100008044                 BL              __TFCSo15GADInterstitialCfT8adUnitIDSS_S_ ; __ObjC.GADInterstitial.__allocating_init(adUnitID:String)

Notice it first puts "ca-app-pub-3940256099942544/4411468910" into x30 and later put into x0 and then it call BL BL __TFSSCfT21_builtinStringLiteralBp17utf8CodeUnitCountBw7isASCIIBi1__SS

inside __TFSSCfT21_builtinStringLiteralBp17utf8CodeUnitCountBw7isASCIIBi1__SS:

__stubs:00000001001435D4 ; =============== S U B R O U T I N E =======================================
__stubs:00000001001435D4
__stubs:00000001001435D4
__stubs:00000001001435D4 ; String.init(_builtinStringLiteral : Builtin.RawPointer, utf8CodeUnitCount : Builtin.Word, isASCII : Builtin.Int1) -> String
__stubs:00000001001435D4 __TFSSCfT21_builtinStringLiteralBp17utf8CodeUnitCountBw7isASCIIBi1__SS
__stubs:00000001001435D4                                         ; CODE XREF: InterstitialExample.ViewController.createAndLoadInterstitial()+34↑p
__stubs:00000001001435D4                                         ; InterstitialExample.ViewController.createAndLoadInterstitial()+E4↑p ...
__stubs:00000001001435D4                 NOP
__stubs:00000001001435D8                 LDR             X16, =__imp___TFSSCfT21_builtinStringLiteralBp17utf8CodeUnitCountBw7isASCIIBi1__SS
__stubs:00000001001435DC                 BR              X16     ; __imp___TFSSCfT21_builtinStringLiteralBp17utf8CodeUnitCountBw7isASCIIBi1__SS
__stubs:00000001001435DC ; End of function String.init(_builtinStringLiteral:Builtin.RawPointer,utf8CodeUnitCount:Builtin.Word,isASCII:Builtin.Int1)
We see it does not use `x0`. Now we continue to check `BL              __TFCSo15GADInterstitialCfT8adUnitIDSS_S_`:
__text:0000000100008274 ; GoogleMobileAds::GADInterstitial __cdecl __ObjC.GADInterstitial.__allocating_init(adUnitID:String)->__ObjC.GADInterstitial()
__text:0000000100008274 __TFCSo15GADInterstitialCfT8adUnitIDSS_S_
__text:0000000100008274                                         ; CODE XREF: InterstitialExample.ViewController.createAndLoadInterstitial()+3C↑p
__text:0000000100008274
__text:0000000100008274 var_30          = -0x30
__text:0000000100008274 var_28          = -0x28
__text:0000000100008274 var_20          = -0x20
__text:0000000100008274 var_18          = -0x18
__text:0000000100008274 var_10          = -0x10
__text:0000000100008274 var_8           = -8
__text:0000000100008274 var_s0          =  0
__text:0000000100008274
__text:0000000100008274                 SUB             SP, SP, #0x40
__text:0000000100008278                 STP             X29, X30, [SP,#0x30+var_s0]
__text:000000010000827C                 ADD             X29, SP, #0x30
__text:0000000100008280                 LDR             X8, [X3]
__text:0000000100008284                 CMP             X8, #0xE
__text:0000000100008288                 MOV             X8, X3
__text:000000010000828C                 STUR            X2, [X29,#var_8]
__text:0000000100008290                 STUR            X1, [X29,#var_10]
__text:0000000100008294                 STR             X0, [SP,#0x30+var_18]
__text:0000000100008298                 STR             X3, [SP,#0x30+var_20]
__text:000000010000829C                 STR             X8, [SP,#0x30+var_28]
__text:00000001000082A0                 B.NE            loc_1000082B0
__text:00000001000082A4                 LDR             X8, [SP,#0x30+var_20]
__text:00000001000082A8                 LDR             X9, [X8,#8]
__text:00000001000082AC                 STR             X9, [SP,#0x30+var_28]
__text:00000001000082B0
__text:00000001000082B0 loc_1000082B0                           ; CODE XREF: __ObjC.GADInterstitial.__allocating_init(adUnitID:String)+2C↑j
__text:00000001000082B0                 LDR             X0, [SP,#0x30+var_28]
__text:00000001000082B4                 BL              _objc_allocWithZone
__text:00000001000082B8                 LDR             X30, [SP,#0x30+var_18]
__text:00000001000082BC                 STR             X0, [SP,#0x30+var_30]
__text:00000001000082C0                 MOV             X0, X30
__text:00000001000082C4                 LDUR            X1, [X29,#var_10]
__text:00000001000082C8                 LDUR            X2, [X29,#var_8]
__text:00000001000082CC                 LDR             X3, [SP,#0x30+var_30]
__text:00000001000082D0                 BL              __TTOFCSo15GADInterstitialcfT8adUnitIDSS_S_ ; __ObjC.GADInterstitial.init(adUnitID:String)
__text:00000001000082D4                 LDP             X29, X30, [SP,#0x30+var_s0]
__text:00000001000082D8                 ADD             SP, SP, #0x40
__text:00000001000082DC                 RET
__text:00000001000082DC ; End of function __ObjC.GADInterstitial.__allocating_init(adUnitID:String)
First, we saw it store `x0` into `[SP, #0x18]` ( `STR             X0, [SP,#0x18]`)
and later use `x30` to put back to `x0` again:
__text:00000001000082B8                 LDR             X30, [SP,#0x18]
__text:00000001000082BC                 STR             X0, [SP,#0x30+var_30]
__text:00000001000082C0                 MOV             X0, X30
and then another BL: `BL              __TTOFCSo15GADInterstitialcfT8adUnitIDSS_S_`
inside `__TTOFCSo15GADInterstitialcfT8adUnitIDSS_S_`, which is the true function `__ObjC.GADInterstitial.init(adUnitID:String)`:
__text:000000010000ACB8                 SUB             SP, SP, #0x30
__text:000000010000ACBC                 STP             X29, X30, [SP,#0x20]
__text:000000010000ACC0                 ADD             X29, SP, #0x20
__text:000000010000ACC4                 STUR            X2, [X29,#var_8]
__text:000000010000ACC8                 STR             X3, [SP,#0x20+var_10]
__text:000000010000ACCC                 BL              __TFE10FoundationSS19_bridgeToObjectiveCfT_CSo8NSString ; String._bridgeToObjectiveC()
__text:000000010000ACD0                 ADRP            X1, #selRef_initWithAdUnitID_@PAGE
__text:000000010000ACD4                 ADD             X1, X1, #selRef_initWithAdUnitID_@PAGEOFF
__text:000000010000ACD8                 LDR             X1, [X1] ; "initWithAdUnitID:"
__text:000000010000ACDC                 MOV             X2, X0
__text:000000010000ACE0                 LDR             X3, [SP,#0x20+var_10]
__text:000000010000ACE4                 STR             X0, [SP,#0x20+var_18]
__text:000000010000ACE8                 MOV             X0, X3  ; void *
__text:000000010000ACEC                 BL              _objc_msgSend

We will see it eventually calls initWithAdUnitID:, whose parameter is on x2, which is exactly previous x0.

A very simple swift function goes so long to finally get initialized, which is very different from ObjC.

ObjC counterpart

First we write the same way:

- (void)createAndLoadInterstitial {
  self.interstitial =
      [[GADInterstitial alloc] initWithAdUnitID:@"ca-app-pub-3940256099942544/4411468910"];
}

Inside its ASM code, stripping off irrelevant code:

__text:00000001000082E4                 ADRP            X8, #0x100186000
__text:00000001000082E8                 ADD             X8, X8, #0xD78  // addr of "ca-app-pub-3940256099942544/4411468910"
__text:00000001000082EC                 ADRP            X9, #0x1001CA000
__text:00000001000082F0                 ADD             X9, X9, #0xAC8 // addr of initWithAdUnitID:
__text:00000001000082F4                 LDR             X1, [X9] ; "initWithAdUnitID:"
__text:00000001000082F8                 MOV             X2, X8
__text:00000001000082FC                 BL              _objc_msgSend ; -[GADInterstitial initWithAdUnitID:]

This is the ObjC output, quite straightforward, right? Why swift makes so different?