而通常我們拿到這個檔案,如果單純從客戶端那邊看(沒有 .dSYM 檔的話) 是會看到以下的情形
.Crash File
// 1:Thread 資訊
Incident Identifier: CAF9ED40-2D59-45EA-96B0-52BDA1115E9F CrashReporter Key: 30af939d26f6ecc5f0d08653b2aaf47933ad8b8e Process: TestEditor [12506] Path: /var/mobile/Applications/60ACEDBC-600E-42AF-9252-42E32188A044/TestEditor.app/TestEditor Identifier: TestEditor Version: ??? (???) Code Type: ARM (Native) Parent Process: launchd [1]// 2:基本資訊
Date/Time: 2013-09-23 11:25:56.357 +0900 OS Version: iPhone OS 3.1.3 (7E18) Report Version: 104// 3:例外
Exception Type: EXC_BAD_ACCESS (SIGBUS) Exception Codes: KERN_PROTECTION_FAILURE at 0x00000059 Crashed Thread: 0// 4:Back Trace
Thread 0 Crashed: 0 UIKit 0x332b98d8 0x331b2000 + 1079512 1 UIKit 0x3321d1a8 0x331b2000 + 438696 2 UIKit 0x3321d028 0x331b2000 + 438312 3 UIKit 0x332b9628 0x331b2000 + 1078824 4 UIKit 0x33209d70 0x331b2000 + 359792 5 UIKit 0x33209c08 0x331b2000 + 359432 6 QuartzCore 0x324cc05c 0x324ae000 + 122972 7 QuartzCore 0x324cbe64 0x324ae000 + 122468 8 CoreFoundation 0x3244f4bc 0x323f8000 + 357564 9 CoreFoundation 0x3244ec18 0x323f8000 + 355352 10 GraphicsServices 0x342e91c0 0x342e5000 + 16832 11 UIKit 0x331b5c28 0x331b2000 + 15400 12 UIKit 0x331b4228 0x331b2000 + 8744 13 TestEditor 0x00002c3a 0x1000 + 7226 14 TestEditor 0x00002c04 0x1000 + 7172// 5:Thread State
Thread 0 crashed with ARM Thread State (32-bit): r0: 0x00000000 r1: 0x00000000 r2: 0x00000001 r3: 0x39529fc8 r4: 0xffffffff r5: 0x2fd7d301 r6: 0x2fd7d300 r7: 0x2fd7d9d0 r8: 0x2fd7d330 r9: 0x3adbf8a8 r10: 0x2fd7d308 r11: 0x00000032 ip: 0x00000025 sp: 0x2fd7d2ec lr: 0x001bdb25 pc: 0x30301838 cpsr: 0x00000010// 6:二進制映像
Binary Images: 0x1000 - 0x7fff +TestEditor armv7 /var/mobile/Applications/60ACEDBC-600E-42AF-9252-42E32188A044/TestEditor.app/TestEditor
我們可以看到4:Back Trace 那邊,後面的記憶體位置 對我們而言沒任何的幫助。
因此,如果遇到這種情況的話,我們就必須將這些memory address 丟到memory stack 下去尋找。
而apple也提供了我們一個很好用的工具 symbolicatecrash 我們只需將 crash file與 dSYM file一併給他,就可以得到以下的結果
格式 : symbolicatecrash [crash file] [dSYM file]
Thread 0 Crashed: 0 UIKit 0x332b98d8 -[UIWindowController transitionViewDidComplete:fromView:toView:] + 668 1 UIKit 0x3321d1a8 -[UITransitionView notifyDidCompleteTransition:] + 160 2 UIKit 0x3321d028 -[UITransitionView _didCompleteTransition:] + 704 3 UIKit 0x332b9628 -[UITransitionView _transitionDidStop:finished:] + 44 4 UIKit 0x33209d70 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 284 5 UIKit 0x33209c08 -[UIViewAnimationState animationDidStop:finished:] + 60 6 QuartzCore 0x324cc05c _ZL23run_animation_callbacksdPv + 440 7 QuartzCore 0x324cbe64 _ZN2CAL14timer_callbackEP16__CFRunLoopTimerPv + 156 8 CoreFoundation 0x3244f4bc CFRunLoopRunSpecific + 2192 9 CoreFoundation 0x3244ec18 CFRunLoopRunInMode + 44 10 GraphicsServices 0x342e91c0 GSEventRunModal + 188 11 UIKit 0x331b5c28 -[UIApplication _run] + 552 12 UIKit 0x331b4228 UIApplicationMain + 960 13 TestEditor 0x00002c3a main (main.m:14) 14 TestEditor 0x00002c04 start
這時候對應adress的method name全都出來了!!但是相信這時候應該很多人會有疑問,symbolicatecrash 在哪裡呢? .dSYM file 又在哪裡呢?Symbolicatecrash:(預設location)
/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash
通常會將Symbolicatecrash檔案,複製到/usr/bin/ 裡面,好讓Terminate可以直接執行呼叫
sudo cp /Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash /usr/local/bin
.dSYM檔基本上預設是放在
{TARGET_BUILD}/TestEditor.app.dSYM
但是通常的情況下,是不需要有這些動作的,因為XCODE在開啟的時候,預設是會去驗證相同的UUID下的dSYM檔,而自動幫你轉好。
難道以上的都是廢話嗎?
這倒不至於,為了避免發生dSYM檔案遺失而照成mapping不到symbole,可以參照這段sh file,在release並且實機的環境下,先將dSYM複製一份到你的專案上,再用以上的方法,自行輸出產生一個LOG FILE。
另外再補充一點
atos -arch armv7 -o app name.app/app name 0x0003b508
armv7,這個要取決於你的arm的指令集,這邊也有可能是armv6, armv7s之類的,.crash file裡面有提供訊息。app name.app/app name,則是要填入你build完的app。
0x0003b508,這個則是要填入相對的address。什麼是相對的address?
address = slide Address + crash Address - image Address
slide Address 通常是0x1000,或是可用指令取得。
image Address 就是 binary image裡面對應的memory sector的起始位址。
而驗證app 與 crash 檔的UUID的指令為
xcrun dwarfdump --uuid ${dSYMInput} | tr '[:upper:]' '[:lower:]' | tr -d '-'(這行會印出uuid 與 指令集)grep {uuid} {.crash} (uuid為上述看到的uuid值,.crash為實體檔案)補上 將dSYM以及app 檔案複製一份到專案的sh file#!/bin/shif [ "${CONFIGURATION}" = "Debug" ]; thenecho “Skipping debug”exit 0;fiif [ "$EFFECTIVE_PLATFORM_NAME" == "-iphonesimulator" ]; thenecho “Skipping simulator build”exit 0;fimkdir -p "${PROJECT_DIR}/dSYM"mkdir -p "${PROJECT_DIR}/dSYM/$(date +%Y%m%d)"SRC_PATH=${TARGET_BUILD_DIR}/${DWARF_DSYM_FILE_NAME}SRC_PATH_APP=${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}#UUID PathRELATIVE_DEST_PATH_UUID=dSYM/$(date +%Y%m%d)/${EXECUTABLE_NAME}_UUIDDEST_PATH_UUID=${PROJECT_DIR}/${RELATIVE_DEST_PATH_UUID}rm -f ${DEST_PATH_UUID}xcrun dwarfdump --uuid ${SRC_PATH_APP} | tr '[:upper:]' '[:lower:]' | tr -d '-' | tr -d '(' | tr -d ')' > ${DEST_PATH_UUID}exec < $DEST_PATH_UUIDwhile read -a LINE; doUUID_NAME="${LINE[1]}_${LINE[2]}"done#dSYM PathRELATIVE_DEST_PATH=dSYM/$(date +%Y%m%d)/${EXECUTABLE_NAME}.${UUID_NAME}.app.dSYMDEST_PATH=${PROJECT_DIR}/${RELATIVE_DEST_PATH}#APP PathRELATIVE_DEST_PATH_APP=dSYM/$(date +%Y%m%d)/${EXECUTABLE_NAME}.${UUID_NAME}.appDEST_PATH_APP=${PROJECT_DIR}/${RELATIVE_DEST_PATH_APP}echo "moving ${SRC_PATH} to ${DEST_PATH}"echo "moving ${SRC_PATH_APP} to ${DEST_PATH_APP}"cp -r "${SRC_PATH}" "${DEST_PATH}"cp -r "${SRC_PATH_APP}" "${DEST_PATH_APP}"下一章 我們要來分析 如何從上述的.crash裡面劃分的六大項,來取得發生crash的地方。
沒有留言:
張貼留言