我用下面的算法出來:
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_STRIP
,DEAD_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 address
和main 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
我有同樣的問題。我有一個崩潰報告提供了堆棧跟蹤,但是在我的存檔的dSYM中可以找到我的項目中沒有最後堆棧中的符號。 UUID匹配但符號全部關閉。這怎麼可能,我該如何解決這個問題?在發佈到應用商店之前,蘋果是否會修改二進制文件,從而破壞與我的dSYM的對齊? – NSProgrammer 2012-09-17 17:45:29
您必須考慮二進制幻燈片和應用程序的起始地址。您不能只使用堆棧跟蹤中的內存地址。只需使用Xcode中的symboliccrash腳本即可完成所有您需要的操作。 – Kerni 2012-09-17 17:52:30
但是,如果我所有的符號(我應該說堆棧轉儲,而不是跟蹤),這純粹給我十六進制值如何考慮「幻燈片」? – NSProgrammer 2012-09-17 17:55:35