如何在C(gcc)中获取自定义ELF部分的起始和结束地址?
我已经看到使用gcc __section__
属性 (特别是在Linux内核中)将数据(通常是函数指针)收集到自定义ELF部分中。 如何检索和使用这些自定义部分中的“东西”?
只要节名称产生有效的C变量名称, gcc
( ld
,而不是)就会生成两个魔术变量: __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); ...