2012-09-03 23 views
6

Tôi đang cố gắng lấy thông tin về các quy ước gọi điện từ thông tin DWARF. Cụ thể hơn, tôi muốn nhận được vị trí đăng ký/ngăn xếp nào được sử dụng để chuyển đối số cho các hàm. Vấn đề của tôi là tôi nhận được thông tin sai bằng cách nào đó trong một số trường hợp từ DWARF dump. Ví dụ tôi đang sử dụng là sau "mã C":Nhận các quy ước về cuộc gọi từ thông tin DWARF

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

tôi biên dịch ví dụ này bằng cách sử dụng lệnh sau:

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

Bây giờ khi tôi sử dụng lệnh sau đây để có được những bãi lùn:

dwarfdump test.o 

tôi nhận được thông tin sau về chức năng này:

< 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 

Nhìn vào các mục nhập DW_AT_location, nó là một số bù đắp từ cơ sở khung. Điều này ngụ ý rằng chúng là các đối số bộ nhớ, nhưng các quy ước gọi là "fastcall" thực thi truyền chúng thành các thanh ghi. Bằng cách xem xét việc tháo gỡ tệp đối tượng được tạo ra, tôi có thể thấy chúng được sao chép từ sổ đăng ký đến các vị trí ngăn xếp tại điểm vào của hàm. Có cách nào để biết từ bãi lùn - hay sử dụng bất kỳ cách nào khác-- nơi các đối số được truyền vào cuộc gọi ban đầu?

Xin cảm ơn,

Trả lời

6

Vì bạn đang sử dụng gcc -c -g -m32 test.c -o test.o. Mặc dù nó là một hàm fastcall, GCC vẫn cần tạo mã để lưu các giá trị từ sổ đăng ký vào khung ngăn xếp ở đầu hàm. Nếu không có điều đó, bất kỳ trình gỡ lỗi hoặc gdb không thể gỡ lỗi chương trình hoặc họ sẽ nói đối số đang được tối ưu hóa và không được hiển thị. Nó làm cho việc gỡ rối không thể.

Trong x86_64, trình biên dịch cũng sử dụng một số thanh ghi để chuyển một số đối số theo mặc định, ngay cả khi không chỉ định thuộc tính fastcall cho hàm. Bạn cũng có thể tìm thấy những thanh ghi đang được sao chép vào ngăn xếp là tốt.

// 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 

Nếu bạn bật tối ưu hóa cờ -O, -O2, -O3 (dù -g hay không), bạn có thể tháo rời và tìm thấy ở đó không có gì được sao chép vào khung stack là. Và khi bạn gdb tệp thực thi được tối ưu hóa và dừng ở đầu hàm để hiển thị các biến cục bộ, gdb sẽ cho bạn biết các đối số đó đang được tối ưu hóa.

các dwarfdump ví dụ về chương trình 32-bit sẽ trông như thế

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) 

Và bạn có thể tìm thấy mã lắp ráp tạo ra nhiều đơn giản và sạch sẽ.

_mult: 
     pushl %ebp 
     movl %esp, %ebp 
     movl %ecx, %eax 
     imull %edx, %eax 
     popl %ebp 
     ret  $12 
Các vấn đề liên quan