我有以下代码:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
char *MASTER_PASSWORD = "password";
bool login(char * password){
bool is_logged_in=false;
char buf[8];
strcpy(buf,password);
if(strcmp(buf, MASTER_PASSWORD)==0){
is_logged_in=true;
}
return is_logged_in;
}
int main(int argc, char *argv[]){
if(argc <2)
{
printf("Syntax: %s <input string>\n", argv[0]);
exit (0);
}
if(login(argv[1]))
printf("you are authorized");
return 0;
}
我正在使用gdb来调试它,我需要知道is_logged_in
的值在堆栈中的保存位置。我怎么能这样做?
答案 0 :(得分:12)
除非你获取局部变量(&is_logged_in
)的地址,否则优化编译器通常不会将它们存储在堆栈中。您可以在gdb中使用 info scope 来查看:
$ gcc -Os -g3 stack-layout.c -o stack-layout
$ gdb -q stack-layout
(gdb) info scope login
会显示:
Scope for login:
<...>
Symbol is_logged_in is multi-location:
Range 0x40064c-0x40066e: the constant 0
Range 0x40066e-0x400673: a complex DWARF expression:
0: DW_OP_breg0 0 [$rax]
2: DW_OP_const1u 32
4: DW_OP_shl
5: DW_OP_lit0
6: DW_OP_eq
7: DW_OP_stack_value
, length 1.
<...>
即使您不熟悉x86-64程序集,也请在此处与我联系。反汇编登录()给出:
8 bool login(char * password){
0x000000000040064c <+0>: sub $0x18,%rsp
0x0000000000400650 <+4>: mov %rdi,%rsi
9 bool is_logged_in=false;
10 char buf[8];
11 strcpy(buf,password);
0x0000000000400653 <+7>: lea 0x8(%rsp),%rdi
0x0000000000400658 <+12>: callq 0x4004c0 <strcpy@plt>
12 if(strcmp(buf, MASTER_PASSWORD)==0){
0x000000000040065d <+17>: mov 0x2009ec(%rip),%rsi # 0x601050 <MASTER_PASSWORD>
0x0000000000400664 <+24>: lea 0x8(%rsp),%rdi
0x0000000000400669 <+29>: callq 0x4004f0 <strcmp@plt>
0x000000000040066e <+34>: test %eax,%eax
0x0000000000400670 <+36>: sete %al
13 is_logged_in=true;
14 }
15
16 return is_logged_in;
17 }
0x0000000000400673 <+39>: add $0x18,%rsp
0x0000000000400677 <+43>: retq
gdb info scope
对 is_logged_in :
此时有人可能会争辩说,如果我们使用较低的优化级别进行编译, is_logged_in 的分配会有所不同,但我的观点是局部变量只是保证是在堆栈上,如果你采用他们的地址,并使用该地址做一些编译器不会优化的地址。在这种情况下,如果您想更改 is_logged_in 的值,最好更改 strcmp()返回的值,即更改 RAX 在 strcmp()之后返回。
如果在堆栈上分配了 is_logged_in , p&amp; is_logged_in 会在GDB中打印其地址。如果它不在堆栈上,你会收到类似
的错误(gdb) p &is_logged_in
Can't take address of "is_logged_in" which isn't an lvalue.
DWARF调试信息格式(包括其堆栈机器操作)记录在dwarfstd.org。