Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting calling conventions from DWARF info

I am trying to get information about calling conventions from DWARF info. More specific, I want to get which registers / stack locations are used to pass arguments to functions. My problem is that I am getting somehow wrong information in some cases from DWARF dump. The example I am using is the following "C code":

int __attribute__ ((fastcall)) __attribute__ ((noinline)) mult (int x, int y) {
return x*y;
}

I compile this example using the following command:

gcc -c -g -m32 test.c -o test.o

Now when I use the following command to get the dwarf dump:

dwarfdump test.o

I am getting the following information about this function:

< 2><0x00000042>      DW_TAG_formal_parameter
                        DW_AT_name                  "x"
                        DW_AT_decl_file             0x00000001 /home/khaled/Repo_current/trunk/test.c
                        DW_AT_decl_line             0x00000001
                        DW_AT_type                  <0x0000005b>
                        DW_AT_location              DW_OP_fbreg -12
< 2><0x0000004e>      DW_TAG_formal_parameter
                        DW_AT_name                  "y"
                        DW_AT_decl_file             0x00000001 /home/khaled/Repo_current/trunk/test.c
                        DW_AT_decl_line             0x00000001
                        DW_AT_type                  <0x0000005b>
                        DW_AT_location              DW_OP_fbreg -16

Looking at the DW_AT_location entries, it is some offset from the frame base. This implies they are memory arguments, but the actual calling convention "fastcall" forces passing them into registers. By looking at the disassembly of the produced object file, I can see they are copied from registers to stack locations at the entry point of the function. Is there a way to know from the dwarf dump --or using any other way-- where the arguments are passed at the call initially?

Thanks,

like image 668
Khaled ElWazeer Avatar asked Sep 03 '12 17:09

Khaled ElWazeer


1 Answers

Because you are using gcc -c -g -m32 test.c -o test.o. Although it is a fastcall function, GCC still needs to generate code to save values from registers to the stack frame at the beginning of the function. Without that, any debugger or gdb cannot debug the program or they will say the argument is being optimized and not shown. It makes debugging impossible.

In x86_64, compiler also uses some registers to pass some arguments by default, even without specifying attribute fastcall for a function. You can also find those registers are being copied to the stack as well.

// x86_64 assembly code
_mult:
Leh_func_begin1:
      pushq   %rbp
Ltmp0:
      movq    %rsp, %rbp
Ltmp1:
      movl    %edi, -4(%rbp)
      movl    %esi, -8(%rbp)
      movl    -4(%rbp), %eax
      movl    -8(%rbp), %ecx
      imull   %ecx, %eax

If you turn on optimization flag -O, -O2, -O3 (no matter -g or not), you can disassemble and find there is nothing being copied to the stack frame. And when you gdb the optimized executable file, and stop at the beginning of the function to show local variables, gdb will tell you those arguments are being optimized out.

the dwarfdump example of the 32-bit program would look like

0x00000083:      TAG_formal_parameter [4]  
                 AT_name( "x" )
                 AT_decl_file( "test.c" )
                 AT_decl_line( 1 )
                 AT_type( {0x0000005f} ( int ) )
                 AT_location( 0x00000000
                    0x00000000 - 0x00000003: ecx
                    0x00000003 - 0x00000018: ecx )

0x00000090:      TAG_formal_parameter [4]  
                 AT_name( "y" )
                 AT_decl_file( "test.c" )
                 AT_decl_line( 1 )
                 AT_type( {0x0000005f} ( int ) )
                 AT_location( 0x0000001e
                    0x00000000 - 0x00000003: edx
                    0x00000003 - 0x00000018: edx )

And you can find the generated assembly code is much simple and clean.

_mult:
        pushl   %ebp
        movl    %esp, %ebp
        movl    %ecx, %eax
        imull   %edx, %eax
        popl    %ebp
        ret     $12
like image 58
jclin Avatar answered Oct 06 '22 20:10

jclin