mips64非法地址访问(汇编实现结构体成员地址访问)

现场1

Cpu 2
$ 0   : 0000000000000000 00000000508080e0 980000004a57e530 980000004a4fac48
$ 4   : ff0000004a57e530 00000000000000d0 980000001fc3a900 980000004a4fab28
$ 8   : 980000004a4faaf8 0000000000000000 980000004a4fac10 980000004a282758
$12   : 00000000508080e1 000000001000001e 98000000020b1d40 fffffffffffffff8
$16   : 980000004a57e528 980000004a4fabe0 0000000000000000 980000004a57e528
$20   : 980000004bc07338 0000005557128054 0000000000000001 000000000000000b
$24   : 00000000000008b5 00000055556ba7b8                                  
$28   : 9800000003764000 9800000003767d30 980000004a28d558 98000000020b4dc4
Hi    : 0000000000002997
Lo    : 0000000000000ddd
epc   : 98000000020b4de4 anon_vma_prepare+0xb0/0x16c     Not tainted
ra    : 98000000020b4dc4 anon_vma_prepare+0x90/0x16c
Status: 508080e3    KX SX UX KERNEL EXL IE 
Cause : 0000000c
BadVA : ff0000004a57e530
PrId  : 000c0009
Modules linked in: ossmod tipc cpp_base bootflash util mtdchar bsp_flash_init boardmem boardctrl
Process CSMGR_L_COMMON_ (pid: 1146, threadinfo=9800000003764000, task=980000000375f618)
Stack : 6800000000000000 0000000000000000 9800000003776250 980000004bc072a0
        980000004a4fabe0 98000000020abf8c 980000004bc072a0 980000004a4fabe0
        0000000000002250 0000005557128000 000000555712c000 0000000000000001
        0000005557128054 980000004bc072a0 980000004bc07300 980000004a4fabe0
        980000000375f618 9800000003767eb0 0000000000000001 000000000000000b
        000000ffffeaf780 980000000202acb8 0000005500030002 98000000020b22fc
        0000000000000000 0000000000000000 980000004a4fabe0 0000000000000802
        0000000000000a03 0000000000000000 9800000003ea8868 980000004bc0c028
        980000004bc072a0 0000000000000001 000000555712c000 0000000000000003
        0000000000000070 0000000000000032 0000005557128000 0000005557128000
        ...
Call Trace:
[<98000000020b4de4>] anon_vma_prepare+0xb0/0x16c
[<98000000020abf8c>] __handle_mm_fault+0x718/0x1288
[<980000000202acb8>] do_page_fault+0x228/0x530
[<980000000200b8e4>] ret_from_exception+0x0/0x10

非法地址访问对应着下面anon_vma_prepare函数的line 3:

		if (likely(!vma->anon_vma)) {
			vma->anon_vma = anon_vma;
			list_add_tail(&vma->anon_vma_node, &anon_vma->head);
根据反汇编,出错的情景模拟一下:

 98000000020b4dc0:   0280202d    move    a0,s4
 98000000020b4dc4:   de220078    ld  v0,120(s1)
 98000000020b4dc8:   14400009    bnez    v0,98000000020b9020 <anon_vma_prepare+0xbc>
 98000000020b8ffc:   66020008    daddiu  v0,s0,8   //步骤1:取head = &anon_vma->head  
 98000000020b9000:   fe300078    sd  s0,120(s1)
 98000000020b4dd4:   dc440008    ld  a0,8(v0)     //步骤2:取prev = head->prev
 98000000020b4dd8:   66230068    daddiu  v1,s1,104
 98000000020b4ddc:   fe220068    sd  v0,104(s1)
 98000000020b4de0:   fc430008    sd  v1,8(v0)
 98000000020b4de4:   fc830000    sd  v1,0(a0)   //步骤3:将v1的值存放到prev->next,非法地址访问
 98000000020b4de8:   fc640008    sd  a0,8(v1)

步骤1: s0 = $16   : 980000004a57e528 , v0 = $2 :980000004a57e530  满足v0 = s0 + 8
步骤2: a0 = $4   : ff0000004a57e530 , 即从980000004a57e530取到一个非法的值,导致后续的访问出错。
即anon_vma->head->prev的成员变成了非法值。

理解反汇编时有一个难点,反汇编代码line 5对应着vma->anon_vma = anon_vma,即s0对应着anon_vma的值,那么反汇编代码line 4将anon_vma的值

加8后为什么就表示了anon_vma->head的地址?

看了下面简单的例子就明白了:

struct A
{
int x;
int y;
}

struct A *a = kmalloc(sizeof(struct A);
设kmalloc分配出来的一块内存地址为v,

a的值就是v,

a->y的值是*(v+4),

而a指向的struct A的成员y所在的内存地址就是v+4,也即&a->y ,这就是反汇编代码line 4的来历。

另外顺便说一句,a+4的值,是&a + 4×sizeof(struct A),这些不要搞混了。

再回到开始的分析,anon_vma是个什么结构?(未完)

你可能感兴趣的:(内存)