在共享对象库中查找函数的函数参数

Edw*_*hen 9 libraries dynamic-linking

我目前正在摆弄一些没有文档的 c 库。我想知道是否有可能在调用nm -Dor提供的内容之外检索更多元数据,例如参数和返回值objdump -T filename | grep text。我不确定这是否可行,但如果可行,我就不用去追捕负责图书馆的人了!

编辑:如果可能的话,我希望能够在不阅读机器代码的情况下做到这一点。如果我是机器代码方面的专家,似乎有一些解决方案可以让我轻松地做到这一点,但是由于我不是并且目前没有跳下那个兔子洞的愿望,我真的希望还有另一个解决方案道路。

Mat*_*Mat 10

Stack Overflow 上提出了一个非常相似的问题:如何从 ELF 文件中提取函数原型?

简而言之:通常你不能。如果可执行文件(或共享库)没有调试信息,则有关参数数量和类型的信息不会存储在可执行文件中。

如果共享对象文件确实有调试信息,那么您应该能够readelf -wi使用 或使用调试器提取信息。

例如,我有一个 ELF 可执行文件,其中包含一个int foo(char a, long b)使用调试信息编译的函数。GDB 告诉我:

(gdb) p foo
$1 = {int (char, long int)} 0x40051c <foo>
Run Code Online (Sandbox Code Playgroud)

并且readelf -wi(有点神秘,你必须自己匹配条目)有:

 <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 
Run Code Online (Sandbox Code Playgroud)

请注意,对于 C++,您看到的符号nm带有更多信息(除非它们已被声明extern "C"- 参数的数量和类型必须可供链接器使用以处理重载。但返回类型信息也不存在。(但是符号被破坏 -c++filt可用于破坏。)

编译与 C++ 相同的源文件为 提供以下输出nm a.out | c++filt:

...
0000000000400554 T foo(char, long)
...
Run Code Online (Sandbox Code Playgroud)