如何理解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 标记注释所有块。