如何使用GDB调试jonesforth?

3

jonesforth通常以下面的方式启动:

cat jonesforth.f  - | ./jonesforth

有什么好的方法可以调试 jonesforth

2个回答

5

在Ubuntu上?

如果您正在使用Ubuntu系统,请允许gdb附加到正在运行的进程:

echo 0 > /proc/sys/kernel/yama/ptrace_scope

如果您希望该设置在重新启动后保持不变:

vim /etc/sysctl.d/10-ptrace.conf

更新Makefile文件

在你的jonesforthMakefile配方中添加g标志:

jonesforth: jonesforth.S
    gcc -g -m32 -nostdlib -static $(BUILD_ID_NONE) -o $@ $<

开始使用gdb

然后,在终端中像往常一样启动jonesforth:

cat jonesforth.f - | ./jonesforth

在另一个终端中,启动gdb并附加到正在运行的jonesforth:
gdb --quiet --pid=`pgrep jonesforth`  ./jonesforth 

示例会话

当我启动 gdb 时,我看到的内容如下:

$ gdb --quiet --pid=`pgrep jonesforth`  ./jonesforth 
Reading symbols from ./jonesforth...done.
Attaching to program: /home/dharmatech/Dropbox/Documents/jonesforth-annexia/jonesforth, process 3406
_KEY () at jonesforth.S:1290
1290        test %eax,%eax      // If %eax <= 0, then exit.
(gdb) 

Jonesforth正在等待我们输入内容。这在_KEY汇编程序中指示。这由上面的gdb显示。它还显示行1290是下一个要执行的行。这是_KEY例程:

_KEY:
    mov (currkey),%ebx
    cmp (bufftop),%ebx
    jge 1f          // exhausted the input buffer?
    xor %eax,%eax
    mov (%ebx),%al      // get next key from input buffer
    inc %ebx
    mov %ebx,(currkey)  // increment currkey
    ret

1:  // Out of input; use read(2) to fetch more input from stdin.
    xor %ebx,%ebx       // 1st param: stdin
    mov $buffer,%ecx    // 2nd param: buffer
    mov %ecx,currkey
    mov $BUFFER_SIZE,%edx   // 3rd param: max length
    mov $__NR_read,%eax // syscall: read
    int $0x80
    test %eax,%eax      // If %eax <= 0, then exit.
    jbe 2f
    addl %eax,%ecx      // buffer+%eax = bufftop
    mov %ecx,bufftop
    jmp _KEY

2:  // Error or end of input: exit the program.
    xor %ebx,%ebx
    mov $__NR_exit,%eax // syscall: exit
    int $0x80

_KEY使用内存中的一些变量:buffercurrkeybufftop。它还使用了几个寄存器。让我们使用gdb自动显示功能来显示这些:

display/8cb &buffer
display/1xw &currkey
display/1xw &bufftop
display/x   $eax
display/x   $ebx

现在,如果我们在gdb中输入display,就会一次性看到所有内容:
(gdb) display
1: x/8cb &buffer
0x804c000:  97 'a'  98 'b'  108 'l' 121 'y' 46 '.'  32 ' '  32 ' '  84 'T'
2: x/xw &currkey  0x8049d54:    0x0804c000
3: x/xw &bufftop  0x8049d58:    0x0804c7e3
4: /x $eax = 0xfffffe00
5: /x $ebx = 0x0

现在也是启用gdb TUI的好时机:

tui enable

现在,gdb应该看起来像这样:

enter image description here

好的,jonesforth仍在等待输入。所以让我们给它一些东西:

JONESFORTH VERSION 47 
14499 CELLS REMAINING
OK 123

好的,在 gdb 中,我们终于可以要求它执行步进操作了:
(gdb) s
1: x/8cb &buffer
0x804c000:      49 '1'  50 '2'  51 '3'  10 '\n' 46 '.'  32 ' '  32 ' '  84 'T'
2: x/xw &currkey  0x8049d54:    0x0804c000
3: x/xw &bufftop  0x8049d58:    0x0804c7e3
4: /x $eax = 0x4
5: /x $ebx = 0x0

嘿,看那个!buffer中的前3个字符是123

如果%eax <= 0,下一步将跳转到2f标签。但正如我们在上面看到的那样,%eax4。所以它应该继续执行。

如果我们逐步执行接下来的三行,bufftop将被设置为buffer的地址加上4('123'的三个字符加上一个换行符)。与buffer地址相关的值检查通过:

3: x/xw &bufftop  0x8049d58:    0x0804c004

现在数据已经读入输入缓冲区,_KEY会执行其任务并返回给调用者。以下是返回之前的几条指令:

enter image description here

当您逐步执行这些指令时,自动显示功能将相应地更新变量和寄存器。

0

我的(相当有限的)经验是,当涉及汇编语言程序时,LLVM调试器lldb更加友好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接