In some senario, LLVM will remove llvm.dbg.labels in IR. For example, when the labels are in unreachable blocks, these labels will not be generated in LLVM IR. In the case, these debug labels will have address zero as their address. It is not legal address for debugger to set breakpoints or query sources. So, the patch inhibits the address info (DW_AT_low_pc) of removed labels.
Details
- Reviewers
aprantl sammccall vext01 probinson dblaikie - Commits
- rG55321d82bd32: [DebugInfo] Do not generate address info for removed debug labels.
rG9c2463622dd5: [DebugInfo] Do not generate address info for removed debug labels.
rL343062: [DebugInfo] Do not generate address info for removed debug labels.
rL342943: [DebugInfo] Do not generate address info for removed debug labels.
Diff Detail
- Repository
- rL LLVM
Event Timeline
Technically, I would think it might be best to produce the debug info for the label in the appropriate scope, but without an address - so that users can see that the label is there, name lookup finds that label not some other label or object?
If it has no DW_AT_low_pc in label debug info, GDB seems to assume it is 0x0.
(gdb) info scope foo Scope for foo: Symbol done is a label at address 0x400551, length 8. Symbol unreach is a label at address 0x0, length 8.
llvm-dwarfdump results:
0x00000056: DW_TAG_label DW_AT_abstract_origin (0x00000075 "done") DW_AT_low_pc (0x0000000000400551) 0x00000063: DW_TAG_label DW_AT_abstract_origin (0x0000007c "unreach") 0x00000068: NULL ... 0x00000075: DW_TAG_label DW_AT_name ("done") DW_AT_decl_file ("edd2.c") DW_AT_decl_line (13) 0x0000007c: DW_TAG_label DW_AT_name ("unreach") DW_AT_decl_file ("edd2.c") DW_AT_decl_line (11) 0x00000083: NULL
It will trigger assertions in GDB if we set breakpoint on labels with address 0x0 on x86 platform.
(gdb) b foo:done Note: breakpoint 1 also set at pc 0x400581. Breakpoint 2 at 0x400551: foo:done. (2 locations) (gdb) list foo:done 8 int foo(void) 9 { 10 goto done; 11 unreach: 12 printf("hi\n"); 13 done: 14 return rand() % 666; 15 } 16 17 int main() (gdb) list foo:unreach 6 } 7 8 int foo(void) 9 { 10 goto done; 11 unreach: 12 printf("hi\n"); 13 done: 14 return rand() % 666; 15 } (gdb) b foo:unreach /build/gdb-GT4MLW/gdb-8.1/gdb/linespec.c:3302: internal-error: void decode_line_full(const event_location*, int, program_space*, symtab*, int, linespec_result*, const char*, const char*): Assertion `result.size () == 1 || canonical->pre_expanded' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n)
So, to avoid the assertion failed in GDB, I removed debug info of these unreachable labels in this patch.
Can you preserved the declaration DIE (at 0x0000007c) while omitting the definition DIE (at 0x00000063)? Does that still cause a problem for GDB?
Hmm - what's the test case you're using here? Is there inlining? What about in cases without inlining?
My test case is as follow. I compile it with optimization on, so there is inlining in the result.
int foo(void) { goto done; unreach: printf("hi\n"); done: return rand() % 666; } int main() { return foo(); }
I removed the function call as follow:
int main() { goto done; unreach: printf("hi\n"); done: return rand() % 666; }
llvm-dwarfdump results:
0x00000043: DW_TAG_label DW_AT_name ("done") DW_AT_decl_file ("noinline.c") DW_AT_decl_line (9) DW_AT_low_pc (0x0000000000400541) 0x00000052: DW_TAG_label DW_AT_name ("unreach") DW_AT_decl_file ("noinline.c") DW_AT_decl_line (7) 0x00000059: NULL
It still caused GDB to crash if set breakpoint on unreach
Hi,
It seems to me that the correct thing to do with unreachable labels is to emit a label with no low_pc attribute and fix gdb to accept such labels. Instead of crashing, it should print a message like "label was optimised out".
(It also shouldn't crash if a label has a zero low_pc value. I guess that zero could (in esoteric scenarios) be a valid code address. Perhaps for raw (headerless) binaries on some system which doesn't relocate code at load time?).
If you guys agree, I don't mind raising the bug, but we'd need an easily reproducible crash case to show them.
Agreed, though producing debug info that's likely to break any GDB in the interim's not ideal either - I'd certainly encourage folks to file the GDB bug and encourage a discussion with GDB folks about whether a label with no low_pc attribute is the right representation (I think it is, but open to other ideas)
(It also shouldn't crash if a label has a zero low_pc value. I guess that zero could (in esoteric scenarios) be a valid code address. Perhaps for raw (headerless) binaries on some system which doesn't relocate code at load time?).
Agreed
If you guys agree, I don't mind raising the bug, but we'd need an easily reproducible crash case to show them.
*nod* looks like that's been provided elsewhere in this review (though I've not gone through the repro steps myself).
Perhaps we could implement this behavior only if we're tuning for GDB & otherwise produce a label without a low_pc? Not sure how other folks (@aprantl @echristo @probinson @JDevlieghere) feel about this - apply the workaround generally, because it's not super important to have a label for name-lookup porpoises? or is it worth carrying the two codepaths to ensure that slightly more accurate debug info where it's possible (presuming LLDB can cope with it)?
Special cases for GDB bugs are not great. While on principle I'd rather see the entry with no location, I agree it's not super important to keep it and it's less grody to behave the same for all tunings here.
I use the same test program to generate executable with gcc. The executable has DW_TAG_label without DW_AT_low_pc. However, it will not crash GDB. There should be other debug attributes that will affect the behavior as setting breakpoints on labels.
I will dig into the difference and report here if I found the root cause.
By default, gcc will generate relocatable executable. So, when users set breakpoints on labels without address, address zero will be relocated to load address. It is not correct locations for labels. However, it will not cause gdb to crash. If I compile the test case with -no-pie, it will encounter the same problem.
I think that all of us agreed that it is a bug in GDB to crash when setting breakpoints on labels without address information. So, I updated the patch to generate label debug information without address even when the labels are removed after optimizations.
lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | ||
---|---|---|
871 ↗ | (On Diff #165952) | Fold the if and getSymbol together: if (Label) if (const MCSymbol *Sym = Label->getSymbol()) addLabelAddress(*Die, dwarf::DW_AT_low_pc, Sym); You could maybe use auto * as well, instead of spelling out the type. |
test/DebugInfo/Generic/debug-label-unreached.ll | ||
8 ↗ | (On Diff #165952) | Make sure the low_pc is part of the same tag by putting this in front of it: |