当我执行以下命令时,我得到不同的函数地址()
(gdb) break function()
函数()0x804834a处的断点1
(gdb) print function()
函数()0x8048344处的断点1
为什么两个地址都有差异?
答案 0 :(得分:4)
此输出无法正确,如果你执行了以下操作:
int func(void) {
int a = 10;
printf("%d\n", a);
return 1;
}
将其加载到gdb中后:
(gdb) p func
$1 = {int (void)} 0x4016b0 <func>
(gdb) b func
Breakpoint 1 at 0x4016b6: file file.c, line 4.
(gdb) disassemble func
Dump of assembler code for function func:
0x004016b0 <+0>: push %ebp
0x004016b1 <+1>: mov %esp,%ebp
0x004016b3 <+3>: sub $0x28,%esp
0x004016b6 <+6>: movl $0xa,-0xc(%ebp)
0x004016bd <+13>: mov -0xc(%ebp),%eax
0x004016c0 <+16>: mov %eax,0x4(%esp)
0x004016c4 <+20>: movl $0x405064,(%esp)
0x004016cb <+27>: call 0x403678 <printf>
0x004016d0 <+32>: mov $0x1,%eax
0x004016d5 <+37>: leave
0x004016d6 <+38>: ret
End of assembler dump.
(gdb)
这里func
指向函数push %ebp
中的确切第一条指令,但是当你设置一个断点时,gdb在堆栈帧初始化指令之后设置它:
0x004016b0 <+0>: push %ebp
0x004016b1 <+1>: mov %esp,%ebp
0x004016b3 <+3>: sub $0x28,%esp
函数指令实际开始的地方:
=> 0x004016b6 <+6>: movl $0xa,-0xc(%ebp)
0x004016bd <+13>: mov -0xc(%ebp),%eax
0x004016c0 <+16>: mov %eax,0x4(%esp)
0x004016c4 <+20>: movl $0x405064,(%esp)
0x004016cb <+27>: call 0x403678 <printf>
0x004016d0 <+32>: mov $0x1,%eax
0x004016d5 <+37>: leave
0x004016d6 <+38>: ret
这条指令:
movl $0xa,-0xc(%ebp) ; 0xa = 10
是这部分:
int a = 10;
答案 1 :(得分:3)
Gdb在function prologue之后设置一个断点,就像之前正确设置它一样,它无法像局部变量那样显示预期的状态等。
中断设置断点并在序言后打印第一条指令的地址,而print打印功能中实际第一条指令的地址。
你可以通过break * 0x8048344设置一个断点到实际的第一条指令,然后在prologue之后观察局部变量的值。