利用gcc的__attribute__编译属性section子项构建初始化函数表【转】
生活随笔
收集整理的這篇文章主要介紹了
利用gcc的__attribute__编译属性section子项构建初始化函数表【转】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
轉自:https://my.oschina.net/u/180497/blog/177206
gcc的__attribute__編譯屬性有很多子項,用于改變作用對象的特性。這里討論section子項的作用。__attribute__的section子項使用方式為:__attribute__((section("section_name")))其作用是將作用的函數或數據放入指定名為"section_name"的段。看以下程序片段:#include <unistd.h> #include <stdint.h> #include <stdio.h>typedef void (*myown_call)(void);extern myown_call _myown_start; extern myown_call _myown_end;#define _init __attribute__((unused, section(".myown"))) #define func_init(func) myown_call _fn_##func _init = funcstatic void mspec1(void) {write(1, "aha!\n", 5); }static void mspec2(void) {write(1, "aloha!\n", 7); }static void mspec3(void) {write(1, "hello!\n", 7); }func_init(mspec1); func_init(mspec2); func_init(mspec3);/* exactly like below: static myown_call mc1 __attribute__((unused, section(".myown"))) = mspec1; static myown_call mc2 __attribute__((unused, section(".myown"))) = mspec2; static myown_call mc3 __attribute__((unused, section(".myown"))) = mspec3; */void do_initcalls(void) {myown_call *call_ptr = &_myown_start;do {fprintf (stderr, "call_ptr: %p\n", call_ptr);(*call_ptr)();++call_ptr;} while (call_ptr < &_myown_end);}int main(void) {do_initcalls();return 0; }在自定義的.myown段依次填入mspec1/mspec2/mspec3的函數指針,并在do_initcalls中依次調用,從而達到構造并調用初始化函數列表的目的。兩個extern變量:extern myown_call _myown_start; extern myown_call _myown_end;來自ld的鏈接腳本,可以使用:ld --verbose獲取內置lds腳本,并在:__bss_start = .;之前添加以下內容:_myown_start = .;.myown : { *(.myown) } = 0x90000000_myown_end = .;code_segment : { *(code_segment) }即定義了.myown段及_myown_start/_myown_end變量(0x90000000這個數值可能需要調整)。保存修改后的鏈接器腳本,假設程序為s.c,鏈接器腳本保存為s.lds,使用以下命令編譯:gcc s.c -Wl,-Ts.lds執行結果:[root@localhost ]# ./a.out call_ptr: 0x8049768 aha! call_ptr: 0x804976c aloha! call_ptr: 0x8049770 hello!Have Fun! ? 著作權歸作者所有?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的利用gcc的__attribute__编译属性section子项构建初始化函数表【转】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: KandQ:那年,那树,那些知识点
- 下一篇: git仓库的简单使用