This is an archive of the discontinued LLVM Phabricator instance.

Fix the remainder of PR22762 (GDB is crashing on DW_OP_piece being used inside of DW_AT_frame_base)
Needs ReviewPublic

Authored by aprantl on Mar 10 2015, 2:50 PM.

Details

Reviewers
dblaikie
echristo
Summary

http://llvm.org/bugs/show_bug.cgi?id=22762
The symptom was that DW_AT_frame_base should never use a DW_OP_(bit)_piece, the bug was that AddMachineRegPiece incorrectly created pieces to describe values that occupy only a subregister. Change this to emit a bit mask instead.

I'm posting this for review because emitting the bit mask increases the size occupied for DWARF expressions for sub-registers (~5 bytes for a 32-bit subregister). Previously we would (incorrectly!) use DW_OP_piece to describe a value occupying part of a register. However, "DW_OP_piece provides a way of describing how large a part of a variable a particular DWARF location description refers to.", not the size and offset of an entire variable inside a super-register. The way that most debuggers implement DW_OP_piece this sort of works out for subregisters that are at offset 0, but it causes confusion if the expression needs to be composed (such as in DW_AT_frame_base, or if the subregister contains only a part of the variable).

Diff Detail

Event Timeline

aprantl updated this revision to Diff 21641.Mar 10 2015, 2:50 PM
aprantl retitled this revision from to Fix the remainder of PR22762 (GDB is crashing on DW_OP_piece being used inside of DW_AT_frame_base) .
aprantl updated this object.
aprantl edited the test plan for this revision. (Show Details)
aprantl added reviewers: echristo, dblaikie.
aprantl set the repository for this revision to rL LLVM.
aprantl added a subscriber: Unknown Object (MLST).
aprantl updated this revision to Diff 21746.Mar 11 2015, 11:10 AM
aprantl removed rL LLVM as the repository for this revision.

For completeness, here is the updated version that uses DW_OP_piece where it is safe to do so (for subregisters at offset 0). In the end it doesn't actually look all that ugly.

dblaikie added inline comments.Mar 11 2015, 1:23 PM
lib/CodeGen/AsmPrinter/DwarfDebug.cpp
1536–1544

This code looks repetitious (same as the code in addAddress) - should it be wrapped up somewhere?

lib/CodeGen/AsmPrinter/DwarfExpression.cpp
81

Maybe name this flag "MayUsePiece" - I imagine that if GDB has trouble with piece for subregs, it'd have trouble with it for anything else too?

106

Not quite sure what this asciiart is meant to add?

115

I'd phrase this the other way - this comment should just describe the obvious case in the positive "use the shorter encoding if no shifting is required" (paraphrased - those exact words are a bit too brief)

121

This looks like it should be an elseif - since the last line of the previous if block establishes a condition that can't possibly be true for this condition anyway, right?

lib/CodeGen/AsmPrinter/DwarfUnit.cpp
550

Same repetition again

aprantl added inline comments.Mar 11 2015, 2:13 PM
lib/CodeGen/AsmPrinter/DwarfDebug.cpp
1536–1544

Yes absolutely, I intentionally wrote it that way so I could factor out the (now) obvious similarities in an NFC follow-up commit.

lib/CodeGen/AsmPrinter/DwarfExpression.cpp
81

I'm pretty sure we would have heard that by now. Besides, if this was a general flag to disable DW_OP_piece, what condition should it be triggered on: a command line option?

106

Good point, renaming Size -> SubRegSize seems to carry the same information.

115

"Use the shorter DW_OP_piece to describe a subregister at offset 0."

121

Correct.

lib/CodeGen/AsmPrinter/DwarfUnit.cpp
550

I'd like to clean this up in a follow-up commit since this is orthogonal to this bugfix.

aprantl updated this revision to Diff 21877.Mar 12 2015, 2:03 PM

Address remaining comments (sans the refactoring).

Maybe it is specific to x32. When a register is used as frame register,
the upper 32 bits are guaranteed to zero by hardware. We don't need
DW_OP_piece to describe the lower 32 bits of a frame register.

[Just noticed that I forgot to rename MayUsePieceForSubRegMask in DwarfCompileUnit.]

The problem is that the TargetRegisterInfo tells us that the frame register is ebp, for which there is no separate register number, so it must be constructed from rbp. The DWARF backend doesn't know about what is in the upper half of rbp so it must mask out the upper bits.

[Just noticed that I forgot to rename MayUsePieceForSubRegMask in DwarfCompileUnit.]

The problem is that the TargetRegisterInfo tells us that the frame register is ebp, for which there is no separate register number, so it must be constructed from rbp. The DWARF backend doesn't know about what is in the upper half of rbp so it must mask out the upper bits.

Not if ebp is used as frame register. It is OK to use rbp's DWARF register
number to map ebp when ebp is used as frame register.

I think I'm ok with generally disabling DW_OP_piece inside of DW_AT_frame_base, but I would like to avoid putting in a target-specific hack (emitting rbp instead of ebp inside of DW_AT_frame_base) to work around a bug in GDB.