簡體   English   中英

如果以下行不包含決策或分支,則 GDB 無法跳過函數

[英]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.

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