本帖最后由 keer_zu 于 2021-7-19 10:27 编辑
linux下使用readelf -S prog, 可以看到一张elf格式的表。表中以.开头的是一个一个的段。 __attribute((section(name)))的作用就是将被该属性修饰的符号都放到名为name的段中。
示例代码main.c中的_func1与_func2被__section宏修饰,最终都会被放到自定义的名为.app_init_sec段中。
#include <stdio.h>
#include <string.h>
#define __section __attribute((section(".app_init_sec")))
typedef struct init_t{
int (*func)(void);
char *name;
}_init_t;
_init_t __app_init_start__;
_init_t __app_init_end__;
static int func1(void)
{
printf("call %s\n", __FUNCTION__);
return 0;
}
_init_t _func1 __section = {func1, "func1"};
static int func2(void)
{
printf("call %s\n", __FUNCTION__);
return 0;
}
_init_t _func2 __section = {func2, "func2"};
int main(int argc, char **argv)
{
_init_t *p;
for(p = &__app_init_start__; p < &__app_init_end__; p++){
printf("==%s\n", p->name);
p->func();
}
return 0;
}
也许你已经注意到.app_init_sec段尚未定义,且__app_init_start__与__app_init_end__未做初始化就直接使用了。这是因为这些工作都是在一个.lds格式的文件中完成的。一个简单的.lds文件内容如下所示:
//script.lds
SECTIONS
{
. = ALIGN(16);
__app_init_start__ = .;
.app_init_sec : { *(.app_init_sec) }
__app_init_end__ = .;
}
INSERT AFTER .rodata
为了编译出可执行的文件,需要运行如下的命令:
gcc main.c -T script.lds -g -o prog
运行程序prog, 输出如下所示:
zkq@zkq-VirtualBox:~/src/test/src$ ./prog
==func1
call func1
==func2
call func2
运行命令readelf -S prog查看elf表,可以在.rodata后找到自定义的.app_init_sec段: zkq@zkq-VirtualBox:~/src/test/src$ readelf -S prog
There are 37 section headers, starting at offset 0x202058:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 00000000004001c8 000001c8
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 00000000004001e4 000001e4
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.build-i NOTE 0000000000400204 00000204
0000000000000024 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400228 00000228
000000000000001c 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 0000000000400248 00000248
0000000000000060 0000000000000018 A 6 1 8
[ 6] .dynstr STRTAB 00000000004002a8 000002a8
000000000000003f 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 00000000004002e8 000002e8
0000000000000008 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 00000000004002f0 000002f0
0000000000000020 0000000000000000 A 6 1 8
[ 9] .rela.dyn RELA 0000000000400310 00000310
0000000000000018 0000000000000018 A 5 0 8
[10] .rela.plt RELA 0000000000400328 00000328
0000000000000030 0000000000000018 AI 5 25 8
[11] .init PROGBITS 0000000000400358 00000358
000000000000001a 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 0000000000400380 00000380
0000000000000030 0000000000000010 AX 0 0 16
[13] .plt.got PROGBITS 00000000004003b0 000003b0
0000000000000008 0000000000000000 AX 0 0 8
[14] .text PROGBITS 00000000004003c0 000003c0
0000000000000202 0000000000000000 AX 0 0 16
[15] .fini PROGBITS 00000000004005c4 000005c4
0000000000000009 0000000000000000 AX 0 0 4
[16] .rodata PROGBITS 00000000004005d0 000005d0
000000000000002b 0000000000000000 A 0 0 4
[17] .app_init_sec PROGBITS 0000000000400600 00000600
0000000000000020 0000000000000000 WA 0 0 16
[18] .eh_frame_hdr PROGBITS 0000000000400620 00000620
0000000000000044 0000000000000000 A 0 0 4
[19] .eh_frame PROGBITS 0000000000400668 00000668
0000000000000134 0000000000000000 A 0 0 8
[20] .init_array INIT_ARRAY 0000000000600e10 00200e10
0000000000000008 0000000000000000 WA 0 0 8
[21] .fini_array FINI_ARRAY 0000000000600e18 00200e18
0000000000000008 0000000000000000 WA 0 0 8
[22] .jcr PROGBITS 0000000000600e20 00200e20
0000000000000008 0000000000000000 WA 0 0 8
[23] .dynamic DYNAMIC 0000000000600e28 00200e28
00000000000001d0 0000000000000010 WA 6 0 8
[24] .got PROGBITS 0000000000600ff8 00200ff8
0000000000000008 0000000000000008 WA 0 0 8
[25] .got.plt PROGBITS 0000000000601000 00201000
0000000000000028 0000000000000008 WA 0 0 8
[26] .data PROGBITS 0000000000601028 00201028
0000000000000010 0000000000000000 WA 0 0 8
[27] .bss NOBITS 0000000000601038 00201038
0000000000000008 0000000000000000 WA 0 0 1
[28] .comment PROGBITS 0000000000000000 00201038
0000000000000035 0000000000000001 MS 0 0 1
[29] .debug_aranges PROGBITS 0000000000000000 0020106d
0000000000000030 0000000000000000 0 0 1
[30] .debug_info PROGBITS 0000000000000000 0020109d
00000000000001e8 0000000000000000 0 0 1
[31] .debug_abbrev PROGBITS 0000000000000000 00201285
00000000000000f2 0000000000000000 0 0 1
[32] .debug_line PROGBITS 0000000000000000 00201377
0000000000000061 0000000000000000 0 0 1
[33] .debug_str PROGBITS 0000000000000000 002013d8
0000000000000120 0000000000000001 MS 0 0 1
[34] .shstrtab STRTAB 0000000000000000 00201efe
000000000000015a 0000000000000000 0 0 1
[35] .symtab SYMTAB 0000000000000000 002014f8
0000000000000798 0000000000000018 36 57 8
[36] .strtab STRTAB 0000000000000000 00201c90
000000000000026e 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
|