__attribute__ ((section(.text)))のテスト

9743 ワード

一、テスト原因
u-bootの環境変数を学習する過程で,このようなコードが見られ,関連する内容を実験的にテストした. 
二、テストの目的
1、gccがセグメントの属性を変更できる方法を理解する.
2、解決」ENV_IS_EMBEDDED"解惑および関連移植実験において,環境変数(構造体変数environment)をコードセグメントの0 x 33 f 84000の位置にどのように位置決めし,環境変数領域をコードセグメントに埋め込む機能を実現するか.
三、テスト原理(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!
" };

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 
00000004 : 4: eafffffe b 4 ... 00004000 : 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 0x85b1b8> ... 00006000
: 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 : 6018: 00000005 andeq r0, r0, r5 Disassembly of section .data: 0000601c : 601c: 00000005 andeq r0, r0, r5 Disassembly of section .bss: 00006020 : 6020: 00000000 andeq r0, r0, r0 Disassembly of section .comment:

 
参照:attribute使用法sectionセクション