4

从这个问题的第二个答案中可以看出,使用节的名称从程序自身内部获取指向程序特定节的指针非常简单。使用libelf,只需打开程序自己的文件,遍历其中的所有部分(由Elf64_Shdr结构表示),当部分名称与您想要的部分匹配时停止并使用存储在结构sh_addr元素中的指针Elf64_Shdr。在这种情况下,获取想要的指针非常简单,因为它是在 ELF 可执行文件中定义的。

但是,假设您有一个使用动态库的程序,并且您需要获取指向该动态库的一部分的指针。由于其部分的地址是在运行时定义的,如何获得指向动态库部分的指针?

顺便说一句,动态库和主程序本身都有一个同名的部分(这是我需要获得指针的部分)。那么,在这种情况下,这两个具有相同名称的部分是否有可能在内存中相邻存储,所以我只需要获取指向主文件部分的指针(正如我在第一段中解释的那样)并添加一个偏移量到达动态库部分?

4

2 回答 2

5

从自身内部获取指向程序特定部分的指针非常简单

不必要。在运行时实际上不需要节表,并且可以完全剥离(只有段重要,而不是节)。

由于其部分的地址是在运行时定义的,如何获得指向动态库部分的指针?

该库与主可执行文件完全不同。主要区别在于库通常在地址处链接0(主可执行文件不是),并由运行时加载程序重新定位到其他一些常量偏移量。

一旦知道了偏移量,只需将其添加到节开始(您可以readelf -S foo.so从 libelf 或从 libelf 中找到),瞧:您已经获得了该节的运行时地址。

那么如何找到给定共享库的重定位呢?

不优雅的解决方案(尼克已经建议)是解析/proc/self/maps.

更好的解决方案是使用 (glibc-specific) dl_iterate_phdr。文档在这里。你会想要使用dlpi_addr.

于 2012-11-14T05:49:31.370 回答
0

很简单,这里举个例子:

#include <stdio.h>

int i __attribute__((section("my_section"))) = 2;
int j __attribute__((section("my_section"))) = 3;
int k __attribute__((section("my_section"))) = 5;

extern int __start_my_section;
extern int __stop_my_section;

int main(void)
{
    int *p = &__start_my_section;

    printf("%d\n", *p++); /* print k value */
    printf("%d\n", *p++); /* print j value */
    printf("%d\n", *p);   /* print i value */

   return 0;
}   
于 2016-05-21T11:07:52.243 回答