簡體   English   中英

如何在gdb中逐步通過longjmp

[英]How to step through a longjmp in gdb

我正在嘗試修復其他人編寫的代碼中的錯誤,並且試圖在gdb中逐步解決該問題。 但是我打的一行是對longjmp()的調用,在該行上打了“ next”之后,gdb繼續常規執行,而不是中斷正在執行的下一個源代碼行。 如果我在longjmp()行上嘗試“ step”,則會發生類似的繼續。 在longjmp()之后正在執行的下一個源代碼行上,有沒有什么我可以用來中斷的gdb命令?

值得注意的是,gdb的行為與系統有關。

在Linux上,通過longjmpthrow next工作大致與您期望的一樣:如果非本地跳轉的目標位於當前幀或當前幀之上,則執行將在此處停止。

這是在longjmpthrow實現中使用調試鈎子實現的。 對於throw這可以通過輔助函數(較舊的方法)和所謂的SystemTap探針(也稱為“ sdt探針”)來完成。 對於longjmp僅使用glibc中的sdt探針完成此操作。

為此,必須將探針支持編譯到相關的庫中。 您可以使用readelf -n檢查。 至少Fedora可以正確執行此操作。

從理論上講,有可能為gdb中的其他平台實現對longjmp支持。 但是,這可能並不簡單。

您可以嘗試解碼jmp_buf ,如其他注釋中所述。 但是請注意,出於安全原因,在某些系統(例如Linux)上, jmp_buf的目標PC已編碼。 因此,您將必須弄清楚如何對其進行解碼。

解決此問題的另一種方法是簡單地單步執行longjmp本身。 在此處設置一個斷點,例如break longjmp ; 使用disassemble查看組裝; 然后si直到您逐步完成將執行轉移到目標的指令為止。

您需要通過setjmp非零返回碼之后的行上設置斷點。

例如:

#include <stdio.h>
#include <setjmp.h>

jmp_buf jb;

void f1()
{
    printf("jumping\n");
    longjmp(jb, 1);
    printf("what???\n");
}

int main()
{
    if (!setjmp(jb)) {
        printf("calling f1\n");
        f1();
    } else {
        printf("jumped!!\n");    // line 19
    }
    return 0;
}

調用longjmp ,要執行的下一行是第19行(請參見注釋)。 因此,在這種情況下,請在gdb提示符下運行break 19 ,然后在longjmp調用之后停在該行。

gdb輸出:

(gdb) break 19
Breakpoint 2 at 0x40056d: file /tmp/x1.c, line 19.
(gdb) start
Temporary breakpoint 3 at 0x400549: file /tmp/x1.c, line 15.
Starting program: /tmp/x1
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x2aaaaaaab000

Temporary breakpoint 3, main () at /tmp/x1.c:15
15          if (!setjmp(jb)) {
(gdb) step
16              printf("calling f1\n");
(gdb)
calling f1
17              f1();
(gdb)
f1 () at /tmp/x1.c:8
8           printf("jumping\n");
(gdb)
jumping
9           longjmp(jb, 1);
(gdb)

Breakpoint 2, main () at /tmp/x1.c:19
19              printf("jumped!!\n");
(gdb)
jumped!!
21          return 0;
(gdb)
22      }
(gdb)
0x0000003fa441d9f4 in __libc_start_main () from /lib64/libc.so.6
(gdb)

在longjmp()之后正在執行的下一個源代碼行上,有沒有什么我可以用來中斷的gdb命令?

據我所知,不。 您需要在調用堆棧中追溯jmp_buf的起源,以找到填充它的setjmp() 如果源中的setjmp()調用很少,則可以考慮在每個調用之后設置一個斷點。 否則,您可能只是單步執行程序,在傳遞的每個setjmp()之后設置一個斷點。

還要注意,當達到相應的longjmp()時,您確實應該在調用堆棧中的一個函數中找到相關的setjmp() ,否則jmp_buf無效。

您可以使用bt命令來獲取調用堆棧,使用frame命令來切換並檢查堆棧中的任何幀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM