打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
利用libbfd获取elf可执行文件的section(节)及symbol(符号)信息

一. 安装bfd库

libbfd(Binary File Descriptor library是binutils中附带的一个C库。
从 http://ftp.gnu.org/gnu/binutils 下载binutils。
我们这里下载binutils-2.23.2.tar.gz
下载后,解压安装libbfd。方法如下:
tar -xzf binutils-2.23.2.tar.gz
cd binutils-2.23.2/bfd
./configure
make
make install


安装完成后,可以看到有如下文件生成。
/usr/local/include/bfd.h
/usr/local/lib/libbfd.a


二. 使用bfd库需要注意的地方

1. 头文件包含

程序使用bfd,需要包含bfd.h头文件。

但是,在包含bfd.h之前,还需要包含config.h。

即代码中需要有如下形式的文件包含:


  1. #include "config.h"  
  2. #include <bfd.h>  

那么这个config.h是什么东东呢?他不是系统的头文件,也不是bfd库的头文件,而是应用程序自己的头文件。

然而用户可能会感到奇怪,我的应用程序源码中并不存在这个config.h文件。那是因为你开发应用时,没有采用GNU autotools。

采用GNU autotools的项目,在编译前一般都会执行一下configure脚本,生成Makefile及config.h文件。

那么,对于没有使用GNU autotools的应用,怎么解决呢?本文这里提供一个简单的config.h文件。

这个文件的内容,相当于是使用GNU autotools开发一个hello world项目而得到的config.h。

  1. /* config.h.  Generated from config.h.in by configure.  */  
  2. /* config.h.in.  Generated from configure.ac by autoheader.  */  
  3.   
  4. /* Name of package */  
  5. #define PACKAGE "hello"  
  6.   
  7. /* Define to the address where bug reports for this package should be sent. */  
  8. #define PACKAGE_BUGREPORT "bug-report@address"  
  9.   
  10. /* Define to the full name of this package. */  
  11. #define PACKAGE_NAME "hello"  
  12.   
  13. /* Define to the full name and version of this package. */  
  14. #define PACKAGE_STRING "hello 1.0"  
  15.   
  16. /* Define to the one symbol short name of this package. */  
  17. #define PACKAGE_TARNAME "hello"  
  18.   
  19. /* Define to the home page for this package. */  
  20. #define PACKAGE_URL ""  
  21.   
  22. /* Define to the version of this package. */  
  23. #define PACKAGE_VERSION "1.0"  
  24.   
  25. /* Version number of package */  
  26. #define VERSION "1.0"  


2. 链接

需要带上这几个库:bfd iberty  dl z

例如,假设hello.c是一个完整的使用bfd库的程序,则他的编译方法如下。

gcc hello.c -lbfd -liberty  -ldl -lz


三. 应用实例

  1. #include <stdio.h>  
  2. #include <stdint.h>  
  3. #include "config.h"  
  4. #include <bfd.h>  
  5. #include <strings.h>  
  6. #include <linux/elf.h>  
  7.   
  8. /*  
  9.    这里定义3个static变量,并把他们放到一个单独的section中。 
  10.    后面,我们通过bfd找出这个section,并得到这3个变量的内容。 
  11.    同时,我们还通过符号查找操作,找到a_haha这个static变量的信息。 
  12. */  
  13. static uint64_t  a_haha   __attribute__((section ("my_test_sec"))) =3;  
  14. static uint64_t  b        __attribute__((section ("my_test_sec"))) =7;  
  15. static uint64_t  c        __attribute__((section ("my_test_sec"))) =8;  
  16.   
  17. /* 获取当前进程自己的elf文件路径 */  
  18. int get_self_path(char *buf, int buf_len)  
  19. {  
  20.     int ret = readlink("/proc/self/exe", buf, buf_len);  
  21.     buf[ret]='\0';  
  22.     return ret;   
  23. }  
  24.   
  25. void section_proc(bfd *abfd,  asection *sect, PTR obj)  
  26. {  
  27.     if (strcmp(sect->name, "my_test_sec")==0)  
  28.         printf("section %s exists\n", sect->name);  
  29. }  
  30.   
  31.   
  32.   
  33. void search_a_given_symbol(bfd *ibfd, const char *name)  
  34. {  
  35.          long storage_needed;  
  36.          asymbol **symbol_table;  
  37.          long number_of_symbols;  
  38.          long i;  
  39.          symbol_info symbolinfo ;  
  40.   
  41.          storage_needed = bfd_get_symtab_upper_bound(ibfd);  
  42.   
  43.   
  44.          symbol_table =  (void *)(unsigned long)xmalloc(storage_needed);  
  45.          number_of_symbols =  bfd_canonicalize_symtab (ibfd, symbol_table);  
  46.   
  47.   
  48.         printf("Scanning %i symbols\n", number_of_symbols);  
  49.         for(i=0;i<number_of_symbols;i++)  
  50.         {  
  51.                 if (symbol_table[i]->section==NULL) continue;  
  52.                   
  53.                 bfd_symbol_info(symbol_table[i],&symbolinfo);  
  54.                 if (strcmp(name, symbolinfo.name))  continue;  
  55.   
  56.                 printf("Section %s  ",symbol_table[i]->section->name);  
  57.                 printf("Symbol \"%s\"  value 0x%x\n",  
  58.                          symbolinfo.name, symbolinfo.value);  
  59.         }  
  60.   
  61.   
  62. }  
  63.   
  64. int main()  
  65. {  
  66.     char our_self_path[1024];  
  67.     bfd *ibfd;  
  68.     char **matching;  
  69.   
  70.     asection *psection;  
  71.   
  72.     bfd_init();  
  73.   
  74.     get_self_path(our_self_path, sizeof(our_self_path));  
  75.     printf("our elf file path:%s\n", our_self_path);  
  76.   
  77.     ibfd = bfd_openr(our_self_path, NULL);  
  78.     bfd_check_format_matches(ibfd, bfd_object, &matching);  
  79.   
  80.     printf("number of sections = %d\n", bfd_count_sections(ibfd));  
  81.   
  82.     /* 遍历所有section,让section_proc对每一个section进行处理 */  
  83.     bfd_map_over_sections(ibfd,  section_proc,  NULL);  
  84.   
  85.     /* 查找特定名称的section,打印出其信息 */  
  86.     psection = bfd_get_section_by_name(ibfd, "my_test_sec");  
  87.     printf("section name=%s; start_address=0x%llx; size=%d\n"  
  88.          , psection->name  
  89.          , psection->vma  
  90.          , psection->size);  
  91.   
  92.     /* 打印出my_test_sec section中的3个uint64_t变量的值 */  
  93.     {  
  94.         uint64_t *pu64 = (void *) psection->vma;  
  95.         printf("%lu %lu %lu \n", pu64[0], pu64[1], pu64[2]);  
  96.     }  
  97.   
  98.     printf("address of a_haha=%p\n", &a_haha);  
  99.   
  100.     /* 遍历所有符号,以找出名称为a_haha的符号 */  
  101.     search_a_given_symbol(ibfd, "a_haha");  
  102.     return 0;  
  103. }  


最后,程序运行效果如下:


  1. [root@smb test]# gcc hello.c -lbfd -liberty  -ldl -lz  
  2. [root@smb test]# ./a.out   
  3. our elf file path:/home/shared/sunmingbao/test/a.out  
  4. number of sections = 34  
  5. section my_test_sec exists  
  6. section name=my_test_sec; start_address=0x6c9a28; size=24  
  7. 3 7 8   
  8. address of a_haha=0x6c9a28  
  9. Scanning 1905 symbols  
  10. Section my_test_sec  Symbol "a_haha"  value 0x6c9a28  
  11. [root@smb test]#   



本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
编译GDB(主要针对LINUX平台)
15 readelf
ELF动态解析符号过程(修订版)
Linux ELF二进制文件解析及实战
[转]ELF 文件格式分析
Linux 查看 elf可执行文件格式的两个命令
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服