英文:
Can't read n bytes of data at an assembly label via GDB
问题
我不确定是否在错误地阅读关于“x”和“print”命令的GDB文档,但似乎它建议将其用作“x {expr}”时将“expr”视为地址。在我的程序的`.data`部分中,有一个标记为`string`的数据位:
```asm
SECTION .data
string: db "KANGAROO"
如果我想使用x
检查地址string
处的内存,发生以下情况:
(gdb) x/8 string
产生:
'string' has unknown type; cast it to its declared type
为什么GDB会抱怨类型转换?我只是要求它转到内存位置string
(这显然是一个地址 - 如果我将string
加载到寄存器中,它看起来明显像一个偏移量)。
简单地进行类型转换,假设它要我将string
转换为指向某些数据的指针:
(gdb) x/8 (char*)string
做了一些非常奇怪的事情: 它以某种方式知道读取string
的确切字节数(我尝试了几种不同大小的字符串),显示这些字节,但然后抱怨它试图访问string
的值的地址,而不是string
本身的地址:
0x4f4f5241474e414b: Cannot access memory at address 0x4f4f5241474e414b
其中数据0x4f4...
是字符串的ASCII代码。所以它完全跳过了string
的地址,现在正在将位于位置string
的数据视为地址表达式。什么?
我在哪里弄混了?string
标签实际上不是内存地址吗?因为我本来希望x
命令只是将其视为地址表达式,但它似乎不这样做。它为什么要求我进行数据转换?我只是想读取.data
中特定标记位置的n个字节。我在这里漏掉了什么?
<details>
<summary>英文:</summary>
I'm not sure if I'm misreading the GDB documentation about the `x` and `print` commands, but it seems to suggest that its use as `x {expr}` should treat `expr` as an address. I have a labeled bit of data in my program's `.data` section, called `string`:
```asm
SECTION .data
string: db "KANGAROO"
If I want to inspect the memory at address string
with x, this happens:
(gdb) x/8 string
yields:
'string' has unknown type; cast it to its declared type
Why is GDB complaining about type casting? All I've asked it to do is go to memory location string
(which is clearly an address - if I load string
into a register it looks distinctly like an offset).
simply casting, assuming that it wants me to cast string
as a pointer to some data:
(gdb) x/8 (char*)string
does something really bizarre: it somehow knows to read the exact number of bytes of string
(I tried this with a few different sizes of string), shows those bytes, but then complains that it tried to access memory at the address of the value at string
, rather than string
itself:
0x4f4f5241474e414b: Cannot access memory at address 0x4f4f5241474e414b
where the data 0x4f4...
are the ASCII codes of the string. So it's jumped completely over the address of string
and is now treating the data contained at the location string
as an address expression. What?
Where am I getting confused here? Is the string
label not actually a memory address? Because I would have expected the x
command to simply treat it as an address expression, but it doesn't seem to. And why is it asking me to cast data? I just want to read n bytes at a particular labeled location in .data
. What am I missing here?
答案1
得分: 1
所有 GDB 对于 string
只有一个符号 value。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"
英文:
All GDB has for string
is a symbol value. GDB has no idea how to turn that symbol value into an address of something.
Consider the following program:
const char *string1 = "abcd";
const char string2[] = "efgh";
int main() { return 0; }
When compiled without -g
, you need to tell GDB that &string2
is the address of a string in memory, but &string1
is the address of a pointer to a string:
(gdb) x/s *(char**)&string1
0x2004: "abcd"
(gdb) x/s (char*)&string2
0x2009 <string2>: "efgh"
答案2
得分: 1
使用 x /8c &string
来转储带有该符号标签的地址处的内存。
英文:
Use x /8c &string
to dump memory at the address labeled with that symbol.
> it seems to suggest that its use as x {expr}
should treat expr
as an address
GDB syntax is a lot like C. If it doesn't know the type from debug info, it assumes it's a value type like C int string
or float string
where the bare name evaluates to the value stored in memory, not like char string[]
where using the bare name in most contexts gives you the address.
When GDB doesn't have a type, it refuses to evaluate expressions that use the symbol without an &
address-of operator. That includes the expression you use as an operand for the x
command. It doesn't implicitly take the address of a symbol.
GDB knows that string
is a symbol in the symbol-table of your executable, and therefore it has an address, but that's all GDB knows. It doesn't know that string
should evaluate to the symbol's address, whether it's an operand for x
or print
. (Although print
does have a lot of magic built-in for when GDB does know the type.)
For example:
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
If you have a char *ptr
variable in C, x ptr
uses the value of the variable and examines the pointed-to memory, dumping . Not the 8 bytes of pointer data itself like you'd get from x &ptr
to examine memory at the address of that C variable or asm symbol.
The type isn't the problem, it defaults to 32-bit chunks dumped as hex. It's the same problem you'd have if you used p without a cast.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论