Thread (16 messages) 16 messages, 9 authors, 2013-08-14

Understanding disassembly x86 + understanding function call + parameter pass and stack frame

From: Tobias Boege <hidden>
Date: 2013-08-12 12:51:45

On Mon, 12 Aug 2013, nidhi mittal hada wrote:
*this is disassembly of that function*

crash> dis ffffffff811798a0
0xffffffff811798a0 <deactivate_super+112>:      mov    %r12,%rdi
crash> dis deactivate_super
0xffffffff81179830 <deactivate_super>:  push   %rbp
0xffffffff81179831 <deactivate_super+1>:        mov    %rsp,%rbp
0xffffffff81179834 <deactivate_super+4>:        push   %r12
0xffffffff81179836 <deactivate_super+6>:        push   %rbx
0xffffffff81179837 <deactivate_super+7>:        nopl   0x0(%rax,%rax,1)
0xffffffff8117983c <deactivate_super+12>:       mov    0x30(%rdi),%r12
0xffffffff81179840 <deactivate_super+16>:       mov
$0xffffffff81fc0a00,%rsi
0xffffffff81179847 <deactivate_super+23>:       mov    %rdi,%rbx
0xffffffff8117984a <deactivate_super+26>:       lea    0xb8(%rdi),%rdi
0xffffffff81179851 <deactivate_super+33>:       callq  0xffffffff8126a820
<_atomic_dec_and_lock>
0xffffffff81179856 <deactivate_super+38>:       test   %eax,%eax
0xffffffff81179858 <deactivate_super+40>:       je     0xffffffff811798b0
<deactivate_super+128>
0xffffffff8117985a <deactivate_super+42>:       subl
$0x3fffffff,0xb0(%rbx)
0xffffffff81179864 <deactivate_super+52>:       mov
$0xffffffff81fc0a00,%rax
0xffffffff8117986b <deactivate_super+59>:       incw   (%rax)
0xffffffff8117986e <deactivate_super+62>:       data32 xchg %ax,%ax
0xffffffff81179871 <deactivate_super+65>:       mov    0x48(%rbx),%rax
0xffffffff81179875 <deactivate_super+69>:       test   %rax,%rax
0xffffffff81179878 <deactivate_super+72>:       je     0xffffffff8117988f
<deactivate_super+95>
0xffffffff8117987a <deactivate_super+74>:       mov    0x8(%rax),%rax
0xffffffff8117987e <deactivate_super+78>:       test   %rax,%rax
0xffffffff81179881 <deactivate_super+81>:       je     0xffffffff8117988f
<deactivate_super+95>
0xffffffff81179883 <deactivate_super+83>:       xor    %edx,%edx
0xffffffff81179885 <deactivate_super+85>:       mov    $0xffffffff,%esi
0xffffffff8117988a <deactivate_super+90>:       mov    %rbx,%rdi
0xffffffff8117988d <deactivate_super+93>:       callq  *%rax
0xffffffff8117988f <deactivate_super+95>:       lea    0x70(%rbx),%rdi
0xffffffff81179893 <deactivate_super+99>:       callq  0xffffffff814ee5c0
<down_write>
0xffffffff81179898 <deactivate_super+104>:      mov    %rbx,%rdi
0xffffffff8117989b <deactivate_super+107>:      callq  *0x18(%r12)
0xffffffff811798a0 <deactivate_super+112>:      mov    %r12,%rdi
0xffffffff811798a3 <deactivate_super+115>:      callq  0xffffffff81193c20
<put_filesystem>


*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 <deactivate_super>:          push   %rbp
[1] 0xffffffff81179831 <deactivate_super+1>:        mov    %rsp,%rbp
[2] 0xffffffff81179834 <deactivate_super+4>:        push   %r12
[2] 0xffffffff81179836 <deactivate_super+6>:        push   %rbx
[3] 0xffffffff81179837 <deactivate_super+7>:        nopl   0x0(%rax,%rax,1)
[4] 0xffffffff8117983c <deactivate_super+12>:       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 <deactivate_super+104>:      mov    %rbx,%rdi
[2] 0xffffffff8117989b <deactivate_super+107>:      callq  *0x18(%r12)
[3] 0xffffffff811798a0 <deactivate_super+112>:      mov    %r12,%rdi
[4] 0xffffffff811798a3 <deactivate_super+115>:      callq  0xffffffff81193c20 <put_filesystem>

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 <deactive_super+23>).
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:

put_super(s);

And this makes sense, since we know %r12 is a copy of 's'.

I hope this shows that analysing (such small) functions is actually quite
easy. What you need, however, is the ABI in your head.
3)bt -f gives highlighted above, register dump at the end, does that help
in finding this information ???
Yes. You'll find the address in 's' in the %rdi register.

Regards,
Tobi
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help