如何从一个精灵文件中提取函数原型? [英] How to extract function prototypes from an elf file?

查看:272
本文介绍了如何从一个精灵文件中提取函数原型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这个问题上我找不到答案。

使用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提供。它有代码来做你想做的事情,并提出以下警告:




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 and libdwfl from elfutils. Not sure how you'd feel about growing those external library dependencies.

这篇关于如何从一个精灵文件中提取函数原型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆