__attribute__ ((section(".text")))的測試


一、測試原因

   在學習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:

 

參考:attribute 用法 section 部分


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM