c – 获取主要可执行文件的ELF标题

前端之家收集整理的这篇文章主要介绍了c – 获取主要可执行文件的ELF标题前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
为了各种目的,我正在尝试获取主要可执行文件的ELF头的地址,而无需解析/ proc / self / maps.我尝试解析由dlopen / dlinfo函数给出的link_list链,但是它们不包含一个条目,其中l_addr指向主可执行文件的基址.有没有办法这样做(标准与否),无需解析/ proc / self / maps?

我想要做的一个例子:

  1. #include <stdio.h>
  2. #include <elf.h>
  3. int main()
  4. {
  5. Elf32_Ehdr* header = /* Somehow obtain the address of the ELF header of this program */;
  6. printf("%p\n",header);
  7. /* Read the header and do stuff,etc */
  8. return 0;
  9. }

解决方法

由dlopen(0,RTLD_LAZY)返回的void *指针给出一个对应于主可执行文件的struct link_map *.

调用dl_iterate_phdr也会在首次执行回调时返回主可执行文件的条目.

你可能会被链接映射中的.l_addr == 0这个事实所困惑,而使用dl_iterate_phdr的那个dlpi_addr == 0.

这正在发生,因为l_addr(和dlpi_addr)实际上并没有记录ELF映像的加载地址.相反,它们记录已应用于该映像的重定位.

通常,主可执行文件的加载位置为0x400000(对于x86_64 Linux)或0x08048000(对于ix86 Linux),并且加载在相同的地址(即它们不被重新定位).

但是如果您将可执行文件与-pie标记链接,那么它将链接到0x0,并将其重定位到其他地址.

那么如何到达ELF标题?简单:

  1. #ifndef _GNU_SOURCE
  2. #define _GNU_SOURCE
  3. #endif
  4.  
  5. #include <link.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8.  
  9. static int
  10. callback(struct dl_phdr_info *info,size_t size,void *data)
  11. {
  12. int j;
  13. static int once = 0;
  14.  
  15. if (once) return 0;
  16. once = 1;
  17.  
  18. printf("relocation: 0x%lx\n",(long)info->dlpi_addr);
  19.  
  20. for (j = 0; j < info->dlpi_phnum; j++) {
  21. if (info->dlpi_phdr[j].p_type == PT_LOAD) {
  22. printf("a.out loaded at %p\n",(void *) (info->dlpi_addr + info->dlpi_phdr[j].p_vaddr));
  23. break;
  24. }
  25. }
  26. return 0;
  27. }
  28.  
  29. int
  30. main(int argc,char *argv[])
  31. {
  32. dl_iterate_phdr(callback,NULL);
  33. exit(EXIT_SUCCESS);
  34. }
  35.  
  36.  
  37. $gcc -m32 t.c && ./a.out
  38. relocation: 0x0
  39. a.out loaded at 0x8048000
  40.  
  41. $gcc -m64 t.c && ./a.out
  42. relocation: 0x0
  43. a.out loaded at 0x400000
  44.  
  45. $gcc -m32 -pie -fPIC t.c && ./a.out
  46. relocation: 0xf7789000
  47. a.out loaded at 0xf7789000
  48.  
  49. $gcc -m64 -pie -fPIC t.c && ./a.out
  50. relocation: 0x7f3824964000
  51. a.out loaded at 0x7f3824964000

更新:

Why does the man page say “base address” and not relocation?

这是一个bug

猜你在找的C&C++相关文章