gpt4 book ai didi

gdb - 了解局部变量所在的堆栈布局

转载 作者:行者123 更新时间:2023-12-01 16:11:50 26 4
gpt4 key购买 nike

我有以下代码:

#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的值保存在堆栈中的位置。我怎样才能做到这一点?

最佳答案

除非您获取局部变量的地址 (&is_logged_in),否则优化编译器通常不会将它们存储在堆栈中。您可以通过在 gdb 中使用信息范围来查看这一点:

$ 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 汇编,也请耐心等待。反汇编 login() 给出:

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 range 关于 is_logged_in 的说法:

  • 0x40064c0x40066e之间,即函数开始和调用strcmp()之间,is_logged_in 的常数值为 0。
  • 0x40066e0x400673之间,即调用strcmp()之后直到函数结束,的值is_logged_in 可以通过以下方式计算:
    • 读取存储 strcmp() 返回值的 64 位寄存器 (RAX)
    • 左移32位
    • 将结果与 0 进行比较。如果相等比较为真,则 is_logged_in 的值为 1,否则为 0。

在这一点上,有些人可能会说,如果我们使用较低的优化级别进行编译,is_logged_in 的分配方式会有所不同,但我的观点是,局部变量只能保证如果您获取它们的地址并对该地址执行编译器不会优化掉的操作,则在堆栈上。在这种情况下,如果您想更改 is_logged_in 的值,最好更改 strcmp() 返回的值,即更改 RAX就在 strcmp() 返回之后。

如果is_logged_in在堆栈上分配,p &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 .

关于gdb - 了解局部变量所在的堆栈布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16742231/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com