如何在C(gcc)中获取自定义ELF部分的起始和结束地址?

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

只要节名称产生有效的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 */ } 

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

如果您正在使用自己的链接器脚本(就像Linux内核那样),您必须自己添加魔术变量(请参阅vmlinux.lds.[Sh]和此SO答案 )。

有关使用自定义ELF部分的另一个示例,请参见此处 。

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

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

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

 #include  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; } 

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

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

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

 const void * _smysection; 

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

 u32 someVar = (u32)&_smysection; 

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

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