diff options
author | Reid Kleckner <rnk@google.com> | 2016-02-02 17:41:18 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2016-02-02 17:41:18 +0000 |
commit | 1fcd610c9499d8f1eb42f339926ed17ec6d98ddd (patch) | |
tree | b80a02a7939d74d6657ce1523b272f81ea84b403 /llvm/lib/MC/MCCodeView.cpp | |
parent | 7d6b924df841faff6893207044cc57b02464b255 (diff) | |
download | llvm-1fcd610c9499d8f1eb42f339926ed17ec6d98ddd.zip llvm-1fcd610c9499d8f1eb42f339926ed17ec6d98ddd.tar.gz llvm-1fcd610c9499d8f1eb42f339926ed17ec6d98ddd.tar.bz2 |
[codeview] Wire up the .cv_inline_linetable directive
This directive emits the binary annotations that describe line and code
deltas in inlined call sites. Single-stepping through inlined frames in
windbg now works.
llvm-svn: 259535
Diffstat (limited to 'llvm/lib/MC/MCCodeView.cpp')
-rw-r--r-- | llvm/lib/MC/MCCodeView.cpp | 121 |
1 files changed, 96 insertions, 25 deletions
diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp index a876470..ea226f7 100644 --- a/llvm/lib/MC/MCCodeView.cpp +++ b/llvm/lib/MC/MCCodeView.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCCodeView.h" +#include "llvm/MC/MCAsmLayout.h" #include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/Line.h" @@ -226,40 +227,110 @@ static uint32_t encodeSignedNumber(uint32_t Data) { void CodeViewContext::emitInlineLineTableForFunction( MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId, - unsigned SourceLineNum, ArrayRef<unsigned> SecondaryFunctionIds) { - std::vector<MCCVLineEntry> Locs = getFunctionLineEntries(PrimaryFunctionId); - std::vector<std::pair<BinaryAnnotationsOpCode, uint32_t>> Annotations; + unsigned SourceLineNum, const MCSymbol *FnStartSym, + ArrayRef<unsigned> SecondaryFunctionIds) { + // Create and insert a fragment into the current section that will be encoded + // later. + new MCCVInlineLineTableFragment( + PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, + SecondaryFunctionIds, OS.getCurrentSectionOnly()); +} + +unsigned computeLabelDiff(MCAsmLayout &Layout, const MCSymbol *Begin, + const MCSymbol *End) { + MCContext &Ctx = Layout.getAssembler().getContext(); + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + const MCExpr *BeginRef = MCSymbolRefExpr::create(Begin, Variant, Ctx), + *EndRef = MCSymbolRefExpr::create(End, Variant, Ctx); + const MCExpr *AddrDelta = + MCBinaryExpr::create(MCBinaryExpr::Sub, EndRef, BeginRef, Ctx); + int64_t Result; + bool Success = AddrDelta->evaluateKnownAbsolute(Result, Layout); + assert(Success && "failed to evaluate label difference as absolute"); + (void)Success; + assert(Result >= 0 && "negative label difference requested"); + assert(Result < UINT_MAX && "label difference greater than 2GB"); + return unsigned(Result); +} - const MCCVLineEntry *LastLoc = nullptr; - unsigned LastFileId = SourceFileId; - unsigned LastLineNum = SourceLineNum; +void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout, + MCCVInlineLineTableFragment &Frag) { + size_t LocBegin; + size_t LocEnd; + std::tie(LocBegin, LocEnd) = getLineExtent(Frag.SiteFuncId); + for (unsigned SecondaryId : Frag.SecondaryFuncs) { + auto Extent = getLineExtent(SecondaryId); + LocBegin = std::min(LocBegin, Extent.first); + LocEnd = std::max(LocEnd, Extent.second); + } + if (LocBegin >= LocEnd) + return; + ArrayRef<MCCVLineEntry> Locs = getLinesForExtent(LocBegin, LocEnd + 1); + if (Locs.empty()) + return; + SmallSet<unsigned, 8> InlinedFuncIds; + InlinedFuncIds.insert(Frag.SiteFuncId); + InlinedFuncIds.insert(Frag.SecondaryFuncs.begin(), Frag.SecondaryFuncs.end()); + + // Make an artificial start location using the function start and the inlinee + // lines start location information. All deltas start relative to this + // location. + MCCVLineEntry StartLoc(Frag.getFnStartSym(), MCCVLoc(Locs.front())); + StartLoc.setFileNum(Frag.StartFileId); + StartLoc.setLine(Frag.StartLineNum); + const MCCVLineEntry *LastLoc = &StartLoc; + bool WithinFunction = true; + + SmallVectorImpl<char> &Buffer = Frag.getContents(); + Buffer.clear(); // Clear old contents if we went through relaxation. for (const MCCVLineEntry &Loc : Locs) { - if (!LastLoc) { - // TODO ChangeCodeOffset - // TODO ChangeCodeLength + if (!InlinedFuncIds.count(Loc.getFunctionId())) { + // We've hit a cv_loc not attributed to this inline call site. Use this + // label to end the PC range. + if (WithinFunction) { + unsigned Length = + computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel()); + compressAnnotation(ChangeCodeLength, Buffer); + compressAnnotation(Length, Buffer); + } + WithinFunction = false; + continue; } + WithinFunction = true; - if (Loc.getFileNum() != LastFileId) - Annotations.push_back({ChangeFile, Loc.getFileNum()}); + if (Loc.getFileNum() != LastLoc->getFileNum()) { + compressAnnotation(ChangeFile, Buffer); + compressAnnotation(Loc.getFileNum(), Buffer); + } - if (Loc.getLine() != LastLineNum) - Annotations.push_back( - {ChangeLineOffset, encodeSignedNumber(Loc.getLine() - LastLineNum)}); + int LineDelta = Loc.getLine() - LastLoc->getLine(); + if (LineDelta == 0) + continue; + + unsigned EncodedLineDelta = encodeSignedNumber(LineDelta); + unsigned CodeDelta = + computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel()); + if (CodeDelta == 0) { + compressAnnotation(ChangeLineOffset, Buffer); + compressAnnotation(EncodedLineDelta, Buffer); + } else if (EncodedLineDelta < 0x8 && CodeDelta <= 0xf) { + // The ChangeCodeOffsetAndLineOffset combination opcode is used when the + // encoded line delta uses 3 or fewer set bits and the code offset fits + // in one nibble. + unsigned Operand = (EncodedLineDelta << 4) | CodeDelta; + compressAnnotation(ChangeCodeOffsetAndLineOffset, Buffer); + compressAnnotation(Operand, Buffer); + } else { + // Otherwise use the separate line and code deltas. + compressAnnotation(ChangeLineOffset, Buffer); + compressAnnotation(EncodedLineDelta, Buffer); + compressAnnotation(ChangeCodeOffset, Buffer); + compressAnnotation(CodeDelta, Buffer); + } LastLoc = &Loc; - LastFileId = Loc.getFileNum(); - LastLineNum = Loc.getLine(); - } - - SmallString<32> Buffer; - for (auto Annotation : Annotations) { - BinaryAnnotationsOpCode Opcode = Annotation.first; - uint32_t Operand = Annotation.second; - compressAnnotation(Opcode, Buffer); - compressAnnotation(Operand, Buffer); } - OS.EmitBytes(Buffer); } // |