From mboxrd@z Thu Jan 1 00:00:00 1970 From: tobias@gambas-buch.de (Tobias Boege) Date: Mon, 12 Aug 2013 16:44:17 +0200 Subject: Understanding disassembly x86 + understanding function call + parameter pass and stack frame In-Reply-To: <20130812125145.GB682@aurora> References: <742998C661BDD3408828420187AB7B8D0151718D@bosmb1.netscout.com> <20130812125145.GB682@aurora> Message-ID: <20130812144417.GC682@aurora> To: kernelnewbies@lists.kernelnewbies.org List-Id: kernelnewbies.lists.kernelnewbies.org On Mon, 12 Aug 2013, Tobias Boege wrote: > On Mon, 12 Aug 2013, nidhi mittal hada wrote: > > *this is disassembly of that function* > > > > crash> dis ffffffff811798a0 > > 0xffffffff811798a0 : mov %r12,%rdi > > crash> dis deactivate_super > > 0xffffffff81179830 : push %rbp > > 0xffffffff81179831 : mov %rsp,%rbp > > 0xffffffff81179834 : push %r12 > > 0xffffffff81179836 : push %rbx > > 0xffffffff81179837 : nopl 0x0(%rax,%rax,1) > > 0xffffffff8117983c : mov 0x30(%rdi),%r12 > > 0xffffffff81179840 : mov > > $0xffffffff81fc0a00,%rsi > > 0xffffffff81179847 : mov %rdi,%rbx > > 0xffffffff8117984a : lea 0xb8(%rdi),%rdi > > 0xffffffff81179851 : callq 0xffffffff8126a820 > > <_atomic_dec_and_lock> > > 0xffffffff81179856 : test %eax,%eax > > 0xffffffff81179858 : je 0xffffffff811798b0 > > > > 0xffffffff8117985a : subl > > $0x3fffffff,0xb0(%rbx) > > 0xffffffff81179864 : mov > > $0xffffffff81fc0a00,%rax > > 0xffffffff8117986b : incw (%rax) > > 0xffffffff8117986e : data32 xchg %ax,%ax > > 0xffffffff81179871 : mov 0x48(%rbx),%rax > > 0xffffffff81179875 : test %rax,%rax > > 0xffffffff81179878 : je 0xffffffff8117988f > > > > 0xffffffff8117987a : mov 0x8(%rax),%rax > > 0xffffffff8117987e : test %rax,%rax > > 0xffffffff81179881 : je 0xffffffff8117988f > > > > 0xffffffff81179883 : xor %edx,%edx > > 0xffffffff81179885 : mov $0xffffffff,%esi > > 0xffffffff8117988a : mov %rbx,%rdi > > 0xffffffff8117988d : callq *%rax > > 0xffffffff8117988f : lea 0x70(%rbx),%rdi > > 0xffffffff81179893 : callq 0xffffffff814ee5c0 > > > > 0xffffffff81179898 : mov %rbx,%rdi > > 0xffffffff8117989b : callq *0x18(%r12) > > 0xffffffff811798a0 : mov %r12,%rdi > > 0xffffffff811798a3 : callq 0xffffffff81193c20 > > > > > > > > *This is code for this function* > > > > /** > > * deactivate_super - drop an active reference to > > superblock > > * @s: superblock to deactivate > > * > > * Drops an active reference to superblock, acquiring a temprory one if > > * there is no active references left. In that case we lock > > superblock, > > * tell fs driver to shut it down and drop the temporary reference we > > * had just acquired. > > */ > > void deactivate_super(struct super_block *s) > > { > > struct file_system_type *fs = s->s_type; > > if (atomic_dec_and_test(&s->s_active)) { > > vfs_dq_off(s, 0); > > down_write(&s->s_umount); > > fs->kill_sb(s); > > put_filesystem(fs); > > put_super(s); > > } > > } > > > > EXPORT_SYMBOL(deactivate_super); > > > > *now i want to get superblock dump from the stack frame of deactivate_super > > obtained from bt -f.* > > > > > > How do i proceed... > > > > *Questions:-* > > 1)Which memory address in stack contains struct super_block *s > > It's not on the stack in this case. > > > 2)how does disassembly helps in knowing which register contain the struct > > super_block *s > > The disassembly doesn't help you in this particular case. Well, it does but > it is way easier to think as follows: > > The super_block pointer is the first argument to this function. We know from > the AMD 64 ABI that the first argument, if it fits, is to be delivered in > the %rdi register. Since 's' is a pointer, it fits, so you'll find the value > in the %rdi register. > > Maybe it's a good idea to examine a little bit of the disassembly for your > understanding: > > At the beginning of the disassembly, you see instructions > > [1] 0xffffffff81179830 : push %rbp > [1] 0xffffffff81179831 : mov %rsp,%rbp > [2] 0xffffffff81179834 : push %r12 > [2] 0xffffffff81179836 : push %rbx > [3] 0xffffffff81179837 : nopl 0x0(%rax,%rax,1) > [4] 0xffffffff8117983c : mov 0x30(%rdi),%r12 > > which sets up the stack frame ([1]), saves callee-saved registers as per the > ABI ([2]), does nothing ([3]) and then loads some data relative to %rdi into > %r12 ([4]). We already know that %rdi is 's' from the C code. So we could > guess that the above disassembly is performing > > struct file_system_type *fs = s->s_type; > > from the beginning of the C code. There is also proof for this assumption > later in the disassembly. The %r12 is used near the end of the disassembly > again: > > [1] 0xffffffff81179898 : mov %rbx,%rdi > [2] 0xffffffff8117989b : callq *0x18(%r12) > [3] 0xffffffff811798a0 : mov %r12,%rdi > [4] 0xffffffff811798a3 : callq 0xffffffff81193c20 > > First something (we haven't tracked) is moved into %rdi ([1]), followed by a > call of a function from inside %r12 ([2]). This supposedly is a function > pointer in 'fs'. If we look at the C code, this is likely to be: > > fs->kill_sb(s); > > So %rbx must be a saved 's' (and it is: look at ). > Anyways, what follows is that %r12 is moved to %rdi ([3]) and another call > is made (which means that %r12 is to be the first parameter to this > function). put_filesystem() is called, so this must be the C code: > Sorry, the following is wrong: > put_super(s); > > And this makes sense, since we know %r12 is a copy of 's'. > It was meant to read: put_filesystem(fs); And this makes sense, since we know %r12 is 'fs'. Regards, Tobi