如何使用GDB调试jonesforth?

时间:2016-09-22 01:11:54

标签: assembly gdb gas forth

jonesforth通常按以下方式开始:

cat jonesforth.f  - | ./jonesforth

调试jonesforth的好方法是什么?

2 个答案:

答案 0 :(得分:3)

在Ubuntu上?

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

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

如果您希望该设置保持重新启动:

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

更新Makefile

g标记添加到您的jonesforth Makefile食谱中:

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) 

琼斯福斯正在等我们输入一些东西。它在_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的{​​{1}}功能来显示这些内容:

Auto Display

现在,如果我们在display/8cb &buffer display/1xw &currkey display/1xw &bufftop display/x $eax display/x $ebx 中输入display,我们会立即看到所有这些内容:

gdb

这也许是启用(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 TUI的好时机:

gdb

gdb现在应该是这样的:

enter image description here

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

tui enable

好的,回到gdb,我们终于可以要求它继续:

JONESFORTH VERSION 47 
14499 CELLS REMAINING
OK 123
嘿,看那个! (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 中的前3个字符为buffer12

如果3,下一步将跳转到%eax <= 0标签。但正如我们上面所见,2f%eax。所以它应该继续。

如果我们单步执行接下来的三行,则4将设置为bufftop的地址增加4(&#39; 123&#39;加上换行符的三个字符) 。与buffer地址相关的值检出:

buffer

现在数据已被读入输入缓冲区,3: x/xw &bufftop 0x8049d58: 0x0804c004 将完成其工作并返回给调用者。这是返回前的下几条指令:

enter image description here

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

答案 1 :(得分:0)

我的(非常有限!)经验是,当修改汇编语言程序时,LLVM调试器lldb更友好。