Một câu hỏi tương tự đã được hỏi về Stack Overflow: Làm thế nào để trích xuất nguyên mẫu hàm từ tệp ELF?
Tóm lại: nói chung bạn không thể. Nếu thư viện thực thi (hoặc thư viện dùng chung) không có thông tin gỡ lỗi, thông tin về số lượng và loại đối số sẽ không được lưu trữ trong tệp thực thi.
Nếu tệp đối tượng được chia sẻ không có thông tin gỡ lỗi, thì bạn sẽ có thể trích xuất thông tin bằng readelf -wi
hoặc sử dụng trình gỡ lỗi.
Ví dụ: tôi đã có một tệp thực thi ELF có chứa một hàm int foo(char a, long b)
, được biên dịch với thông tin gỡ lỗi. GDB nói với tôi:
(gdb) p foo
$1 = {int (char, long int)} 0x40051c <foo>
Và readelf -wi
(một chút khó hiểu, bạn sẽ phải tự khớp với các mục):
<1><2d>: Abbrev Number: 2 (DW_TAG_subprogram) <= function
<2e> DW_AT_external : 1
<2f> DW_AT_name : foo <= func name
<33> DW_AT_decl_file : 1
<34> DW_AT_decl_line : 1
<35> DW_AT_prototyped : 1
<36> DW_AT_type : <0x6c> <= return type
<3a> DW_AT_low_pc : 0x40051c
<42> DW_AT_high_pc : 0x400532
<4a> DW_AT_frame_base : 0x0 (location list)
<4e> DW_AT_GNU_all_call_sites: 1
<4f> DW_AT_sibling : <0x6c>
<2><53>: Abbrev Number: 3 (DW_TAG_formal_parameter) <= parameter
<54> DW_AT_name : a
<56> DW_AT_decl_file : 1
<57> DW_AT_decl_line : 1
<58> DW_AT_type : <0x73>
<5c> DW_AT_location : 2 byte block: 91 6c (DW_OP_fbreg: -20)
<2><5f>: Abbrev Number: 3 (DW_TAG_formal_parameter) <= other param
<60> DW_AT_name : b
<62> DW_AT_decl_file : 1
<63> DW_AT_decl_line : 1
<64> DW_AT_type : <0x7a>
<68> DW_AT_location : 2 byte block: 91 60 (DW_OP_fbreg: -32)
<1><6c>: Abbrev Number: 4 (DW_TAG_base_type)
<6d> DW_AT_byte_size : 4
<6e> DW_AT_encoding : 5 (signed)
<6f> DW_AT_name : int
<1><73>: Abbrev Number: 5 (DW_TAG_base_type)
<74> DW_AT_byte_size : 1
<75> DW_AT_encoding : 6 (signed char)
<76> DW_AT_name : (indirect string, offset: 0x2e): char
<1><7a>: Abbrev Number: 5 (DW_TAG_base_type)
<7b> DW_AT_byte_size : 8
<7c> DW_AT_encoding : 5 (signed)
<7d> DW_AT_name : (indirect string, offset: 0x0): long int
Lưu ý rằng đối với C ++, các ký hiệu bạn thấy nm
mang theo nhiều thông tin hơn (trừ khi chúng được khai báo extern "C"
- số lượng và loại tham số phải có sẵn cho trình liên kết để xử lý quá tải. Nhưng thông tin loại trả về cũng không có. (Nhưng các biểu tượng được đọc sai - c++filt
có thể được sử dụng để tháo gỡ.)
Biên dịch cùng một tệp nguồn như C ++ cung cấp đầu ra sau cho nm a.out | c++filt
:
...
0000000000400554 T foo(char, long)
...