使用gdb查看栈帧的情况, 没有ebp
0x7fffffffdb58: 0x004005ba 0x00000000 0x00000000 0x00000000 <-----funcb的栈帧 [0x7fffffffdb60, 0x7fffffffdb80],其中a=0x1a,其中这个栈的栈底是返回地址4005d
0x7fffffffdb68: 0x00000000 0x0000001a 0x00000000 0x00000000 0x4005d8,是函数funca的返回地址,然后往上就逐渐是各种局部变量
0x7fffffffdb78: 0x004005d8 0x00000000 0x00400470 0x00000000
0x7fffffffdb88: 0xffffdd90 0x00000019 0x00000000 0x00000000 <-----funca的栈帧,这个栈帧[0x7fffffffdb80, 0x7fffffffdba0], 其中a=0x19
0x7fffffffdb98: 0x0040060d 0x00000000 0x00000000 0x00000000 <----add的栈帧stack frame [0x7fffffffdba0,0x7ffffffdbd0],其中a=0x18,b=0x27
0x7fffffffdba8: 0x00000028 0x00000018 0x00000001 0x00000000
0x7fffffffdbb8: 0x00000040 0x00000000 0x6562b026 0x00000000
0x7fffffffdbc8: 0x0040069f 0x00000000 0xffffdd60 0x00007fff
0x7fffffffdbd8: 0xf7dee923 0x00000002 0x00000000 0x00000017
0x7fffffffdbe8: 0x00000027 0x00000000 0x00000000 0x00000000
0x7fffffffdbf8: 0x00000003 0x00000000 0xffffdda8 0x00007fff
0x7fffffffdc08: 0x00000000 0x00000000 0x00400750 0x00000000
0x7fffffffdc18: 0xf7de7ab0 0x00007fff 0x000000ff 0x00000000
0x7fffffffdc28: 0xff000000 0x00000000 0x00000000 0x00000000
0x7fffffffdc38: 0x00000000 0x00000000 0x00000000 0x00000000
所以说一个栈的栈帧,最开始是上一个函数的返回地址,以及本函数的堆栈
gdb中显示出来的栈帧的信息中,“Stack frame at 0x7fffffffdb80” 都是指栈帧的基地址。
(gdb) info frame 1 Stack frame at 0x7fffffffdb80: rip = 0x4005ba in funcb (sleep.c:15); saved rip = 0x4005d8 called by frame at 0x7fffffffdba0, caller of frame at 0x7fffffffdb60 source language c. Arglist at 0x7fffffffdb58, args: a=26 Locals at 0x7fffffffdb58, Previous frame's sp is 0x7fffffffdb80 Saved registers: rip at 0x7fffffffdb78 (gdb) info frame 2 Stack frame at 0x7fffffffdba0: rip = 0x4005d8 in funca (sleep.c:19); saved rip = 0x40060d called by frame at 0x7fffffffdbd0, caller of frame at 0x7fffffffdb80 source language c. Arglist at 0x7fffffffdb78, args: a=25 Locals at 0x7fffffffdb78, Previous frame's sp is 0x7fffffffdba0 Saved registers: rip at 0x7fffffffdb98 (gdb) info frame 3 Stack frame at 0x7fffffffdbd0: rip = 0x40060d in add (sleep.c:27); saved rip = 0x40069f called by frame at 0x7fffffffdcb0, caller of frame at 0x7fffffffdba0 source language c. Arglist at 0x7fffffffdb98, args: a=24, b=40 Locals at 0x7fffffffdb98, Previous frame's sp is 0x7fffffffdbd0 Saved registers: rip at 0x7fffffffdbc8 (gdb) info frame 4 Stack frame at 0x7fffffffdcb0: rip = 0x40069f in print (sleep.c:35); saved rip = 0x4006c7 called by frame at 0x7fffffffdcc0, caller of frame at 0x7fffffffdbd0 source language c. Arglist at 0x7fffffffdbc8, args: i=2 Locals at 0x7fffffffdbc8, Previous frame's sp is 0x7fffffffdcb0 Saved registers: rip at 0x7fffffffdca8
以函数funca->funcb来看一一下函数的调用过程
00000000004005a2 <funcb>: 4005a2: 48 83 ec 18 sub $0x18,%rsp rsp这个时候的值就确定了 4005a6: 89 7c 24 0c mov %edi,0xc(%rsp) 4005aa: 83 44 24 0c 01 addl $0x1,0xc(%rsp) 4005af: 8b 44 24 0c mov 0xc(%rsp),%eax 4005b3: 89 c7 mov %eax,%edi 4005b5: e8 ac ff ff ff callq 400566 <funcc> 4005ba: 90 nop 4005bb: 48 83 c4 18 add $0x18,%rsp 4005bf: c3 retq 00000000004005c0 <funca>: 4005c0: 48 83 ec 18 sub $0x18,%rsp 4005c4: 89 7c 24 0c mov %edi,0xc(%rsp) 4005c8: 83 44 24 0c 01 addl $0x1,0xc(%rsp) 4005cd: 8b 44 24 0c mov 0xc(%rsp),%eax 4005d1: 89 c7 mov %eax,%edi 4005d3: e8 ca ff ff ff callq 4005a2 <funcb> callq是push ip;rsp++ 4005d8: 90 nop 4005d9: 48 83 c4 18 add $0x18,%rsp 4005dd: c3 retq
dwarf当中存储的信息是啥样子的呢?
< 1><0x000000ca> DW_TAG_subprogram DW_AT_external yes(1) DW_AT_name "funcb" DW_AT_decl_file 0x00000001 /home/hon/codebox/gcc/sleep.c DW_AT_decl_line 0x0000000d DW_AT_prototyped yes(1) DW_AT_type <0x00000049> DW_AT_low_pc 0x004005a2 DW_AT_high_pc <offset-from-lowpc>30 DW_AT_frame_base len 0x0001: 9c: DW_OP_call_frame_cfa DW_AT_GNU_all_tail_call_sitesyes(1) DW_AT_sibling <0x000000f8> < 2><0x000000eb> DW_TAG_formal_parameter DW_AT_name "a" DW_AT_decl_file 0x00000001 /home/hon/codebox/gcc/sleep.c DW_AT_decl_line 0x0000000d DW_AT_type <0x00000049> DW_AT_location len 0x0002: 916c: DW_OP_fbreg -20
funca中的信息是啥样子的?
< 1><0x000000f8> DW_TAG_subprogram DW_AT_external yes(1) DW_AT_name "funca" DW_AT_decl_file 0x00000001 /home/hon/codebox/gcc/sleep.c DW_AT_decl_line 0x00000011 DW_AT_prototyped yes(1) DW_AT_type <0x00000049> DW_AT_low_pc 0x004005c0 DW_AT_high_pc <offset-from-lowpc>30 DW_AT_frame_base len 0x0001: 9c: DW_OP_call_frame_cfa DW_AT_GNU_all_tail_call_sitesyes(1) DW_AT_sibling <0x00000126> < 2><0x00000119> DW_TAG_formal_parameter DW_AT_name "a" DW_AT_decl_file 0x00000001 /home/hon/codebox/gcc/sleep.c DW_AT_decl_line 0x00000011 DW_AT_type <0x00000049> DW_AT_location len 0x0002: 916c: DW_OP_fbreg -20