作者 | Waleon來源 | 高效程式設計師Breakpad 是 Google 用 C++ 編寫的一個開源、跨平臺的崩潰報告系統,它支援 Windows、Linux 和 macOS,並提供了一個上傳器,可以在程序崩潰時
2021-06-17 03:05:45
Breakpad 是 Google 用 C++ 編寫的一個開源、跨平臺的崩潰報告系統,它支援 Windows、Linux 和 macOS,並提供了一個上傳器,可以在程序崩潰時向一個配置好的 URL 提交 minidump 檔案。
目前,有很多大型項目都在使用 Breakpad,例如:Google Chrome、Firefox、Google Picasa、Camino、Google Earth 等。
主頁:https://chromium.googlesource.com/breakpad/breakpad/
文件:https://chromium.googlesource.com/breakpad/breakpad/+/HEAD/docs
GitHub 地址:https://github.com/google/breakpad
工作原理
BreakPad 工作原理:
其中,包含了三個主要元件:
Breakpad client:是一個庫(即:libbreakpad_client.a),將來要整合到我們的程式中。用於寫 minidump 檔案,捕獲當前執行緒的狀態,以及可執行檔案/共享庫的標識。
Breakpad 符號轉儲工具:是一個程式(即:dump_syms),用於讀取由編譯器產生的偵錯資訊,並以 Breakpad 自己的格式生成一個符號檔案。
Breakpad minidump 處理器:是一個程式(即:minidump_stackwalk),用於讀取 minidump 檔案和符號檔案,並生成一個可讀的 C/C++ 堆棧跟蹤。
編譯安裝
下載 Breakpad 源碼;
由於 Breakpad 依賴於 LSS,所以還需要下載它(地址:https://github.com/adelshokhy112/linux-syscall-support);
將 LSS 中的 linux_syscall_support.h 檔案放至breakpad/src/third_party/lss/ 目錄下;
編譯 Breakpad,步驟非常簡單:
$ cd breakpad
$ ./configure && make
$ make
$ sudo make install
成功之後,會生成 libbreakpad_client.a 庫檔案,以及dump_syms、minidump_stackwalk 等程式。
將 Breakpad 整合到程式中
和其他第三方庫的用法一樣,要將 Breakpad 整合到程式中,先要連結生成的庫 libbreakpad_client.a,並設定包含路徑為breakpad/src/,接下來就可以 include 標頭檔案了。
為了生成 mindump 檔案,我們需要例項化一個ExceptionHandler 物件,並提供一個儲存 mindump 的路徑,以及一個回撥函數來接收關於已寫入的 mindump 的資訊:
#include "client/linux/handler/exception_handler.h"
#include <iostream>
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
void* context,
bool succeeded)
{
std::cout << "Dump path:" << descriptor.path() << std::endl;
return succeeded;
}
void crash()
{
int* a = nullptr;
*a = 1;
}
int main(int argc, char* argv[])
{
google_breakpad::MinidumpDescriptor descriptor("/tmp");
google_breakpad::ExceptionHandler eh(descriptor, nullptr, dumpCallback, nullptr, true, -1);
crash();
return 0;
}
編譯運行這個程式,會在 /tmp/ 目錄下生成一個 minidump 檔案,並在退出之前列印該檔案的路徑。
注意:在使用 Breakpad 時,需要目標程式內包含偵錯資訊,這樣dump_syms 工具才能從中解析出偵錯符號。而在預設情況下,Release 模式編譯的程式是並不包含偵錯資訊,若想包含,需要在編譯程式時新增 -g 選項。
生成可讀的堆棧跟蹤
帶偵錯資訊的目標程式有了,minidump 檔案有了,dump_syms 和minidump_stackwalk 等工具也有了,現在要做的就是生成有用的堆棧跟蹤資訊了!
1. 生成符號檔案
Breakpad 要求我們將目標程式中的偵錯符號轉換為文字格式的符號檔案,這一步需要通過 dump_syms 工具來完成。
假設,我們的程式名為 test,執行以下命令,便會生成一個名為 test.sym 的符號檔案:
$ dump_syms ./test > test.sym
2. 將符號檔案放在特定目錄下
為了使用這些符號,需要將生成的符號檔案放在特定的目錄結構中:
檢視符號檔案,第一行包含了生成目錄結構所需的資訊:
$ head -n1 test.sym
MODULE Linux x86_64 95E20E34BE203CB093B675D606A7D7D20 test
創建以上目錄結構,並將符號檔案移動到該路徑下:
$ mkdir -p ./symbols/test/95E20E34BE203CB093B675D606A7D7D20
$ mv test.sym ./symbols/test/95E20E34BE203CB093B675D606A7D7D20/
3. 生成堆棧跟蹤資訊
當一切準備就緒,minidump_stackwalk 工具就派上用場了。
只需將 mindump 檔案和符號路徑作為命令列參數傳遞給它,便能生成堆棧跟蹤資訊了。為了便於分析,可以將輸出重定向至檔案中:
$ minidump_stackwalk /tmp/48596758-1d7a-4318-15edb4af-a9186ad7.dmp ./symbols > error.log
定位 Crash 所在位置
開啟 error.log,搜尋關鍵字「crashed」,一般與它最接近的一行,就是發生崩潰時程式的堆棧資訊:
可以很清楚地看到,崩潰發生在 main.cpp 的第 16 行。
檢視我們的測試程式,與預期結果一樣:
至此,Crash 所在位置已經準確地定位到了,趕緊抓緊時間修改吧!
將上述過程指令碼化
由於以上過程會經常執行,可以將其做成自動化指令碼,不僅可有效防止步驟命令的遺忘,而且極大的加快了操作速度。
新建一個指令碼 dumptool.sh,內容如下:
#!/bin/bash
if [ $# != 3 ] ; then
echo "USAGE: $0 TARGET_NAME DMP_NAME OUTPUT_NAME"
echo " e.g.: $0 test 48596758-1d7a-4318-15edb4af-a9186ad7.dmp error.log"
exit 1;
fi
#獲取輸入參數
target_file_name=$1
dmp_file_name=$2
output_file_name=$3
getSymbol() {
echo "@getSymbol: start get symbol"
dump_syms ./$target_file_name > $target_file_name'.sym'
}
getStackTrace() {
echo "@getStackTrace: start get StackTrace"
sym_file_name=$target_file_name'.sym'
#獲取符號檔案中的第一行
line1=`head -n1 $sym_file_name`
#從第一行字元串中獲取版本號
OIFS=$IFS; IFS=" "; set -- $line1; aa=$1;bb=$2;cc=$3;dd=$4; IFS=$OIFS
version_number=$dd
#創建特定的目錄結構,並將符號檔案移進去
mkdir -p ./symbols/$target_file_name/$version_number
mv $sym_file_name ./symbols/$target_file_name/$version_number
#將堆棧跟蹤資訊重定向到檔案中
minidump_stackwalk $dmp_file_name ./symbols > $output_file_name
}
main() {
getSymbol
if [ $? == 0 ]
then
getStackTrace
fi
}
#運行main
main
使用比較簡單,先為指令碼增加可執行許可權:
$ chmod +x ./dump_tool.sh
然後執行下述命令,將二進位制檔案、minidump 檔案、輸出日誌檔案作為參數傳遞給它:
$ ./dumptool.sh ./test /tmp/48596758-1d7a-4318-15edb4af-a9186ad7.dmp error.log
完成之後,所有的堆棧跟蹤資訊就會被輸出到 error.log 檔案中了。
很好用吧,學會這個絕招,讓 C++ 崩潰無處可逃!
相關文章
作者 | Waleon來源 | 高效程式設計師Breakpad 是 Google 用 C++ 編寫的一個開源、跨平臺的崩潰報告系統,它支援 Windows、Linux 和 macOS,並提供了一個上傳器,可以在程序崩潰時
2021-06-17 03:05:45
不到一個月的時間,快手頭部主播「驢嫂平榮」已有多次在直播間帶貨山寨手機的「輝煌事蹟」。5月23日,數碼博主「科技小辛"釋出一則視訊稱,自己在短視訊平臺頭部主播「驢嫂平榮」
2021-06-17 03:04:47
大資料文摘授權轉載自機器人大講堂 轉筆,使用筷子,盤核桃等這種「在一隻手內移動物體的動作」,我們稱之為 「手內操作(In-hand manipulation)」。在傳統機械手上,手內操作通常需
2021-06-17 03:01:37
Facebook正在推出一套新的工具,以幫助組管理員掌握他們的社群,其中包括一個由AI驅動的功能,Facebook說它可以識別在評論中發生的有爭議的或不健康的對話。這個工具被稱為"衝突
2021-06-17 03:01:19
618來了,很多手機廠商為了衝擊銷量榜,旗下產品紛紛降價了,而且有的價效比很高,現在手機廠商競爭激烈,給消費者帶來了很多好處,特別是小米主打的價效比手機,拉低了手機價格,線上手機
2021-06-17 03:01:05
榮耀50 Pro的外觀設計延續了榮耀數字系列的美學基因與技術沉澱,我手上這臺榮耀50 Pro的配色叫做「初雪水晶」。從工藝上去進行考究,榮耀50 Pro使用了領先行業的雙膜雙鍍雙紋處
2021-06-17 03:00:30