当前位置 : 主页 > 大数据 > 区块链 >

gdb – 如何从elf文件中提取函数原型?

来源:互联网 收集:自由互联 发布时间:2021-06-22
我没有成功找到这个问题的答案. 使用GDB,我可以使用命令“call”来获取函数的原型. 例: (gdb) call fn$1 = {void (int, int)} 0x8048414 fn 因此,GDB只能从elf文件中找出fn()返回void并将两个整数作为
我没有成功找到这个问题的答案.

使用GDB,我可以使用命令“call”来获取函数的原型.
例:

(gdb) call fn
$1 = {void (int, int)} 0x8048414 <fn>

因此,GDB只能从elf文件中找出fn()返回void并将两个整数作为参数.

但是,我需要使用其他一些工具从elf文件中提取函数原型.最好,我想使用objdump / readelf.

有谁知道这是否可能?
如果不可能,GDB如何做到这一点?
elf文件的哪个部分是存储的函数原型?

GDB通过 DWARF debuginfo知道函数的签名. readelf -w ELF会抛弃它.您可能想要阅读Michael J. Eager的 Introduction to the
DWARF Debugging Format.使用 pyelftools,您可以从交互式Python会话中探索和试验DWARF.

要提取函数原型,您需要子程序调试信息条目. DWARF格式教程中的一个示例是:

strndup.c

1: #include "ansidecl.h"
 2: #include <stddef.h>
 3:
 4: extern size_t strlen (const char*);
 5: extern PTR malloc (size_t);
 6: extern PTR memcpy (PTR, const PTR, size_t);
 7:
 8: char *
 9: strndup (const char *s, size_t n)
10: {
11: char *result;
12: size_t len = strlen (s);
13:
14: if (n < len)
15: len = n;
16:
17: result = (char *) malloc (len + 1);
18: if (!result)
19: return 0;
20:
21: result[len] = '\0';
22: return (char *) memcpy (result, s, len);
23: }

DWARF描述为strndup.c

<1>: DW_TAG_base_type
   DW_AT_name = int
   DW_AT_byte_size = 4
   DW_AT_encoding = signed
<2>: DW_TAG_typedef
   DW_AT_name = size_t
   DW_AT_type = <3>
<3>: DW_TAG_base_type
   DW_AT_name = unsigned int
   DW_AT_byte_size = 4
   DW_AT_encoding = unsigned
<4>: DW_TAG_base_type
   DW_AT_name = long int
   DW_AT_byte_size = 4
   DW_AT_encoding = signed
<5>: DW_TAG_subprogram
   DW_AT_sibling = <10>
   DW_AT_external = 1
   DW_AT_name = strndup
   DW_AT_prototyped = 1
   DW_AT_type = <10>
   DW_AT_low_pc = 0
   DW_AT_high_pc = 0x7b
<6>: DW_TAG_formal_parameter
   DW_AT_name = s
   DW_AT_type = <12>
   DW_AT_location =
   (DW_OP_fbreg: 0)
<7>: DW_TAG_formal_parameter
   DW_AT_name = n
   DW_AT_type = <2>
   DW_AT_location =
   (DW_OP_fbreg: 4)
<8>: DW_TAG_variable
   DW_AT_name = result
   DW_AT_type = <10>
   DW_AT_location =
   (DW_OP_fbreg: -28)
<9>: DW_TAG_variable
   DW_AT_name = len
   DW_AT_type = <2>
   DW_AT_location =
   (DW_OP_fbreg: -24)
<10>: DW_TAG_pointer_type
   DW_AT_byte_size = 4
   DW_AT_type = <11>
<11>: DW_TAG_base_type
   DW_AT_name = char
   DW_AT_byte_size = 1
   DW_AT_encoding =
   signed char
<12>: DW_TAG_pointer_type
   DW_AT_byte_size = 4
   DW_AT_type = <13>
<13>: DW_TAG_const_type
   DW_AT_type = <11>

有关更完整的示例实现,请查看Petr Machata的this C reflection library.它有代码可以通过以下警告执行您想要的操作:

>反射在进程中运行,而不是像GDB那样在进程外运行
>它取决于elfutils中的libdw和libdwfl.不确定如何增长这些外部库依赖项.

网友评论