前言
本文介紹__attribute__ 的使用方法
__attribute__介紹
要了解Linux Kernel代碼的分段資訊,需要了解一下gcc的__attribute__的編繹屬性,__attribute__主要用于改變所聲明或定義的函數或 資料的特性,它有很多子項,用于改變作用對象的特性。比如對函數,noline将禁止進行内聯擴充、noreturn表示沒有傳回值、pure表明函數除 傳回值外,不會通過其它(如全局變量、指針)對函數外部産生任何影響。
子項 | 描述 |
---|---|
section | 将變量(整數變量、字元串和函數等)放入指定的節區段 |
section
子項section對代碼段起作用。其作用是将作用的函數或資料放入指定名為"section_name"輸入段。
__attribute__的section子項的使用格式為:
這裡還要注意一下兩個概念:輸入段和輸出段
輸入段和輸出段是相對于要生成最終的elf或binary時的連結過程說的
輸入段:
連結過程的輸入大都是由源代碼編繹生成的目标檔案.o,那麼這些.o 檔案中包含的段相對連結過程來說就是輸入段
輸出段:
連結過程的輸出一般是可執行檔案elf或庫等,這些輸出檔案中也包含有段,這些輸出檔案中的段就叫做輸出段。
輸入段和輸出段本來沒有什麼必然的聯系,是互相獨立,隻是在連結過程中,Link程式會根據一定的規則(這些規則來源于Link Script),将不同的輸入段重新組合到不同的輸出段中,即使是段的名字,輸入段和輸出段可以完全不同。
使用方法實踐
- 将整型變量var存放到.text段
int var __attribute__((section(".text"))) = 0;
- 将字元串str存放到.data段
char str[] __attribute__((section(".data"))) = "hello world";
- 将函數存放到.mysection段(這個是自定義的段)
void __attribute__((section(".mysection"))) myfunc()
{
printf("ohhh!");
}
-------------------------------------
typedef void (*funcptr)();
funcptr func __attribute__((section(".mysection"))) = myfunc;
void myfunc()
{
printf("ohhh!");
}
---------------------------------------------
typedef void (*funcptr)();
#define init __attribute__((section(".mysection")))
#define init_func(func) funcptr _fn_##func init=func
void myfunc()
{
printf("ohhh!");
}
init_func(myfunc);
注意事項
在.init_array或者constructor中使内聯彙編彙編的時候,需要使用pusha和popa指令儲存指令上下文,不否會報錯
參考
attribute 用法 section 部分
gcc attribute((section(“section_name”))) 使用方法