我試圖修復其他人編寫的代碼中的錯誤,並且我試圖通過gdb來確定發生了什麼。但是我碰到的其中一條線是對longjmp()的調用,並且在該行上點擊「next」後,gdb將繼續執行常規執行,而不是斷開正在執行的下一個源代碼行。如果我在longjmp()行上嘗試「step」,會發生類似的情況。是否有任何gdb命令我可以用來打破longjmp()之後執行的下一個源代碼行?如何通過gdb中的longjmp步驟
回答
您需要在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)
這基本上工作。經過一番搜索,找出setjmp是最後一個setjmp,但是在非零返回足夠的setjmps之後加入了斷點之後,我終於明白了程序的進展情況。 –
是否有任何命令的gdb我可以用來對下一個源線折斷後longjmp的正在執行()?
據我所知,沒有。您需要跟蹤jmp_buf
的來源備份調用堆棧以查找填充它的setjmp()
。如果源中的setjmp()
調用很少,則可以考慮在每個調用後設置一個斷點。否則,您可能只是逐步執行該程序,在您通過每個setjmp()
後設置一個斷點。
還要注意的是,你的確應該找到的調用堆棧的功能之一相關setjmp()
達到相應longjmp()
時,否則該jmp_buf
無效。
您可以使用bt
命令獲取調用堆棧,並使用frame
命令切換到並檢查堆棧上的任何幀。
值得注意的是gdb的行爲是依賴於系統的。
在Linux上,next
在longjmp
或throw
工作約你所期望的:如果非本地跳轉的目標是和當前幀以上,執行將停在那裏。
這是在longjmp
和throw
的實現中使用調試掛鉤實現的。對於throw
,這是通過輔助函數(舊方法)和所謂的SystemTap探針(又稱「sdt探針」)完成的。對於longjmp
,只能使用glibc中的sdt探針完成此操作。
爲此,必須將探針支持編譯到相關庫中。你可以用readelf -n
查詢。至少Fedora正確地做到了這一點。
在理論上可能爲gdb中的其他平臺實現對longjmp
的支持。但是,這可能是不平凡的。
您可以嘗試解碼jmp_buf
,如其他評論中所述。但請注意,在某些系統(如Linux)中,出於安全原因編碼了jmp_buf
中的目標PC。所以你必須弄清楚如何解碼它。
解決此問題的另一種方法是簡單地單步執行longjmp
本身。在那裏設置一個斷點,如break longjmp
;使用disassemble
查看組件;然後執行si
,直到完成將執行轉移到目標的指令。
- 1. 在GDB中顯示的未知代碼步驟通過
- 2. 步驟通過Netbeans中
- 3. 立即有gdb步驟
- 4. 如何安裝谷歌通過步驟
- 5. 通過VS 2010中的HTML步驟?
- 6. 如何跳過XPath中的步驟?
- 7. Zapier:如何跳過多步驟的步驟
- 8. 在Eclipse上發生的GDB崩潰longjmp
- 9. gdb步驟調試C程序
- 10. 跳過步驟()
- 11. 通過步驟與Scapy的,impacket或pcapy
- 12. 如何在IIS7中執行此步驟,通過IIS6描述
- 13. GDB步過命令
- 14. jQuery - 如何通過不同的步驟獲得響應?
- 15. f10不通過循環步驟
- 16. 通過AJAX提交表單步驟
- 17. 步驟通過Visual Studio點擊
- 18. 試圖通過遞歸計算步驟?
- 19. 生成步驟通過與在Matlab
- 20. 使用JavaScript步驟通過CSV
- 21. 當我通過處理步驟
- 22. 如何實現步驟,通過使用RxJS一步異步處理?
- 23. 如何從另一個步驟調用Cucumber-JVM中的步驟
- 24. gdb調試問題:在gdb調試步驟中看到的幻像值
- 25. 如何跳過黃瓜步驟?
- 26. 跳過黃瓜步驟如何?
- 27. node.js請求模塊,如何通過步驟
- 28. 如何通過API編輯工作流步驟?
- 29. 如何通過步驟保護API探索雲端點?
- 30. 如何使Valgrind調試器通過一個程序步驟
你可以通過程序來執行'break main',然後'run'並保持'step'ping。然後它會在每一行提示輸入,包括longjmp()之後的一行。 (如果這回答你的問題,我會把它放在一個答案) –
如果你點擊「step」而不是「next」會發生什麼?你可以做的一件事是在處理來自'setjmp()'的非零返回值的代碼上添加一個斷點。 –
@MDXF,清楚的是,您可以使用'step'命令而不是'next'命令? OP說這對他不起作用。我發現你建議特別打破'main',但我不明白爲什麼這會在'longjmp()'之前在別的地方出現差異。 –