day4- ldによるセクション配置の確認(readelf -S編)

[hirasawa@aspire-white gcc-Programming-Kobo]$ cat address.c
#include <stdio.h>

int a1;
int a2 = 0x11111111;
int a3;
int a4 = 0x22222222;

static int a5;
static int a6 = 0x33333333;

const char * a7 = "const_char_string";

void func( int b1 , int b2 ) 
{
 int c1;
 int c2 = 0x55555555;
 static int c3;
 static int c4 = 0x66666666;

 printf("func (&func) locates at %p\n",&func);
 printf("func (func) locates at %p\n",func);
 printf("f-argv-b1 %X locates at %p\n",b1,&b1);
 printf("f-argv-b2 %X locates at %p\n",b2,&b2);
 printf("f-auto-c1 %X locates at %p\n",c1,&c1);
 printf("f-auto-c2 %X locates at %p\n",c2,&c2);
 printf("f-static-int-NOTinit-c3 %X locates at %p\n",c3,&c3);
 printf("f-static-int-inited-c4 %X locates at %p\n",c4,&c4);
 printf("\n");

}

int main(void)
{

 printf("main (&main) locates at %p\n",&main);
 printf("main (main) loaates at %p\n",main);
 printf("m-a1 %X loaates at %p\n",a1,&a1);
 printf("m-a2 %X loaates at %p\n",a2,&a2);
 printf("m-a3 %X loaates at %p\n",a3,&a3);
 printf("m-a4 %X loaates at %p\n",a4,&a4);
 printf("m-a5 %X loaates at %p\n",a5,&a5);
 printf("m-a6 %X loaates at %p\n",a6,&a6);
 printf("m-a7 %p loaates at %p\n",a7,&a7);
 printf("*(m-a7) %s loaates at %p\n",a7,a7);
 printf("\n");

 func(1,2);

 return 0;
 
}


[hirasawa@aspire-white gcc-Programming-Kobo]$ gcc -Wall -save-temps -o address address.c 
[hirasawa@aspire-white gcc-Programming-Kobo]$ ./address | sort -k5

func (&func) locates at 0x80483f4
func (func) locates at 0x80483f4
main (&main) locates at 0x80484e3
main (main) loaates at 0x80484e3
*(m-a7) const_char_string loaates at 0x8048700
m-a2 11111111 loaates at 0x804a018
m-a4 22222222 loaates at 0x804a01c
m-a6 33333333 loaates at 0x804a020
m-a7 0x8048700 loaates at 0x804a024
f-static-int-inited-c4 66666666 locates at 0x804a028
m-a5 0 loaates at 0x804a034
f-static-int-NOTinit-c3 0 locates at 0x804a038
m-a3 0 loaates at 0x804a03c
m-a1 0 loaates at 0x804a040
f-auto-c2 55555555 locates at 0xbfa3cc58
f-auto-c1 26CFF4 locates at 0xbfa3cc5c
f-argv-b1 1 locates at 0xbfa3cc70
f-argv-b2 2 locates at 0xbfa3cc74
[hirasawa@aspire-white gcc-Programming-Kobo]$ 
[hirasawa@aspire-white gcc-Programming-Kobo]$ 

readelf -Sで確認



[hirasawa@aspire-white gcc-Programming-Kobo]$ readelf -S address | grep -E "text|data|rodata|bss"
  [13] .text             PROGBITS        08048340 000340 00039c 00  AX  0   0 16
  [15] .rodata           PROGBITS        080486f8 0006f8 00020b 00   A  0   0  4
  [23] .data             PROGBITS        0804a010 001010 00001c 00  WA  0   0  4
  [24] .bss              NOBITS          0804a02c 00102c 000018 00  WA  0   0  4
[hirasawa@aspire-white gcc-Programming-Kobo]$ 

address | sort -k5 と readelf -Sの結果を重ねあわせてみると

  [13] .text             PROGBITS        08048340 000340 00039c 00  AX  0   0 16

func (&func) locates at 0x80483f4
func (func) locates at 0x80483f4
main (&main) locates at 0x80484e3
main (main) loaates at 0x80484e3

ちなみに、32ビットのELF形式のプログラムの格納開始アドレス(_start kana?)
は0x08048000

開始アドレスを起点に上位に向かって関数などが配置されるんですな

  [15] .rodata           PROGBITS        080486f8 0006f8 00020b 00   A  0   0  4
*(m-a7) const_char_string loaates at 0x8048700

.dataと.rodataはともにWフラッグがついていないので、readonly。

  [23] .data             PROGBITS        0804a010 001010 00001c 00  WA  0   0  4
m-a2 11111111 loaates at 0x804a018
m-a4 22222222 loaates at 0x804a01c
m-a6 33333333 loaates at 0x804a020
m-a7 0x8048700 loaates at 0x804a024
f-static-int-inited-c4 66666666 locates at 0x804a028

.dataと.bssは隣合わせですね。
どっちもWAフラッグがたってるし、ひとつにまとめてもいいんぢゃない、と考えるが、

初期化、非初期化変数の区別を付けてる理由は、
実行ファイルがメモリ上にロードされる際に、カーネルがヘッダー情報にしたがって、.bssセクション全体を初期化する、ってだそうです。

なるほど

  [24] .bss              NOBITS          0804a02c 00102c 000018 00  WA  0   0  4
m-a5 0 loaates at 0x804a034
f-static-int-NOTinit-c3 0 locates at 0x804a038
m-a3 0 loaates at 0x804a03c
m-a1 0 loaates at 0x804a040 


こっからスタックになるんですな
いわゆるAuto変数

f-auto-c2 55555555 locates at 0xbfa3cc58
f-auto-c1 26CFF4 locates at 0xbfa3cc5c
f-argv-b1 1 locates at 0xbfa3cc70
f-argv-b2 2 locates at 0xbfa3cc74

0xC0000000から上位のアドレスはLinuxカーネルプロセス空間であり、
オート変数は、ユーザープロセス空間の中だが、境界ぎりぎりの所に
配置されてることになる。

こっちは、下位アドレスにむかって伸びていくんですな
つまり、

void func( int b1 , int b2 )
{
int c1;
int c2 = 0x55555555;

をcallする際には、b2,b1,c1,c2の順番で下アドレスに向かって成長。