Linux 逐行调试

Linux 逐行调试,linux,debugging,gdb,pascal,Linux,Debugging,Gdb,Pascal,我有一个用帕斯卡写的脚本。我希望以这种方式调试它:在每一行停止,转储内存中所有变量的值,然后转到下一行。是否可以使用gdb或其他Linux开源工具来实现这一点 是可以在Pascal程序上使用gdb调试器,前提是您的Pascal编译器提供了DWARF调试信息。如果使用(即gpc),则在调用gpc时要传递。如果您使用免费的Pascal,它也可以使用fpc 使用调试信息编译Pascal程序后,您需要学习如何使用。您可能需要显示,步骤,下一步,中断,打印,帧,继续命令(togdb)以及更多命令。使用选项

我有一个用帕斯卡写的脚本。我希望以这种方式调试它:在每一行停止,转储内存中所有变量的值,然后转到下一行。是否可以使用gdb或其他Linux开源工具来实现这一点

是可以在Pascal程序上使用
gdb
调试器,前提是您的Pascal编译器提供了DWARF调试信息。如果使用(即
gpc
),则在调用
gpc
时要传递。如果您使用免费的Pascal,它也可以使用
fpc


使用调试信息编译Pascal程序后,您需要学习如何使用。您可能需要
显示
步骤
下一步
中断
打印
继续
命令(to
gdb
)以及更多命令。

使用选项
-g
编译文件:

fpc/gpc -g file.pas
为此文件运行
gdb

gdb file
设置所有需要的变量:

display first_var
display second_var
...
开始调试:

start

通过按
s
可以继续下一行。

我将演示一个概念验证,通过使用GDB的Python API逐步完成(单线程)程序,转储所有变量:

# Usage: gdb -x dump-vars-each-step.py PROGRAM

import gdb

import re
import logging

LOG_LEVEL = logging.INFO

def dump_all_vars(skip_libc_symbols=True):
    # gdb calls the source of its debug info an 'objfile'
    # libc_objfile_name. e.g. '/usr/lib/debug/lib64/libc-2.16.so.debug'
    libc_objfile_name_pattern = r'libc.*\.so'
    frame = gdb.newest_frame()
    while frame:
        symtab = frame.find_sal().symtab
        if symtab is not None:
            objfile_name = symtab.objfile.filename
        else:
            objfile_name = ''
        logging.debug('F: %s, %s' % (frame, objfile_name))
        if skip_libc_symbols and re.match(r'libc.*\.so', os.path.basename(objfile_name)):
            return
        try:
            block = frame.block()
        except RuntimeError:
            block = None
        while block:
            logging.debug('B: %s, %s' % (block, block.function))
            for symbol in block:
                try:
                    value = frame.read_var(symbol, block)
                except gdb.error:
                    # typedefs etc don't have a value
                    pass
                else:
                    sys.stdout.write('%s: %s\n' % (symbol, value))
            block = block.superblock
        frame = frame.newer()

def dump_globals(names):
    for i in names:
        s = gdb.lookup_global_symbol(i)
        if s is not None:
            sys.stdout.write('%s: %s\n' % (s, s.value()))

inferior_alive = False

def inferior_exited(e):
    global inferior_alive
    inferior_alive = False
    sys.stdout.write('inferior exited with code: %d\n' % (e.exit_code))

def run_and_dump_vars_each_step():
    # precondition: inferior not running
    # NOTE: only handles single threaded programs
    global inferior_alive
    gdb.execute('start')
    inferior_alive = True
    gdb.events.exited.connect(inferior_exited)
    while inferior_alive:
        dump_all_vars()
        gdb.execute('step')
    gdb.execute('quit')

logging.basicConfig(format='%(message)s', level=LOG_LEVEL)
gdb.execute('set pagination no')
gdb.execute('set python print-stack full')
run_and_dump_vars_each_step()
给定以下C语言的河内塔计划:

enum {
     N = 2,
};

int peg_positions[N];

static void hanoi(int n, int src, int dst)
{
    int tmp = (0 + 1 + 2) - src - dst;

    if (n == 0) {
        peg_positions[n] = dst;
        return;
    }
    hanoi(n - 1, src, tmp);
    peg_positions[n] = dst;
    hanoi(n - 1, tmp, dst);
}

int main()
{
    hanoi(N - 1, 0, 2);
    return 0;
}
运行
gcc-g hanoi.c-o hanoi
然后
gdb-x dump-vars-each-step.py hanoi
打印:

Reading symbols from /home/scottt/work/gdb-python-scripts/hanoi...done.
Temporary breakpoint 1 at 0x400400: file hanoi.c, line 21.

Temporary breakpoint 1, main () at hanoi.c:21
21  {
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
22      hanoi(N - 1, 0, 2);
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
hanoi (n=n@entry=1, src=src@entry=0, dst=dst@entry=2) at hanoi.c:8
8   {
n: 1
src: 0
dst: 2
tmp: <optimized out>
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
9       int tmp = (0 + 1 + 2) - src - dst;
n: 1
src: 0
dst: 2
tmp: <optimized out>
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
8   {
n: 1
src: 0
dst: 2
tmp: <optimized out>
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
11      if (n == 0) {
n: 1
src: 0
dst: 2
tmp: 1
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
9       int tmp = (0 + 1 + 2) - src - dst;
n: 1
src: 0
dst: 2
tmp: 1
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
15      hanoi(n - 1, src, tmp);
n: 1
src: 0
dst: 2
tmp: 1
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
9       int tmp = (0 + 1 + 2) - src - dst;
n: 1
src: 0
dst: 2
tmp: 1
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
15      hanoi(n - 1, src, tmp);
n: 1
src: 0
dst: 2
tmp: 1
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
hanoi (n=n@entry=0, src=0, dst=dst@entry=1) at hanoi.c:8
8   {
n: 0
src: 0
dst: 1
tmp: <optimized out>
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
9       int tmp = (0 + 1 + 2) - src - dst;
n: 0
src: 0
dst: 1
tmp: <optimized out>
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
8   {
n: 0
src: 0
dst: 1
tmp: <optimized out>
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
11      if (n == 0) {
n: 0
src: <optimized out>
dst: 1
tmp: 2
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
12          peg_positions[n] = dst;
n: 0
src: <optimized out>
dst: 1
tmp: 2
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {0, 0}
18  }
n: 0
src: <optimized out>
dst: 1
tmp: 2
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {1, 0}
hanoi (n=n@entry=1, src=src@entry=0, dst=dst@entry=2) at hanoi.c:16
16      peg_positions[n] = dst;
n: 1
src: 0
dst: 2
tmp: <optimized out>
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {1, 0}
17      hanoi(n - 1, tmp, dst);
n: 1
src: 0
dst: 2
tmp: <optimized out>
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {1, 2}
11      if (n == 0) {
n: 1
src: 0
dst: 2
tmp: 0
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {1, 2}
12          peg_positions[n] = dst;
n: 1
src: 0
dst: 2
tmp: 0
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {1, 2}
18  }
n: 1
src: 0
dst: 2
tmp: 0
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {2, 2}
main () at hanoi.c:24
24  }
N: N
hanoi: {void (int, int, int)} 0x40050c <hanoi>
main: {int ()} 0x400400 <main>
peg_positions: {2, 2}
__libc_start_main (main=0x400400 <main>, argc=1, ubp_av=0x7fffffffde48, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffde38) at libc-start.c:257
257   exit (result);
__GI_exit (status=0) at exit.c:99
99    __run_exit_handlers (status, &__exit_funcs, true);
98  {
99    __run_exit_handlers (status, &__exit_funcs, true);
__run_exit_handlers (status=0, listp=0x3c777b16a8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true) at exit.c:36
36  {
41    while (*listp != NULL)
45        while (cur->idx > 0)
48          &cur->fns[--cur->idx];
47        const struct exit_function *const f =
49        switch (f->flavor)
73            cxafct = f->func.cxa.fn;
77            cxafct (f->func.cxa.arg, status);
75            PTR_DEMANGLE (cxafct);
77            cxafct (f->func.cxa.arg, status);
0x00000000004004c0 in __do_global_dtors_aux ()
Single stepping until exit from function __do_global_dtors_aux,
which has no line number information.
0x0000000000400450 in deregister_tm_clones ()
Single stepping until exit from function deregister_tm_clones,
which has no line number information.
0x00000000004004d2 in __do_global_dtors_aux ()
Single stepping until exit from function __do_global_dtors_aux,
which has no line number information.
0x00000000004005f4 in _fini ()
Single stepping until exit from function _fini,
which has no line number information.
__run_exit_handlers (status=0, listp=0x3c777b16a8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true) at exit.c:78
78            break;
45        while (cur->idx > 0)
82        *listp = cur->next;
83        if (*listp != NULL)
82        *listp = cur->next;
83        if (*listp != NULL)
89    if (run_list_atexit)
90      RUN_HOOK (__libc_atexit, ());
_IO_cleanup () at genops.c:1003
1003    {
1006      int result = _IO_flush_all_lockp (0);
1003    {
1015      _IO_unbuffer_write ();
_IO_unbuffer_write () at genops.c:958
958         if (fp->_lock == NULL || _IO_lock_trylock (*fp->_lock) == 0)
_IO_cleanup () at genops.c:1003
1003    {
1006      int result = _IO_flush_all_lockp (0);
_IO_flush_all_lockp (do_lock=do_lock@entry=0) at genops.c:819
819 {
825   __libc_cleanup_region_start (do_lock, flush_cleanup, 0);
819 {
825   __libc_cleanup_region_start (do_lock, flush_cleanup, 0);
831   fp = (_IO_FILE *) _IO_list_all;
832   while (fp != NULL)
830   last_stamp = _IO_list_all_stamp;
832   while (fp != NULL)
836     _IO_flockfile (fp);
835       if (do_lock)
834       run_fp = fp;
835       if (do_lock)
838       if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
848       if (do_lock)
852       if (last_stamp != _IO_list_all_stamp)
850       run_fp = NULL;
852       if (last_stamp != _IO_list_all_stamp)
859     fp = fp->_chain;
832   while (fp != NULL)
835       if (do_lock)
834       run_fp = fp;
835       if (do_lock)
838       if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
848       if (do_lock)
852       if (last_stamp != _IO_list_all_stamp)
850       run_fp = NULL;
852       if (last_stamp != _IO_list_all_stamp)
859     fp = fp->_chain;
832   while (fp != NULL)
835       if (do_lock)
834       run_fp = fp;
835       if (do_lock)
838       if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
848       if (do_lock)
852       if (last_stamp != _IO_list_all_stamp)
850       run_fp = NULL;
852       if (last_stamp != _IO_list_all_stamp)
859     fp = fp->_chain;
832   while (fp != NULL)
863   if (do_lock)
865   __libc_cleanup_region_end (0);
869 }
_IO_cleanup () at genops.c:1015
1015      _IO_unbuffer_write ();
_IO_unbuffer_write () at genops.c:947
947   for (fp = (_IO_FILE *) _IO_list_all; fp; fp = fp->_chain)
_IO_cleanup () at genops.c:1006
1006      int result = _IO_flush_all_lockp (0);
1015      _IO_unbuffer_write ();
_IO_unbuffer_write () at genops.c:947
947   for (fp = (_IO_FILE *) _IO_list_all; fp; fp = fp->_chain)
949       if (! (fp->_flags & _IO_UNBUFFERED)
983       fp->_mode = -1;
947   for (fp = (_IO_FILE *) _IO_list_all; fp; fp = fp->_chain)
949       if (! (fp->_flags & _IO_UNBUFFERED)
951           || (fp->_flags & _IO_IS_APPENDING))
950       && (! (fp->_flags & _IO_NO_WRITES)
953       && fp->_mode != 0)
983       fp->_mode = -1;
947   for (fp = (_IO_FILE *) _IO_list_all; fp; fp = fp->_chain)
949       if (! (fp->_flags & _IO_UNBUFFERED)
951           || (fp->_flags & _IO_IS_APPENDING))
950       && (! (fp->_flags & _IO_NO_WRITES)
983       fp->_mode = -1;
947   for (fp = (_IO_FILE *) _IO_list_all; fp; fp = fp->_chain)
_IO_cleanup () at genops.c:1018
1018    }
__run_exit_handlers (status=0, listp=<optimized out>, run_list_atexit=run_list_atexit@entry=true) at exit.c:92
92    _exit (status);
__GI__exit (status=status@entry=0) at ../sysdeps/unix/sysv/linux/_exit.c:28
28  {
32        INLINE_SYSCALL (exit_group, 1, status);
34        INLINE_SYSCALL (exit, 1, status);
32        INLINE_SYSCALL (exit_group, 1, status);
[Inferior 1 (process 32305) exited normally]
inferior exited with code: 0
从/home/scottt/work/gdb python脚本/hanoi读取符号…完成。
0x400400处的临时断点1:文件hanoi.c,第21行。
临时断点1,位于hanoi.c的main():21
21  {
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
22河内(N-1,0,2);
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
河内(北)=n@entry=1,src=src@entry=0,dst=dst@entry=2)在河内。c:8
8   {
n:1
src:0
dst:2
tmp:
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
9 int tmp=(0+1+2)-src-dst;
n:1
src:0
dst:2
tmp:
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
8   {
n:1
src:0
dst:2
tmp:
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
11如果(n==0){
n:1
src:0
dst:2
tmp:1
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
9 int tmp=(0+1+2)-src-dst;
n:1
src:0
dst:2
tmp:1
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
15河内(n-1,src,tmp);
n:1
src:0
dst:2
tmp:1
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
9 int tmp=(0+1+2)-src-dst;
n:1
src:0
dst:2
tmp:1
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
15河内(n-1,src,tmp);
n:1
src:0
dst:2
tmp:1
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
河内(北)=n@entry=0,src=0,dst=dst@entry=1)在河内。c:8
8   {
n:0
src:0
dst:1
tmp:
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
9 int tmp=(0+1+2)-src-dst;
n:0
src:0
dst:1
tmp:
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
8   {
n:0
src:0
dst:1
tmp:
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
11如果(n==0){
n:0
src:
dst:1
tmp:2
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
12个peg_位置[n]=dst;
n:0
src:
dst:1
tmp:2
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{0,0}
18  }
n:0
src:
dst:1
tmp:2
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{1,0}
河内(北)=n@entry=1,src=src@entry=0,dst=dst@entry=2)在河内。c:16
16个peg_位置[n]=dst;
n:1
src:0
dst:2
tmp:
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{1,0}
17河内(n-1,tmp,dst);
n:1
src:0
dst:2
tmp:
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{1,2}
11如果(n==0){
n:1
src:0
dst:2
tmp:0
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{1,2}
12个peg_位置[n]=dst;
n:1
src:0
dst:2
tmp:0
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{1,2}
18  }
n:1
src:0
dst:2
tmp:0
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{2,2}
位于河内的main().c:24
24  }
N:N
河内:{void(int,int,int)}0x40050c
main:{int()}0x400400
peg_位置:{2,2}
__libc start的libc_start_main(main=0x400400,argc=1,ubp_av=0x7fffffffde48,init=,fini=,rtld_fini=,stack_end=0x7fffffffde38)。c:257
257退出(结果);
__出口处的GI_出口(状态=0)。c:99
99个运行退出处理程序(状态和退出函数,true);
98  {
99个运行退出处理程序(状态和退出函数,true);
__运行退出处理程序(状态=0,列表P=0x3c777b16a8,运行列表\u atexit=运行列表_atexit@entry=正确)在出口处。c:36
36  {
41 while(*listp!=NULL)
45 while(cur->idx>0)
48&cur->fns[-cur->idx];
47常量结构退出函数*常量f=
49开关(f->风味)
73 cxafct=f->func.cxa.fn;
77 cxafct(f->func.cxa.arg,状态);
75 PTR_DEMANGLE(cxafct);
77 cxafct(f->func.cxa.arg,状态);
0x00000000004004c0英寸(全球数据源)
单步执行,直到退出功能uu do_global_dtors_aux,
它没有行号信息。
0x000000000040450在注销\u tm\u克隆()中
单步执行,直到退出功能取消注册,
它没有行号信息。
0x0000000000404D2英寸(全球数据源)
单步执行,直到退出功能uu do_global_dtors_aux,
没有