2012-04-20 44 views
9

我收到了一個沒有符號化的AirBrake.io崩潰報告。由於崩潰報告的格式與Apple crashlog不完全一樣,我不能像往常一樣將它放在XCode上,所以我採用了與我的XCode存檔完全相同的版本,試圖在命令行上對其進行符號化。結果如下:atos和dwarfdump不會象徵我的地址

$ atos -o kidsapp.app/kidsapp 0x0002fc4c 
0x0002fc4c (in kidsapp) 

我非常肯定我使用的是與崩潰報告相同的內部版本。所以我也試過侏儒轉儲:

$ dwarfdump --lookup 0x0002fc4c --arch armv7 kidsapp.app.dSYM 
---------------------------------------------------------------------- 
File: kidsapp.app.dSYM/Contents/Resources/DWARF/kidsapp (armv7) 
---------------------------------------------------------------------- 
Looking up address: 0x000000000002fc4c in .debug_info... not found. 
Looking up address: 0x000000000002fc4c in .debug_frame... not found. 

也沒有結果。除了使用錯誤的dSYM文件之外,還有什麼可以做錯的嗎?我知道這是正確的,因爲這是在AirBrake的崩潰報告中提到的版本,它在我的XCode存檔中。

歡迎任何想法/提示!

回答

9

首先檢查的dSYM真的是正確的一個用於應用:

dwarfdump --uuid kidsapp.app/kidsapp 
dwarfdump --uuid kidsapp.app.dSYM 

兩者都應返回相同的結果。

下一個檢查,如果有的dSYM任何有效內容

dwarfdump --all kidsapp.app.dSYM 

這應該給至少一些信息,比其他not found

我想dSYM是腐敗的。一般來說,您可能想要使用崩潰報告器,該報告器會爲您提供完整的崩潰報告,其中包含所有線程和最後一次異常回溯信息。我建議使用基於PLCrashReporter的東西,例如QuincyKit(開源SDK +服務器+你的mac上的象徵)或者HockeyApp(開源SDK +付費服務+服務器端符號)(注意:我是其中一個開發者!)

+0

我有同樣的問題。我有一個崩潰報告提供了堆棧跟蹤,但是在我的存檔的dSYM中可以找到我的項目中沒有最後堆棧中的符號。 UUID匹配但符號全部關閉。這怎麼可能,我該如何解決這個問題?在發佈到應用商店之前,蘋果是否會修改二進制文件,從而破壞與我的dSYM的對齊? – NSProgrammer 2012-09-17 17:45:29

+0

您必須考慮二進制幻燈片和應用程序的起始地址。您不能只使用堆棧跟蹤中的內存地址。只需使用Xcode中的symboliccrash腳本即可完成所有您需要的操作。 – Kerni 2012-09-17 17:52:30

+0

但是,如果我所有的符號(我應該說堆棧轉儲,而不是跟蹤),這純粹給我十六進制值如何考慮「幻燈片」? – NSProgrammer 2012-09-17 17:55:35

22

我用下面的算法出來:

slide + stack address - load address = symbol address

stack address是十六進制值,我從我的堆棧轉儲崩潰報告得到(不是.crash文件,只需堆棧轉儲)。

slide運行otool -arch armv7 -l APP_BINARY_PATH時是LC_SEGMENT CMD的vmaddr。通常我的結果是0x00001000。

load address是複雜的片。它實際上是主線程的最低堆棧地址與運行dwarfdump --arch armv7 --all DSYM_BINARY_PATH時包含符號的二進制部分的FIRST地址之間的差異。這只是main函數的符號地址。所以如果你最底層的崩潰地址是0x8000,你的主函數的符號地址是0x2000那麼你的load address是0x6000。

現在,我可以計算符號地址並將其放入atos或dwarfdump中:dwarfdump --lookup SYM_ADDR --arch armv7 APP_BINARY_PATH。轉儲

例(你可以看到load address是0x00003af4):

----------------------------------------------------------------------

文件:/Users/user/Desktop/MyApp.xcarchive/dSYMs/MyApp.app.dSYM /內容/資源/ DWARF/MyApp的(ARMv7的)

----------------------------------------------------------------------

0x00000024:[0x00003af4 - 0x00003b4e)主

0x00000098:[0x00003b50 - 0x00003d8c) - [MyAppDelegate應用中:didFinishLaunchingWithOptions:]

...轉儲

最難的部分是實現其餘的2個靜態庫我的一個d包括在鏈接到我的應用程序的二進制文件之前剝離了它們的符號!這給符號地址留下了巨大的差距,所以我最終只用了我在dSYM中需要的三分之二的符號。

一定要具有設置爲NO下面的標誌在靜態庫中的Xcode項目,這樣當你反對它鏈接,你可以在符號拉到你的應用程序的二進制文件(以後可以剝離):COPY_PHASE_STRIPDEAD_CODE_STRIPPING,和STRIP_INSTALLED_PRODUCT

現在你可能會問,「如果堆棧轉儲不包含主函數,因爲它不在主線程中,所以我無法獲取主函數的堆棧地址?」,我該怎麼辦?對此我會回答,「我沒有一個想法的線索!」。只需交叉手指,並希望獲得包含符號地址的堆棧跟蹤或使用模擬Apple的崩潰日誌的崩潰報告系統,如PLCrashReporter。

[編輯2013年5月26日] -

它帶給我的注意的是,load address是真正的Mach-O的二進制地址。雖然我上面描述的可以經常工作 - 這實際上並不正確。這可以通過CRASH REPORT獲得,但是這個答案的要點是當你沒有崩潰報告時提供崩潰的符號。我想要確定load address時最好的方法是確保我使用stack addresses登錄load address

我已經親自創建了一個記錄崩潰(不是崩潰報告)的系統,並讓它們發送到S3存儲桶,我可以稍後檢索它們以進行調試。當我開始我的應用程序時,緩存slide,load addressmain function address供我的應用程序崩潰時使用,併發送一個stack addresses

注:dyld的功能使用#include <mach-o/dyld.h>

slide = =由_dyld_get_image_vmaddr_slide(0)

load address返回的地址=由_dyld_get_image_header(0)

main function address返回的地址[NSThread callStackReturnAddresses]時 最後一個地址,稱爲主螺紋

在宕機時我是sur E要登錄[NSThread callStackReturnAddresses][NSThread callStackSymbols],以及可通過具有這種方法來檢索架構:

- (NSString*) arch 
{ 
    NSString* arch = 
#ifdef _ARM_ARCH_7 
     @"armv7"; 
#elif defined (_ARM_ARCH_6) 
     @"armv6"; 
#else 
     nil; 
#endif 

    return arch; 
} 

我還不知道怎麼的ARMv7和armv7s區分雖然。

所以這可能有助於未來。我計劃把我學到的所有東西都變成一個簡單的碰撞工具 - 比natos工具(可能是natos v2)更好。

我已經更新了北約支持load address手動供應:https://github.com/NSProgrammer/natos

+3

我創建了一個命令行工具來完成所有的辛苦工作。只需要1)xcarchive路徑,2)主函數的堆棧地址符號,3)所需符號的堆棧地址,4)感興趣的體系結構。它位於github上:https://github.com/nob1984/natos – NSProgrammer 2012-09-30 00:43:48

+0

很好的寫作,但遺憾的是它有一個重大的錯誤:加載地址是**不**你寫的。加載地址可以在崩潰報告的二進制映像部分中找到,並且是相應二進制文件的地址範圍的起始地址。 – Kerni 2012-11-21 00:36:49

+0

我使用過你的工具,但是我怎樣才能得到_mainFunctionStackAddress?我通過dwarfdump發現了我的dsym文件的一個地址並使用了它,但是他給我的結果與atos解釋的結果是一樣的,我仍然無法找到崩潰點的正確位置。 – Zhou 2012-11-27 13:12:16

0

我認爲這篇文章可以幫助你,https://stackoverflow.com/a/12559150/1773317。 喬的提交解決了我的問題。

原因是我的.app和.dSYM文件不能被聚光燈索引,所以我的XCode不能正確地標記崩潰信息。

2

爲誰某些時候不具備這樣的加載地址值:

Jan 14 11:02:39 Dennins-iPhone AppName[584] <Critical>: Stack Trace: (
    0 CoreFoundation      0x2c3084b7 <redacted> + 150 
    1 libobjc.A.dylib      0x39abec8b objc_exception_throw + 38 
    2 CoreFoundation      0x2c21cc35 CFRunLoopRemoveTimer + 0 
    3 AppName        0x0005a7db AppName + 272347 

我創建了一個簡單的bash幫我調試:

#! /bin/bash 
read -p "[Path] [App Name] [Stack Address] [Relative Address] " path appName runtimeAddress relativeAddress 
loadAddress=`echo "obase=16;ibase=10;$((runtimeAddress-relativeAddress))" | bc` 
atos -o $path/Payload/$appName.app/$appName -l $loadAddress $runtimeAddress -arch armv7 

它只是讀取應用程序的路徑,應用程序名稱,運行時地址以及「+」信號(十進制值)後的值,然後查找加載地址的值以運行atos命令。