4

私はを使用してbinutils-2.21.53.0.1-6.fc16.x86_64います。

hello.oすべてのセクションにコンテンツを含めるのに十分な「もの」を含む小さなオブジェクトファイルがあります。

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       000000000000005d  0000000000000000  AX       0     0     4
  [ 2] .rela.text        RELA             0000000000000000  00000808
       0000000000000060  0000000000000018          15     1     8
  [ 3] .data             PROGBITS         0000000000000000  000000a0
       0000000000000000  0000000000000000  WA       0     0     4
  [ 4] .bss              NOBITS           0000000000000000  000000a0
       0000000000000053  0000000000000000  WA       0     0     32
  [ 5] .rodata           PROGBITS         0000000000000000  000000a0
       000000000000000f  0000000000000000   A       0     0     1
  [ 6] .data.rel.local   PROGBITS         0000000000000000  000000b0
       0000000000000008  0000000000000000  WA       0     0     8
  [ 7] .rela.data.rel.lo RELA             0000000000000000  00000868
       0000000000000018  0000000000000018          15     6     8
  [ 8] .data.rel         PROGBITS         0000000000000000  000000b8
       0000000000000008  0000000000000000  WA       0     0     8
  [ 9] .rela.data.rel    RELA             0000000000000000  00000880
       0000000000000018  0000000000000018          15     8     8
  [10] .comment          PROGBITS         0000000000000000  000000c0
       000000000000002d  0000000000000001  MS       0     0     1
  [11] .note.GNU-stack   PROGBITS         0000000000000000  000000ed
       0000000000000000  0000000000000000           0     0     1
  [12] .eh_frame         PROGBITS         0000000000000000  000000f0
       0000000000000058  0000000000000000   A       0     0     8
  [13] .rela.eh_frame    RELA             0000000000000000  00000898
       0000000000000030  0000000000000018          15    12     8
  [14] .shstrtab         STRTAB           0000000000000000  00000148
       0000000000000085  0000000000000000           0     0     1
  [15] .symtab           SYMTAB           0000000000000000  00000610
       00000000000001b0  0000000000000018          16    11     8
  [16] .strtab           STRTAB           0000000000000000  000007c0
       0000000000000045  0000000000000000           0     0     1

リンカースクリプトを使用し、リンカースクリプトを使用-pieしない場合、結果は期待どおりです。

$ ld -pie -Map hello_pie.map -o hello_pie.elf hello.o 

$ ll hello_pie.elf 
-rwxrwx---. 1 jreinhart jreinhart 3453 Mar 13 23:44 hello_pie.elf

ただし、何らかのリンカースクリプトを含めると、出力サイズが爆発します。

$ cat 1.ld 
SECTIONS
{

}
$ ld -T 1.ld -pie -Map hello_pie.map -o hello_pie.elf hello.o 
$ ll hello_pie.elf 
-rwxrwx---. 1 jreinhart jreinhart 2100070 Mar 13 23:45 hello_pie.elf

ご覧のとおり、このファイルは巨大になりました。

.textこれは、セクションがファイルのオフセット0x200000から開始することを要求しているために発生するように見えることに注意してください。

$ readelf -l -S hello_pie.elf 
There are 19 section headers, starting at offset 0x200400:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00200000  <--- Why?
       000000000000005d  0000000000000000  AX       0     0     4
  [ 2] .rodata           PROGBITS         000000000000005d  0020005d
       000000000000000f  0000000000000000   A       0     0     1
  [ 3] .eh_frame         PROGBITS         0000000000000070  00200070
       0000000000000058  0000000000000000   A       0     0     8
  [ 4] .interp           PROGBITS         00000000000000c8  002000c8
       000000000000000f  0000000000000000   A       0     0     1
  [ 5] .dynsym           DYNSYM           00000000000000d8  002000d8
       0000000000000078  0000000000000018   A       6     2     8
  [ 6] .dynstr           STRTAB           0000000000000150  00200150
       0000000000000014  0000000000000000   A       0     0     1
  [ 7] .hash             HASH             0000000000000168  00200168
       0000000000000028  0000000000000004   A       5     0     8
  [ 8] .rela.dyn         RELA             0000000000000190  00200190
       0000000000000078  0000000000000018   A       5     0     8
  [ 9] .data.rel.local   PROGBITS         0000000000000208  00200208
       0000000000000008  0000000000000000  WA       0     0     8
  [10] .data.rel         PROGBITS         0000000000000210  00200210
       0000000000000008  0000000000000000  WA       0     0     8
  [11] .dynamic          DYNAMIC          0000000000000218  00200218
       00000000000000f0  0000000000000010  WA       6     0     8
  [12] .got              PROGBITS         0000000000000308  00200308
       0000000000000018  0000000000000008  WA       0     0     8
  [13] .got.plt          PROGBITS         0000000000000320  00200320
       0000000000000018  0000000000000008  WA       0     0     8
  [14] .bss              NOBITS           0000000000000340  00200338
       0000000000000053  0000000000000000  WA       0     0     32
  [15] .comment          PROGBITS         0000000000000000  00200338
       000000000000002c  0000000000000001  MS       0     0     1
  [16] .shstrtab         STRTAB           0000000000000000  00200364
       000000000000009a  0000000000000000           0     0     1
  [17] .symtab           SYMTAB           0000000000000000  002008c0
       0000000000000258  0000000000000018          18    19     8
  [18] .strtab           STRTAB           0000000000000000  00200b18
       000000000000004e  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

Elf file type is DYN (Shared object file)
Entry point 0x0
There are 5 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000200040 0x0000000000000000
                 0x0000000000000118 0x0000000000000118  R E    8
  INTERP         0x00000000002000c8 0x00000000000000c8 0x00000000000000c8
                 0x000000000000000f 0x000000000000000f  R      1
      [Requesting program interpreter: /lib/ld64.so.1]
  LOAD       --> 0x0000000000200000 0x0000000000000000 0x0000000000000000
                 0x0000000000000338 0x0000000000000393  RWE    200000
  DYNAMIC        0x0000000000200218 0x0000000000000218 0x0000000000000218
                 0x00000000000000f0 0x00000000000000f0  RW     8
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     8

これは、リンカースクリプトの内容に関係なく発生しています。何が起こっているのかアイデアはありますか?

4

3 に答える 3

6

ld (または gcc) で次のコマンド ライン オプションを試してください。

-z max-page-size=0x1000
于 2016-01-23T21:51:35.313 に答える
5

デフォルトldでは、入力セクションをページで揃えます。カーネルはスーパーページ (2MB のページ = 0x200000 バイト) を強制するため、.textセクションはオフセット 0x200000 に配置されます。代わりにオフセット 0x0000000 を使用する必要があるため、バグのようですld(考えられる説明については、以下の編集を参照してください)。

より大きなファイルを作成するこの整列を防ぐには、--nmagicld へのフラグを使用して、副作用はありますが、.text セクションのページ整列を防ぐことができます (共有ライブラリへのリンクも無効にします)。ただし、他のセクション ( .data.rodata、...) を 2M ページに配置するように注意してください。これらのセクションはすべて異なるアクセス ビットを必要とするため、.text と同じページに配置することはできません。

編集: 考えてみると、仮想アドレス 0x00000000 へのアクセスが例外 (segfault) を生成することを期待しています。これを行うには、2 つの可能性があります。カーネルがアクセス権のないページをマップするか (r/w/x)、または (より可能性が高い) 単に何もマップせず (ページがマップされていない => segfault)、リンカがどういうわけかそれを知っています...これは、ldがアドレス0にある最初のページをスキップする理由を説明できます。これは未定です。

于 2014-09-09T23:41:56.370 に答える