一、 crash log 格式
圖片來源:www.cnblogs.com/ciml/p/7422…
基本資訊:
Binary Images :
大概分三部分吧,1、基本資訊2、執行緒3、Binary Images(二進位制檔案)
1、基本資訊
重點看:
1、 CodeType: Arm-64
2、Exception Type
:崩潰型別
3、Triggered by Thread: 1
崩潰的是哪個執行緒,那麼執行緒就可以重點看對應的 thread 就好了。
2、執行緒
主要四列
第一列:呼叫堆疊序號 第二列:二進位制包名 第三列:二進位制執行時的地址 第四列: 二進位制的基地址加偏移量(偏移量是十進位制,計算時要轉為16進位制)
計算規則:執行時地址 = 起始地址 + 偏移量(轉為16進位制)
每個二進位制包的起始地址是不一樣的,在 crash log 底部會列出所有的二進位制包的名字,路徑和 起始地址和結束地址
正常情況下根據 自己的 app 的起始地址,可以通過 atos
和 dSYM
檔案,算出對應的程式碼是什麼。
atos
atos
命令的引數:
-arch : 對應的就是Code Type,`Arm-64`對應的就是 arm64。
-o : 二進位制路徑
-l : 執行時記憶體地址
複製程式碼
可以參考下面的圖片:
atos -arch arm64 -o TheElements.app.dSYM/Contents/Resources/DWARF/TheElements -l 0x1000e4000 0x00000001000effdc
算出結果:
-[AtomicElementViewController myTransitionDidStop:finished:context:]
複製程式碼
atos
後面的-l
引數可以跟好幾個地址,解析出對應的堆疊,但是第一個應該是基地址,例如:
atos -o ***.ipa.dSYM/Contents/Resources/DWARF/*** -arch arm64 -l 0x102fa8000 0x0000000103c2cd7c 0x0000000103bff898 0x0000000103bfd438
輸出:
-[BLYCrashManager didCrashAccidentHappened] (in ***) + 204
BLYCrashHandlerCallback (in ***) + 432
BLYBSDSignalHandlerCallback (in ***) + 92
複製程式碼
附上 Code Type 可能的值:
其中arm64是指架構型別,這個就需要根據APP是在哪個手機上執行決定的,這裡有個型號對應表 armv6:iPhone、iPhone2、iPhone3G armv7:iPhone4、iPhone4S armv7s:iPhone5、iPhone5C arm64:iPhone5S
3、Binary Images
0x100004000 - 0x10000ffff CrashTest arm64 <5fc8820b297631d087e5e665b261ed0c> /var/mobile/Containers/Bundle/Application/D8F09771-5B65-4403-A19C-CE77DAF32623/CrashTest.app/CrashTest
0x120070000 - 0x120097fff dyld arm64 <f958ba064181388a9658f927da42e9e7> /usr/lib/dyld
複製程式碼
分為5列:
第1列: 地址區間 ,二進位制檔案執行時 其實地址(基址)和結束地址
第2列:二進位制包名,app 的名字,動態連結庫等等
第3列:二進位制 架構型別: arm64
第4列:UUID
第5列:二進位制路徑
二、symbolicatecrash
xcode 提供的一個命令,可以符號化 crash log。 這個指令碼的地址在:
/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash
複製程式碼
可以拷貝到 usr/local/bin
目錄下,這樣就可以全域性使用了,不用每次都輸入那麼一長串。
cp /Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash /usr/local/bin
複製程式碼
把 crash.log 和 dSYM 檔案拷貝到一個目錄下面執行:
symbolicatecrash ***.crash ***.dSYM > ***_symbol.crash
複製程式碼
執行如果報錯:
Error: "DEVELOPER_DIR" is not defined at /usr/local/bin/symbolicatecrash line 69.
複製程式碼
則需要執行:
export DEVELOPER_DIR="/Applications/XCode.app/Contents/Developer"
複製程式碼
如果執行成功,就可以在當前目錄得到符號化的 crashlog 了
三、slide address
ASLR
技術Address space layout randomization
,ASLR通過將系統可執行程式隨機裝載到記憶體裡,從而防止緩衝區溢位攻擊
由於 ASLR 的緣故,導致 程式crash後生成的crash log 中的 stack address 與 對應的 symbol address 不一致,有一個偏移量 slide,slide是程式裝在時隨機生成的隨機數。
很簡單 symble address
= stack address
-slide
;
引入新的概念:
stack address
: 程式執行時執行緒棧中 所有 函式呼叫的地址
symble address
: dsym檔案中函式符號對應的地址,用此地址 在 dsym 檔案中可以 查出對應的 符號資訊。
無 ASLR 機制時 stack address
等於symble address
。
slide address
獲取程式碼:
/** 獲取載入偏移地址 */
long long getSlide()
{
long long slide = 0;
for (uint32_t i = 0; i < _dyld_image_count(); i++) {
if (_dyld_get_image_header(i)->filetype == MH_EXECUTE) {
slide = _dyld_get_image_vmaddr_slide(i);
break;
}
}
return slide;
}
複製程式碼
atos
和 symbolicatecrash
不需要獲取 Slide Address
,只要知道執行時地址就可以符號化。使用最為簡單方便。
還有其他工具如:lldb
和 Dwarfdump
就需要複雜點的計算了。
因為它們採用檔案地址(0x10000ECC4),因此您需要考慮為這些工具設定偏移量。 從 dSYM 獲取偏移量的一種方法是使用“otool”,它可以與 OSX 上的 XCode 開發人員工具一起使用。
您需要查詢 LC_SEGMENT_64(arm64)或 LC_SEGMENT(armv7,armv7s)段和“vmaddr”條目。 對於iOS,對於32位通常為0x4000,對於64位架構通常為0x100000000。
otool -l ApteligentExampleApp.dSYM > ApteligentExampleApp.otool.output
Load command 3
cmd LC_SEGMENT_64
cmdsize 1032
segname __TEXT
vmaddr 0x0000000100000000
複製程式碼
最後
參考連結: