2009-11-19 17 views
12

これは、Linuxのmanページからのコードです:etext、edata、endのシンボルはどこにありますか?

#include <stdio.h> 
#include <stdlib.h> 

extern char etext, edata, end; 

int main() { 
    printf("First address past:\n"); 
    printf(" program text (etext)  %10p\n", &etext); 
    printf(" initialized data (edata) %10p\n", &edata); 
    printf(" uninitialized data (end) %10p\n", &end); 

    exit(EXIT_SUCCESS); 
} 

実行すると、以下のプログラムは、以下のような出力を生成します

etextedata endを定義している
$ ./a.out 
First address past: 
    program text (etext)  0x8048568 
    initialized data (edata) 0x804a01c 
    uninitialized data (end) 0x804a024 

?それらのシンボルにどのように値が割り当てられていますか?それはリンカーか何か他の人ですか?

+0

どのmanページですか? –

+1

'man 3 end'をチェックしてください。 –

答えて

3

これらのシンボルは、さまざまなプログラムセグメントの初めに対応しています。それらはリンカーによって設定されます。

7

Mac OS Xでは、上記のコードが機能しないことに注意してください。代わりにあなたが持つことができます。

#include <stdio.h> 
#include <stdlib.h> 
#include <mach-o/getsect.h> 

int main(int argc, char *argv[]) 
{ 
    printf(" program text (etext)  %10p\n", (void*)get_etext()); 
    printf(" initialized data (edata) %10p\n", (void*)get_edata()); 
    printf(" uninitialized data (end) %10p\n", (void*)get_end()); 

    exit(EXIT_SUCCESS); 
} 
2

もう少しkgiannakakisを拡大どういうGCC。

これらのシンボルはhttps://sourceware.org/binutils/docs-2.25/ld/PROVIDE.html#PROVIDE

で文書化され、デフォルトのスクリプトは、あなたがのBinutilsをビルドするときに生成、およびld実行可能ファイルに埋め込まれ、リンカスクリプトのPROVIDEキーワードによって定義されています。あなたのディストリビューションにインストールすることができる外部ファイル/usr/lib/ldscriptsのようなものは、デフォルトでは使用されません。

エコーリンカスクリプトを使用する:

は、binutilsの2.24で
ld -verbose | less 

それが含まれています

  • __etext_etextも動作します:

    .text   : 
    { 
        *(.text.unlikely .text.*_unlikely .text.unlikely.*) 
        *(.text.exit .text.exit.*) 
        *(.text.startup .text.startup.*) 
        *(.text.hot .text.hot.*) 
        *(.text .stub .text.* .gnu.linkonce.t.*) 
        /* .gnu.warning sections are handled specially by elf32.em. */ 
        *(.gnu.warning) 
    } 
    .fini   : 
    { 
        KEEP (*(SORT_NONE(.fini))) 
    } 
    PROVIDE (__etext = .); 
    PROVIDE (_etext = .); 
    PROVIDE (etext = .); 
    .rodata   : { *(.rodata .rodata.* .gnu.linkonce.r.*) } 
    .rodata1  : { *(.rodata1) } 
    

    だから、我々はまた、ことを発見します

  • etextはまた、コード
  • etextがBinutilsのは、同じセグメント
にすべての読み取り専用セクションをダンプするので、それを以下 .rodataと、セグメントの終わりではない含まなく .fini.textセクションの終わりではなく、

PROVIDEは弱いシンボルを生成します:あなたがCコードでそれらのシンボルも定義していれば、あなたの定義は勝利してこれを隠すでしょう。

最小限のLinux 32ビットの例

本当に物事の仕組みを理解するために、私は、最小限の例を作成したいです!

main.S

.section .text 
    /* Exit system call. */ 
    mov $1, %eax 
    /* Exit status. */ 
    mov sdata, %ebx 
    int $0x80 
.section .data 
    .byte 2 

link.ld

SECTIONS 
{ 
    . = 0x400000; 
    .text : 
    { 
     *(.text) 
     sdata = .; 
     *(.data) 
    } 
} 

コンパイルして実行します。

gas --32 -o main.o main.S 
ld -m elf_i386 -o main -T link.ld main.o 
./main 
echo $? 

出力:

2 

説明:sdataは、後に続く.dataセクションの先頭の最初のバイトを指します。

そのセクションの最初のバイトを制御することによって、終了ステータスを制御します。

This example on GitHub

関連する問題