逆向iOS SDK -- _UIImageAtPath 的實現(SDK 6.1)

proteas發表於2013-07-07

彙編程式碼:

; 狀態:R0 = imageFileName, R1 = mainBundle, R2 = isRetina

      PUSH    {R4-R7,LR}; R0 = imageFileName, R1 = mainBundle, R2 = isRetina

      ADD      R7, SP, #0xC

      PUSH.W  {R8,R10,R11}

      STR.W    R2, [SP,#0x18+var_1C]!

      MOV      R4, R0  ; R4 = R0 = imageFileName

      MOV      R0, #(selRef_length - 0x17BB0); selRef_length

      MOV      R10, R1 ; R10 = R1 = mainBundle

      ADD      R0, PC ; selRef_length

      LDR      R1, [R0] ; "length"

      MOV      R0, R4  ; R0 = R4 = imageFileName

      BLX.W    _objc_msgSend; [imageFileName length]

      MOVS     R6, #0  ; R6 = 0

      CMP      R0, #0  ; check if R0 is 0

      BEQ.W    loc_17D1C; if R0 is 0, goto the label

      MOV      R0, R4  ; R0 = R4 = imageFileName

      MOV      R1, R10 ; R1 = R10 = mainBundle

      BL     __UICacheNameForImageAtPath; arg_0:imageFileName, arg_1:mainBundle, result:com.proteas.hello_Default.png

      MOVW     R8, #(:lower16:(__MergedGlobals_36 - 0x17BD4))

      MOV      R5, R0  ; R5 = R0 = imageCacheName

      MOVT.W   R8, #(:upper16:(__MergedGlobals_36 - 0x17BD4))

      ADD      R8, PC ; __MergedGlobals_36

      ADD.W    R11, R8, #0x10; R11 = R8 + 16

      MOV      R0, R11 ; lock, OSSpinLock*, 訪問全域性變數,加鎖

      BLX.W    _OSSpinLockLock; arg_0: OSSpinLock*

      LDR.W    R0, [R8,#(dword_62C524 - 0x62C510)]; R0 = cachedImageMap, key:imageCacheName, value:UIImageObject

      MOVS      R6, #0  ; R6 = 0

      CBZ       R0, loc_17BEC; if cachedImageMap is nil, goto the label

      MOV       R1, R5  ; R1 = R5 = imageCacheName

      BLX.W _CFDictionaryGetValue; CFDictionaryGetValue(cachedImageMap, imageCacheName)

      MOV       R6, R0  ; R6 = R0 = cachedUIImageObject

loc_17BEC:

      MOV       R0, #(selRef_retainCount - 0x17BF8); selRef_retainCount

      ADD       R0, PC ; selRef_retainCount

      LDR       R1, [R0]; "retainCount"

      MOV       R0, R6  ; R0 = R6 = cachedUIImageObject

      BLX.W     _objc_msgSend; [cachedUIImageObject retainCount]

      CBNZ     R0, loc_17C08; if retainCount of cachedUIImageObject is not 0, goto the label

      MOV      R0, R11 ; lock

      BLX.W    _OSSpinLockUnlock

      B        loc_17C50

loc_17C08:

      MOV      R0, #(selRef__isCached - 0x17C14); selRef__isCached

      ADD      R0, PC ; selRef__isCached

      LDR      R1, [R0] ; R1 = "_isCached"

      MOV      R0, R6  ; R0 = R6 = cachedUIImageObject

      BLX.W    _objc_msgSend; R0 = isCached

      TST.W    R0, #0xFF; check if R0 is true

      BNE      loc_17C46; if not cached, goto the label

      MOV      R0, #(selRef_retain - 0x17C2C); selRef_retain

      ADD      R0, PC ; selRef_retain

      LDR      R1, [R0] ; "retain"

      MOV      R0, R6  ; R0 = R6 = cachedUIImageObject

      BLX.W    _objc_msgSend; [cachedUIImageObject retain]

      MOVW     R0, #(:lower16:(selRef__setCached_ - 0x17C40))

      MOVS     R2, #1  ; R2 = 1

      MOVT.W   R0, #(:upper16:(selRef__setCached_ - 0x17C40))

      ADD      R0, PC ; selRef__setCached_

      LDR      R1, [R0] ; "_setCached:"

      MOV      R0, R6  ; R0 = R6 = cachedUIImageObject

      BLX.W    _objc_msgSend ; [cachedUIImageObject _setCached:YES]

loc_17C46:

      MOV      R0, R11 ; lock

      BLX.W    _OSSpinLockUnlock;釋放鎖

      CMP      R6, #0  ; check if cachedUIImageObject is nil

      BNE      loc_17D1C; if not nil, goto the label

loc_17C50:

      MOVW     R3, #(:lower16:(_GetImageAtPath+1 - 0x17C60))

      MOV      R0, R4  ; R0 = R4 = imageFileName

      MOVT.W   R3, #(:upper16:(_GetImageAtPath+1 - 0x17C60))

      LDR      R2, [SP,#0x1C+var_1C]; R2 = isRetina

      ADD      R3, PC ; _GetImageAtPath ; R3 = _GetImageAtPath

      MOV      R1, R10 ; R1 = R10 = mainBundle

      BL    __UIImageCallFunctionForAppropriatePath; arg_0:imageFileName, arg_1 = mainBundle, arg_2 = isRetina, arg_3 = _GetImageAtPath    

      MOV      R6, R0  ; R6 = R0 = UIImageObject

      CMP      R6, #0  ; check if UIImageObject is nil

      BEQ      loc_17D1C; if failed, goto label

      MOV      R0, R11 ; lock

      BLX.W    _OSSpinLockLock

      LDR.W    R0, [R8,#0x14]; R0 = pointer to imageCacheMap

      CBNZ     R0, loc_17CAE; R1 = R5 = imageCacheName

      MOVW     R0, #(:lower16:(_kCFTypeDictionaryKeyCallBacks_ptr - 0x17C86))

      MOVS     R1, #0  ; R1 = capacity = 0

      MOVT.W R0, #(:upper16:(_kCFTypeDictionaryKeyCallBacks_ptr - 0x17C86))

      MOVS     R3, #0  ; R3 = valueCallBacks = 0

      ADD      R0, PC ; _kCFTypeDictionaryKeyCallBacks_ptr

      LDR      R2, [R0] ; _kCFTypeDictionaryKeyCallBacks

      MOVS     R0, #0  ; R0 = allocator = NULL

      BLX.W    _CFDictionaryCreateMutable ; R0 = cachedImageMap

      MOVW     R1, #(:lower16:(_kCFTypeDictionaryValueCallBacks_ptr - 0x17C9E))

      MOVS     R2, #0  ; R2 = keyCallBacks = NULL

      MOVT.W          R1, #(:upper16:(_kCFTypeDictionaryValueCallBacks_ptr - 0x17C9E))

      STR.W   R0, [R8,#0x14]

      ADD      R1, PC ; _kCFTypeDictionaryValueCallBacks_ptr

      MOVS     R0, #0  ; R0 = allocator = NULL

      LDR      R3, [R1] ; _kCFTypeDictionaryValueCallBacks

      MOVS     R1, #0  ; R1 = capacity = 0

      BLX.W    _CFDictionaryCreateMutable

      STR.W    R0, [R8,#0x18]

      LDR.W    R0, [R8,#0x14]

loc_17CAE:

      MOV      R1, R5  ; R1 = R5 = imageCacheName

      BLX.W    _CFDictionaryContainsKey

      CBNZ     R0, loc_17CF8; if has cached, goto the label

      MOVW     R0, #(:lower16:(selRef__setNamed_ - 0x17CC4))

      MOVS     R2, #1  ; R2 = YES

      MOVT.W   R0, #(:upper16:(selRef__setNamed_ - 0x17CC4))

      ADD      R0, PC ; selRef__setNamed_

      LDR      R1, [R0] ; "_setNamed:"

      MOV      R0, R6  ; R0 = R6 = UIImageObject

      BLX.W    _objc_msgSend; [UIImageObject _setNamed:YES]

      MOVW     R0, #(:lower16:(selRef__setCached_ - 0x17CD8))

      MOVS     R2, #1

      MOVT.W   R0, #(:upper16:(selRef__setCached_ - 0x17CD8))

      ADD      R0, PC ; selRef__setCached_

      LDR      R1, [R0] ; "_setCached:"

      MOV      R0, R6

      BLX.W   _objc_msgSend; [UIImageObject _setCached:YES]

      LDR.W    R0, [R8,#0x14]; R0 = cachedImageMap

      MOV      R1, R5  ; R1 = R5 = imageCacheName

      MOV      R2, R6  ; R2 = R6 = UIImageObject

      BLX.W   _CFDictionarySetValue; arg_0:cachedImageMap, arg_1 = imageCacheName, arg_2 = imageObject

      LDR.W    R0, [R8,#0x18]

      MOV      R1, R6  ; R1 = R6 = UIImageObject

      MOV      R2, R5  ; R2 = R5 = imageCacheName

      BLX.W  _CFDictionarySetValue; arg_0: dictionary, arg_1: imageObject, arg_2 = imageCacheName

      B        loc_17D16

loc_17CF8:

      MOV     R0, #(selRef_release - 0x17D04); selRef_release

      ADD     R0, PC ; selRef_release

      LDR     R1, [R0] ; "release"

      MOV     R0, R6  ; R0 = R6 = UIImageObject

      BLX.W  _objc_msgSend; [UIImageObject release]

      LDR.W  R0, [R8,#0x14]; R0 = cachedImageMap

      MOV    R1, R5  ; R1 = R5 = imageCacheName

      BLX.W  _CFDictionaryGetValue

      MOV    R6, R0  ; R6 = R0 = result UIImage instance

loc_17D16:

      MOV    R0, R11 ; lock

      BLX.W  _OSSpinLockUnlock; release spin lock

loc_17D1C:

      MOV    R0, R6  ; R0 = R6 = nil

      ADD    SP, SP, #4

      POP.W  {R8,R10,R11}

      POP     {R4-R7,PC}

 

虛擬碼:

 

NSDictionary *gCachedImageMapNameToImage =nil;

NSDictionary *gCachedImageMapImageToName =nil;

_UIImageAtPath(NSString *imageFileName,NSBundle *mainBundle,BOOL isRetina) {

      if ([imageFileNamelength] ==0)

           return nil;

      if (gCachedImageMapNameToImage ==nil) {

           gCachedImageMapNameToImage = [[NSMutableDictionaryalloc]init];

           gCachedImageMapImageToName = [[NSMutableDictionaryalloc]init];

      }

      NSString *imageCacheName =_UICacheNameForImageAtPath(imageFileName, mainBundle);

      UIImage *cachedImage = [gCachedImageMapNameToImageobjectForKey:imageCacheName];

      if (cachedImage ==nil) {

           cachedImage = _UIImageCallFunctionForAppropriatePath(imageFileName, mainBundle, isRetina,_UIImageAtPath);        

           if (cachedImage == nil) {

                 return nil;

           } else {

                 [gCachedImageMapNameToImagesetObject:cachedImageforKey:imageCacheName];

                 [gCachedImageMapImageToNamesetObject:imageCacheNameforKey:cachedImage];

                 [cachedImage _setNamed:YES];

                 [cachedImage _setCached:YES];

           }

      } else {

           if (![cachedImage _isCached]) {

                 [cachedImage _setCached:YES];

           }

      }

      return cachedImage;

}

 

相關文章