繁体   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