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

huangapple go评论65阅读模式
英文:

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&#39;m not sure if I&#39;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&#39;s `.data` section, called `string`:

```asm
SECTION .data
string: db &quot;KANGAROO&quot;

If I want to inspect the memory at address string with x, this happens:
(gdb) x/8 string
yields:
&#39;string&#39; 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 = &quot;abcd&quot;;
const char string2[] = &quot;efgh&quot;;

int main() { return 0; }

在没有使用 -g 编译时,您需要告诉 GDB &amp;string2 是内存中字符串的地址,但 &amp;string1 是指向字符串的指针的地址:

(gdb) x/s *(char**)&amp;string1
0x2004: &quot;abcd&quot;

(gdb) x/s (char*)&amp;string2
0x2009 &lt;string2&gt;:       &quot;efgh&quot;
英文:

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 = &quot;abcd&quot;;
const char string2[] = &quot;efgh&quot;;

int main() { return 0; }

When compiled without -g, you need to tell GDB that &amp;string2 is the address of a string in memory, but &amp;string1 is the address of a pointer to a string:

(gdb) x/s *(char**)&amp;string1
0x2004: &quot;abcd&quot;

(gdb) x/s (char*)&amp;string2
0x2009 &lt;string2&gt;:       &quot;efgh&quot;

答案2

得分: 1

使用 x /8c &string 来转储带有该符号标签的地址处的内存。

英文:

Use x /8c &amp;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 &amp; 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 = &quot;aaaaaaa&quot;;
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 &amp;ptr
0x555555558010 &lt;ptr&gt;:   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 &amp;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.

huangapple
  • 本文由 发表于 2023年6月5日 06:25:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76402644.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定