uboot.lds解読------詳細
はい.ldsファイルは、プログラムコンパイル後の接続プロセス全体を定義し、実行可能なプログラムの各セグメントの格納場所を決定します.今はまだあまり使っていませんが、とても重要な感じがします.理解する必要があります.
まずGNUの公式サイトを見てみましょう.ldsファイル形式の完全な説明:
SECTIONS {
...
secname
start BLOCK(
align) (NOLOAD) : AT (
ldadr )
{
contents } >
region :
phdr =
fill
...
}
1、secname:セグメント名
2、contents:どの内容がこのセグメントに置かれるかを決定し、ターゲットファイル全体であってもよいし、ターゲットファイルのあるセグメント(コードセグメント、データセグメントなど)であってもよい.
3、start:本セグメント接続(実行)のアドレスであり、AT(ldadr)が使用されていない場合、本セグメントに格納されているアドレスもstartである.GNUのウェブサイトでは、startは任意のアドレスを記述する記号で記述することができると述べている.
4、AT(ldadr):このセグメントに格納(ロード)されるアドレスを定義します.
簡単な例を見てみましょう.(『2410完全開発』)
/* nand.lds */
SECTIONS {
firtst 0x00000000 : { head.o init.o }
second 0x30000000 : AT(4096) { main.o }
}
以上o 0 x 00000000アドレスの先頭に置く、init.-置いてoの後、彼らの運転アドレスも0 x 00000000であり、接続と記憶アドレスは同じ(AT指定なし)である.main.oは4096(0 x 1000、AT指定、記憶アドレス)の先頭に置かれているが、その運転アドレスは0 x 300000であり、実行前に0 x 1000(ロード先)から0 x 3000000(運転先)にコピーする必要があり、このプロセスはNand flashの読み取りにも用いられる.
これがストレージアドレスと接続(実行)アドレスの違いです.ロード時間領域と実行時間領域と呼ばれ、.lds接続スクリプトファイルでそれぞれ指定できます.
作成済みldsファイルはarm-linux-ld接続コマンドで-Tfilenameを使用して実行を呼び出します.
arm-linux-ld –Tnand.lds x.o y.o –o xy.o.-ttextパラメータを使用して接続アドレスを直接指定します.
arm-linux-ld –Ttext 0x30000000 x.o y.o –o xy.o.
プログラムに2つのアドレスがある以上、いくつかのジャンプ命令の违いに関连して、ここはちょうど书いて、后で万一忘れても见ることができて、以前は多くのものを覚えていなかったが、今はあまり忘れていません.の
ARMアセンブリでは、bジャンプ命令、ldr命令がPCに値を付与する2つのジャンプ方法がよくあります.
私自身の経緯は以下の通りです.
(1)b step 1:bジャンプ命令は相対ジャンプであり、現在のPCの値に依存し、オフセット量はその命令そのもののbit[23:0]で算出されるので、b命令を用いるプログラムはジャンプするコードの位置に依存せず、命令そのもののみを見ることができる.
(2)ldr pc,=step 1:この命令はメモリ内のある位置(step 1)からデータを読み出してPCに付与し,同様に現在のPCの値に依存するが,オフセット量はその位置(step 1)の接続アドレス(実行時のアドレス)であるため,FlashからRAMへのプログラムジャンプを実現できる.
(3)また、adrダミー命令を振り返る必要があります.U-bootのrelocateコードは、adrによって現在のプログラムがRAMにあるかflashにあるかを実現します.私の当時の注釈を使用します.
relocate:/*U-BootをRAMに再配置*/
adr r0, _start/*r 0はコードの現在位置*/
/*adrダミー命令、アセンブラは自動的に現在のPCの値を通じて計算してもし_に実行するならばstart時のPCの値は、r 0に入れます.
このセグメントがflashで実行されるとr 0=start = 0;このセグメントがRAMで実行されるとき_start = _TEXT_BASE(board/smdk 2410/config.mkで指定した値は0 x 33 F 80000、すなわちu-bootがRAMにコードをコピーして実行するコードセグメントの開始)*/
ldr r1, _TEXT_BASE/*テストはFlashから起動するか、RAM*/
/*この文の実行結果r 1は常に0 x 33 FF 80000であり、この値はまたコンパイラによって指定された(adsで設定されているか、-Dでコンパイラパラメータを設定されている)*/
cmp r 0,r 1/*r 0とr 1を比較し、デバッグ時に再位置決めを実行しない*/
以下、u-boot.ldsは正式な接続スクリプトファイルを見ます.このファイルの基本的な机能はまだ见ることができて、上で多くの分析をしましたが、その中のGNUスタイルのシンボルはやはり私を困惑させて、良い料理、道理で3つの会社に軽蔑されて、自分で自分を軽蔑します.
OUTPUT_FORMAT("elf32littlearm", "elf32littlearm", "elf32littlearm")
;指定出力実行ファイルはelf形式、32ビットARM命令、小端
OUTPUT_ARCH(arm)
;実行可能ファイルを出力するプラットフォームをARMと指定
ENTRY(_start)
;出力実行ファイルの開始コードセグメントを指定します.start.
SECTIONS
{
. = 0x00000000 ; 0 x 0位置から
. = ALIGN(4) ; コードを4バイトで整列
.text : ;コードセグメントの指定
{
cpu/arm920t/start.o (.text) ; コードの最初のコード部分
*(.text) ;その他のコードセクション
}
. = ALIGN(4)
.rodata : { *(.rodata) } ;読取り専用データ・セグメントの指定
. = ALIGN(4);
.data : { *(.data) } ;リード/ライトセグメントの指定
. = ALIGN(4);
.got : { *(.got) } ;gotセグメントを指定します.gotセグメント式はubootカスタムセグメントで、標準セグメントではありません.
__u_boot_cmd_start = . ;__をu_boot_cmd_startは現在位置、すなわち開始位置に値を付与する
.u_boot_cmd : { *(.u_boot_cmd) } ;u_の指定boot_cmdセグメント、ubootはすべてのubootコマンドをこのセグメントに置く.
__u_boot_cmd_end = .;__をu_boot_cmd_end現在位置、すなわち終了位置に付与
. = ALIGN(4);
__bss_start = .; __をbss_startは現在位置、すなわちbssセグメントの開始位置に値を付与する
.bss : { *(.bss) }; bssセグメントの指定
_end = .; を選択します.endは現在位置、すなわちbssセグメントの終了位置に値を割り当てる
}
まずGNUの公式サイトを見てみましょう.ldsファイル形式の完全な説明:
SECTIONS {
...
secname
start BLOCK(
align) (NOLOAD) : AT (
ldadr )
{
contents } >
region :
phdr =
fill
...
}
secname contents , 。 :
1、secname:セグメント名
2、contents:どの内容がこのセグメントに置かれるかを決定し、ターゲットファイル全体であってもよいし、ターゲットファイルのあるセグメント(コードセグメント、データセグメントなど)であってもよい.
3、start:本セグメント接続(実行)のアドレスであり、AT(ldadr)が使用されていない場合、本セグメントに格納されているアドレスもstartである.GNUのウェブサイトでは、startは任意のアドレスを記述する記号で記述することができると述べている.
4、AT(ldadr):このセグメントに格納(ロード)されるアドレスを定義します.
簡単な例を見てみましょう.(『2410完全開発』)
/* nand.lds */
SECTIONS {
firtst 0x00000000 : { head.o init.o }
second 0x30000000 : AT(4096) { main.o }
}
以上o 0 x 00000000アドレスの先頭に置く、init.-置いてoの後、彼らの運転アドレスも0 x 00000000であり、接続と記憶アドレスは同じ(AT指定なし)である.main.oは4096(0 x 1000、AT指定、記憶アドレス)の先頭に置かれているが、その運転アドレスは0 x 300000であり、実行前に0 x 1000(ロード先)から0 x 3000000(運転先)にコピーする必要があり、このプロセスはNand flashの読み取りにも用いられる.
これがストレージアドレスと接続(実行)アドレスの違いです.ロード時間領域と実行時間領域と呼ばれ、.lds接続スクリプトファイルでそれぞれ指定できます.
作成済みldsファイルはarm-linux-ld接続コマンドで-Tfilenameを使用して実行を呼び出します.
arm-linux-ld –Tnand.lds x.o y.o –o xy.o.-ttextパラメータを使用して接続アドレスを直接指定します.
arm-linux-ld –Ttext 0x30000000 x.o y.o –o xy.o.
プログラムに2つのアドレスがある以上、いくつかのジャンプ命令の违いに関连して、ここはちょうど书いて、后で万一忘れても见ることができて、以前は多くのものを覚えていなかったが、今はあまり忘れていません.の
ARMアセンブリでは、bジャンプ命令、ldr命令がPCに値を付与する2つのジャンプ方法がよくあります.
私自身の経緯は以下の通りです.
(1)b step 1:bジャンプ命令は相対ジャンプであり、現在のPCの値に依存し、オフセット量はその命令そのもののbit[23:0]で算出されるので、b命令を用いるプログラムはジャンプするコードの位置に依存せず、命令そのもののみを見ることができる.
(2)ldr pc,=step 1:この命令はメモリ内のある位置(step 1)からデータを読み出してPCに付与し,同様に現在のPCの値に依存するが,オフセット量はその位置(step 1)の接続アドレス(実行時のアドレス)であるため,FlashからRAMへのプログラムジャンプを実現できる.
(3)また、adrダミー命令を振り返る必要があります.U-bootのrelocateコードは、adrによって現在のプログラムがRAMにあるかflashにあるかを実現します.私の当時の注釈を使用します.
relocate:/*U-BootをRAMに再配置*/
adr r0, _start/*r 0はコードの現在位置*/
/*adrダミー命令、アセンブラは自動的に現在のPCの値を通じて計算してもし_に実行するならばstart時のPCの値は、r 0に入れます.
このセグメントがflashで実行されるとr 0=start = 0;このセグメントがRAMで実行されるとき_start = _TEXT_BASE(board/smdk 2410/config.mkで指定した値は0 x 33 F 80000、すなわちu-bootがRAMにコードをコピーして実行するコードセグメントの開始)*/
ldr r1, _TEXT_BASE/*テストはFlashから起動するか、RAM*/
/*この文の実行結果r 1は常に0 x 33 FF 80000であり、この値はまたコンパイラによって指定された(adsで設定されているか、-Dでコンパイラパラメータを設定されている)*/
cmp r 0,r 1/*r 0とr 1を比較し、デバッグ時に再位置決めを実行しない*/
以下、u-boot.ldsは正式な接続スクリプトファイルを見ます.このファイルの基本的な机能はまだ见ることができて、上で多くの分析をしましたが、その中のGNUスタイルのシンボルはやはり私を困惑させて、良い料理、道理で3つの会社に軽蔑されて、自分で自分を軽蔑します.
OUTPUT_FORMAT("elf32littlearm", "elf32littlearm", "elf32littlearm")
;指定出力実行ファイルはelf形式、32ビットARM命令、小端
OUTPUT_ARCH(arm)
;実行可能ファイルを出力するプラットフォームをARMと指定
ENTRY(_start)
;出力実行ファイルの開始コードセグメントを指定します.start.
SECTIONS
{
. = 0x00000000 ; 0 x 0位置から
. = ALIGN(4) ; コードを4バイトで整列
.text : ;コードセグメントの指定
{
cpu/arm920t/start.o (.text) ; コードの最初のコード部分
*(.text) ;その他のコードセクション
}
. = ALIGN(4)
.rodata : { *(.rodata) } ;読取り専用データ・セグメントの指定
. = ALIGN(4);
.data : { *(.data) } ;リード/ライトセグメントの指定
. = ALIGN(4);
.got : { *(.got) } ;gotセグメントを指定します.gotセグメント式はubootカスタムセグメントで、標準セグメントではありません.
__u_boot_cmd_start = . ;__をu_boot_cmd_startは現在位置、すなわち開始位置に値を付与する
.u_boot_cmd : { *(.u_boot_cmd) } ;u_の指定boot_cmdセグメント、ubootはすべてのubootコマンドをこのセグメントに置く.
__u_boot_cmd_end = .;__をu_boot_cmd_end現在位置、すなわち終了位置に付与
. = ALIGN(4);
__bss_start = .; __をbss_startは現在位置、すなわちbssセグメントの開始位置に値を付与する
.bss : { *(.bss) }; bssセグメントの指定
_end = .; を選択します.endは現在位置、すなわちbssセグメントの終了位置に値を割り当てる
}