如何在程序完成之前循环GDB脚本?

use*_*621 8 macros gdb loops while-loop

define traverse
    while(CONDITION)
        if $start == 0
            set $start = 1
            print_node
            print_rss_item
        else
            continue
            print_node
            print_rss_item
        end
    end
end
Run Code Online (Sandbox Code Playgroud)

如果程序完成,我需要什么条件来停止循环?

Pet*_*eoh 7

看看你的gdb脚本:

define traverse
    while(CONDITION)
        if $start == 0
            set $start = 1
            print_node
            print_rss_item
        else
            continue
            print_node
            print_rss_item
        end
    end
end
Run Code Online (Sandbox Code Playgroud)

有几点需要注意:

  1. gdb脚本(所谓的"调试器")和调试对象始终以切换模式运行:无论GDB SCRIPT RUN,调试对象都暂停并且没有运行,并且每当DEBUGGEE运行时,gdb脚本都会暂停而不是运行.

  2. 为什么会这样?这是因为每当调试对象处于暂停模式(读取"ptrace()"API及其各种选项:PEEKUSER,POKEUSER,PTRACE_CONT)时,调试器实际上可以干净地(并且内存一致地)读取调试对象的内存而不用担心腐败,因此它的所有变量值等.

当调试器没有运行时,即它执行"继续"操作,其中控制被传递给调试对象,调试对象因此可以继续运行并改变自己的内存,而不用担心被另一个进程错误地读取 - 因为它不能发生了.

那么我们如何知道调试对象何时结束?当"继续"失败时,gdbscript将无法继续运行.但是如果你设置一个没有任何断点的调试对象,那么执行gdb"run"命令就会发现调试对象连续运行,而gdb脚本没有机会执行.

如果您的脚本正在运行,那么调试对象处于STOP模式,反之亦然.如果调试对象通过调用exit()结束,则gdb脚本也不会运行.

例如:

defining the macro (inside .gdbinit file):

define myloop_print
set $total = $arg0
set $i = 0
   while($i<$total)
     set $i = $i + 1
     print $i, $i
     cont
   end
end
Run Code Online (Sandbox Code Playgroud)

然后运行"gdb/bin/ls",接着是"break write"和"run -al",然后是"myloop_print 10000"(序列或顺序很重要),我们可以看到每次"写入"都会破坏gdbscript将打印出柜台.

最后执行的几行是:

Breakpoint 1, write () at ../sysdeps/unix/syscall-template.S:81
81  in ../sysdeps/unix/syscall-template.S
$40571 = 285
drwxrwxr-x   2 tthtlc tthtlc    4096 Feb 18 00:00 yocto_slide
[Inferior 1 (process 7395) exited normally]
$40572 = 286
The program is not being run.
(gdb) 
Run Code Online (Sandbox Code Playgroud)

这清楚地表明,最后一个打印的计数器是286,即使我已指定10000作为限制.

在没有运行调试对象的情况下运行宏:

(gdb) myloop_print 10000
$40573 = 1
The program is not being run.
(gdb) 
Run Code Online (Sandbox Code Playgroud)

我们可以看到gdbscript不会运行.

如果你执行"gdb/bin/ls"并后跟"myloop_print 10000"(假设宏在.gdbinit中定义),那么你将得到gdbscript运行完成10000循环 - 没有调试对象运行.


pet*_*ohn 2

简单地无限循环。当程序完成时它将退出。

define traverse
    while(1)
        if $start == 0
            set $start = 1
            print_node
            print_rss_item
        else
            continue
            print_node
            print_rss_item
        end
    end
end
Run Code Online (Sandbox Code Playgroud)