jonesforth通常以下面的方式启动:
cat jonesforth.f - | ./jonesforth
有什么好的方法可以调试 jonesforth
?
jonesforth通常以下面的方式启动:
cat jonesforth.f - | ./jonesforth
有什么好的方法可以调试 jonesforth
?
如果您正在使用Ubuntu系统,请允许gdb
附加到正在运行的进程:
echo 0 > /proc/sys/kernel/yama/ptrace_scope
如果您希望该设置在重新启动后保持不变:
vim /etc/sysctl.d/10-ptrace.conf
在你的jonesforth
的Makefile
配方中添加g
标志:
jonesforth: jonesforth.S
gcc -g -m32 -nostdlib -static $(BUILD_ID_NONE) -o $@ $<
然后,在终端中像往常一样启动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
使用内存中的一些变量:buffer
,currkey
和bufftop
。它还使用了几个寄存器。让我们使用gdb
的自动显示
功能来显示这些:
display/8cb &buffer
display/1xw &currkey
display/1xw &bufftop
display/x $eax
display/x $ebx
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应该看起来像这样:
好的,jonesforth仍在等待输入。所以让我们给它一些东西:
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
嘿,看那个!buffer
中的前3个字符是1
、2
和3
。
如果%eax <= 0
,下一步将跳转到2f
标签。但正如我们在上面看到的那样,%eax
是4
。所以它应该继续执行。
如果我们逐步执行接下来的三行,bufftop
将被设置为buffer
的地址加上4('123'的三个字符加上一个换行符)。与buffer
地址相关的值检查通过:
3: x/xw &bufftop 0x8049d58: 0x0804c004
_KEY
会执行其任务并返回给调用者。以下是返回之前的几条指令:当您逐步执行这些指令时,自动显示功能将相应地更新变量和寄存器。我的(相当有限的)经验是,当涉及汇编语言程序时,LLVM调试器lldb更加友好。