Home > other >  Address of an ASM label in GDB
Address of an ASM label in GDB

Time:04-04

I'm confused about the use of "&" when examining a label using GDB.

I'm following a book from 2008. The author's debugger apparently shows the value stored at the label. However, I can't get the same debugger and am using GDB. I found somewhere that I can see the value using:

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

If I instead call x/8c Snippet, I get an error, "'Snippet' has unknown type; cast it to its declared type".

The x command takes an address and I understand that & works as the "address of" operator, like in C. In the code, I don't need to use &. Isn't a label just a human readable handle for a memory address? I'm confused about why I need to use & in GDB.


The code defines the bytes "KANGAROO" at Snippet. It then loops 8 times, switching the letters at Snippet to lowercase.

        ;; 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

CodePudding user response:

GDB is not just an asm debugger, and is in fact primarily designed to debug compiled C programs and stuff like that. And its treatment of variable names / labels is designed around C variable-name semantics, not asm label semantics.

If GDB doesn't have symbol-type information, it doesn't know whether it should have value semantics like a C int global variable, where using the bare name loads from that address (with some width that's also unknown to GDB), or like a C array where using the bare name decays to the address (in most contexts). Or whether it's a code label.

Older GDB I think used to have a default, but current GDB doesn't.

You're correct that an asm label is best thought of as having semantics like C char label[] (at global scope).
Especially in NASM syntax where mov reg, name is a mov-immediate of the absolute address, unlike GAS .intel_syntax noprefix where it's a load, like MASM.

For more philosophical musings about the meaning of life (for an asm label), see Is every variable and register name just a pointer in NASM Assembly?


If you're debugging a program compiled from C with debug info which does define a char foo[8] = {1,2,3}; you should be able to use x /8c foo to see the contents of memory there.

Indeed, I tested that and it works with this C program, on x86-64 Arch 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
$1 = "\001\002\003\000\000\000\000"
(gdb) x /8c foo
0x4028 <foo>:   1 '\001'        2 '\002'        3 '\003'        0 '\000'        0 '\000'        0 '\000'        0 '\000'        0 '\000'

(It's a PIE executable that I haven't started, so the address is just an offset relative to the image base at this point.)

I wouldn't recommend trying to write your own debug-info metadata by hand in asm. If you want to see what GCC does, though, you can look at it's gcc -g -S output, e.g. on https://godbolt.org/z/q7EPT8jGG if you uncheck the directives filter. It's mostly numeric like:

        .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
...

Next to the asm that defines the static storage in .data for foo[] itself, there's this which is still around without gcc -g, but it's not sufficient for GDB to know how to treat it.

        .type   foo, @object
        .size   foo, 8

(This is GAS syntax; I'm not sure of the NASM equivalents.)

  • Related