如何理解gdb输出的反汇编代码
How to understand the disassemble code output from gdb
看下面gdb的输出,为什么指令代码乱了?
显示:
0xffffffff81107714 <+7>: mov %rdi,%rbx
然后显示
0xffffffff8110770f <+2>: cmpq [=11=]x0,0x10(%rdi)
.
(gdb) disassemble /m __d_rehash
Dump of assembler code for function __d_rehash:
1997 {
0xffffffff8110770d <+0>: push %rbp
0xffffffff8110770e <+1>: push %rbx
0xffffffff81107714 <+7>: mov %rdi,%rbx
1998 BUG_ON(!d_unhashed(entry));
0xffffffff8110770f <+2>: cmpq [=12=]x0,0x10(%rdi)
0xffffffff81107717 <+10>: je 0xffffffff8110771b <__d_rehash+14>
0xffffffff81107719 <+12>: ud2
1999 hlist_bl_lock(b);
2000 entry->d_flags |= DCACHE_RCUACCESS;
0xffffffff81107726 <+25>: orl [=12=]x80,(%rbx)
2001 hlist_bl_add_head_rcu(&entry->d_hash, b);
0xffffffff8110772c <+31>: lea 0x8(%rbx),%rdx
2002 hlist_bl_unlock(b);
2003 }
0xffffffff81107756 <+73>: pop %rbx
0xffffffff81107757 <+74>: pop %rbp
0xffffffff81107758 <+75>: retq
内核 oops 的以下输出表明 __d_rehash+0x19/0x4c
是崩溃的父调用。但是我无法从上面的反汇编输出中找到响应 __d_rehash+0x19
的确切来源。
[ 2630.421613] RIP: 0010:[<ffffffff8110739c>] [<ffffffff8110739c>] bit_spin_lock.constprop.17+0xb/0x1f
[ 2630.421618] RSP: 0018:ffff8800b4a83c00 EFLAGS: 00000202
[ 2630.421619] RAX: 0000000000000001 RBX: 0000000000000000 RCX: 0000000000000013
[ 2630.421620] RDX: ffffc90000000000 RSI: ffffc900003b6130 RDI: ffffc900003b6130
[ 2630.421621] RBP: ffffc900003b6130 R08: ffff8800b4a83c70 R09: ffff8800bc286880
[ 2630.421622] R10: 0000000000000000 R11: ffff8800bc283940 R12: ffff8800bc283940
[ 2630.421623] R13: ffffc900003b6130 R14: 0000000000000000 R15: 0000000000000000
[ 2630.421625] FS: 00007fd5c5c2f7a0(0000) GS:ffff8800bfd80000(0000) knlGS:0000000000000000
[ 2630.421626] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 2630.421627] CR2: 000000000042ba30 CR3: 00000000ad201000 CR4: 00000000000406e0
[ 2630.421631] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 2630.421632] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[ 2630.421633] Process dpkg (pid: 9941, threadinfo ffff8800b4a82000, task ffff880030871000)
[ 2630.421634] Stack:
[ 2630.421635] ffff88002f20b600 ffffffff81107726 ffff88002f20b600 ffff88002f20b600
[ 2630.421637] ffffffff8110848b 0000000000000000 ffffffff81108fef 000000000000000c
[ 2630.421639] ffff8800bc283940 ffff88002f20b600 ffff8800b4a83d68 ffff8800bc11bb40
[ 2630.421641] Call Trace:
[ 2630.421644] [<ffffffff81107726>] ? __d_rehash+0x19/0x4c
[ 2630.421646] [<ffffffff8110848b>] ? d_rehash+0x24/0x2a
[ 2630.421648] [<ffffffff81108fef>] ? d_splice_alias+0xb2/0xbd
[ 2630.421655] [<ffffffffa016a121>] ? ext4_lookup+0xc5/0xd2 [ext4]
[ 2630.421658] [<ffffffff8110013a>] ? d_alloc_and_lookup+0x33/0x62
[ 2630.421661] [<ffffffff81100996>] ? walk_component+0x1e7/0x3a0
[ 2630.421663] [<ffffffff81101a29>] ? path_lookupat+0x8b/0x2ac
[ 2630.421666] [<ffffffff8103a683>] ? should_resched+0x5/0x23
[ 2630.421669] [<ffffffff813453b9>] ? _cond_resched+0x7/0x1c
[ 2630.421671] [<ffffffff81101c66>] ? do_path_lookup+0x1c/0x81
[ 2630.421673] [<ffffffff8110346a>] ? user_path_at_empty+0x48/0x7d
[ 2630.421675] [<ffffffff810fb89e>] ? cp_new_stat+0xf0/0x104
[ 2630.421677] [<ffffffff810fb675>] ? vfs_fstatat+0x2d/0x63
[ 2630.421678] [<ffffffff810fb949>] ? sys_newstat+0x12/0x2d
[ 2630.421681] [<ffffffff8134b792>] ? system_call_fastpath+0x16/0x1b
__d_rehash+0x19为16进制,25为十进制,对应
2000 entry->d_flags |= DCACHE_RCUACCESS;
0xffffffff81107726 <+25>: orl [=10=]x80,(%rbx)
这不是 "parent call" 而是 return 地址,可能来自 "hidden" 在
的电话
1999 hlist_bl_lock(b);
代码是 "reordered",因为编译器可以自由生成它,但它认为只要结果语义相同就合适,并且它认为将事情打乱是有益的。然后正如您所见,gdb 认为它将以移位的方式显示它。
一个明显更好的 linux 内核调试器是 "crash"。如果你这样做 'dis -l',它会碰巧按顺序显示所有程序集并用 file:line 标记注释所有块。
看下面gdb的输出,为什么指令代码乱了?
显示:
0xffffffff81107714 <+7>: mov %rdi,%rbx
然后显示
0xffffffff8110770f <+2>: cmpq [=11=]x0,0x10(%rdi)
.
(gdb) disassemble /m __d_rehash
Dump of assembler code for function __d_rehash:
1997 {
0xffffffff8110770d <+0>: push %rbp
0xffffffff8110770e <+1>: push %rbx
0xffffffff81107714 <+7>: mov %rdi,%rbx
1998 BUG_ON(!d_unhashed(entry));
0xffffffff8110770f <+2>: cmpq [=12=]x0,0x10(%rdi)
0xffffffff81107717 <+10>: je 0xffffffff8110771b <__d_rehash+14>
0xffffffff81107719 <+12>: ud2
1999 hlist_bl_lock(b);
2000 entry->d_flags |= DCACHE_RCUACCESS;
0xffffffff81107726 <+25>: orl [=12=]x80,(%rbx)
2001 hlist_bl_add_head_rcu(&entry->d_hash, b);
0xffffffff8110772c <+31>: lea 0x8(%rbx),%rdx
2002 hlist_bl_unlock(b);
2003 }
0xffffffff81107756 <+73>: pop %rbx
0xffffffff81107757 <+74>: pop %rbp
0xffffffff81107758 <+75>: retq
内核 oops 的以下输出表明 __d_rehash+0x19/0x4c
是崩溃的父调用。但是我无法从上面的反汇编输出中找到响应 __d_rehash+0x19
的确切来源。
[ 2630.421613] RIP: 0010:[<ffffffff8110739c>] [<ffffffff8110739c>] bit_spin_lock.constprop.17+0xb/0x1f
[ 2630.421618] RSP: 0018:ffff8800b4a83c00 EFLAGS: 00000202
[ 2630.421619] RAX: 0000000000000001 RBX: 0000000000000000 RCX: 0000000000000013
[ 2630.421620] RDX: ffffc90000000000 RSI: ffffc900003b6130 RDI: ffffc900003b6130
[ 2630.421621] RBP: ffffc900003b6130 R08: ffff8800b4a83c70 R09: ffff8800bc286880
[ 2630.421622] R10: 0000000000000000 R11: ffff8800bc283940 R12: ffff8800bc283940
[ 2630.421623] R13: ffffc900003b6130 R14: 0000000000000000 R15: 0000000000000000
[ 2630.421625] FS: 00007fd5c5c2f7a0(0000) GS:ffff8800bfd80000(0000) knlGS:0000000000000000
[ 2630.421626] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 2630.421627] CR2: 000000000042ba30 CR3: 00000000ad201000 CR4: 00000000000406e0
[ 2630.421631] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 2630.421632] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[ 2630.421633] Process dpkg (pid: 9941, threadinfo ffff8800b4a82000, task ffff880030871000)
[ 2630.421634] Stack:
[ 2630.421635] ffff88002f20b600 ffffffff81107726 ffff88002f20b600 ffff88002f20b600
[ 2630.421637] ffffffff8110848b 0000000000000000 ffffffff81108fef 000000000000000c
[ 2630.421639] ffff8800bc283940 ffff88002f20b600 ffff8800b4a83d68 ffff8800bc11bb40
[ 2630.421641] Call Trace:
[ 2630.421644] [<ffffffff81107726>] ? __d_rehash+0x19/0x4c
[ 2630.421646] [<ffffffff8110848b>] ? d_rehash+0x24/0x2a
[ 2630.421648] [<ffffffff81108fef>] ? d_splice_alias+0xb2/0xbd
[ 2630.421655] [<ffffffffa016a121>] ? ext4_lookup+0xc5/0xd2 [ext4]
[ 2630.421658] [<ffffffff8110013a>] ? d_alloc_and_lookup+0x33/0x62
[ 2630.421661] [<ffffffff81100996>] ? walk_component+0x1e7/0x3a0
[ 2630.421663] [<ffffffff81101a29>] ? path_lookupat+0x8b/0x2ac
[ 2630.421666] [<ffffffff8103a683>] ? should_resched+0x5/0x23
[ 2630.421669] [<ffffffff813453b9>] ? _cond_resched+0x7/0x1c
[ 2630.421671] [<ffffffff81101c66>] ? do_path_lookup+0x1c/0x81
[ 2630.421673] [<ffffffff8110346a>] ? user_path_at_empty+0x48/0x7d
[ 2630.421675] [<ffffffff810fb89e>] ? cp_new_stat+0xf0/0x104
[ 2630.421677] [<ffffffff810fb675>] ? vfs_fstatat+0x2d/0x63
[ 2630.421678] [<ffffffff810fb949>] ? sys_newstat+0x12/0x2d
[ 2630.421681] [<ffffffff8134b792>] ? system_call_fastpath+0x16/0x1b
__d_rehash+0x19为16进制,25为十进制,对应
2000 entry->d_flags |= DCACHE_RCUACCESS;
0xffffffff81107726 <+25>: orl [=10=]x80,(%rbx)
这不是 "parent call" 而是 return 地址,可能来自 "hidden" 在
的电话1999 hlist_bl_lock(b);
代码是 "reordered",因为编译器可以自由生成它,但它认为只要结果语义相同就合适,并且它认为将事情打乱是有益的。然后正如您所见,gdb 认为它将以移位的方式显示它。
一个明显更好的 linux 内核调试器是 "crash"。如果你这样做 'dis -l',它会碰巧按顺序显示所有程序集并用 file:line 标记注释所有块。