如何从一个精灵文件中提取函数原型? [英] How to extract function prototypes from an elf file?
问题描述
在这个问题上我找不到答案。
使用GDB,我可以使用call命令来获取函数的原型。
示例:
(gdb)call fn
$ 1 = {void(int,int)} 0x8048414 < FN>
因此,GDB只能从elf-file中找出fn()返回void然后以两个整数作为参数。
但是,我需要使用其他工具从elf文件中提取函数原型。最好,我想使用objdump / readelf。
有谁知道这是否可能?
如果不可能,GDB如何做?
在elf文件的哪一部分是函数原型存储的?
GDB知道函数的签名 DWARF debuginfo。 readelf -w ELF
会转储它。您可能需要阅读简介
DWARF调试格式由Michael J. Eager撰写。使用 pyelftools ,您可以从交互式Python中探索和实验DWARF会话。
要提取函数原型,需要子程序
调试信息条目。 DWARF格式教程中的示例是:
strndup.c
<$ p $
1:#includeansidecl.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 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:}
strndup.c的DWARF描述
< 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>
要获得更完整的示例实现,请查看这个C反射库由Petr Machata提供。它有代码来做你想做的事情,并提出以下警告:
- 反射运行在进程中而不是像GDB那样的进程外
- 它取决于 libdw 和
libdwfl
://fedorahosted.org/elfutils/rel =nofollow> elfutils 。不知道如何增加这些外部库依赖关系。
- 它取决于 libdw 和
I have not been successful in finding an answer on this question.
Using GDB, I can use the command "call" to get the prototype of a function. Example:
(gdb) call fn
$1 = {void (int, int)} 0x8048414 <fn>
So, GDB is able to figure out, only from the elf-file, that fn() returns void and takes two integers as arguments.
However, I need to use some other tool to extract the function prototypes from an elf file. Preferably, I want to use objdump / readelf.
Does anyone know if this is possible? If it is not possible, how does GDB do it? In which section of the elf file is the function prototypes stored?
GDB knows the signature of a function through DWARF debuginfo. readelf -w ELF
would dump that. You'd probably want to read Introduction to the
DWARF Debugging Format by Michael J. Eager. Using pyelftools you can explore and experiment with DWARF from an interactive Python session.
To extract function prototypes, you want the subprogram
debug information entries. An example in the DWARF format tutorial is:
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 description for 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>
For a more complete sample implementation, take a look at this C reflection library by Petr Machata. It has the code to do what you want with the following caveat:
- Reflection runs in-process instead of out-of-process like GDB
- It depends on
libdw
andlibdwfl
from elfutils. Not sure how you'd feel about growing those external library dependencies.
这篇关于如何从一个精灵文件中提取函数原型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!