如何在GDB脚本中循环直到程序结束? [英] How to loop in a GDB script till program is finished?

查看:1207
本文介绍了如何在GDB脚本中循环直到程序结束?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 定义遍历
while(CONDITION)
if $ start == 0
set $ start = 1
print_node
print_rss_item
else
continue
print_node
print_rss_item
end
end
end

如果程序结束,我需要停止循环的条件是什么?

解决方案看看你的gdb脚本:

 定义遍历
while(CONDITION)
if $ start == 0
set $ start = 1
print_node
print_rss_item
else
continue
print_node
print_rss_item
end
end
end

需要注意的几件事:


  1. gdb脚本(所谓的调试器)和调试对象总是以切换模式:WHENEVER THE GDB SCRIPT RUN,调试对象处于暂停状态且不运行,并且每当DEBUGGEE运行时,gdb脚本暂停且不运行。

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

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



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



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



例如:

 定义宏(内部的.gdbinit文件):

定义myloop_print
set $ total = $ arg0
set $ i = 0
while($ i <$ total)
set $ i = $ i + 1
print $ i,$ i
cont
end
结束

然后运行gdb / bin / ls,然后跟着break write和run -al,然后是myloop_print 10000(序列或顺序很重要),我们可以看到每写入一次,它就会中断,gdbscript将打印出计数器。



 断点1,write()在../sysdeps/unix/syscall-template .S:81 
81 in ../sysdeps/unix/syscall-template.S
$ 40571 = 285
drwxrwxr-x 2 tttlc tthtlc 4096 Feb 18 00:00 yocto_slide
[下1(进程7395)正常退出]
$ 40572 = 286
该程序不是bei运行。
(gdb)

这清楚地显示最后一次打印的计数是286,即使我已经指定10000作为限制。



运行没有运行调试程序的宏:

 (gdb)myloop_print 10000 
$ 40573 = 1
程序没有运行。
(gdb)

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



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


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

What condition do I need to stop the loop if the program is finished?

解决方案

Looking at your gdb script:

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

Several things to note:

  1. The gdb script (so called "debugger") and debuggee are always operating in a toggling mode: WHENEVER THE GDB SCRIPT RUN, the debuggee is paused and NOT running, and whenever the DEBUGGEE is running, the gdb script is paused and NOT RUNNING.

  2. Why is this so? This is because whenever the debuggee is in paused mode (read up "ptrace()" API and its various option: PEEKUSER, POKEUSER, PTRACE_CONT) the debugger actually can cleanly (and memory-consistently) read the memory of the debuggee without fear of corruption, and thus all its variables values etc.

When debugger is not running, ie, it executed the "continue" operation, where control is passed to the debuggee, the debuggee can thus continue to run and change its own memory, without fear of wrongly being read by another process - because it cannot happened.

So how do we know when the debuggee has ended? When "continue" failed and thus the gdbscript will not continue running. But if you setup a debuggee without any breakpoints, then executing the gdb "run" command you will find the the debuggee run continuously, without the gdb script having a chance to execute.

So effectively if your script is running, then debuggee is in STOP mode, and vice versa. And if the debuggee has ended by calling exit(), the gdb script will not be running as well.

eg:

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

And then running "gdb /bin/ls" and followed by "break write" and "run -al" and then "myloop_print 10000" (the sequence or order is important), we can see that every "write" it will break and gdbscript will print out the counter.

And last few lines executed are:

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) 

Which clearly shows that the last counter printed is 286, even though I had specified 10000 as the limit.

Running the macro without the debuggee running:

(gdb) myloop_print 10000
$40573 = 1
The program is not being run.
(gdb) 

We can see that the gdbscript will not run.

And if you do "gdb /bin/ls" and followed by "myloop_print 10000" (assuming the macro is defined inside .gdbinit) then you will get gdbscript running to completion 10000 loops - without the debuggee ever running.

这篇关于如何在GDB脚本中循环直到程序结束?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆