Linuxのプログラムのメモリレイアウトについていくつか質問があります。私は様々な情報源から知っています(私は「プログラミングを地上から」を読んでいます)、各セクションはそれ自身のメモリ領域にロードされています。テキストセクションは仮想アドレス0x8048000で最初にロードされ、データセクションはその直後にロードされ、次にbssセクションが続き、ヒープとスタックが続きます。Linuxのプログラムのメモリレイアウトについて
レイアウトを試してみるために、私はこのプログラムを組み立てました。まず、いくつかのラベルのアドレスを出力し、システムブレークポイントを計算します。その後、無限ループに入ります。ループはポインタをインクリメントし、そのアドレスのメモリにアクセスしようとします。ある時点でセグメント化エラーがプログラムを終了します(これは意図的に行いました)。
これはプログラムです:
.section .data
start_data:
str_mem_access:
.ascii "Accessing address: 0x%x\n\0"
str_data_start:
.ascii "Data section start at: 0x%x\n\0"
str_data_end:
.ascii "Data section ends at: 0x%x\n\0"
str_bss_start:
.ascii "bss section starts at: 0x%x\n\0"
str_bss_end:
.ascii "bss section ends at: 0x%x\n\0"
str_text_start:
.ascii "text section starts at: 0x%x\n\0"
str_text_end:
.ascii "text section ends at: 0x%x\n\0"
str_break:
.ascii "break at: 0x%x\n\0"
end_data:
.section .bss
start_bss:
.lcomm buffer, 500
.lcomm buffer2, 250
end_bss:
.section .text
start_text:
.globl _start
_start:
# print address of start_text label
pushl $start_text
pushl $str_text_start
call printf
addl $8, %esp
# print address of end_text label
pushl $end_text
pushl $str_text_end
call printf
addl $8, %esp
# print address of start_data label
pushl $start_data
pushl $str_data_start
call printf
addl $8, %esp
# print address of end_data label
pushl $end_data
pushl $str_data_end
call printf
addl $8, %esp
# print address of start_bss label
pushl $start_bss
pushl $str_bss_start
call printf
addl $8, %esp
# print address of end_bss label
pushl $end_bss
pushl $str_bss_end
call printf
addl $8, %esp
# get last usable virtual memory address
movl $45, %eax
movl $0, %ebx
int $0x80
incl %eax # system break address
# print system break
pushl %eax
pushl $str_break
call printf
addl $4, %esp
movl $start_text, %ebx
loop:
# print address
pushl %ebx
pushl $str_mem_access
call printf
addl $8, %esp
# access address
# segmentation fault here
movb (%ebx), %dl
incl %ebx
jmp loop
end_loop:
movl $1, %eax
movl $0, %ebx
int $0x80
end_text:
そして、この出力の関連する部分(これはDebianの32ビットです):
text section starts at: 0x8048190
text section ends at: 0x804823b
Data section start at: 0x80492ec
Data section ends at: 0x80493c0
bss section starts at: 0x80493c0
bss section ends at: 0x80493c0
break at: 0x83b4001
Accessing address: 0x8048190
Accessing address: 0x8048191
Accessing address: 0x8048192
[...]
Accessing address: 0x8049fff
Accessing address: 0x804a000
Violación de segmento
私の質問は以下のとおりです。
1)なぜされます私のプログラムは0x8048000の代わりに0x8048190番地から始まっていますか?これで私は "_start"ラベルの命令が最初にロードされるものではないと推測します。したがって、アドレス0x8048000と0x8048190の間に何がありますか?
2)テキストセクションの終わりとデータセクションの開始の間にギャップがあるのはなぜですか?
3)bssの開始アドレスと終了アドレスは同じです。私は2つのバッファが別の場所に格納されていると仮定しますが、これは正しいですか?
4)システムブレークポイントが0x83b4001にある場合、なぜセグメンテーションフォルトが0x804a000にあるのですか?
[読んだことがないなら、それを見てください](http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html) - ほぼ完全にオフトピックです。素晴らしい読書。 –
ELFローダーは、実行可能ファイルの*セグメント*のみを扱うことに注意してください。 '.text'セクション(リンク後)がテキストセグメント内の唯一のものであるように、多くの場合1:1のマッピングがあります。リンカは '.rodata'のようなセクションを' .text'に結合します。また、「ヒープ」は実際には存在するものではなく、概念のものです(mmap(MAP_ANONYMOUS)による割り当ては 'brk'と連続していません)。ヒープの一部としてBSSと静的データを考慮するかどうかはわかりません。また、LinuxがBSSの直後に最初の 'brk'を置くかどうかはわかりません。 –