llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.01k stars 11.56k forks source link

[clang] clang generates incompatible types on DWARF stack #102294

Open IOVOVHS opened 1 month ago

IOVOVHS commented 1 month ago

When I use gdb to print the variables of a program compiled by clang, gdb displays "incompitable types on dwarf stack". I was going to submit this to gdb, but someone has already submitted the same issue to gdb. This is the gdb issue. gdb developer said that the operand type of DW_OP_constu is generic and cannot be used as an operand with the base type, and quoted the official dwarf documentation. It seems that the operand of DW_OP_constu also needs to be converted. In fact, someone has already submitted the same issue https://github.com/llvm/llvm-project/issues/62118, but no one has responded. If this is correct, just ignore this issue.

This is the problem I encountered:

(gdb) b 350
Breakpoint 2 at 0x555555555170: file /home/hzw/experiment/csmith_prog/mutated_progs/random_92.c, line 350.
(gdb) c
Continuing.

Breakpoint 2, func_1 () at /home/hzw/experiment/csmith_prog/mutated_progs/random_92.c:350
350 int8_t c_20455 = c_20443 - c_20444;
(gdb) p c_20383
Incompatible types on DWARF stack
(gdb) info addr c_20383
Symbol "c_20383" is multi-location:
  Range 0x555555555157-0x555555555194: a complex DWARF expression:
     0: DW_OP_constu 66
     2: DW_OP_breg1 0 [$rdx]
     4: DW_OP_constu 4294967295
    10: DW_OP_and
    11: DW_OP_convert<DW_ATE_unsigned_32 [0x27]>
    16: DW_OP_convert<DW_ATE_unsigned_8 [0x2c]>
    21: DW_OP_minus
    22: DW_OP_stack_value

The value of the variable should be: "66 - (( $rdx & 4294967295) as 32-bit as 8-bit)" ,but gdb think the type of "66" is generic type as the explanation in dwarf document 2.5.1.1 which is incompatible.But lldb prints the variable correctly. random_92.zip

version: clang 15.07 lldb 15.07 gdb 13.2

Maybe it is acceptable to ignore this difference between gdb and lldb, but I am not sure.

llvmbot commented 1 month ago

@llvm/issue-subscribers-debuginfo

Author: None (IOVOVHS)

When I use gdb to print the variables of a program compiled by clang, gdb displays "incompitable types on dwarf stack". I was going to submit this to gdb, but someone has already submitted the same issue to gdb. This is the gdb [issue](https://sourceware.org/bugzilla/show_bug.cgi?id=30319). gdb developer said that the operand type of DW_OP_constu is generic and cannot be used as an operand with the base type, and quoted the official dwarf documentation. It seems that the operand of DW_OP_constu also needs to be converted. In fact, someone has already submitted the same issue https://github.com/llvm/llvm-project/issues/62118, but no one has responded. If this is correct, just ignore this issue. This is the problem I encountered: ``` c (gdb) b 350 Breakpoint 2 at 0x555555555170: file /home/hzw/experiment/csmith_prog/mutated_progs/random_92.c, line 350. (gdb) c Continuing. Breakpoint 2, func_1 () at /home/hzw/experiment/csmith_prog/mutated_progs/random_92.c:350 350 int8_t c_20455 = c_20443 - c_20444; (gdb) p c_20383 Incompatible types on DWARF stack (gdb) info addr c_20383 Symbol "c_20383" is multi-location: Range 0x555555555157-0x555555555194: a complex DWARF expression: 0: DW_OP_constu 66 2: DW_OP_breg1 0 [$rdx] 4: DW_OP_constu 4294967295 10: DW_OP_and 11: DW_OP_convert<DW_ATE_unsigned_32 [0x27]> 16: DW_OP_convert<DW_ATE_unsigned_8 [0x2c]> 21: DW_OP_minus 22: DW_OP_stack_value ``` The value of the variable should be: "66 - (( $rdx & 4294967295) as 32-bit as 8-bit)" ,but gdb think the type of "66" is generic type as the explanation in dwarf document 2.5.1.1 which is incompatible.But lldb prints the variable correctly. [random_92.zip](https://github.com/user-attachments/files/16521763/random_92.zip) version: clang 15.07 lldb 15.07 gdb 13.2 Maybe it is acceptable to ignore this difference between gdb and lldb, but I am not sure.
jmorse commented 1 month ago

I can see what the objection to that expression is, in that a subtract between a generic number and a uint8_t doesn't have a clear result type (although promoting to the generic type seems wise). However it also feels like a major pain to solve this in LLVM, where type promotion can happen in several places (SelectionDAG does it, I think x86 load-widening can do it?) without involving debug-info. We also don't keep the structure of the expression stack, we just chuck more opcodes into a DIExpression, so we'd have to reverse-engineer it at emission.

Perhaps that could happen if one explicitly requests gdb tuning? CC @dwblaikie , I don't know what precedent there is for how much effort we put in to slight disagreements on the spec here.

CC @scott-linder who has an interest in typed expression stacks.

dwblaikie commented 1 month ago

I really don't have much context for DWARF expression work, that's mostly been your domain, and before that perhaps @adrian-prantl had some context (I recall discussing DW_OP_bit_piece many years ago)...

It seems like a reasonable objection - what do debuggers that don't object (lldb? sce?) do when they see this? Promote the result to the generic type if any operand is generic? Could we propose that behavior to DWARF6?

Otherwise, yeah, seems worth fixing and I wouldn't want to leave it under an explicit gdb tuning unless there's a pretty good argument to do so (like it takes up /a lot/ more space)? If we end up doing the work to make this spec-compliant, seems like we should just make that the only path?