GDB 多執行緒除錯基本命令 實現簡介

2021-06-16 07:25:07 字數 2462 閱讀 1504

一直對gdb多執行緒除錯接觸不多,最近因為工作有了一些接觸,簡單作點記錄吧。

先介紹一下gdb多執行緒除錯的基本命令。

info threads

顯示當前可除錯的所有執行緒,每個執行緒會有乙個gdb為其分配的id,後面操作執行緒的時候會用到這個id。

前面有*的是當前除錯的執行緒。

thread id

切換當前除錯的執行緒為指定id的執行緒。

讓乙個或者多個執行緒執行gdb命令command。

讓所有被除錯執行緒執行gdb命令command。

set scheduler-locking off|on|step

估計是實際使用過多執行緒除錯的人都可以發現,在使用step或者continue命令除錯當前被除錯執行緒的時候,其他執行緒也是同時執行的,怎麼只讓被除錯程式執行呢?通過這個命令就可以實現這個需求。

off 不鎖定任何執行緒,也就是所有執行緒都執行,這是預設值。

on 只有當前被除錯程式會執行。

step 在單步的時候,除了next過乙個函式的情況(熟悉情況的人可能知道,這其實是乙個設定斷點然後continue的行為)以外,只有當前執行緒會執行。

在介紹完基本的多執行緒除錯命令後,大概介紹一下gdb多執行緒除錯的實現思路。

比較主要的**是thread.c,前面介紹的幾個命令等都是在其中實現。

thread_list這個表儲存了當前可除錯的所有執行緒的資訊。

函式add_thread_silent或者add_thread(不同版本gdb不同)用來向thread_list列表增加乙個執行緒的資訊。

函式delete_thread用來向thread_list列表刪除乙個執行緒的資訊。

上面提到的這2個函式會被有執行緒支援的target呼叫,用來增加和刪除執行緒,不同的os對執行緒的實現差異很大,這麼實現比較好的保證了gdb多執行緒除錯支援的擴充套件性。

函式info_threads_command是被命令info threads呼叫的,就是顯示thread_list列表的資訊。

函式thread_command是被命令thread呼叫,切換當前執行緒最終呼叫的函式是switch_to_thread,這個函式會先將當前除錯執行緒變數inferior_ptid,然後對暫存器和frame緩衝進行重新整理。

比較特別的是set scheduler-locking沒有實現在thread.c中,而是實現在控制被除錯程式執行的檔案infrun.c中。

對其的設定會儲存到變數scheduler_mode中,而實際使用這個變數的函式只有用來令被除錯程式執行的函式resume。在預設情況下,傳遞給target_resume的變數是resume_ptid,預設情況下其的值為resume_all,也就是告訴target程式執行的時候所有被除錯執行緒都要被執行。而當scheduler_mode設定為只讓當前執行緒執行的時候,resume_ptid將被設定為inferior_ptid,這就告訴target只有inferior_ptid的執行緒會被執行。

最後特別介紹一下linux下多執行緒的支援,基本的除錯功能在linux-nat.c中,這裡有對linux輕量級別程序本地除錯的支援。但是其在除錯多執行緒程式的時候,還需要對pthread除錯的支援,這個功能實現在linux-thread-db.c中。對pthread的除錯要通過呼叫libthread_db庫來支援。

這裡有乙個單獨的target"multi-thread",這個target有2點很特別:

第一,一般target的裝載是在呼叫相關to_open函式的時候呼叫push_target進行裝載。而這個target則不同,在其初始化的時候,就註冊了函式thread_db_new_objfile到庫檔案attach事件中。這樣當gdb為除錯程式的動態載入庫時候attach庫檔案的時候,就會呼叫這個函式thread_db_new_objfile。這樣當gdb裝載libpthread庫的時候,最終會裝載target"multi-thread"。

第二,這個target並沒有像大部分target那樣自己實現了全部除錯功能,其配合linux-nat.c的**的功能,這裡有乙個target多層結構的設計,要介紹的比較多,就不詳細介紹了。

最後介紹一下我最近遇見的乙個多執行緒除錯和解決。

基本問題是在乙個linux環境中,除錯多執行緒程式不正常,info threads看不到多執行緒的資訊。

我先用命令maintenance print target-stack看了一下target的裝載情況,發現target"multi-thread"沒有被裝載,用gdb對gdb進行除錯,發現在函式check_for_thread_db在呼叫libthread_db中的函式td_ta_new的時候,返回了td_nolibthread,所以沒有裝載target"multi-thread"。

在時候我就懷疑是不是libpthread有問題,於是檢查了一下發現了問題,這個環境中的libpthread是被strip過的,我想可能就是以為這個影響了td_ta_new對libpthread符號資訊的獲取。當我換了乙個沒有strip過的libpthread的時候,問題果然解決了。

最終我的解決辦法是拷貝了乙個.debug版本的libpthread到lib目錄中,問題解決了。

GDB 多執行緒除錯基本命令

多執行緒除錯的基本命令 顯示當前可除錯的所有執行緒。每個執行緒會有gdb為其分配的id,後面的操作會用到這個id。前面帶 號的是當前正在除錯的執行緒。切換當前除錯的執行緒為指定id的執行緒。在所有執行緒中相應的行上設定斷點 讓乙個或者多個執行緒執行gdb命令command。讓所有被除錯執行緒執行gd...

gdb除錯基本命令

gdb是乙個由gnu開源組織發布的 unix linux作業系統下的 基於命令列的 功能強大的程式除錯工具。對於一名linux下工作的c 程式設計師,gdb是必不可少的工具 對c c 程式的除錯,需要在編譯前就加上 g選項 g g hello.cpp o hello 除錯可執行檔案 gdb prog...

GDB除錯基本命令

一 列檔案清單 list l 列出產生執行檔案的源 的一部分 列出 line1 到 line2 行之間的源 gdb list line1,line2 輸出從上次呼叫list命令開始往後的10行程式 gdb list 輸出第 n 行附近的10行程式 gdb list n 輸出函式function前後的...