「ld」--リンク

205137 ワード

リンクの機能:実行可能プログラムに必要なターゲットファイルとライブラリを最終的に統合します.
1つのプログラムは3つのセグメントを含む:.text 、.dataと.bssセグメント.
各ターゲットファイルとライブラリにはこの3つのセグメントが含まれているので、ldリンクの機能は各ターゲットファイルとライブラリの3つのセグメントを統合することです.
もちろん、リンクが完了するリンク作業は、各ターゲットファイルとライブラリの3つのメモリを簡単に積み重ねるだけでなく、「再配置」の作業も完了します.
1、再配置:
    
リンクして生成された実行可能プログラムはファイルに格納されますが、プログラムが実行されるとメモリにロードする必要があります.上記の3つの悩みは,メモリのどの位置に光が実行可能プログラムファイル内のヘッダ情報によって指定されるかである.
    
プログラムがメモリにロードされると、関数でも変数でもメモリに一定の空間を占めることを意味します.これはメモリアドレスに関係します.
    
プロセッサの観点から、Cプログラムに呼び出し関数のコードを1行書くと、この関数を呼び出すときに対応するメモリアドレス(main:0 x 03 Hなど)にジャンプする必要があることを意味します.では、プロセッサはどのようにして0 x 03 Hのメモリアドレスにジャンプするかを知っていますか.これがリンクの仕事です.
    
ソースファイルがターゲットファイルにコンパイルされると、ターゲットファイルの各セグメントには具体的なアドレスはなく、プログラム内のシンボルと各シンボルのセグメント内の相対アドレスがターゲットファイルに記録されるだけである.リンクがすべてのターゲットファイルを実行可能なプログラムファイルに統合すると、各ターゲットファイルの各セグメントは、メモリ内の特定のアドレスを実際に取得します.これにより、真の関数呼び出しと変数参照機能が実現され、この動作は再配置されます.
    
では、リンクはどのようにして各ターゲットファイルの各セグメントがどのアドレスに配置されるべきかを知っていますか?これを指定するには、リンクスクリプトが必要です.
2、リンクスクリプト:
 
    
    
    
    
  1. GNU ld version 2.17.50.0.6-5.el5 20061020 Supported emulations: elf_i386 i386linux using internal linker script: 
  2. ==================================================
  3. * Script for -z combreloc: combine and sort reloc sections */
  4. OUTPUT_FORMAT("elf32-i386", "elf32-i386",
  5. "elf32-i386")
  6. OUTPUT_ARCH(i386)
  7. ENTRY(_start)
  8. SEARCH_DIR("/usr/i386-redhat-linux/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
  9. SECTIONS
  10. {
  11. /* Read-only sections, merged into text segment: */
  12.     PROVIDE (__executable_start = 0x08048000); . = 0x08048000 + SIZEOF_HEADERS;
  13.     .interp : { *(.interp) }
  14.      .hash : { *(.hash) }
  15.      .gnu.hash : { *(.gnu.hash) }
  16.      .dynsym : { *(.dynsym) }
  17.      .dynstr : { *(.dynstr) }
  18.      .gnu.version : { *(.gnu.version) }
  19.      .gnu.version_d : { *(.gnu.version_d) }
  20.      .gnu.version_r : { *(.gnu.version_r) }
  21.      .rel.dyn :
  22.      {
  23.          *(.rel.init)
  24.          *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
  25.          *(.rel.fini)
  26.          *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
  27.          *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
  28.          *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
  29.          *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
  30.          *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
  31.          *(.rel.ctors)
  32.          *(.rel.dtors)
  33.          *(.rel.got)
  34.          *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
  35.      }
  36.      .rela.dyn :
  37.      {
  38.          *(.rela.init)
  39.          *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
  40.          *(.rela.fini)
  41.          *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
  42.          *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
  43.          *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
  44.          *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
  45.          *(.rela.ctors)
  46.          *(.rela.dtors)
  47.          *(.rela.got)
  48.          *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
  49.      }
  50.      .rel.plt : { *(.rel.plt) }
  51.      .rela.plt : { *(.rela.plt) }
  52.      .init :
  53.      {
  54.           KEEP (*(.init))
  55.      } =0x90909090
  56.      .plt : { *(.plt) }
  57.      .text :
  58.      {
  59.          *(.text .stub .text.* .gnu.linkonce.t.*)
  60.          KEEP (*(.text.*personality*))
  61.          /* .gnu.warning sections are handled specially by elf32.em. */
  62.          *(.gnu.warning)
  63.      } =0x90909090
  64.      .fini :
  65.      {
  66.           KEEP (*(.fini))
  67.      } =0x90909090
  68.      PROVIDE (__etext = .);
  69.      PROVIDE (_etext = .);
  70.      PROVIDE (etext = .);
  71.      .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
  72.      .rodata1 : { *(.rodata1) }
  73.      .eh_frame_hdr : { *(.eh_frame_hdr) }
  74.      .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
  75.      .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
  76.      /* Adjust the address for the data segment. We want to adjust up to
  77.     the same address within the page on the next page up. */
  78.      . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1    )); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
  79.      /* Exception handling */
  80.     .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
  81.      .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
  82.      /* Thread Local Storage sections */
  83.      .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
  84.      .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
  85.      .preinit_array :
  86.      {
  87.          PROVIDE_HIDDEN (__preinit_array_start = .);
  88.          KEEP (*(.preinit_array))
  89.          PROVIDE_HIDDEN (__preinit_array_end = .);
  90.      }
  91.      .init_array :
  92.      {
  93.          PROVIDE_HIDDEN (__init_array_start = .);
  94.          KEEP (*(SORT(.init_array.*)))
  95.          KEEP (*(.init_array))
  96.          PROVIDE_HIDDEN (__init_array_end = .);
  97.      }
  98.      .fini_array :
  99.      {
  100.          PROVIDE_HIDDEN (__fini_array_start = .);
  101.          KEEP (*(.fini_array))
  102.          KEEP (*(SORT(.fini_array.*)))
  103.          PROVIDE_HIDDEN (__fini_array_end = .);
  104.      }
  105.      .ctors :
  106.      {
  107.           /* gcc uses crtbegin.o to find the start of
  108.          the constructors, so we make sure it is
  109.          first. Because this is a wildcard, it
  110.         doesn't matter if the user does not
  111.          actually link against crtbegin.o; the
  112.          linker won't look for a file to match a
  113.          wildcard. The wildcard also means that it
  114.         doesn't matter which directory crtbegin.o
  115.          is in. */
  116.          KEEP (*crtbegin.o(.ctors))
  117.          KEEP (*crtbegin?.o(.ctors))
  118.           /* We don't want to include the .ctor section from
  119.         the crtend.o file until after the sorted ctors.
  120.          The .ctor section from the crtend file contains the
  121.          end of ctors marker and it must be last */
  122.          KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
  123.          KEEP (*(SORT(.ctors.*)))
  124.          KEEP (*(.ctors))
  125.     }
  126.      .dtors :
  127.      {
  128.          KEEP (*crtbegin.o(.dtors))
  129.          KEEP (*crtbegin?.o(.dtors))
  130.          KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
  131.           KEEP (*(SORT(.dtors.*)))
  132.          KEEP (*(.dtors))
  133.    }
  134.      .jcr : { KEEP (*(.jcr)) }
  135.      .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.link     once.d.rel.ro.*) }
  136.      .dynamic : { *(.dynamic) }
  137.      .got : { *(.got) }
  138.      . = DATA_SEGMENT_RELRO_END (12, .);
  139.      .got.plt : { *(.got.plt) }
  140.      .data :
  141.      {
  142.          *(.data .data.* .gnu.linkonce.d.*)
  143.          KEEP (*(.gnu.linkonce.d.*personality*))
  144.          SORT(CONSTRUCTORS)
  145.      }
  146.      .data1 : { *(.data1) }
  147.     _edata = .; PROVIDE (edata = .);
  148.    _bss_start = .;
  149.    .bss :    
  150.     {
  151.          *(dynbss)
  152.          *(.bss .bss.* .gnu.linkonce.b.*)
  153.          *(COMMON)
  154.          /* Align here to ensure that the .bss section occupies space up to
  155.          _end. Align after .bss to ensure correct alignment even if the
  156.          .bss section disappears because there are no input sections.
  157.          FIXME: Why do we need it? When there is no .bss section, we don't
  158.          pad the .data section. */
  159.          . = ALIGN(. != 0 ? 32 / 8 : 1);
  160.      }
  161.      . = ALIGN(32 / 8);
  162.      . = ALIGN(32 / 8);
  163.      _end = .; PROVIDE (end = .);
  164.      . = DATA_SEGMENT_END (.);
  165.      /* Stabs debugging sections. */
  166.      .stab 0 : { *(.stab) }
  167.      .stabstr 0 : { *(.stabstr) }
  168.      .stab.excl 0 : { *(.stab.excl) }
  169.      .stab.exclstr 0 : { *(.stab.exclstr) }
  170.      .stab.index 0 : { *(.stab.index) }
  171.      .stab.indexstr 0 : { *(.stab.indexstr) }
  172.      .comment 0 : { *(.comment) }
  173.      /* DWARF debug sections.
  174.     Symbols in the DWARF debugging sections are relative to the beginning
  175.     of the section so we begin them at 0. */
  176.      /* DWARF 1 */
  177.      .debug 0 : { *(.debug) }
  178.      .line 0 : { *(.line) }
  179.      /* GNU DWARF 1 extensions */
  180.      .debug_srcinfo 0 : { *(.debug_srcinfo) }
  181.      .debug_sfnames 0 : { *(.debug_sfnames) }
  182.      /* DWARF 1.1 and DWARF 2 */
  183.      .debug_aranges 0 : { *(.debug_aranges) }
  184.      .debug_pubnames 0 : { *(.debug_pubnames) }
  185.      /* DWARF 2 */
  186.      .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
  187.      .debug_abbrev 0 : { *(.debug_abbrev) }
  188.      .debug_line 0 : { *(.debug_line) }
  189.      .debug_frame 0 : { *(.debug_frame) }
  190.      .debug_str 0 : { *(.debug_str) }
  191.      .debug_loc 0 : { *(.debug_loc) }
  192.     .debug_macinfo 0 : { *(.debug_macinfo) }
  193.      /* SGI/MIPS DWARF 2 extensions */
  194.      .debug_weaknames 0 : { *(.debug_weaknames) }
  195.      .debug_funcnames 0 : { *(.debug_funcnames) }
  196.      .debug_typenames 0 : { *(.debug_typenames) }
  197.      .debug_varnames 0 : { *(.debug_varnames) }
  198.      /* DWARF 3 */
  199.      .debug_pubtypes 0 : { *(.debug_pubtypes) }
  200.      .debug_ranges 0 : { *(.debug_ranges) }
  201.      /DISCARD/ : { *(.note.GNU-stack) }
  202. }

    
    
リンクスクリプトの機能:リンクに、ライブラリを含む異なるターゲットファイルのセグメントを結合し、最終的に実行可能なプログラムを生成する方法を教えます.リンクスクリプトの観点から、出力を記述する必要がある一方で、最終的に実行可能なプログラムのセグメントを生成する必要がある.一方、入力、すなわち、各ターゲットファイルからのセグメントについても説明する.
    
2.1、セグメント
    
1つの実行可能プログラムは最終的に複数のセグメントに分割され、ブートローダが実行可能プログラムをロードすると、ファイルのヘッダ情報に基づいて各セグメントがファイルにある内容がメモリにコピーされ、メモリにコピーされた特定のアドレスはリンクスクリプトで指定されます.
    
以下は簡単なリンクスクリプトです.
    
    
    
    
  1. SECTIONS
  2. {
  3. . = 0x1000000;
  4. .text :
  5. {
  6. *(.text)
  7. }
  8. .data 0x8000000;
  9. {
  10. *(.data)
  11. }
  12. .bss :
  13. {
  14. *(.bss)
  15. }
  16. }

    
位置ポインタを使用して操作することで、各セグメントのアドレス空間の配置が実現され、位置ポインタの値はプロセッサのアドレス空間を表します.
    
以上の手順を以下のように分析する.
SECTIONSに入ったばかりで、位置ポインタは0です.
3行目は位置ポインタを変更する文です.「位置ポインタです.0 x 100000に設定すると、後の.textセグメントがメモリアドレス0 x 100000から格納されます..
第4~7行目は、生成する実行可能プログラムのうちの1つを示す第1の出力セグメント記述文ブロックである.textセグメント.によってtextセグメントの位置ポインタの値は0 x 100000であるため、ロードが発生すると実行可能プログラムに存在する.textセグメントの内容は、0 x 1000000メモリアドレスの先頭にコピーされます.実行可能プログラムに出力されるセグメントには何が含まれていますか?6行目の入力セグメントで指定します.これは、すべてのターゲットファイルを表します.textセグメント.
8行目~11行目は実行可能プログラムを定義する.dataセグメント.なお、ここで採用する位置ポインタの指定方法は異なります.8行目の指示dataセグメントがプログラム実行時に格納する開始アドレスは0 x 800000である.10行目の入力セグメントの説明は、すべてのライブラリとターゲットファイルを指定する.dataセグメント.
12~15行目に実行可能プログラムが定義されている.bssセグメントは、このリンクスクリプトには指定されていないことに注意する.bssセグメントの位置ポインタは、プログラムがリンクするときの位置ポインタの値に完全に依存し、位置ポインタの値はその前に依存する.data出力セグメントのサイズ.
リンクが実行可能プログラムを生成すると、各セグメントのメモリ内の開始アドレスとセグメントサイズの情報が実行可能プログラムファイルのヘッダに配置され、これらの情報はプログラムローダローダに準備されます.
2.2、記号
    
リンクスクリプトでは、メモリ内のセグメントとセグメントのアドレスのほかに、シンボルを定義できます.
    
    
    
    
  1. SECTIONS
  2. {
  3. . = 0x1000000;
  4. .text :
  5. {
  6. *(.text)
  7. }
  8. .data 0x8000000;
  9. {
  10. *(.data)
  11. }
  12. .bss :
  13. {
  14. __bss_start__ = .;
  15. *(.bss)
  16. __bss_end__ = .;
  17. }
  18. __end__ = .;
  19. }

    
14行目、16行目、18行目にそれぞれ3つの記号が定義されています.end__シンボルは、プログラムの各セグメントが占有するメモリ領域の終了アドレス、またはスタックの開始アドレスを表す.これらの記号の値は、位置ポインタを使用して指定されます.シンボルは、リンクスクリプトで定義されると、プログラムで使用できます.
    
    
    
    
  1. #include
  2. extern char _bss_start__[];
  3. extern char _bss_end__[];
  4. extern char _end__[];
  5. int main()
  6. {
  7. printf("__bss_start__ = %p
    "
    , _bss_start__);
  8. printf("__bss_end__ = %p
    "
    , _bss_end__);
  9. printf("__end__ = %p
    "
    , _end__);
  10. return 0;
  11. }
         :

         :
$ gcc -Wl,-Map=main.map main.c -o main.exe
$ ./main.exe
__bss_start__ = 0x404000
__bss_end__ = 0x404130
__end__ = 0x406000

    2.3、
         ,ld 。 , MEMORY 。
    
    
    
    
  1. MEMORY
  2. {
  3. RAM0 (WX) : ORIGIN = 0x40000000, LENGTH = 256K
  4. RAM1 (WX) : ORIGIN = 0, LENGTH = 2M
  5. }
  6. SECTIONS
  7. {
  8. .text :
  9. {
  10. . += 0x10000;
  11. *(.text)
  12. } > RAM1
  13. .data :
  14. {
  15. *(.data)
  16. } > RAM1
  17. .bss :
  18. {
  19. *(.bss)
  20. } > RAM0
  21. }
         RAM0 RAM1 。 SECTIONS , .bss RAM0 , .text .data RAM1 。
         , , , ( ) 。

    2.4、
         2.4.1 ALIGN BLOCK
              ALIGN :
  • ALIGN (_align)
  • ALIGN (_exp, _align)
              ALIGN _align ,
              ALIGN _exp 、 _align 。
         BLOCK ALIGN ,

         2.4.2、BYTE、SHORT、LONG QUAD
              :
  • BYTE ( _value)
  • SHORT ( _value)
  • LONG ( _value)
  • QUAD ( _value)
              1、2、4 8 , _value 。
     
     
     
     
  1. SECTIONS
  2. {
  3. .text :
  4. {
  5. *(.text)
  6. }
  7. LONG(1)
  8. .data :
  9. {
  10. *(.data)
  11. }
  12. }
    
         2.4.3、ENTRY
              :
  • ENTRY (_symbol)
              。 ,

         2.4.4、MEMORY
              :
  •        
           
           
           
    1. MEMORY
    2. {
    3. name [(_attr)] : ORIGIN = _origin, LENGTH = _len
    4. ...
    5. }
  •         
            
            
            
    1. MEMORY
    2. {
    3. name [(_attr)] : org = _origin, l = _len
    4. ...
    5. }

         2.4.5、PROVIDE
              :
  • PROVIDE (_symbol = _expression)
              , , PROVIDE 。
     
     
     
     
  1. SECTIONS
  2. {
  3. . = 0x1000000;
  4. .text :
  5. {
  6. *(.text)
  7. }
  8. .data 0x8000000;
  9. {
  10. *(.data)
  11. }
  12. .bss :
  13. {
  14. PROVIDE (__bss_start__ = .);
  15. PROVIDE (_bss_start__ = .);
  16. *(.bss)
  17. PROVIDE (__bss_end__ = .);
  18. PROVIDE (_bss_end__ = .);
  19. }
  20. PROVIDE (__end__ = .);
  21. PROVIDE (_end__ = .);
  22. }
         
          2.4.6、SECTIONS
              :
                   SECTIONS
                   {
                             sections-command
                              sections-command
                             ...
                    }
                      :《 》 ·                                                             2016 7 11 ,