Search code examples
crashgdbkernelobjdump

How to understand the disassemble code output from gdb


Look at the following output from gdb, why does the instruction code is disordered?

It shows:

0xffffffff81107714 <+7>: mov    %rdi,%rbx 

then shows

0xffffffff8110770f <+2>: cmpq   $0x0,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   $0x0,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    $0x80,(%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   

The following output by kernel oops shows that __d_rehash+0x19/0x4c is the parent call of crash. But I can't find the exact source responding to __d_rehash+0x19 from above disassemble output.

[ 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

Solution

  • __d_rehash+0x19 is hex, 25 decimal, which corresponds to

    2000        entry->d_flags |= DCACHE_RCUACCESS;
       0xffffffff81107726 <+25>:    orl    $0x80,(%rbx)
    

    This is not "parent call" but return address, presumably from a call "hidden" in

    1999        hlist_bl_lock(b);
    

    The code is "reordered" because the compiler is free to generate it however it sees fit as long as the resulting semantics are the same and it figured it is beneficial to shuffle things up. Then as you can see gdb figured it will show it in a displaced manner.

    A significantly better linux kernel debugger is "crash". It will happen to show all the assembly in order and annotate all blocks with file:line marks if you do 'dis -l'.