mit_6.828_lab1_exercise11_讲解

test_backtrace反汇编后长这样

test_backtrace(int x)
{
f0100040:	55                   	push   %ebp
f0100041:	89 e5                	mov    %esp,%ebp
f0100043:	53                   	push   %ebx
f0100044:	83 ec 0c             	sub    $0xc,%esp
f0100047:	8b 5d 08             	mov    0x8(%ebp),%ebx
	cprintf("entering test_backtrace %d\n", x);
f010004a:	53                   	push   %ebx
f010004b:	68 c0 18 10 f0       	push   $0xf01018c0
f0100050:	e8 e1 08 00 00       	call   f0100936 <cprintf>
	if (x > 0)
f0100055:	83 c4 10             	add    $0x10,%esp
f0100058:	85 db                	test   %ebx,%ebx
f010005a:	7e 11                	jle    f010006d <test_backtrace+0x2d>
		test_backtrace(x-1);
f010005c:	83 ec 0c             	sub    $0xc,%esp
f010005f:	8d 43 ff             	lea    -0x1(%ebx),%eax
f0100062:	50                   	push   %eax
f0100063:	e8 d8 ff ff ff       	call   f0100040 <test_backtrace>
f0100068:	83 c4 10             	add    $0x10,%esp
f010006b:	eb 11                	jmp    f010007e <test_backtrace+0x3e>
	else
		mon_backtrace(0, 0, 0);
f010006d:	83 ec 04             	sub    $0x4,%esp
f0100070:	6a 00                	push   $0x0
f0100072:	6a 00                	push   $0x0
f0100074:	6a 00                	push   $0x0
f0100076:	e8 f3 06 00 00       	call   f010076e <mon_backtrace>
f010007b:	83 c4 10             	add    $0x10,%esp
	cprintf("leaving test_backtrace %d\n", x);
f010007e:	83 ec 08             	sub    $0x8,%esp
f0100081:	53                   	push   %ebx
f0100082:	68 dc 18 10 f0       	push   $0xf01018dc
f0100087:	e8 aa 08 00 00       	call   f0100936 <cprintf>
}
f010008c:	83 c4 10             	add    $0x10,%esp
f010008f:	8b 5d fc             	mov    -0x4(%ebp),%ebx
f0100092:	c9                   	leave  
f0100093:	c3                   	ret  

下面是gdb调试过程,breakpoint 4 之前的是test_backtrace(4),之后的是调用test_backtrace(3)的测试过程。

(gdb) info registers ebp
ebp            0xf010ffb8	0xf010ffb8
(gdb) x/1x 0xf010ffb8
0xf010ffb8:	0xf010ffd8
(gdb) x/8x 0xf010ffd8
0xf010ffd8:	0xf010fff8	0xf01000d4	0x00000005	0x00001aac
0xf010ffe8:	0x00000640	0x00000000	0x00000000	0x00000000
(gdb) x/8x 0xf010ffb8
0xf010ffb8:	0xf010ffd8	0xf0100068	0x00000004	0x00000005
0xf010ffc8:	0x00000000	0x00010094	0x00010094	0x00010094
(gdb) info registers ebp
ebp            0xf010ffb8	0xf010ffb8
(gdb) si
=> 0xf0100063 <test_backtrace+35>:	call   0xf0100040 <test_backtrace>
0xf0100063	16			test_backtrace(x-1);
(gdb) x/8x ($ebp)
0xf010ffb8:	0xf010ffd8	0xf0100068	0x00000004	0x00000005
0xf010ffc8:	0x00000000	0x00010094	0x00010094	0x00010094
(gdb) x/8x 0xf010fff8
0xf010fff8:	0x00000000	0xf010003e	0x00111021	0x00000000
0xf0110008 <entry_pgdir+8>:	0x00000000	0x00000000	0x00000000	0x00000000
(gdb) p $esp
$6 = (void *) 0xf010ffa0
(gdb) si
=> 0xf0100040 <test_backtrace>:	push   %ebp
test_backtrace (x=3) at kern/init.c:13
13	{
(gdb) b *0xf0100063
Breakpoint 4 at 0xf0100063: file kern/init.c, line 16.
(gdb) c
Continuing.
=> 0xf0100050 <test_backtrace+16>:	call   0xf0100936 <cprintf>

Breakpoint 1, 0xf0100050 in test_backtrace (x=3) at kern/init.c:14
14		cprintf("entering test_backtrace %d\n", x);
(gdb) c
Continuing.
=> 0xf0100055 <test_backtrace+21>:	add    $0x10,%esp

Breakpoint 3, test_backtrace (x=3) at kern/init.c:15
15		if (x > 0)
(gdb) c
Continuing.
=> 0xf010005a <test_backtrace+26>:	jle    0xf010006d <test_backtrace+45>

Breakpoint 2, 0xf010005a in test_backtrace (x=3) at kern/init.c:15
15		if (x > 0)
(gdb) c
Continuing.
=> 0xf0100063 <test_backtrace+35>:	call   0xf0100040 <test_backtrace>

Breakpoint 4, 0xf0100063 in test_backtrace (x=3) at kern/init.c:16
16			test_backtrace(x-1);
(gdb) info registers ebp
ebp            0xf010ff98	0xf010ff98
(gdb) x/8x ($ebp)
0xf010ff98:	0xf010ffb8	0xf0100068	0x00000003	0x00000004
0xf010ffa8:	0x00000000	0x00000000	0x00000000	0x00000005
(gdb) p $eax
$7 = 2
(gdb) p $eip
$8 = (void (*)()) 0xf0100063 <test_backtrace+35>
(gdb) p $esp
$9 = (void *) 0xf010ff80
(gdb) x/16x ($esp)
0xf010ff80:	0x00000002	0x00000003	0xf010ffb8	0x00000000
0xf010ff90:	0xf01008fd	0x00000004	0xf010ffb8	0xf0100068
0xf010ffa0:	0x00000003	0x00000004	0x00000000	0x00000000
0xf010ffb0:	0x00000000	0x00000005	0xf010ffd8	0xf0100068
(gdb) x/20x ($esp)
0xf010ff80:	0x00000002	0x00000003	0xf010ffb8	0x00000000
0xf010ff90:	0xf01008fd	0x00000004	0xf010ffb8	0xf0100068
0xf010ffa0:	0x00000003	0x00000004	0x00000000	0x00000000
0xf010ffb0:	0x00000000	0x00000005	0xf010ffd8	0xf0100068
0xf010ffc0:	0x00000004	0x00000005	0x00000000	0x00010094

在递归到同一个位置时,观察了两次栈。发现,

test_backtrace(4)时 ebp 0xf010ffb8,*(ebp) 0xf010ffd8,

test_backtrace(3)时 ebp 0xf010ff98,*(ebp) 0xf010ffb8,

两次调用下一层递归前,ebp都指向上一层的ebp,而且*(ebp)[0] 就相当于上一层的ebp,从*(ebp)[1]开始才是eip、args啥的。

*(ebp)[1]是ret返回后的eip,其实就是call指令下的那条语句。这里就是

f0100068:	83 c4 10             	add    $0x10,%esp

mon_backtrace这样写

mon_backtrace(int argc, char **argv, struct Trapframe *tf)
{
	uint32_t *ebp;

    ebp = (uint32_t *)read_ebp();

    cprintf("Stack backtrace:\r\n");

    while (ebp)
    {
        cprintf("  ebp %08x  eip %08x  args %08x %08x %08x %08x %08x\r\n", 
                ebp, ebp[1], ebp[2], ebp[3], ebp[4], ebp[5], ebp[6]);

        ebp = (uint32_t *)*ebp;
    }
	return 0;
}

因为我们要打印的是test_backtrace的参数和eip什么的,而不是mon_backtrace的,而且test调用mon,所以必须要对指针取一次值,才能访问到它的上层函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值