2016-11-09 21 views
0

をリンクLD私はimx6qのため(のCortex-A9)のコードをリンクするリンカスクリプトを持っている間は:巨大なバイナリサイズ

OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 
OUTPUT_ARCH(arm) 
ENTRY(Reset_Handler) 
/* SEARCH_DIR(.) */ 
GROUP(libgcc.a libc.a) 
/* INPUT (crtbegin.o crti.o crtend.o crtn.o) */ 

MEMORY { 
/* IROM (rwx) : ORIGIN = 0x00000000, LENGTH = 96K */ 
    IRAM (rwx) : ORIGIN = 0x00900000, LENGTH = 256K 
    IRAM_MMU (rwx): ORIGIN = 0x00938000, LENGTH = 24K 
    IRAM_FREE(rwx): ORIGIN = 0x00907000, LENGTH = 196K 
    DDR (rwx) : ORIGIN = 0x10000000, LENGTH = 1024M 
} 

/* PROVIDE(__cs3_heap_start = _end); */ 

SECTIONS { 
    .vector (ORIGIN(IRAM) + LENGTH(IRAM) - 144):ALIGN (32) { 
    __ram_vectors_start = . ; 
    . += 72 ; 
    __ram_vectors_end = . ; 
    . = ALIGN (4); 
    } >IRAM 

    . = ORIGIN(DDR); 
    .text(.) :ALIGN(8) { 
     *(.entry) 
     *(.text) 
     /* __init_array_start = .; */ 
     /* __init_array_end = .; */ 
     . = ALIGN (4); 
     __text_end__ = .; 
    } >DDR 

    .data :ALIGN(8) { 
     *(.data .data.*) 
     __data_end__ = .; 
    } 

    .bss(__data_end__) : { 
     . = ALIGN (4); 
     __bss_start__ = .; 
     *(.shbss) 
     *(.bss .bss.* .gnu.linkonce.b.*) 
     *(COMMON) 
     __bss_end__ = .; 
    } 

    /*  . += 10K; */ 
    /*  . += 5K; */ 

    top_of_stacks = .; 
    . = ALIGN (4); 
    . += 8; 
    free_memory_start = .; 

    .mmu_page_table : { 
    __mmu_page_table_base__ = .; 
    . = ALIGN (16K); 
    . += 16K; 
    } >IRAM_MMU 

    _end = .; 
    __end = _end; 
    PROVIDE(end = .); 
} 

私が構築され、バイナリサイズはわずか6 KBです。しかし、私は初期化された変数を追加することはできません。初期化された変数を追加すると、バイナリサイズは〜246 MBにジャンプします。何故ですか?私は、正確な場所を指定し、データセグメントの> DDRを提供することによって、テキストセクションの次の場所にデータセグメントをリンクしようとしました。バイナリサイズを6 KBに戻すように見えても、バイナリは起動に失敗します。どのようにして私のコードをDDRとデータ、bss、スタック、およびヒープ内のラム自体に、軽いバイナリサイズで保つことができますか?

別のスレッドで「リンカースクリプトでMEMORYタグを使用するとメモリの浪費問題を解決できる」と読みましたが、どうすればこのことができますか?

linker script wastes my memory

pleseはは、他の何かが必要かどうか尋ねるん。私はリンカースクリプトの経験がありません。 、次のように与えられていない初期化されたデータとバイナリの

readelfが--sections出力が助けてください

There are 19 section headers, starting at offset 0xd804: 

Section Headers: 
    [Nr] Name    Type   Addr  Off Size ES Flg Lk Inf Al 
    [ 0]     NULL   00000000 000000 000000 00  0 0 0 
    [ 1] .vector   NOBITS   0093ff80 007f80 000048 00 WA 0 0 32 
    [ 2] .text    PROGBITS  10000000 008000 0016fc 00 AX 0 0 8 
    [ 3] .text.vectors  PROGBITS  100016fc 0096fc 000048 00 AX 0 0 4 
    [ 4] .text.proc  PROGBITS  10001744 009744 000034 00 AX 0 0 4 
    [ 5] .bss    NOBITS   0093ffc8 007fc8 000294 00 WA 0 0 4 
    [ 6] .mmu_page_table NOBITS   00938000 008000 004000 00 WA 0 0 1 
    [ 7] .comment   PROGBITS  00000000 009778 00001f 01 MS 0 0 1 
    [ 8] .ARM.attributes ARM_ATTRIBUTES 00000000 009797 00003d 00  0 0 1 
    [ 9] .debug_aranges PROGBITS  00000000 0097d8 000108 00  0 0 8 
    [10] .debug_info  PROGBITS  00000000 0098e0 0018a7 00  0 0 1 
    [11] .debug_abbrev  PROGBITS  00000000 00b187 00056f 00  0 0 1 
    [12] .debug_line  PROGBITS  00000000 00b6f6 00080e 00  0 0 1 
    [13] .debug_frame  PROGBITS  00000000 00bf04 000430 00  0 0 4 
    [14] .debug_str  PROGBITS  00000000 00c334 0013dd 01 MS 0 0 1 
    [15] .debug_ranges  PROGBITS  00000000 00d718 000020 00  0 0 8 
    [16] .shstrtab   STRTAB   00000000 00d738 0000cb 00  0 0 1 
    [17] .symtab   SYMTAB   00000000 00dafc 000740 10  18 60 4 
    [18] .strtab   STRTAB   00000000 00e23c 000511 00  0 0 1 
Key to Flags: 
    W (write), A (alloc), X (execute), M (merge), S (strings) 
    I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) 
    O (extra OS processing required) o (OS specific), p (processor specific) 

、与えられた初期化されたデータとバイナリのreadelfが--sections出力は、

There are 20 section headers, starting at offset 0xd82c: 

Section Headers: 
    [Nr] Name    Type   Addr  Off Size ES Flg Lk Inf Al 
    [ 0]     NULL   00000000 000000 000000 00  0 0 0 
    [ 1] .vector   NOBITS   0093ff80 007f80 000048 00 WA 0 0 32 
    [ 2] .text    PROGBITS  10000000 008000 0016fc 00 AX 0 0 8 
    [ 3] .text.vectors  PROGBITS  100016fc 0096fc 000048 00 AX 0 0 4 
    [ 4] .text.proc  PROGBITS  10001744 009744 000034 00 AX 0 0 4 
    [ 5] .data    PROGBITS  0093ffc8 007fc8 000004 00 WA 0 0 8 
    [ 6] .bss    NOBITS   0093ffcc 007fcc 000294 00 WA 0 0 4 
    [ 7] .mmu_page_table NOBITS   00938000 008000 004000 00 WA 0 0 1 
    [ 8] .comment   PROGBITS  00000000 009778 00001f 01 MS 0 0 1 
    [ 9] .ARM.attributes ARM_ATTRIBUTES 00000000 009797 00003d 00  0 0 1 
    [10] .debug_aranges PROGBITS  00000000 0097d8 000108 00  0 0 8 
    [11] .debug_info  PROGBITS  00000000 0098e0 0018b6 00  0 0 1 
    [12] .debug_abbrev  PROGBITS  00000000 00b196 000580 00  0 0 1 
    [13] .debug_line  PROGBITS  00000000 00b716 00080e 00  0 0 1 
    [14] .debug_frame  PROGBITS  00000000 00bf24 000430 00  0 0 4 
    [15] .debug_str  PROGBITS  00000000 00c354 0013dd 01 MS 0 0 1 
    [16] .debug_ranges  PROGBITS  00000000 00d738 000020 00  0 0 8 
    [17] .shstrtab   STRTAB   00000000 00d758 0000d1 00  0 0 1 
    [18] .symtab   SYMTAB   00000000 00db4c 000770 10  19 62 4 
    [19] .strtab   STRTAB   00000000 00e2bc 000513 00  0 0 1 
Key to Flags: 
    W (write), A (alloc), X (execute), M (merge), S (strings) 
    I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) 
    O (extra OS processing required) o (OS specific), p (processor specific) 

これで十分です... !!!

注:私はをarm-none-eabi-gccにリンクして使用しています。

+0

あなたのバイナリに 'readelf --sections'の出力を投稿できますか? –

+0

出力が追加されました。 2番目のケースでは、バイナリのサイズは、前の1つで6KBに圧縮されて〜246MBになります。 – Ajeesh

+1

これは明らかです(同様の問題(またはQ/A)がSOにある)。バイナリで 'DDR(256MB) - IRAM(9MB)〜= 256MB'の' IRAM LENGTH = 256K'が246MBに増えます。 [VMA/LMAについて読む](https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html)を検索用語として使用してください。** BINARY **はバイナリの連続した塊でなければなりません!セクション情報はありません。あなたはその問題を見ていますか? gnu LDスクリプトには、これに対処するための 'AT'型指令とLMA/VMAがあります。 –

答えて

1

リンカースクリプトに慣れていない場合は、単に動作するものを使用するか、より簡単なものを作ったり借りたりしてください。ここには単純なものがあり、これは最も起こりそうなことを実証するはずです。ちょうどセグメントにいくつかのバイトを作成し、実際のプログラムであることを意味しない

MEMORY 
{ 
    bob : ORIGIN = 0x00001000, LENGTH = 0x100 
    ted : ORIGIN = 0x00002000, LENGTH = 0x100 
    alice : ORIGIN = 0x00003000, LENGTH = 0x100 
} 

SECTIONS 
{ 
    .text : { *(.text*) } > bob 
    .data : { *(.text*) } > ted 
    .bss : { *(.text*) } > alice 
} 

まずプログラム

.text 
.globl _start 
_start: 
mov r0,r1 
mov r1,r2 
b . 

が全てです。私たちが行うことを告げまさにしているメモリのアドレス0x1000番地にあるの.textで

Section Headers: 
    [Nr] Name    Type   Addr  Off Size ES Flg Lk Inf Al 
    [ 0]     NULL   00000000 000000 000000 00  0 0 0 
    [ 1] .text    PROGBITS  00001000 001000 00000c 00 AX 0 0 4 

12バイト。

-objcopy a.elf -Oバイナリa.binを使用すると、期待どおりの12バイトのファイルが得られます。バイナリファイル形式は、アドレスに内容がある最初のアドレスから始まるメモリイメージですアドレス空間内のコンテンツの最後のバイトで終わります。したがって、0x1000 + 12バイトの代わりに、バイナリはユーザーが0x1000にロードする必要があることを知る必要がある12バイトの広告です。

だから、少しこれを変更します。

.text 
.globl _start 
_start: 
mov r0,r1 
mov r1,r2 
b . 
.data 
some_data: .word 0x12345678 

Section Headers: 
    [Nr] Name    Type   Addr  Off Size ES Flg Lk Inf Al 
    [ 0]     NULL   00000000 000000 000000 00  0 0 0 
    [ 1] .text    PROGBITS  00001000 001000 00000c 00 AX 0 0 4 
    [ 2] .data    PROGBITS  00002000 002000 000004 00 WA 0 0 1 

今、私たちは0x2000での0x1000の4バイトで12バイトを持っているので、-Oバイナリは、最後に私たちに最初に定義されたバイトから1つのメモリイメージを与えることがあります0x1000 + 4になります。

確かに4100バイトは、まさしくそれがしたものです。

私は4100バイトのファイルを持って、それが実際には驚くべきことではない今、didntのが「育つようにするため、ブートストラップがゼロ.bssのに起こっていることが想定される

Section Headers: 
    [Nr] Name    Type   Addr  Off Size ES Flg Lk Inf Al 
    [ 0]     NULL   00000000 000000 000000 00  0 0 0 
    [ 1] .text    PROGBITS  00001000 001000 00000c 00 AX 0 0 4 
    [ 2] .data    PROGBITS  00002000 002000 000004 00 WA 0 0 1 
    [ 3] .bss    NOBITS   00003000 003000 000004 00 WA 0 0 1 

を与える

.text 
.globl _start 
_start: 
mov r0,r1 
mov r1,r2 
b . 
.data 
some_data: .word 0x12345678 
.bss 
some_more_data: .word 0 

バイナリーファイル。

親密な関係があります。システムレベルの設計。リンカスクリプトとブートストラップの間。あなたがしようとしているように見えるもの(ちょうどROMがない場合)は、私が持っているものと同じレベルのもっと簡単なリンカスクリプトを使うことができますが、.bssをゼロにすることを心配すれば、使用:

MEMORY 
{ 
    ram : ORIGIN = 0x00001000, LENGTH = 0x3000 
} 
SECTIONS 
{ 
    .text : { *(.text*) } > ram 
    .bss : { *(.text*) } > ram 
    .data : { *(.text*) } > ram 
} 

少なくとも一つの.dataの項目があることを確認し、あなたの「バイナリ」BSSは既にゼロとの完全なイメージを持っていますが、ブートストラップは、単にスタックポインタ(複数可)を設定し、メインにジャンプする必要があります(これがCの場合)。

とにかく、12バイトから4100バイトへのジャンプが.data要素と "バイナリ"ファイルを埋め込むための "バイナリ"形式の追加のためであることがわかります(この場合、0x1000から0x2000 + sizeof(.data)-1までの)データを有する最上位アドレスまでの最下位アドレスからの画像。リンカースクリプト、0x1000と0x2000を変更し、これがすべて変更されます。今、 "バイナリ" ファイルではなく0x2000-0x1000 +はsizeof(.dataセクション)より0x2000-0x1000 +はsizeof(.textセクション)にする必要があり、それらは0x1000ので0x2000からと.dataセクションでは.text置く交換します。または0x1004の代わりに0x100Cバイト。それは単一のファイルにメモリイメージを作成するために必要なパディングを含む情報であるため、「バイナリ」0x20000000-0x1000 +はsizeof(.dataセクション)になりますすぐに戻って最初のリンカスクリプトに行くと0x20000000で.DATAを作ります。

それは何が起こっているかである可能性が高いです。ここで示したように、ファイルのサイズは1ワードのデータを追加するだけで12バイトから4100になりました。

EDIT。まあ

あなたが初期化された変数が文句を言わない初期化され、データをNOLOADた場合、それは簡単な

unsigned int型のx = 5です。あなたは(NOLOAD).dataセクションを破棄した場合

は5ではありません。

は述べて、再び述べたように、あなたは.textの分野に入れたデータを持つことができ、その後、ブートストラップは、そのデータを見つけるために持って、より多くのリンカスクリプトFOOを使用しています。

MEMORY {ボブ:ORIGIN = 0x00001000、LENGTH = 0x100の テッド:ORIGIN = 0x00002000、LENGTH = 0x100の アリス:ORIGIN = 0x00003000、LENGTH = 0x100の } SECTIONS { の.text:{( .text)}>ボブ .DATA:{の.text)}>テッドAT>ボブ .bssの:{の.text)}>アリスAT>ボブ

}

これは16バイトの "バイナリ"ファイルを作成します。命令の12バイトと.dataの4バイト。しかし、あなたが悪い考えであるハードコーディングをしないと、データがどこにあるのかわかりません。これは、bss_startbss_endのようなものは、あなたのリンカースクリプトにあります。私たちを与えるこの

MEMORY 
    { 
     bob : ORIGIN = 0x00001000, LENGTH = 0x100 
     ted : ORIGIN = 0x00002000, LENGTH = 0x100 
     alice : ORIGIN = 0x00003000, LENGTH = 0x100 
    } 
    SECTIONS 
    { 
     .text : { *(.text*) } > bob 
     .data : { 
      __data_start__ = .; 
      *(.data*) 
     } > ted AT > bob 
     __data_end__ = .; 
     __data_size__ = __data_end__ - __data_start__; 
     .bss : { *(.text*) } > alice AT > bob 
    } 

    .text 
    .globl _start 
    _start: 
    mov r0,r1 
    mov r1,r2 
    b . 


hello: 
    .word __data_start__ 
    .word __data_end__ 
    .word __data_size__ 

    .data 
    some_data: .word 0x12345678 

よう

何か。

Disassembly of section .text: 

00001000 <_start>: 
    1000: e1a00001 mov r0, r1 
    1004: e1a01002 mov r1, r2 
    1008: eafffffe b 1008 <_start+0x8> 

0000100c <hello>: 
    100c: 00002000 andeq r2, r0, r0 
    1010: 00002004 andeq r2, r0, r4 
    1014: 00000004 andeq r0, r0, r4 

Disassembly of section .data: 

00002000 <__data_start__>: 
    2000: 12345678 eorsne r5, r4, #120, 12 ; 0x7800000 

はとツールチェーン/リンカが作成され、リンカスクリプトでこれらの定義された名前を記入し、それはそれらの外観を解決するとき、あなたのコードにそれらを埋めます。あなたのブートストラップはそれらの変数を使用する必要があります(そして、ここでは、ここでは.dataを見つけるための場所は4バイトあり、0x2000に着陸する必要があることを上記から知っています。その4バイトが見つかりましたか?より多くのリンカースクリプトfoo。gnuリンカースクリプトは、それらの変数をどこで定義するかについて非常に敏感ですので、括弧の前後で異なる結果が出る可能性があります。

これはromベースのターゲットで、あなたが.dataと.bssをゼロにしたいなら、.bataの.dataとサイズと位置をflash/rom領域に入れなければならず、ブートストラップには.dataも.bssも使用しないこともできます。

unsigned int x=5; 
unsigned int y; 

代わり

unsigned int x; 
unsigned int y; 
... 
x=5; 
y=0; 

はい、それは効率的でバイナリサイズは賢明ではありませんが、リンカスクリプトが前に働いていたものを、のlangauge /ルールが変更リンカスクリプト非常ツールチェインに依存し、例えば、GNUと時間をかけていますgnu ldのメジャーバージョンは必ずしも現在または次の作業には関係しません。その結果、私は最小限のリンカースクリプトを何年もかけて再構築しなければなりませんでした。

ここで説明したように、コマンドラインツールを使用して設定や場所を試し、ツールチェーンがどのように生成したのかを確認できます。

ボトムライン.dataにいくつかの情報を追加したようですが、NOLOADにしたいと言っています。基本的には.data isnt /あなたの変数が正しく初期化されていないので、とにかくそれがうまくいかないようにするために起こっているのはどれですか? .dataを持っていて、それを正しく使うには、適切なブートストラップとリンカスクリプトのペアを持っているか、またはRAMであれば同じRAM空間にすべてパックするか、使用している "バイナリ"フォーマットを使わないでください。 ihexまたはsrecまたはその他。

あなたのシステムに依存する別のトリックは、RAMのバイナリをビルドし、すべてパックしてから、そのバイナリをラップする別のプログラムをROMとROMからRAMとジャンプに実行することです。上の16バイトのプログラムを取って、そのビルドから16バイトを含む別のものを書き出し、0x1000にコピーして0x1000に分岐します。とにかくこれをやりたいと思うかもしれないシステムとフラッシュ/ロムの技術とインターフェースによっては、私の日の仕事からのシステムは、読み込み障害の問題を抱えていると知られているspiフラッシュを使っています。 。最も速く、最もクリーンで、最も信頼性の高いソリューションは、何か他のことをする前にコピージャンプをすることです。リンカースクリプトを自由な副作用としてより簡単にする。

+0

問題が発生している可能性がありますデータセクションに(NOLOAD)を追加したときに消えてしまいます。とにかく確かめるには? – Ajeesh

+1

'NOLOAD'は、データセクションがバイナリの一部ではないことを意味します。あなたがしなければならないこと(BSSや初期化されたメモリがない場合)は、最初のデータ値をメインイメージに置き、ブートコードを使って最終的な場所にコピーします。 (すべてのアセンブラが参照すべき実際の最終絶対アドレスであるLMAロードメモリアドレスおよびVMA仮想メモリアドレス) –