[英]GDB cannot step over a function if the following lines don't include a decision or branch
我在使用 GDB 在 C++ 中調試(跳過)時遇到問題。 我有一個內部開發的RTOS ,它在 PowerPC e500mc目標上運行。
軟件版本:GCC 4.9.2、gdb-server 5~(我不確定確切的版本)、GDB 7.9.1(我也試過8.3.1)。
源文件是使用-g
和-O0
參數編譯的。
如果以下幾行不包含任何跳轉、一定數量的分支指令、GDB 丟失了在函數返回時停止並繼續運行的位置,那么在單步執行函數后,問題似乎發生在 C++ 中。
我已經在 x86-64 目標版本上嘗試了相同的代碼。 它按預期運行,沒有任何問題。 首先,我檢查了 gdb-server 的目標移植部分,然后記錄了主機和目標之間的消息傳遞。 正如您在下面看到的,問題似乎出在 GDB 端,因為 GDB 本身決定在哪里放置斷點。
有利用該錯誤的示例代碼,我還添加了日志文件。 以“gdb:”開頭的行是從 GDB 到目標的消息。 我不包括 gdb-server 的響應以避免混淆。
其他行由目標打印。 <..> 是我后來加的評論。 它講述了代碼、數據或地址的含義,以及我當時所做的事情。 我還包括了 ELF 文件的相關部分,以使其更易於理解。
這里發生了什么。 首先我將我的程序加載到目標,禁用自動啟動。 該程序在內存中並等待我的命令運行。 然后我附加到調試過程。 GDB 接管並開始通信。 經過一些握手和查詢后,它會捕獲該過程。 它沒有運行,所以它在一開始就捕獲了 0x210106E8 處主函數之前的初始化代碼。 所以GDB知道,我想停在我的代碼(主),在0x21010250把一個斷點在主的第一個指令功能的堆棧操作之后。
然后程序在目標上運行並在斷點處捕獲陷阱異常。 當執行停止時,GDB 移除斷點(陷阱指令)並放回原始指令。
后來我做了一個步驟,即 int i=0 行。 GDB 設置為跟蹤模式並開始執行。
程序在運行第一條指令后捕獲跟蹤異常。 由於我不在指令步進模式,GDB 再次開始執行,直到 c 行結束,GDB 捕獲第二個跟蹤異常並到達跟蹤模式的 c 行集的末尾。
現在我們在函數調用行並再次跨步。 GDB 設置為跟蹤模式並開始執行程序。 程序調用該函數並捕獲跟蹤異常。 GDB 看到它不在我們感興趣的函數(main)中,因為我們正在跳過,並為函數返回點設置斷點。 程序開始執行並打印消息。 該函數返回並命中 0x2101025C 處的斷點。 到現在為止還挺好。
它應該在這里停止,因為我的初始命令(跳過函數調用)已完成,但仍在繼續。
現在,正如您在日志輸出中看到的那樣,GDB 開始查詢代碼塊,它之前已經完成過,但數量不多,查找前面的 52 條指令(都是i++
s)。 GDB 移除斷點並設置跟蹤模式並執行i++命令的第一條指令。
在第一條指令執行並捕獲異常后,再次查詢 52 條指令。 在這一切之后,GDB 應該設置為跟蹤模式並開始執行。 取而代之的是,它在當前 PC 之前,在它剛剛執行的指令的地址處放置一個斷點。 當跟蹤模式關閉並且執行開始時,程序將執行到完成,因為斷點不會被命中。
如果我將 i++ 的數量減少到這樣的程度,即在 52 條指令查詢中 GDB 會看到一些跳轉或分支,那么一切都會按預期進行。
如果相同的代碼編譯為 C,而不是 C++,那么一切都會按預期進行。
正如我之前提到的,在 x86 目標上運行相同的代碼,一切都按預期工作。
代碼:
#include <iostream>
using namespace std;
void printHello(void)
{
cout << "Hello, World!" << endl;
}
int main()
{
int i = 0;
printHello();
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
i++;
return 0;
}
終端輸出:
<attach to process>
gdb:qSupported:multiprocess+;qRelocInsn+
gdb:!
gdb:Hgp0.0
gdb:QNonStop:0
gdb:qTStatus
gdb:?
gdb:qXfer:osdata:read:processes:0,35b
gdb:qXfer:threads:read::0,35b
gdb:vAttach;10000
stopping 65537 @210106e8 <_posix_lib_process_start>
gdb:qC
gdb:Hgp10000.10001
gdb:g
gdb:qSymbol::
gdb:m21010250,4 <main>
gdb:m21010250,4
gdb:m21010250,4
gdb:m210151c8,4 <_ZSt9terminatev>
gdb:m2102e288,4 <_Unwind_DebugHook>
gdb:qXfer:threads:read::0,763
gdb:qXfer:osdata:read:processes:0,763
gdb:qXfer:threads:read::0,763
gdb:Z0,21010250,4
gdb:m21010250,4 <backup>
gdb:X21010250,0:
gdb:X21010250,4:}] <put breakpoint @ main>
gdb:vCont?
gdb:vCont;c:p10000.-1 <cont all, breakpoint ready>
starting 65537 @210106e8
trap callback
stopping 65537 @21010250 <stop @ breakpoint>
gdb:m21010250,4
gdb:m21010254,4
gdb:m21010258,4
gdb:m2101023c,4 <main's head>
gdb:m2101023c,4
gdb:m21010240,4
gdb:m21010244,4
gdb:m21010248,4
gdb:m2101024c,4
gdb:m21441fa0,4
gdb:g
gdb:qXfer:threads:read::0,763
gdb:X21010250,4:9 <remove breakpoint>
gdb:qXfer:threads:read::0,763
gdb:qXfer:threads:read::0,763
gdb:qXfer:threads:read::0,763
<stop @ int=0 line>
<step>
gdb:m2102e288,4 <backup>
gdb:X2102e288,4:}] <??put breakpoint>
gdb:m21010250,4
gdb:vCont;s:p10000.10001;c:p10000.-1 <stop thread, set trace>
single step set
starting 65537 @21010250
trace callback <instruction complete exception>
stopping 65537 @21010254
single step reset
gdb:m21010254,4
gdb:m21010258,4
gdb:m2101023c,4
gdb:m2101023c,4
gdb:m21010240,4
gdb:m21010244,4
gdb:m21010248,4
gdb:m2101024c,4
gdb:m21010250,4
gdb:m21441fa0,4
gdb:g
gdb:m21010254,4
gdb:vCont;s:p10000.10001;c:p10000.-1 <stop thread, set trace>
single step set
starting 65537 @21010254
trace callback <instruction complete exception>
stopping 65537 @21010258
single step reset <step done, new c line>
gdb:m21010258,4
gdb:m2101023c,4
gdb:m2101023c,4
gdb:m21010240,4
gdb:m21010244,4
gdb:m21010248,4
gdb:m2101024c,4
gdb:m21010250,4
gdb:m21441fa0,4
gdb:g
gdb:qXfer:threads:read::0,763
gdb:X2102e288,4:N <??remove breakpoint>
gdb:qXfer:threads:read::0,763
gdb:qXfer:threads:read::0,763
<stop @ printHello() line>
<step>
gdb:m2102e288,4
gdb:X2102e288,4:}] <??put breakpoint>
gdb:m21010258,4
gdb:vCont;s:p10000.10001;c:p10000.-1 <stop thread, set trace>
single step set
starting 65537 @21010258
trace callback
stopping 65537 @210101e8 <printHello>
single step reset
gdb:m210101e8,4
gdb:m210101ec,4
gdb:m210101f0,4
gdb:m210101f4,4
gdb:m210101f8,4
gdb:m210101fc,4
gdb:m21010200,4
gdb:m21010204,4
gdb:m21010208,4
gdb:m2101020c,4
gdb:m210101e8,4
gdb:g
gdb:m2101023c,4
gdb:m2101023c,4
gdb:m21010240,4
gdb:m21010244,4
gdb:m21010248,4
gdb:m2101024c,4
gdb:m21010250,4
gdb:m21441fa0,4
gdb:m2101025c,4
gdb:m2101025c,4
gdb:X2101025c,4:}] <put breakpoint>
gdb:vCont;c:p10000.-1 <cont all, breakpoint ready>
starting 65537 @210101e8
Hello World
trap callback <stop @ breakpoint>
stopping 65537 @2101025c
gdb:m2101025c,4
gdb:m21010260,4
gdb:m21010264,4
gdb:m21010268,4
gdb:m2101026c,4
gdb:m21010270,4
gdb:m21010274,4
gdb:m21010278,4
gdb:m2101027c,4
gdb:m21010280,4
gdb:m21010284,4
gdb:m21010288,4
gdb:m2101028c,4
gdb:m21010290,4
gdb:m21010294,4
gdb:m21010298,4
gdb:m2101029c,4
gdb:m210102a0,4
gdb:m210102a4,4
gdb:m210102a8,4
gdb:m210102ac,4
gdb:m210102b0,4
gdb:m210102b4,4
gdb:m210102b8,4
gdb:m210102bc,4
gdb:m210102c0,4
gdb:m210102c4,4
gdb:m210102c8,4
gdb:m210102cc,4
gdb:m210102d0,4
gdb:m210102d4,4
gdb:m210102d8,4
gdb:m210102dc,4
gdb:m210102e0,4
gdb:m210102e4,4
gdb:m210102e8,4
gdb:m210102ec,4
gdb:m210102f0,4
gdb:m210102f4,4
gdb:m210102f8,4
gdb:m210102fc,4
gdb:m21010300,4
gdb:m21010304,4
gdb:m21010308,4
gdb:m2101030c,4
gdb:m21010310,4
gdb:m21010314,4
gdb:m21010318,4
gdb:m2101031c,4
gdb:m21010320,4
gdb:m21010324,4
gdb:m21010328,4
gdb:m21010258,4
gdb:g
gdb:X2101025c,4:? <remove breakpoint>
gdb:m2101025c,4
gdb:vCont;s:p10000.10001 <stop thread, trace ready><??c:-1 neden yok>
single step set
starting 65537 @2101025c
trace callback <instruction complete exception>
stopping 65537 @21010260
single step reset
gdb:m21010260,4
gdb:m21010264,4
gdb:m21010268,4
gdb:m2101026c,4
gdb:m21010270,4
gdb:m21010274,4
gdb:m21010278,4
gdb:m2101027c,4
gdb:m21010280,4
gdb:m21010284,4
gdb:m21010288,4
gdb:m2101028c,4
gdb:m21010290,4
gdb:m21010294,4
gdb:m21010298,4
gdb:m2101029c,4
gdb:m210102a0,4
gdb:m210102a4,4
gdb:m210102a8,4
gdb:m210102ac,4
gdb:m210102b0,4
gdb:m210102b4,4
gdb:m210102b8,4
gdb:m210102bc,4
gdb:m210102c0,4
gdb:m210102c4,4
gdb:m210102c8,4
gdb:m210102cc,4
gdb:m210102d0,4
gdb:m210102d4,4
gdb:m210102d8,4
gdb:m210102dc,4
gdb:m210102e0,4
gdb:m210102e4,4
gdb:m210102e8,4
gdb:m210102ec,4
gdb:m210102f0,4
gdb:m210102f4,4
gdb:m210102f8,4
gdb:m210102fc,4
gdb:m21010300,4
gdb:m21010304,4
gdb:m21010308,4
gdb:m2101030c,4
gdb:m21010310,4
gdb:m21010314,4
gdb:m21010318,4
gdb:m2101031c,4
gdb:m21010320,4
gdb:m21010324,4
gdb:m21010328,4
gdb:m2101032c,4
gdb:m2101025c,4
gdb:m21010258,4
gdb:g
gdb:m2101025c,4
gdb:X2101025c,4:}] <HATA put breakpoint>
gdb:vCont;c:p10000.-1 <cont all><HATA -1 gönderdiği için, trace yapmıyor>
starting 65537 @21010260
void printHello(void)
{
210101e8: 94 21 ff f0 stwu r1,-16(r1)
210101ec: 7c 08 02 a6 mflr r0
210101f0: 90 01 00 14 stw r0,20(r1)
210101f4: 93 e1 00 0c stw r31,12(r1)
210101f8: 7c 3f 0b 78 mr r31,r1
cout << "Hello World" << endl;
210101fc: 3d 20 21 04 lis r9,8452
21010200: 38 69 01 78 addi r3,r9,376
21010204: 3d 20 21 04 lis r9,8452
21010208: 38 89 82 48 addi r4,r9,-32184
2101020c: 48 02 1f a9 bl 210321b4
21010210: 7c 69 1b 78 mr r9,r3
21010214: 7d 23 4b 78 mr r3,r9
21010218: 3d 20 21 03 lis r9,8451
2101021c: 38 89 26 ec addi r4,r9,9964
21010220: 48 02 25 45 bl 21032764
}
21010224: 39 7f 00 10 addi r11,r31,16
21010228: 80 0b 00 04 lwz r0,4(r11)
2101022c: 7c 08 03 a6 mtlr r0
21010230: 83 eb ff fc lwz r31,-4(r11)
21010234: 7d 61 5b 78 mr r1,r11
21010238: 4e 80 00 20 blr
2101023c <main>:
int main()
{
2101023c: 94 21 ff e0 stwu r1,-32(r1)
21010240: 7c 08 02 a6 mflr r0
21010244: 90 01 00 24 stw r0,36(r1)
21010248: 93 e1 00 1c stw r31,28(r1)
2101024c: 7c 3f 0b 78 mr r31,r1
int i = 0;
21010250: 39 20 00 00 li r9,0
21010254: 91 3f 00 08 stw r9,8(r31)
printHello();
21010258: 4b ff ff 91 bl 210101e8 <_Z10printHellov>
i++;
2101025c: 81 3f 00 08 lwz r9,8(r31)
21010260: 39 29 00 01 addi r9,r9,1
21010264: 91 3f 00 08 stw r9,8(r31)
i++;
21010268: 81 3f 00 08 lwz r9,8(r31)
2101026c: 39 29 00 01 addi r9,r9,1
21010270: 91 3f 00 08 stw r9,8(r31)
i++;
21010274: 81 3f 00 08 lwz r9,8(r31)
21010278: 39 29 00 01 addi r9,r9,1
2101027c: 91 3f 00 08 stw r9,8(r31)
問題已經解決了。 至少現在跨步工作正常。
該錯誤是由 rs6000_in_function_epilogue_frame_p() 函數引起的。
如您所見,該函數向前掃描,直到下一個 BLR 為 52(似乎很熟悉)指令。 它向后掃描,直到調整到堆棧指針。 這會導致它在來自 PC 的先前代碼上放置一個斷點,並且無法停止執行。
函數修改后只是返回 0。
我對host端沒有很深的了解,也許你會找到更好的解決方案。
我懷疑之前版本的 step 功能有設計更改,更新了 Intel 架構代碼,但忘記了 PowerPC。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.