探尋不同版本的SDK對iOS程式的影響
相同的代碼,使用不同版本的SDK來編譯,會影響MachO頭中的值, 從而使程式表現出不同的外觀。
代碼:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ UIScreen *mainScreen = [UIScreen mainScreen]; CGRect frm = [mainScreen bounds]; UIWindow *win = [[UIWindow alloc] initWithFrame:frm]; win.backgroundColor = [UIColor blueColor]; self.window = win; [win release]; [self.window makeKeyAndVisible]; return YES;}
問題:如上的代碼非常簡單,沒有任何功能, 分別使用 xcode v4.6.3 與 v5.0.2 編譯, 然後安裝到iOS8的裝置上,表現卻不同, 主要就是iOS6與iOS7之間關於狀態條的差別,如: __________
代碼都是一樣的,只是使用了不同的SDK進行編譯, 差別具體在哪裡?
說明:
xcode版本:4.6.3 VS 5.0.2 裝置:iPhone 5s,iOS 8.0 可執行檔名: APIDiff-SDK61表示使用iOS SDK 6.1 編譯出的可執行檔 APIDiff-SDK70表示使用iOS SDK 7.0編譯出的可執行檔 IPA檔案名稱: APIDiff-SDK61.ipa表示iOS SDK 6.1編譯出的安裝包 APIDiff-SDK70.ipa表示iOS SDK 7.0編譯出的安裝包
分析:
分析一:確認是可執行程式引起
驗證方法:
用APIDiff-SDK70.ipa中的可執行程式替換APIDiff-SDK61.ipa中的可執行程式,
然後使用codesign命令重新簽名,
打包,安裝到手機上後發現狀態條是透明的,
說明差別確實在可執行程式中。
重新簽名方法:
codesign -f -s 認證名 --resource-rules Payload/*.app/ResourceRules.plist Payload/*.app
分析二:比較二進位差別
既然在可執行檔中, 首先想到的是使用二進位比較工具來看看二者的差別, 結果如:
可以看到差別太大,這樣比較沒什麼意義, 這條路不可行。
分析三:比較代碼差別
既然比較二進位沒什麼意義, 那我們就比較下反組譯碼代碼, 看看是不是編譯器做了什麼手腳,
可以看到二者的代碼幾乎一樣, 具體的一點差別, 也是由不同版本的編譯器造成的, 邏輯是一樣的,因此不是代碼引起的程式外觀不同。 另外,代碼裡沒有讀什麼全域變數, 說明不是因為UIKit中有什麼預設值被編譯到程式中, 從而引起狀態條的外觀不同。
分析四:比較UIKit版本號碼對程式的影響
既然代碼沒有差別,
我們首先會想到是不是由於UIKit版本不同而引起的程式外觀不同。
雖然程式是動態連結的UIKit,
並且裝置上只有一個版本的UIKit庫,
但是我們還是要驗證下。
首先確定二者的差別,如:
可以看到二者的版本號碼確實有差別, 但是相容版本都是1.0, 理論上講不是因為這個造成程式差別。 理論是理論,我們現在正在使用排除法確定問題原因, 還是要實打實的驗證。 驗證方法:將APIDiff-SDK61中的UIKit版本號碼改成2903.23.0。 修改方法:這個值在二進位檔案中的位移為:0x6EC, 需要注意下小端問題。 修改後,重新簽名,打包安裝到手機上, 發現狀態條沒有發生變化, 因此原因不是UIKit版本號碼的差別。
分析五:使用MachOView逐項比較
走到這裡,多少有點兒黔驢技窮了,
問題就在那裡而我們卻找不到原因。
那就上最原始的工具:體力勞動,使用MachOView一項一項的對比。
從__LINKEDIT
--->LC_DYLD_INFO_ONLY
--->LC_LOAD_DYLINKER
--->LC_VERSION_MIN_IPHONEOS
在LC_VERSION_MIN_IPHONEOS中發現了一個保留值的差別:
感覺有可能這就是問題的原因, 進行驗證:修改APIDiff-SDK61,位移地址0x69C, 將值改為00070000, 重新簽名,打包安裝到手機, 發現狀態條變成透明了,問題就在這裡!
TODO:這種差別又是如何影響了程式的外觀
這種差別又是如何影響了程式的外觀,可能的原因為:
1、UIKit中會讀這個屬性。
可能性極小,UIKit只是一個庫,
而如上的差別會首先被載入器獲得,
離UIKit還很遠。
2、SpringBoard及其相關服務。
可能性大,
①:SpringBoard幾其服務本身就有繪圖的職責;
②:點擊案頭上的表徵圖,程式是由SpringBoard啟動的。