• [原]逆向iOS SDK -- _UIImageAtPath 的实现(SDK 6.1)


     

    汇编代码:

    ; 状态: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 ([imageFileName length] == 0)

               returnnil;

       

          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) {

                     returnnil;

               } else {

                     [gCachedImageMapNameToImagesetObject:cachedImage forKey:imageCacheName];

                     [gCachedImageMapImageToNamesetObject:imageCacheName forKey:cachedImage];

                    

                     [cachedImage _setNamed:YES];

                     [cachedImage _setCached:YES];

               }

          } else {

               if (![cachedImage _isCached]) {

                     [cachedImage _setCached:YES];

               }

          }

          return cachedImage;

    }

     

  • 相关阅读:
    [RxJS] Filtering operators: throttle and throttleTime
    [RxJS] Transformation operators: debounce and debounceTime
    [AngularJS] Default Child state and nav between child state
    [RxJS] Transformation operator: bufferToggle, bufferWhen
    [RxJS] Transformation operators: delay and delayWhen
    [RxJS] Transformation operator: buffer, bufferCount, bufferTime
    [RxJS] Transformation operator: scan
    [置顶] 利用Global.asax的Application_Error实现错误记录,错误日志
    Java方法重写与方法重载
    Inside GDALAllRegister之一: 五大部分
  • 原文地址:https://www.cnblogs.com/Proteas/p/3175713.html
Copyright © 2020-2023  润新知