void test_function(int a, int b, int c, int d){
int flag;
char buffer[10];
flag = 31337;
buffer[0] = 'A';
}
int main() {
test_function(1, 2, 3, 4);
return 0;
}
$ gcc -g main.c
$ gdb -q ./a.out
Reading symbols from ./a.out…
(gdb) disass main
Dump of assembler code for function main:
0x000000000000087c <+0>: stp x29, x30, [sp, #-16]!
0x0000000000000880 <+4>: mov x29, sp
0x0000000000000884 <+8>: mov w3, #0x4 // #4
0x0000000000000888 <+12>: mov w2, #0x3 // #3
0x000000000000088c <+16>: mov w1, #0x2 // #2
0x0000000000000890 <+20>: mov w0, #0x1 // #1
0x0000000000000894 <+24>: bl 0x814
0x0000000000000898 <+28>: mov w0, #0x0 // #0
0x000000000000089c <+32>: ldp x29, x30, [sp], #16
0x00000000000008a0 <+36>: ret
End of assembler dump.
(gdb) disass test_function
Dump of assembler code for function test_function:
0x0000000000000814 <+0>: stp x29, x30, [sp, #-64]!
0x0000000000000818 <+4>: mov x29, sp
0x000000000000081c <+8>: str w0, [sp, #28]
0x0000000000000820 <+12>: str w1, [sp, #24]
0x0000000000000824 <+16>: str w2, [sp, #20]
0x0000000000000828 <+20>: str w3, [sp, #16]
0x000000000000082c <+24>: adrp x0, 0x10000
0x0000000000000830 <+28>: ldr x0, [x0, #4072]
0x0000000000000834 <+32>: ldr x1, [x0]
0x0000000000000838 <+36>: str x1, [sp, #56]
0x000000000000083c <+40>: mov x1, #0x0 // #0
0x0000000000000840 <+44>: mov w0, #0x7a69 // #31337
0x0000000000000844 <+48>: str w0, [sp, #36]
–Type for more, q to quit, c to continue without paging–
0x0000000000000848 <+52>: mov w0, #0x41 // #65
0x000000000000084c <+56>: strb w0, [sp, #40]
0x0000000000000850 <+60>: nop
0x0000000000000854 <+64>: adrp x0, 0x10000
0x0000000000000858 <+68>: ldr x0, [x0, #4072]
0x000000000000085c <+72>: ldr x2, [sp, #56]
0x0000000000000860 <+76>: ldr x1, [x0]
0x0000000000000864 <+80>: subs x2, x2, x1
0x0000000000000868 <+84>: mov x1, #0x0 // #0
0x000000000000086c <+88>: b.eq 0x874 // b.none
0x0000000000000870 <+92>: bl 0x6a0 <__stack_chk_fail@plt>
0x0000000000000874 <+96>: ldp x29, x30, [sp], #64
0x0000000000000878 <+100>: ret
End of assembler dump.
4, 3, 2, 1はスタックフレームにpushされる
(gdb) list main
6
7 flag = 31337;
8 buffer[0] = ‘A’;
9 }
10
11 int main() {
12 test_function(1, 2, 3, 4);
13 return 0;
14 }
(gdb) break 12
Breakpoint 1 at 0x884: file main.c, line 12.
(gdb) break test_function
Breakpoint 2 at 0x82c: file main.c, line 3.
(gdb) run
Starting program: /home/vagrant/dev/c/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library “/lib/aarch64-linux-gnu/libthread_db.so.1”.
Breakpoint 1, main () at main.c:12
12 test_function(1, 2, 3, 4);
メモリ中の各セグメントは、低位アドレスから高位アドレスへ向かって並べられていく
– 低位アドレス
テキスト(コード)セグメント
データセグメント
bssセグメント
ヒープセグメント
スタックセグメント
– 高位アドレス
### メモリセグメント
int global_var;
int global_initialized_var = 5;
void function() {
int stack_var;
printf("function()のstack_varは、アドレス0x%08xにあります。\n", &stack_var);
}
int main() {
int stack_var;
static int static_initialized_var = 5;
static int static_var;
int *heap_var_ptr;
heap_var_ptr = (int *)malloc(4);
// データセグメントに確保される
printf("global_initialized_varはアドレス0x%08xにあります。\n", &global_initialized_var);
printf("static_initialized_varはアドレス0x%08xにあります。\n", &static_initialized_var);
// bssセグメントに確保される
printf("static_varはアドレス0x%08xにあります。\n", &static_var);
printf("global_varはアドレス0x%08xにあります。\n", &global_var);
// ポインタ変数はヒープセグメント内に確保される
printf("heap_var_ptrはアドレス0x%08xにあります。\n", heap_var_ptr);
// 以下の変数はスタックセグメント内に確保される
printf("stack_varはアドレス0x%08xにあります。\n", &stack_var);
return 0;
}
$ ./a.out
global_initialized_varはアドレス0xc5b21010にあります。
static_initialized_varはアドレス0xc5b21014にあります。
static_varはアドレス0xc5b21020にあります。
global_varはアドレス0xc5b2101cにあります。
heap_var_ptrはアドレス0xefedb2a0にあります。
stack_varはアドレス0xecf4957cにあります。