一、測試原因
在學習u-boot的環境變量過程中,看到有如此的代碼,現對涉及到的內容進行實驗測試。
二、測試目的
1、了解gcc允許對段的屬性進行更改的方法。
2、解決”ENV_IS_EMBEDDED“解惑以及相關的移植實驗中如何將環境變量(結構體變量environment)定位在代碼段的0x33f84000的位置,以實現環境變量區嵌入到代碼段的功能。
三、測試原理(參考attribute 用法 section 部分)
gcc通過選項__attribute__可以改變所聲明或定義的函數、數據的特性。它有很多子項,用於改變作用對象的特性。比如對函數,noline將禁止進行內聯擴展、noreturn表示沒有返回值、pure表明函數除返回值外,不會通過其它(如全局變量、指針)對函數外部產生任何影響。但這里我們比較感興趣的是對代碼段起作用子項section。
__attribute__的section子項的使用格式為:
__attribute__((section("section_name")))
其作用是將作用的函數或數據放入指定名為"section_name"輸入段。
輸入段和輸出段
輸入段和輸出段是相對於要生成最終的elf或binary時的Link過程說的。
Link過程的輸入大都是由源代碼編繹生成的目標文件.o,那么這些.o 文件中包含的段相對link過程來說就是輸入段,而Link的輸出一般是可執行文件elf或庫等,這些輸出文件中也包含有段,這些輸出文件中的段就叫做輸出段。輸入段和輸出段本來沒有什么必然的聯系,是互相獨立。只是在Link過程中,Link程序會根據一定的規則(這些規則其實來源於Link Script),將不同的輸入段重新組合到不同的輸出段中,即使是段的名字,輸入段和輸出段可以完全不同。
需要着重注意的是,__attribute__的section屬性只指定對象的輸入段,它並不能影響所指定對象最終會放在可執行文件的什么段。
舉例如下:
更改變量的段屬性
定義的變量var將被放入名為.xdata的輸入段,(注意:__attribute__這種用法中的括號好像很嚴格,這里的幾個括號好象一個也不能少。)
int var __attribute__((section(".xdata"))) = 0;
更改函數的段屬性
這個例子將使函數functionA被放入名叫.xinit的輸入段。
static int __attribute__((section(".xinit"))) functionA(void) { ..... }
四、測試代碼
測試代碼主要是從common/environment.c中摘取的,以測試本應該放在數據段(.data)的environment如何嵌入到代碼段。
1、start.S
@****************************************************************************** @ File:crt0.S @ 功能:通過它轉入C程序 @****************************************************************************** .text .global _start _start: bl main @ 調用C程序中的main函數 halt_loop: b halt_loop
2、main.c
int DATA = 5; int BSS; const int RODATA = 5; int main(void) { return 0; }
3、environment.c
#define __PPCENV__ __attribute__ ((section(".text"))) asm (".globl " "env_offset"); //定義全局變量env_offset以供連接腳本調用 asm ("env_offset" " = " "0x04000"); #define CFG_ENV_SIZE 0x2000 //環境變量大小 # define ENV_HEADER_SIZE (sizeof(unsigned long)) #define ENV_SIZE (CFG_ENV_SIZE - ENV_HEADER_SIZE) typedef struct environment_s { unsigned long crc; /* CRC32 over data bytes */ unsigned char data[ENV_SIZE]; /* Environment data */ } env_t; env_t environment __PPCENV__ = { //將environment的數據段屬性更改為代碼段 1, "this is in environment!\n" };
4、environment.lds
SECTIONS { . = 0x00000000;
. = ALIGN(4); .text : { start.o (.text); . = env_offset; environment.o(.text); *(.text) }
. = ALIGN(4); .rodata : { *(.rodata) }
. = ALIGN(4); .data : { *(.data) }
. = ALIGN(4); .bss : { *(.bss) } }
五、測試結果
Disassembly of section .text: 00000000 <_start>: 0: eb0017fe bl 6000 <main> 00000004 <halt_loop>: 4: eafffffe b 4 <halt_loop> ... 00004000 <environment>: 4000: 00000001 andeq r0, r0, r1 4004: 73696874 cmnvc r9, #7602176 ; 0x740000 4008: 20736920 rsbcss r6, r3, r0, lsr #18 400c: 65206e69 strvs r6, [r0, #-3689]! 4010: 7269766e rsbvc r7, r9, #115343360 ; 0x6e00000 4014: 656d6e6f strvsb r6, [sp, #-3695]! 4018: 0a21746e beq 8611d8 <BSS+0x85b1b8> ... 00006000 <main>: 6000: e1a0c00d mov ip, sp 6004: e92dd800 stmdb sp!, {fp, ip, lr, pc} 6008: e24cb004 sub fp, ip, #4 ; 0x4 600c: e3a03000 mov r3, #0 ; 0x0 6010: e1a00003 mov r0, r3 6014: e89da800 ldmia sp, {fp, sp, pc} Disassembly of section .rodata: 00006018 <RODATA>: 6018: 00000005 andeq r0, r0, r5 Disassembly of section .data: 0000601c <DATA>: 601c: 00000005 andeq r0, r0, r5 Disassembly of section .bss: 00006020 <BSS>: 6020: 00000000 andeq r0, r0, r0 Disassembly of section .comment: