如何获得自定义ELF部分的起始和结束地址?

时间:2013-05-14 20:57:00

标签: c gcc elf

我在Linux上使用C语言。我已经看到使用gcc __section__ attribute(特别是在Linux内核中)将数据(通常是函数指针)收集到自定义ELF部分中。如何检索和使用这些自定义部分的“东西”?

5 个答案:

答案 0 :(得分:17)

只要部分名称产生有效的C变量名称,gccld,而不是)会生成两个神奇变量:__start_SECTION__stop_SECTION。这些可用于检索节的开始和结束地址,如下所示:

/**
 * Assuming you've tagged some stuff earlier with:
 * __attribute((__section__("my_custom_section")))
 */

struct thing *iter = &__start_my_custom_section;

for ( ; iter < &__stop_my_custom_section; ++iter) {
    /* do something with *iter */
}

我找不到任何关于此功能的正式文档,只有一些不起眼的邮件列表引用。如果您知道文档的位置,请发表评论!

如果您正在使用自己的链接描述文件(就像Linux内核那样),您必须自己添加魔术变量(请参阅vmlinux.lds.[Sh]this SO answer)。

有关使用自定义ELF部分的另一个示例,请参阅here

答案 1 :(得分:5)

从各种答案中收集信息,以下是如何将信息收集到自定义链接器部分,然后使用魔术变量__start_SECTION__stop_SECTION从该部分读取信息的工作示例您的C程序,其中SECTION是链接图中部分的名称。

链接器提供__start_SECTION__stop_SECTION变量,因此当从C代码中使用这些变量时,需要为这些变量创建显式extern引用。

如果编译器用于计算指针/数组偏移的对齐方式与链接器在每个节中打包的对象的对齐方式不同,也存在一些问题。一个解决方案(在本例中使用)是仅存储指向链接器部分中数据的指针。

#include <stdio.h>

struct thing {
    int val;
    const char* str;
    int another_val;
};
struct thing data1 = {1, "one"};
struct thing data2 = {2, "two"};

/* The following two pointers will be placed in "my_custom_section".
 * Store pointers (instead of structs) in "my_custom_section" to ensure
 * matching alignment when accessed using iterator in main(). */
struct thing *p_one __attribute__((section("my_custom_section"))) = &data1; 
struct thing *p_two __attribute__((section("my_custom_section"))) = &data2;

/* The linker automatically creates these symbols for "my_custom_section". */
extern struct thing *__start_my_custom_section;
extern struct thing *__stop_my_custom_section;

int main(void) {
    struct thing **iter = &__start_my_custom_section;
    for ( ; iter < &__stop_my_custom_section; ++iter) {
        printf("Have thing %d: '%s'\n", (*iter)->val, (*iter)->str);
    }
    return 0;
}

答案 2 :(得分:2)

链接器可以使用代码中定义的符号,如果在链接描述文件中使用确切的名称,则可以分配它们的初始值:

_smysection = .;
*(.mysection)
*(.mysection*)
_emysection = .;

只需在C代码中定义一个变量:

const void * _smysection;

然后您可以将其作为常规变量进行访问。

u32 someVar = (u32)&_smysection;

答案 3 :(得分:0)

所以上面的答案,__start_SECTION__stop_SECTION将起作用,但是为了使程序能够使用链接器中的信息,您需要将这些变量声明为extern char* __start_SECTION。享受!

extern char * __start_blobby;

...
printf("This section starts at %p\n", (unsigned int)&__start_blobby);
...

答案 4 :(得分:0)

HI:这样。

extern const struct pseudo_ta_head __start_ta_head_section;
extern const struct pseudo_ta_head __stop_ta_head_section;    

const struct pseudo_ta_head *start = &__start_ta_head_section;
const struct pseudo_ta_head *end = &__stop_ta_head_section;