GDB shows error message when trying to print a variable in an Assembly program
Asked Answered
M

2

12

While learning assembly language from a book there is a listing showing some basic operations:

segment .data
a   dq  176
b   dq  4097

segment .text
global _start

_start:
    mov rax, [a]    ; Move a into rax.
    add rax, [b]    ; add b o rax.
    xor rax, rax
    ret

After assembling with "$yasm -f elf64 -g dwarf2 -l listing.lst listing.asm" command and linking with "$ld -o listing listing.o" I ran the program in gdb. There whenever I tried to print the value of a variable, gdb showed this error message:

(gdb) p a
'a' has unknown type; cast it to its declared type

Same for the other variable 'b'. However casting 'a' or 'b' for int worked:

(gdb) p (int)a
$11 = 176
(gdb) p (int)b
$12 = 4097

But isn't this supposed to work without casting? Why do I need to cast? What mistake I've made in my source file?

Modulate answered 10/9, 2018 at 3:2 Comment(5)
dq is most likely NOT int on your target platform (I'm never sure from head on which target platform the int is 64b). So you are probably printing only 32 bit part of the value by the casting. (and I'm also not sure what type the gdb recognizes, does p (int64_t)a work, or you have to use base C types like p (long long)a? Or even some asm are recognized like p (qword)a?)Compass
Thanks for noting that Ped7g. sizeof() returns 4 for int in my PC. So it should be dd. But changing dq to dd didn't cure the problem.Modulate
mov rax,[a] does read 8 bytes, so it should be then mov eax,[a] if you want to use only dd to define the data (or movsx rax,dword [a] in case you want sign-extend the 32 bit memory value into 64 bit rax). Also I don't see how dq vs dd would fix anything, it just changes amount of memory defined after label a. Giving label a some kind of type information in debug info is beyond what I usually do in assembly (you make me sort of recognize how the 8 bit era forced me so much to keep track of everything in head, that I didn't even think about debugger being aware of "type").Compass
I mean, for me your question is not even "problem", I simply always pick the correct size in debugger by myself for particular symbol. Now that you asked about it, yeah, it would be sort of nice if the assembler would provide more info about symbols for debugger. Then again usually when one needs assembler (very rarely), he often does need also non-conventional work with memory, so defining some kind of "type" for label a may get actually into your way (if you access that memory by different instructions, for example if you vectorize some code, accessing several elements at one time).Compass
so "But isn't this supposed to work without casting?" - no, not on it's own. The debugger will do that when the particular label has attached also information about the expected "type" of data stored there, which high level languages often provide, because in C something like int32_t a = 1; does define 32 bit integer, but in assembly something like a: dd 1 does define label pointing at next first byte of emitted machine code (the a: part of line), and then it defines four bytes 1, 0, 0, 0 (the dd 1 part of line), they are like disconnected entities, you can even use two lines.Compass
B
3

But isn't this supposed to work without casting?

No. GDB tells you that it has no idea what type a and b are.

What mistake I've made in my source file?

You didn't make any mistakes, but you also didn't supply any debugging info that GDB could use.

You may have expected yasm -g dwarf2 ... to do so, but it only creates minimal debug info describing the source, nothing else:

$ readelf -wi listing.o

Contents of the .debug_info section:

  Compilation Unit @ offset 0x0:
   Length:        0x37 (32-bit)
   Version:       2
   Abbrev Offset: 0x0
   Pointer Size:  8
 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <c>   DW_AT_stmt_list   : 0x0
    <10>   DW_AT_low_pc      : 0x0
    <18>   DW_AT_high_pc     : 0x14
    <20>   DW_AT_name        : listing.asm
    <28>   DW_AT_comp_dir    : /tmp/
    <2e>   DW_AT_producer    : yasm 1.3.0
    <39>   DW_AT_language    : 32769    (MIPS assembler)
Buntline answered 10/9, 2018 at 3:58 Comment(0)
A
3

Older GDB used to default to assuming that a symbol was an int when it didn't have debug info describing the size / type.

This generally caused more confusion than the current behaviour, so it was changed.
(e.g. The value displayed in Kdbg is wrong -- NASM)

Ashworth answered 10/9, 2018 at 18:9 Comment(2)
So having to specify variable type is not a bad thing after all. And its definitely not a bug, aye? PS: I'm using GDB version 8.1.0.20180409Modulate
@AnikSamiurRahman: that's correct, this is the expected behaviour. The fact that NASM doesn't have syntax to create the necessary debug info could be considered a missing feature. Unlike MASM, there's no magical association between a label and a dq on the same line. Don't forget the : after a label name before the dq, to avoid ambiguity with instruction mnemonics. e.g. bound: dq 1 is legal, but bound dq 1 won't assemble because bound is an instruction. There's zero advantage to using a dq 1 instead of a: dq 1 in NASM syntax.Ashworth

© 2022 - 2024 — McMap. All rights reserved.