gpt4 book ai didi

c - 如何在到达给定断点之前自动打印 GDB 中的每一行?

转载 作者:太空狗 更新时间:2023-10-29 16:24:09 28 4
gpt4 key购买 nike

我希望能够在 GDB 中设置一个断点,并让它运行到那个点 - 在这个过程中,打印出它“逐步通过”的行。

这是一个示例,基于这个带有 main 的简单文件和一个函数,以及每个函数的两个断点:

$ cat > test.c <<EOF
#include "stdio.h"

int count=0;

void doFunction(void) {
// two steps forward
count += 2;
// one step back
count--;
}

int main(void) {
// some pointless init commands;
count = 1;
count += 2;
count = 0;
//main loop
while(1) {
doFunction();
printf("%d\n", count);
}
}
EOF

$ gcc -g -Wall test.c -o test.exe
$ chmod +x test.exe
$ gdb -se test.exe
...
Reading symbols from /path/to/test.exe...done.
(gdb) b main
Breakpoint 1 at 0x80483ec: file test.c, line 14.
(gdb) b doFunction
Breakpoint 2 at 0x80483c7: file test.c, line 7.

要启动 session ,我需要运行 ( r ) 程序,然后该程序将在第一个断点 ( main ) 处停止:
(gdb) r
Starting program: /path/to/test.exe

Breakpoint 1, main () at test.c:14
14 count = 1;
(gdb)

在这一点上 - 例如,我可以点击继续( c );并且该过程将运行,不输出任何内容,并在请求的行处中断:
(gdb) c
Continuing.

Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb)

另一方面,不是继续 - 我可以通过使用 step ( s ) 或 next ( n ) 逐行进行;例如:
14    count = 1;
(gdb) n
15 count += 2;
(gdb) s
16 count = 0;
(gdb) s
19 doFunction();
(gdb) s

Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb) s
9 count--;
(gdb) s
10 }
(gdb) s
main () at test.c:20
20 printf("%d\n", count);
(gdb) s
...
(gdb) s
_IO_vfprintf_internal (s=Cannot access memory at address 0xe5853361
) at vfprintf.c:210
210 vfprintf.c: No such file or directory.
in vfprintf.c
(gdb) s
245 in vfprintf.c
(gdb) s
210 in vfprintf.c
(gdb) n
245 in vfprintf.c
...
(gdb) n
2006 in vfprintf.c
(gdb) n
__printf (format=0x80484f0 "%d\n") at printf.c:39
39 printf.c: No such file or directory.
in printf.c
(gdb) n
main () at test.c:21
21 }
(gdb) n
19 doFunction();
(gdb) n

Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb)

无论如何,我知道我可以按住 Enter,最后输入的命令(步骤或下一个)将重复(在第二种情况下留下更长的 session ,以显示“下一步”保持在同一级别,“步骤”步骤在被调用的函数中)。但是,正如所见,根据 step 还是 next 运行,可能需要一段时间才能达到结果 - 因此,我不想手卡在 Enter 按钮上坐 10 分钟 :)

所以,我的问题是 - 我能以某种方式指示 gdb在没有进一步用户干预的情况下运行到“断点 2” - 同时打印出它通过的行,就好像按下了步骤(或下一步)一样?

最佳答案

嗯,这并不容易 - 但我想我有点明白了:) 我经历了一系列失败的尝试(发布 here);相关代码如下。

基本上,“下一个/步骤直到断点”中的问题是如何确定您是否“在”断点,如果调试器停止(在一个步骤)。另请注意,我使用 GDB 7.2-1ubuntu11(当前适用于 Ubuntu 11.04)。所以,事情是这样的:

  • 我第一次发现关于Convenience Variables ,并认为 - 鉴于有程序计数器等可用,必须有一些 GDB 便利变量来提供“断点”状态,并且可以直接在 GDB 脚本中使用。看完后GDB reference Index然而,有一段时间,我根本找不到任何这样的变量(我的尝试是在 nub.gdb 中)
  • 由于缺少这样的“断点状态”内部变量——剩下要做的唯一一件事就是将 GDB(响应命令)的('stdout')命令行输出捕获为一个字符串,并对其进行解析(寻找“断点")
  • 然后,我发现了 Python API到 GDB,以及 gdb.execute("CMDSTR", toString=True) command - 这似乎正是捕获输出所需的内容:“默认情况下,command 产生的任何输出都会发送到 gdb 的标准输出。如果 to_string 参数为 True,则输出将由 gdb.execute 收集并作为字符串[ 1 ]”!
  • 所以,首先我尝试制作一个脚本( pygdb-nub.pygdbwrap )来利用 gdb.execute以推荐的方式;在这里失败 - 因为这个:
  • Bug 627506 – python: gdb.execute([...], to_string=True) partly prints to stdout/stderr
  • Bug 10808 – Allow GDB/Python API to capture and store GDB output
  • 然后,我想我会使用 python 脚本来 subprocess.Popen GDB 程序,同时替换其标准输入和标准输出;然后从那里继续控制 GDB ( pygdb-sub.py ) - 这也失败了......(显然,因为我没有正确重定向 stdin/out)
  • 然后,我想我会使用从 GDB 调用的 Python 脚本(通过 source ),每当 gdb.execute 时,它都会在内部 fork 到 pty 中。应该被调用,以便捕获它的输出( pygdb-fork.gdbpygdb-fork.py )......这几乎奏效了 - 因为有返回的字符串;但是 GDB 注意到有些不对劲:“[tcsetpgrp 在 terminal_inferior 中失败:不允许操作]”,并且随后的返回字符串似乎没有改变。

  • 最后,有效的方法是:临时重定向来自 gdb.execute 的 GDB 输出。到 RAM 中的日志文件(Linux: /dev/shm);然后读回它,解析它并从 python 打印它 - python 还处理一个简单的 while 循环,该循环直到到达断点为止。

    具有讽刺意味的是 - 这些通过重定向日志文件导致此解决方案的大多数错误实际上最近已在 SVN 中修复;这意味着这些将在不久的将来传播到发行版,并且可以使用 gdb.execute("CMDSTR", toString=True)直接:/然而,因为我现在不能冒险从源代码构建 GDB(并且可能会遇到可能的新不兼容问题),这对我来说也足够了 :)

    以下是相关文件(部分也在 pygdb-fork.gdbpygdb-fork.py 中):
    pygdb-logg.gdb是:
    # gdb script: pygdb-logg.gdb
    # easier interface for pygdb-logg.py stuff
    # from within gdb: (gdb) source -v pygdb-logg.gdb
    # from cdmline: gdb -x pygdb-logg.gdb -se test.exe

    # first, "include" the python file:
    source -v pygdb-logg.py

    # define shorthand for nextUntilBreakpoint():
    define nub
    python nextUntilBreakpoint()
    end

    # set up breakpoints for test.exe:
    b main
    b doFunction

    # go to main breakpoint
    run
    pygdb-logg.py是:
    # gdb will 'recognize' this as python
    # upon 'source pygdb-logg.py'
    # however, from gdb functions still have
    # to be called like:
    # (gdb) python print logExecCapture("bt")

    import sys
    import gdb
    import os

    def logExecCapture(instr):
    # /dev/shm - save file in RAM
    ltxname="/dev/shm/c.log"

    gdb.execute("set logging file "+ltxname) # lpfname
    gdb.execute("set logging redirect on")
    gdb.execute("set logging overwrite on")
    gdb.execute("set logging on")
    gdb.execute(instr)
    gdb.execute("set logging off")

    replyContents = open(ltxname, 'r').read() # read entire file
    return replyContents

    # next until breakpoint
    def nextUntilBreakpoint():
    isInBreakpoint = -1;
    # as long as we don't find "Breakpoint" in report:
    while isInBreakpoint == -1:
    REP=logExecCapture("n")
    isInBreakpoint = REP.find("Breakpoint")
    print "LOOP:: ", isInBreakpoint, "\n", REP

    基本上, pygdb-logg.gdb加载 pygdb-logg.py python脚本,设置别名 nubnextUntilBreakpoint , 并初始化 session - 其他一切都由 python 脚本处理。这是一个示例 session - 关于 OP 中的测试源:
    $ gdb -x pygdb-logg.gdb -se test.exe
    ...
    Reading symbols from /path/to/test.exe...done.
    Breakpoint 1 at 0x80483ec: file test.c, line 14.
    Breakpoint 2 at 0x80483c7: file test.c, line 7.

    Breakpoint 1, main () at test.c:14
    14 count = 1;
    (gdb) nub
    LOOP:: -1
    15 count += 2;

    LOOP:: -1
    16 count = 0;

    LOOP:: -1
    19 doFunction();

    LOOP:: 1

    Breakpoint 2, doFunction () at test.c:7
    7 count += 2;

    (gdb) nub
    LOOP:: -1
    9 count--;

    LOOP:: -1
    10 }

    LOOP:: -1
    main () at test.c:20
    20 printf("%d\n", count);

    1
    LOOP:: -1
    21 }

    LOOP:: -1
    19 doFunction();

    LOOP:: 1

    Breakpoint 2, doFunction () at test.c:7
    7 count += 2;

    (gdb)

    ...正如我想要的那样 :P 只是不知道它有多可靠(以及是否可以在 avr-gdb 中使用,这正是我需要的:) 编辑:avr-gdb 的版本Ubuntu 11.04 目前是 6.4,它不能识别 python 命令:()

    嗯,希望这对某人有所帮助,
    干杯!

    这里有一些引用:
  • GDB: error detected on stdin
  • GDB has problems with getting commands piped to STDIN
  • Re: [Gdb] How do i use GDB other input?
  • gdb doesn't accept input on stdin
  • Using gdb in an IDE - comp.os.linux.development.apps | Google Groups
  • rmathew: Terminal Sickness
  • [TUTORIAL] Calling an external program in C (Linux) - GIDForums
  • shell - how to use multiple arguments with a shebang (i.e. #!)? - Stack Overflow
  • Redirecting/storing output of shell into GDB variable? - Stack Overflow
  • Corey Goldberg: Python - Redirect or Turn Off STDOUT and STDERR
  • The Cliffs of Inanity › 9. Scripting gdb
  • gdb python scripting: where has parse_and_eval gone? - Stack Overflow
  • shell - Invoke gdb to automatically pass arguments to the program being debugged - Stack Overflow
  • Storing Files/Directories In Memory With tmpfs | HowtoForge - Linux Howtos and Tutorials
  • simple way to touch a file if it does not exist | Python | Python
  • os.fork() different in cgi-script? - Python
  • java - Writing tests that use GDB - how to capture output? - Stack Overflow
  • Debugging with GDB: How to create GDB Commands in Python - Wiki
  • GDB reference card
  • 关于c - 如何在到达给定断点之前自动打印 GDB 中的每一行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6947389/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com