assembly 无法通过GDB读取程序集标签上的n字节数据

ao218c7q  于 2023-06-06  发布在  其他
关注(0)|答案(2)|浏览(166)

我不确定我是否误解了GDB文档中关于xprint命令的内容,但它似乎建议将其用作x {expr}应该将expr视为地址。我在程序的.data部分中有一个标记的数据位,称为string

SECTION .data
string: db "KANGAROO"

如果我想检查地址为string的内存,会发生以下情况:(gdb) x/8 string得到:'string' has unknown type; cast it to its declared type
为什么广发行抱怨类型转换?我要求它做的就是转到内存位置string(这显然是一个地址-如果我将string加载到寄存器中,它看起来明显像一个偏移量)。
简单的转换,假设它希望我将string转换为指向某些数据的指针:
(gdb) x/8 (char*)string
做了一件很奇怪的事它以某种方式知道要读取string的确切字节数(我尝试了几种不同大小的字符串),显示这些字节,但随后抱怨它试图访问stringvalue 地址的内存,而不是string本身:
0x4f4f5241474e414b: Cannot access memory at address 0x4f4f5241474e414b
其中数据0x4f4...是字符串的ASCII码。因此,它完全跳过了string的地址,现在将位置string中包含的数据视为地址表达式。什么?
我哪里糊涂了?string标签实际上不是内存地址吗?因为我本以为x命令只是将其视为地址表达式,但似乎并非如此。它为什么要我投数据?我只想读取.data中特定标记位置的n个字节。我错过了什么?

w80xi6nr

w80xi6nr1#

GDB对string的所有内容都是一个符号 * 值 *。GDB不知道如何将该符号值转换为某个对象的地址。
考虑以下程序:

const char *string1 = "abcd";
const char string2[] = "efgh";

int main() { return 0; }

在没有-g的情况下编译时,需要告诉GDB &string2是内存中字符串的地址,而&string1是指向字符串的指针的地址:

(gdb) x/s *(char**)&string1
0x2004: "abcd"

(gdb) x/s (char*)&string2
0x2009 <string2>:       "efgh"
mlmc2os5

mlmc2os52#

**使用x /8c &string**将内存转储到标有该符号的地址。

这似乎表明它作为x {expr}的使用应该将expr视为地址
GDB语法很像C。如果它不知道调试信息中的类型,它会假设它是一个值类型,如C int stringfloat string,其中裸名称计算为存储在内存中的值,而不是像char string[]那样,在大多数上下文中使用裸名称会给你地址。
当GDB没有类型时,它拒绝计算使用没有&地址操作符的符号的表达式。其中包括用作x命令操作数的表达式。它不会隐式地接受符号的地址。
GDB知道string是可执行文件的符号表中的一个符号,因此它有一个地址,但GDB只知道这些。它不知道string应该计算符号的地址,无论它是x还是print的操作数。(尽管print确实有很多内置的魔法,当GDB知道类型时。
例如:

char *ptr = "aaaaaaa";
int main(){
// set a breakpoint here and  x ptr
}
$ gcc -g ptr.c            # build *with* debug info
$ gdb ./a.out
...
(gdb) x ptr
0x555555556004: 0x61616161       # the ASCII bytes in .rodata
(gdb) x &ptr
0x555555558010 <ptr>:   0x55556004   # the low 4 bytes of the 8-byte pointer in .data

如果在C中有一个char *ptr变量,x ptr使用该变量的值并检查指向的内存,转储。而不是像从x &ptr获取的8字节指针数据本身,以检查C变量或asm符号地址处的内存。
类型不是问题,它默认为32位块,转储为十六进制。这和使用p而不使用强制转换的问题是一样的。

相关问题