I hate to be a nag, but after several days of working on this I am still utterly stumped.
Let me recap the situation as it currently stands: I’m trying to write code that generates DWARF debugging information for my compiler using DIFactory and friends. Unfortunately the information I am generating appears to be invalid, but I can’t figure out the cause.
Based on the advice in the earlier thread, I’ve been using dwarfdump to try and isolate the problem. This was helpful in solving the earlier problem, but isn’t helping me with the current problem.
When I run dwarfdump -a, it prints a couple hundred pages of debug info, and then segfaults. The last few lines before the segfault look like this:
.debug_inlined contents:
< EMPTY >
.debug_frame contents:
0x00000000: CIE
length: 0x00000010
CIE_id: 0xffffffff
version: 0x01
augmentation: “”
code_align: 1
data_align: -4
ra_register: 0x08
DW_CFA_def_cfa (esp, 4)
DW_CFA_offset (eip, 0)
DW_CFA_nop
DW_CFA_nop
Instructions: Init State: CFA=esp+4 eip=[esp+4]
0x00000014: FDE
length: 0x00000028
CIE_pointer: 0x00000000
Segmentation fault
If I grep through the output of dwarfdump, there are no other CIE or FDE definitions that occur before this point, so I assume that the problem isn’t just this particular FDE.
One difficulty here is that I don’t know which calls to DIFactory produce these data structures. Usually my solution of last resort when dealing with intractable debugging problems like this is to start commenting out code until the problem goes away, but in this case I don’t know where to even start. If I comment out all the DWARF-generating code, then obviously the problem goes away.
I did in fact discover that if I comment out all calls to DIFactory::CreateSubprogram, the problem disappears - but then I don’t have any debugging info. (Well, I still have all the DINodes for my data structures, just not functions.) I’ve also commented out all of the declarations of parameters and local variables, which doesn’t prevent the problem from occurring. (Since my current understanding is that CIE and FDE are used to describe the call frame, I’m trying to simplify the problem as much as possible.)
I’ve carefully studied the source code of CGDebugInfo in clang as a working example. One puzzlement is that there’s a discrepancy between what the “source level debugging with LLVM” docs say and what clang does: According to the docs, DW_TAG_formal_parameter is used to specify a formal parameter in a function type descriptor, but according to a code search, the name “DW_TAG_formal_parameter” does not appear anywhere in the clang source code. Instead, the argument array that is used when creating a function type descriptor contains only the bare types, not types wrapped in a formal parameter DIE.
However, since I’ve tried it both ways (wrapped and unwrapped) and the dwarfdump crash occurs either way, this latter issue is of lesser concern.
At the moment I’m experimenting with the parameters to CreateSubprogram, trying every possible permutation of inputs that I can think of in hope of stumbling on the right answer. I can’t think of what else to do.
Note that I am calling assert(diNode.Verify()) on every DINode after it’s created, so I know that it’s valid up to that point at least. However, the checks in Verify() aren’t very extensive. (Also, I’ve observed in the past that it’s kind of inconvenient that Verify() only returns a boolean result when it fails, with no indication of what you did wrong.)
All of this is with the current LLVM head, although I was getting the same problems with the version from about 2 months ago.