- Notifications
You must be signed in to change notification settings - Fork 15.1k
Description
| Bugzilla Link | 48790 |
| Resolution | FIXED |
| Resolved on | Aug 23, 2021 14:00 |
| Version | trunk |
| OS | Linux |
| Blocks | #48661 |
| Attachments | LLVM-IR to reproduce when fed to llc |
| CC | @adrian-prantl,@dwblaikie,@gregbedwell,@JDevlieghere,@kyulee-com,@modocache,@pogo59,@pogo59,@tstellar,@vedantk,@wjristow |
| Fixed by commit(s) | ef0dcb5 |
Extended Description
The reproducer below causes LLVM master (93592b7) to produce malformed DWARF when built with "-O3 -g -flto". Running llvm-dwarfdump -verify complains "invalid DIE reference", and our debugger becomes displeased. Reverting e08f205 / D70350, "Allow cross-CU references of subprogram definitions", fixes it for us.
Sources:
$ cat -n 1.cpp
1 struct HHH;
2
3 struct xxx {
4 HHH yyy();
5 } zzz;
6
$ cat -n 2.cpp
1 int ggg;
2
3 struct HHH {
4 template int ccc(bbb) {
5 while (--ggg)
6 ;
7 }
8 };
9
10 void eee() {
11 HHH fff;
12 fff.ccc([] {});
13 }
14
Built thus (the target is important it seems):
$ clang++ -O3 -g -flto -w -c 1.cpp -o 1.o -target x86_64-scei-ps4
$ clang++ -O3 -g -flto -w -c 2.cpp -o 2.o -target x86_64-scei-ps4
$ ld.lld 1.o 2.o -o 3.out -r
$ llvm-dwarfdump -verify 3.out
Produces:
--------8<--------
error: invalid DIE reference 0x00000046. Offset is in between DIEs:
0x000000a1: DW_TAG_inlined_subroutine
DW_AT_abstract_origin (0x00000046)
DW_AT_low_pc (0x0000000000000000)
DW_AT_high_pc (0x0000000000000002)
DW_AT_call_file ("1.cpp")
DW_AT_call_line (12)
-------->8--------
I'm attaching an IR reproducer, derived from "ld.lld -save-temps" and the combined-and-optimized IR it produces. Feeding that IR into llc also produces an invalid DIE reference.
I've done some prodding, and while to me the DWARF emission code is a twisty turny maze of passages all alike, I believe the problem is that the DIE for the "eee" function is placed in the wrong compile unit. Here's a chain of events:
- The DIE for "HHH" is placed in the CU for 1.cpp, because the "zzz" global var is emitted there.
- The DIE for "ccc" is created in the context of "HHH", CU is 1.cpp
- The template argument for "ccc", a lambda type, is created
- The scope for that template argument is needed: so a DIE "eee" is created.
- That DIE for "eee" is in the "current" unit, 1.cpp
Normally this wouldn't be a problem. I believe that at the end of DwarfDebug::endFunctionImpl, normally a duplicate DIE would be created for "eee", because a cross-CU subprogram wouldn't be permitted. However, with e08f205 a cross-CU subprogram is permitted.
All the child scopes of "eee" are created before "eee" is created, they expect to be in the CU that the DISubprogram for "eee" specifies, 2.cpp, and they pick references of form "DW_FORM_ref4". They're then attached to a subprogram DIE in a different CU, breaking those forms of references. If you use llvm-dwarfdump -v, you can see that the offset of the DW_AT_abstract_origin above would be correct, if it was in the correct CU (hat-tip James Henderson).
I don't really have a proposal for how to fix this right now, DWARF emission is way out of my comfort zone.