GDB 中 ASM 标签的地址

Address of an ASM label in GDB

我对使用 GDB 检查标签时使用“&”感到困惑。

我正在关注 2008 年的一本书。作者的调试器显然显示了存储在标签中的值。但是,我无法获得相同的调试器并且正在使用 GDB。我发现某个地方可以使用以下命令查看值:

(gdb) x/8c &Snippet
0x804a000 <Snippet>:    107 'k' 97 'a'  78 'N'  71 'G'  65 'A'  82 'R'  79 'O'  79 'O'

如果我改为调用 x/8c Snippet,我会得到一个错误,“'Snippet' 具有未知类型;将其转换为其声明的类型”。

x 命令需要一个地址,我知道 & 作为“地址”运算符,就像在 C 中一样。在代码中,我不需要使用 &。标签不就是内存地址的人类可读句柄吗?我很困惑为什么我需要在 GDB 中使用 &


该代码在 Snippet 处定义了字节“KANGAROO”。然后它循环 8 次,将 Snippet 处的字母切换为小写。

        ;; kangaroo.asm
        section .data

        Snippet db "KANGAROO"

        section .text

        global _start

_start:
        nop                     ; start experiment

        mov ebx, Snippet
        mov eax, 8
DoMore: add byte [ebx], 32
        inc ebx
        dec eax
        jnz DoMore

        nop                     ; end experiment

        section .bss

GDB 只是 asm 调试器,实际上主要设计用于调试已编译的 C 程序和类似的东西。它对变量名/标签的处理是围绕 C variable-name 语义设计的,而不是 asm 标签语义。

如果 GDB 没有 symbol-type 信息,它不知道它是否应该像 C int 全局变量那样具有值语义,其中使用裸名从该地址加载 (具有一些 GDB 也不知道的宽度),或者像 C 数组,其中使用裸名衰减到地址(在大多数情况下)。或者是不是代码标签。

我认为较旧的 GDB 曾经有一个默认值,但当前的 GDB 没有。

你说得对,最好将 asm 标签视为具有 C char label[] 之类的语义(在全局范围内)。
特别是在 NASM 语法中,其中 mov reg, name 是绝对地址的 mov-immediate,不像 GAS .intel_syntax noprefix 它是一个负载,比如 MASM。

有关生命意义的更多哲学思考(对于 asm 标签),请参阅


如果你正在调试一个用调试信息从C编译的程序,它确实定义了一个char foo[8] = {1,2,3};你应该能够使用x /8c foo来查看那里的内存内容。

确实,我测试了它,它可以在 x86-64 Arch 上与这个 C 程序一起使用 GNU/Linux

char foo[8] = {1,2,3};

int main(){}
$ gcc -g foo.c
$ gdb ./a.out

(gdb) ptype foo
type = char [8]
(gdb) p foo
 = "[=11=]1[=11=]2[=11=]3[=11=]0[=11=]0[=11=]0[=11=]0"
(gdb) x /8c foo
0x4028 <foo>:   1 '[=11=]1'        2 '[=11=]2'        3 '[=11=]3'        0 '[=11=]0'        0 '[=11=]0'        0 '[=11=]0'        0 '[=11=]0'        0 '[=11=]0'

(这是一个 PIE 可执行文件,我还没有 started,所以此时地址只是相对于图像基址的偏移量。)

我不建议尝试在 asm 中手动编写您自己的 debug-info 元数据。不过,如果您想查看 GCC 的功能,可以查看它的 gcc -g -S 输出,例如在 https://godbolt.org/z/q7EPT8jGG 上,如果您取消选中指令过滤器。它主要是数字,如:

        .section        .debug_info,"",@progbits
.Ldebug_info0:
        .long   0x84
        .value  0x5
        .byte   0x1
        .byte   0x8
        .long   .Ldebug_abbrev0
        .uleb128 0x2
...
        .long   .LASF3
        .uleb128 0x5
        .string "foo"
        .byte   0x1
        .byte   0x1
        .byte   0x6
        .long   0x2e
        .uleb128 0x9
        .byte   0x3
        .quad   foo
        .uleb128 0x6
        .long   .LASF5
        .byte   0x1
        .byte   0x3
        .byte   0x5
        .long   0x80
        .quad   .LFB0
        .quad   .LFE0-.LFB0
...

.data 中为 foo[] 本身定义静态存储的 asm 旁边,还有一个在没有 gcc -g 的情况下仍然存在,但它不足以让 GDB 知道如何治疗它。

        .type   foo, @object
        .size   foo, 8

(这是 GAS 语法;我不确定 NASM 等价物。)