From da60fc813c225209cadbd137ce17b05e993acd8e Mon Sep 17 00:00:00 2001 From: Nilanjana Basu Date: Mon, 5 Aug 2019 14:16:58 +0000 Subject: [PATCH] Changing representation of .cv_def_range directives in Codeview debug info assembly format for better readability llvm-svn: 367867 --- lld/test/COFF/s_udt.s | 6 +- .../SymbolFile/NativePDB/Inputs/s_constant.s | 4 +- .../Plugins/SymbolFile/NativePDB/PdbUtil.cpp | 4 +- .../llvm/DebugInfo/CodeView/SymbolRecord.h | 6 +- llvm/include/llvm/MC/MCStreamer.h | 17 +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 23 +--- llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp | 2 +- .../CodeView/SymbolRecordMapping.cpp | 2 +- llvm/lib/MC/MCAsmStreamer.cpp | 63 ++++++++-- llvm/lib/MC/MCParser/AsmParser.cpp | 116 ++++++++++++++++-- llvm/lib/MC/MCStreamer.cpp | 46 +++++++ llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp | 2 +- llvm/test/DebugInfo/COFF/fp-stack.ll | 2 +- .../test/DebugInfo/COFF/local-variable-gap.ll | 2 +- llvm/test/DebugInfo/COFF/local-variables.ll | 10 +- llvm/test/DebugInfo/COFF/nrvo.ll | 2 +- llvm/test/DebugInfo/COFF/pieces.ll | 18 +-- .../test/DebugInfo/COFF/register-variables.ll | 14 +-- llvm/test/MC/COFF/cv-def-range-align.s | 4 +- llvm/test/MC/COFF/cv-def-range-errors.s | 95 ++++++++++++++ llvm/test/MC/COFF/cv-def-range-gap.s | 4 +- llvm/test/MC/COFF/cv-def-range.s | 2 +- .../llvm-pdbutil/MinimalSymbolDumper.cpp | 5 +- 23 files changed, 376 insertions(+), 73 deletions(-) create mode 100644 llvm/test/MC/COFF/cv-def-range-errors.s diff --git a/lld/test/COFF/s_udt.s b/lld/test/COFF/s_udt.s index 900948aa8b53b7..63e40997095753 100644 --- a/lld/test/COFF/s_udt.s +++ b/lld/test/COFF/s_udt.s @@ -173,7 +173,7 @@ main: # @main .short 1 # Flags .asciz "argc" .Ltmp13: - .cv_def_range .Ltmp0 .Ltmp1, "B\021\f\000\000\000" + .cv_def_range .Ltmp0 .Ltmp1, frame_ptr_rel, 12 .short .Ltmp15-.Ltmp14 # Record length .Ltmp14: .short 4414 # Record kind: S_LOCAL @@ -181,7 +181,7 @@ main: # @main .short 1 # Flags .asciz "argv" .Ltmp15: - .cv_def_range .Ltmp0 .Ltmp1, "B\021\020\000\000\000" + .cv_def_range .Ltmp0 .Ltmp1, frame_ptr_rel, 16 .short .Ltmp17-.Ltmp16 # Record length .Ltmp16: .short 4414 # Record kind: S_LOCAL @@ -189,7 +189,7 @@ main: # @main .short 0 # Flags .asciz "SPtr" .Ltmp17: - .cv_def_range .Ltmp0 .Ltmp1, "B\021\000\000\000\000" + .cv_def_range .Ltmp0 .Ltmp1, frame_ptr_rel, 0 .short .Ltmp19-.Ltmp18 # Record length .Ltmp18: .short 4360 # Record kind: S_UDT diff --git a/lldb/lit/SymbolFile/NativePDB/Inputs/s_constant.s b/lldb/lit/SymbolFile/NativePDB/Inputs/s_constant.s index 553a5ce06dbf03..6eaa80cf850ac3 100644 --- a/lldb/lit/SymbolFile/NativePDB/Inputs/s_constant.s +++ b/lldb/lit/SymbolFile/NativePDB/Inputs/s_constant.s @@ -165,7 +165,7 @@ GlobalSSEC: # @GlobalSSEC .short 1 # Flags .asciz "argc" .Ltmp13: - .cv_def_range .Ltmp0 .Ltmp1, "B\021\004\000\000\000" + .cv_def_range .Ltmp0 .Ltmp1, frame_ptr_rel, 4 .short .Ltmp15-.Ltmp14 # Record length .Ltmp14: .short 4414 # Record kind: S_LOCAL @@ -173,7 +173,7 @@ GlobalSSEC: # @GlobalSSEC .short 1 # Flags .asciz "argv" .Ltmp15: - .cv_def_range .Ltmp0 .Ltmp1, "B\021\b\000\000\000" + .cv_def_range .Ltmp0 .Ltmp1, frame_ptr_rel, 8 .short 2 # Record length .short 4431 # Record kind: S_PROC_ID_END .Ltmp7: diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp index 1f5c97da81cfce..fc047e25a2f40d 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -641,14 +641,14 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo( llvm::StringRef program; if (GetFrameDataProgram(index, ranges, program)) { result.location = - MakeVFrameRelLocationExpression(program, loc.Offset, module); + MakeVFrameRelLocationExpression(program, loc.Hdr.Offset, module); result.ranges = std::move(ranges); } else { // invalid variable } } else { result.location = - MakeRegRelLocationExpression(base_reg, loc.Offset, module); + MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module); result.ranges = std::move(ranges); } } else if (loc_specifier_cvs.kind() == S_DEFRANGE_REGISTER_REL) { diff --git a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h index 5e9a7432b9b6f5..6aa589cf33eb52 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -520,6 +520,10 @@ class DefRangeFramePointerRelSym : public SymbolRecord { static constexpr uint32_t RelocationOffset = 8; public: + struct Header { + little32_t Offset; + }; + explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} DefRangeFramePointerRelSym(uint32_t RecordOffset) @@ -530,7 +534,7 @@ class DefRangeFramePointerRelSym : public SymbolRecord { return RecordOffset + RelocationOffset; } - int32_t Offset; + Header Hdr; LocalVariableAddrRange Range; std::vector Gaps; diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 731e7515448c01..b8943aeb38c21e 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -18,6 +18,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCSymbol.h" @@ -860,6 +861,22 @@ class MCStreamer { ArrayRef> Ranges, StringRef FixedSizePortion); + virtual void EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeRegisterRelSym::Header DRHdr); + + virtual void EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeSubfieldRegisterSym::Header DRHdr); + + virtual void EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeRegisterSym::Header DRHdr); + + virtual void EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeFramePointerRelSym::Header DRHdr); + /// This implements the CodeView '.cv_stringtable' assembler directive. virtual void EmitCVStringTableDirective() {} diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index b3dabca0a8a4e8..ea83646977188f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -2633,17 +2633,6 @@ void CodeViewDebug::emitLocalVariableList(const FunctionInfo &FI, emitLocalVariable(FI, L); } -/// Only call this on endian-specific types like ulittle16_t and little32_t, or -/// structs composed of them. -template -static void copyBytesForDefRange(SmallString<20> &BytePrefix, - SymbolKind SymKind, const T &DefRangeHeader) { - BytePrefix.resize(2 + sizeof(T)); - ulittle16_t SymKindLE = ulittle16_t(SymKind); - memcpy(&BytePrefix[0], &SymKindLE, 2); - memcpy(&BytePrefix[2], &DefRangeHeader, sizeof(T)); -} - void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, const LocalVariable &Var) { // LocalSym record, see SymbolRecord.h for more info. @@ -2692,8 +2681,9 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, (bool(Flags & LocalSymFlags::IsParameter) ? (EncFP == FI.EncodedParamFramePtrReg) : (EncFP == FI.EncodedLocalFramePtrReg))) { - little32_t FPOffset = little32_t(Offset); - copyBytesForDefRange(BytePrefix, S_DEFRANGE_FRAMEPOINTER_REL, FPOffset); + DefRangeFramePointerRelSym::Header DRHdr; + DRHdr.Offset = Offset; + OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); } else { uint16_t RegRelFlags = 0; if (DefRange.IsSubfield) { @@ -2705,7 +2695,7 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, DRHdr.Register = Reg; DRHdr.Flags = RegRelFlags; DRHdr.BasePointerOffset = Offset; - copyBytesForDefRange(BytePrefix, S_DEFRANGE_REGISTER_REL, DRHdr); + OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); } } else { assert(DefRange.DataOffset == 0 && "unexpected offset into register"); @@ -2714,15 +2704,14 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, DRHdr.Register = DefRange.CVRegister; DRHdr.MayHaveNoName = 0; DRHdr.OffsetInParent = DefRange.StructOffset; - copyBytesForDefRange(BytePrefix, S_DEFRANGE_SUBFIELD_REGISTER, DRHdr); + OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); } else { DefRangeRegisterSym::Header DRHdr; DRHdr.Register = DefRange.CVRegister; DRHdr.MayHaveNoName = 0; - copyBytesForDefRange(BytePrefix, S_DEFRANGE_REGISTER, DRHdr); + OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); } } - OS.EmitCVDefRangeDirective(DefRange.Ranges, BytePrefix); } } diff --git a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp index 27cb7e35234b4c..45b63983beb499 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -315,7 +315,7 @@ Error CVSymbolDumperImpl::visitKnownRecord( Error CVSymbolDumperImpl::visitKnownRecord( CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { - W.printNumber("Offset", DefRangeFramePointerRel.Offset); + W.printNumber("Offset", DefRangeFramePointerRel.Hdr.Offset); printLocalVariableAddrRange(DefRangeFramePointerRel.Range, DefRangeFramePointerRel.getRelocationOffset()); printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps); diff --git a/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp index 70889839ef4861..3b627930e27167 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -229,7 +229,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, DataSym &Data) { Error SymbolRecordMapping::visitKnownRecord( CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { - error(IO.mapInteger(DefRangeFramePointerRel.Offset)); + error(IO.mapObject(DefRangeFramePointerRel.Hdr.Offset)); error(mapLocalVariableAddrRange(IO, DefRangeFramePointerRel.Range)); error(IO.mapVectorTail(DefRangeFramePointerRel.Gaps, MapGap())); diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 7a2b0b8a12207a..c0890b59fe3209 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -254,9 +254,26 @@ class MCAsmStreamer final : public MCStreamer { unsigned SourceLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) override; + + void PrintCVDefRangePrefix( + ArrayRef> Ranges); + + void EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeRegisterRelSym::Header DRHdr) override; + void EmitCVDefRangeDirective( ArrayRef> Ranges, - StringRef FixedSizePortion) override; + codeview::DefRangeSubfieldRegisterSym::Header DRHdr) override; + + void EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeRegisterSym::Header DRHdr) override; + + void EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeFramePointerRelSym::Header DRHdr) override; + void EmitCVStringTableDirective() override; void EmitCVFileChecksumsDirective() override; void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override; @@ -1376,9 +1393,8 @@ void MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym); } -void MCAsmStreamer::EmitCVDefRangeDirective( - ArrayRef> Ranges, - StringRef FixedSizePortion) { +void MCAsmStreamer::PrintCVDefRangePrefix( + ArrayRef> Ranges) { OS << "\t.cv_def_range\t"; for (std::pair Range : Ranges) { OS << ' '; @@ -1386,10 +1402,43 @@ void MCAsmStreamer::EmitCVDefRangeDirective( OS << ' '; Range.second->print(OS, MAI); } - OS << ", "; - PrintQuotedString(FixedSizePortion, OS); +} + +void MCAsmStreamer::EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeRegisterRelSym::Header DRHdr) { + PrintCVDefRangePrefix(Ranges); + OS << ", reg_rel, "; + OS << DRHdr.Register << ", " << DRHdr.Flags << ", " + << DRHdr.BasePointerOffset; + EmitEOL(); +} + +void MCAsmStreamer::EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeSubfieldRegisterSym::Header DRHdr) { + PrintCVDefRangePrefix(Ranges); + OS << ", subfield_reg, "; + OS << DRHdr.Register << ", " << DRHdr.OffsetInParent; + EmitEOL(); +} + +void MCAsmStreamer::EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeRegisterSym::Header DRHdr) { + PrintCVDefRangePrefix(Ranges); + OS << ", reg, "; + OS << DRHdr.Register; + EmitEOL(); +} + +void MCAsmStreamer::EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeFramePointerRelSym::Header DRHdr) { + PrintCVDefRangePrefix(Ranges); + OS << ", frame_ptr_rel, "; + OS << DRHdr.Offset; EmitEOL(); - this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion); } void MCAsmStreamer::EmitCVStringTableDirective() { diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 084f6a7a2e1414..a3d6014dc31f21 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -524,6 +524,19 @@ class AsmParser : public MCAsmParser { /// directives parsed by this class. StringMap DirectiveKindMap; + // Codeview def_range type parsing. + enum CVDefRangeType { + CVDR_DEFRANGE = 0, // Placeholder + CVDR_DEFRANGE_REGISTER, + CVDR_DEFRANGE_FRAMEPOINTER_REL, + CVDR_DEFRANGE_SUBFIELD_REGISTER, + CVDR_DEFRANGE_REGISTER_REL + }; + + /// Maps Codeview def_range types --> CVDefRangeType enum, for + /// Codeview def_range types parsed by this class. + StringMap CVDefRangeTypeMap; + // ".ascii", ".asciz", ".string" bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated); bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc" @@ -671,6 +684,7 @@ class AsmParser : public MCAsmParser { bool parseDirectiveAddrsigSym(); void initializeDirectiveKindMap(); + void initializeCVDefRangeTypeMap(); }; } // end anonymous namespace @@ -720,6 +734,7 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, PlatformParser->Initialize(*this); initializeDirectiveKindMap(); + initializeCVDefRangeTypeMap(); NumOfMacroInstantiations = 0; } @@ -1737,6 +1752,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, StringMap::const_iterator DirKindIt = DirectiveKindMap.find(IDVal); DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end()) + ? DK_NO_DIRECTIVE : DirKindIt->getValue(); switch (DirKind) { @@ -3825,6 +3841,13 @@ bool AsmParser::parseDirectiveCVInlineLinetable() { return false; } +void AsmParser::initializeCVDefRangeTypeMap() { + CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER; + CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL; + CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER; + CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL; +} + /// parseDirectiveCVDefRange /// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes* bool AsmParser::parseDirectiveCVDefRange() { @@ -3846,13 +3869,92 @@ bool AsmParser::parseDirectiveCVDefRange() { Ranges.push_back({GapStartSym, GapEndSym}); } - std::string FixedSizePortion; - if (parseToken(AsmToken::Comma, "unexpected token in directive") || - parseEscapedString(FixedSizePortion)) - return true; - - getStreamer().EmitCVDefRangeDirective(Ranges, FixedSizePortion); - return false; + StringRef CVDefRangeTypeStr; + if (parseToken( + AsmToken::Comma, + "expected comma before def_range type in .cv_def_range directive") || + parseIdentifier(CVDefRangeTypeStr)) + return Error(Loc, "expected def_range type in directive"); + + StringMap::const_iterator CVTypeIt = + CVDefRangeTypeMap.find(CVDefRangeTypeStr); + CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end()) + ? CVDR_DEFRANGE + : CVTypeIt->getValue(); + switch (CVDRType) { + case CVDR_DEFRANGE_REGISTER: { + int64_t DRRegister; + if (parseToken(AsmToken::Comma, "expected comma before register number in " + ".cv_def_range directive") || + parseAbsoluteExpression(DRRegister)) + return Error(Loc, "expected register number"); + + codeview::DefRangeRegisterSym::Header DRHdr; + DRHdr.Register = DRRegister; + DRHdr.MayHaveNoName = 0; + getStreamer().EmitCVDefRangeDirective(Ranges, DRHdr); + break; + } + case CVDR_DEFRANGE_FRAMEPOINTER_REL: { + int64_t DROffset; + if (parseToken(AsmToken::Comma, + "expected comma before offset in .cv_def_range directive") || + parseAbsoluteExpression(DROffset)) + return Error(Loc, "expected offset value"); + + codeview::DefRangeFramePointerRelSym::Header DRHdr; + DRHdr.Offset = DROffset; + getStreamer().EmitCVDefRangeDirective(Ranges, DRHdr); + break; + } + case CVDR_DEFRANGE_SUBFIELD_REGISTER: { + int64_t DRRegister; + int64_t DROffsetInParent; + if (parseToken(AsmToken::Comma, "expected comma before register number in " + ".cv_def_range directive") || + parseAbsoluteExpression(DRRegister)) + return Error(Loc, "expected register number"); + if (parseToken(AsmToken::Comma, + "expected comma before offset in .cv_def_range directive") || + parseAbsoluteExpression(DROffsetInParent)) + return Error(Loc, "expected offset value"); + + codeview::DefRangeSubfieldRegisterSym::Header DRHdr; + DRHdr.Register = DRRegister; + DRHdr.MayHaveNoName = 0; + DRHdr.OffsetInParent = DROffsetInParent; + getStreamer().EmitCVDefRangeDirective(Ranges, DRHdr); + break; + } + case CVDR_DEFRANGE_REGISTER_REL: { + int64_t DRRegister; + int64_t DRFlags; + int64_t DRBasePointerOffset; + if (parseToken(AsmToken::Comma, "expected comma before register number in " + ".cv_def_range directive") || + parseAbsoluteExpression(DRRegister)) + return Error(Loc, "expected register value"); + if (parseToken( + AsmToken::Comma, + "expected comma before flag value in .cv_def_range directive") || + parseAbsoluteExpression(DRFlags)) + return Error(Loc, "expected flag value"); + if (parseToken(AsmToken::Comma, "expected comma before base pointer offset " + "in .cv_def_range directive") || + parseAbsoluteExpression(DRBasePointerOffset)) + return Error(Loc, "expected base pointer offset value"); + + codeview::DefRangeRegisterRelSym::Header DRHdr; + DRHdr.Register = DRRegister; + DRHdr.Flags = DRFlags; + DRHdr.BasePointerOffset = DRBasePointerOffset; + getStreamer().EmitCVDefRangeDirective(Ranges, DRHdr); + break; + } + default: + return Error(Loc, "unexpected def_range type in .cv_def_range directive"); + } + return true; } /// parseDirectiveCVString diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index decbb96817e3ac..254eb2cd7b6dfe 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -327,10 +327,56 @@ void MCStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {} +/// Only call this on endian-specific types like ulittle16_t and little32_t, or +/// structs composed of them. +template +static void copyBytesForDefRange(SmallString<20> &BytePrefix, + codeview::SymbolKind SymKind, + const T &DefRangeHeader) { + BytePrefix.resize(2 + sizeof(T)); + codeview::ulittle16_t SymKindLE = codeview::ulittle16_t(SymKind); + memcpy(&BytePrefix[0], &SymKindLE, 2); + memcpy(&BytePrefix[2], &DefRangeHeader, sizeof(T)); +} + void MCStreamer::EmitCVDefRangeDirective( ArrayRef> Ranges, StringRef FixedSizePortion) {} +void MCStreamer::EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeRegisterRelSym::Header DRHdr) { + SmallString<20> BytePrefix; + copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_REGISTER_REL, DRHdr); + EmitCVDefRangeDirective(Ranges, BytePrefix); +} + +void MCStreamer::EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeSubfieldRegisterSym::Header DRHdr) { + SmallString<20> BytePrefix; + copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_SUBFIELD_REGISTER, + DRHdr); + EmitCVDefRangeDirective(Ranges, BytePrefix); +} + +void MCStreamer::EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeRegisterSym::Header DRHdr) { + SmallString<20> BytePrefix; + copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_REGISTER, DRHdr); + EmitCVDefRangeDirective(Ranges, BytePrefix); +} + +void MCStreamer::EmitCVDefRangeDirective( + ArrayRef> Ranges, + codeview::DefRangeFramePointerRelSym::Header DRHdr) { + SmallString<20> BytePrefix; + copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_FRAMEPOINTER_REL, + DRHdr); + EmitCVDefRangeDirective(Ranges, BytePrefix); +} + void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) { } diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp index 227107c051ddc2..95409fdc3300bb 100644 --- a/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp +++ b/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp @@ -391,7 +391,7 @@ template <> void SymbolRecordImpl::map(IO &IO) { } template <> void SymbolRecordImpl::map(IO &IO) { - IO.mapRequired("Offset", Symbol.Offset); + IO.mapRequired("Offset", Symbol.Hdr.Offset); IO.mapRequired("Range", Symbol.Range); IO.mapRequired("Gaps", Symbol.Gaps); } diff --git a/llvm/test/DebugInfo/COFF/fp-stack.ll b/llvm/test/DebugInfo/COFF/fp-stack.ll index e9b031d6602064..7587b8984cc247 100644 --- a/llvm/test/DebugInfo/COFF/fp-stack.ll +++ b/llvm/test/DebugInfo/COFF/fp-stack.ll @@ -10,7 +10,7 @@ entry: ret double %sub } -; ASM: .cv_def_range Ltmp1 Lfunc_end0, "A\021\200\000\000\000" +; ASM: .cv_def_range Ltmp1 Lfunc_end0, reg, 128 ; OBJ: DefRangeRegisterSym { ; OBJ: Register: ST0 (0x80) ; OBJ: MayHaveNoName: 0 diff --git a/llvm/test/DebugInfo/COFF/local-variable-gap.ll b/llvm/test/DebugInfo/COFF/local-variable-gap.ll index b7c69a65c899e7..db8de6327392a3 100644 --- a/llvm/test/DebugInfo/COFF/local-variable-gap.ll +++ b/llvm/test/DebugInfo/COFF/local-variable-gap.ll @@ -62,7 +62,7 @@ ; ASM: .long 116 # TypeIndex ; ASM: .short 0 # Flags ; ASM: .asciz "p" -; ASM: .cv_def_range [[p_b1]] [[p_e1]] [[p_b2]] .Lfunc_end0, "A\021\027\000\000\000" +; ASM: .cv_def_range [[p_b1]] [[p_e1]] [[p_b2]] .Lfunc_end0, reg, 23 ; ASM: .short 2 # Record length ; ASM: .short 4431 # Record kind: S_PROC_ID_END diff --git a/llvm/test/DebugInfo/COFF/local-variables.ll b/llvm/test/DebugInfo/COFF/local-variables.ll index 5b00383e5393b9..e15152050d811b 100644 --- a/llvm/test/DebugInfo/COFF/local-variables.ll +++ b/llvm/test/DebugInfo/COFF/local-variables.ll @@ -71,30 +71,30 @@ ; ASM: .long 116 # TypeIndex ; ASM: .short 1 # Flags ; ASM: .asciz "param" -; ASM: .cv_def_range [[prologue_end]] [[param_end]], "B\0214\000\000\000" +; ASM: .cv_def_range [[prologue_end]] [[param_end]], frame_ptr_rel, 52 ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .long 116 # TypeIndex ; ASM: .short 0 # Flags ; ASM: .asciz "a" -; ASM: .cv_def_range [[if_start]] [[else_start]], "B\021(\000\000\000" +; ASM: .cv_def_range [[if_start]] [[else_start]], frame_ptr_rel, 40 ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .long 116 # TypeIndex ; ASM: .short 0 # Flags ; ASM: .asciz "b" -; ASM: .cv_def_range [[else_start]] [[else_end]], "B\021$\000\000\000" +; ASM: .cv_def_range [[else_start]] [[else_end]], frame_ptr_rel, 36 ; ASM: .short 4429 # Record kind: S_INLINESITE ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .long 116 # TypeIndex ; ASM: .short 0 # Flags ; ASM: .asciz "v" -; ASM: .cv_def_range [[inline_site1]] [[else_start]], "B\021,\000\000\000" +; ASM: .cv_def_range [[inline_site1]] [[else_start]], frame_ptr_rel, 44 ; ASM: .short 4430 # Record kind: S_INLINESITE_END ; ASM: .short 4429 # Record kind: S_INLINESITE ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .long 116 # TypeIndex ; ASM: .short 0 # Flags ; ASM: .asciz "v" -; ASM: .cv_def_range [[inline_site2]] [[else_end]], "B\0210\000\000\000" +; ASM: .cv_def_range [[inline_site2]] [[else_end]], frame_ptr_rel, 48 ; ASM: .short 4430 # Record kind: S_INLINESITE_END ; OBJ: Subsection [ diff --git a/llvm/test/DebugInfo/COFF/nrvo.ll b/llvm/test/DebugInfo/COFF/nrvo.ll index f4b7ebfe8170ae..e01cbe6e6672fb 100644 --- a/llvm/test/DebugInfo/COFF/nrvo.ll +++ b/llvm/test/DebugInfo/COFF/nrvo.ll @@ -28,7 +28,7 @@ ; ASM-NEXT: .asciz "foo" ; ASM-NEXT: .p2align 2 ; ASM-NEXT: .Ltmp -; ASM: .cv_def_range .Ltmp{{.*}} .Ltmp{{.*}}, "B\021(\000\000\000" +; ASM: .cv_def_range .Ltmp{{.*}} .Ltmp{{.*}}, frame_ptr_rel, 40 ; OBJ: Subsection [ ; OBJ: SubSectionType: Symbols (0xF1) diff --git a/llvm/test/DebugInfo/COFF/pieces.ll b/llvm/test/DebugInfo/COFF/pieces.ll index 2ca07aa4f5a0af..f864931a290098 100644 --- a/llvm/test/DebugInfo/COFF/pieces.ll +++ b/llvm/test/DebugInfo/COFF/pieces.ll @@ -113,10 +113,10 @@ ; ASM: .asciz "loop_csr" # Function name ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "o" -; ASM: .cv_def_range [[oy_ox_start]] [[ox_start]], "C\021\030\000\000\000\000\000\000\000" -; ASM: .cv_def_range [[oy_ox_start]] [[oy_start]], "C\021\027\000\000\000\004\000\000\000" -; ASM: .cv_def_range [[ox_start]] [[loopskip_start]], "C\021\030\000\000\000\000\000\000\000" -; ASM: .cv_def_range [[oy_start]] [[loopskip_start]], "C\021\027\000\000\000\004\000\000\000" +; ASM: .cv_def_range [[oy_ox_start]] [[ox_start]], subfield_reg, 24, 0 +; ASM: .cv_def_range [[oy_ox_start]] [[oy_start]], subfield_reg, 23, 4 +; ASM: .cv_def_range [[ox_start]] [[loopskip_start]], subfield_reg, 24, 0 +; ASM: .cv_def_range [[oy_start]] [[loopskip_start]], subfield_reg, 23, 4 ; OBJ-LABEL: GlobalProcIdSym { @@ -147,7 +147,7 @@ ; ASM: .asciz "pad_right" # Function name ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "o" -; ASM: .cv_def_range [[pad_right_tmp]] [[pad_right_tmp]], "C\021\021\000\000\000\004\000\000\000" +; ASM: .cv_def_range [[pad_right_tmp]] [[pad_right_tmp]], subfield_reg, 17, 4 ; OBJ-LABEL: GlobalProcIdSym { ; OBJ: Kind: S_GPROC32_ID (0x1147) @@ -170,7 +170,7 @@ ; ASM: .asciz "pad_left" # Function name ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "o" -; ASM: .cv_def_range [[pad_left_tmp]] [[pad_left_tmp]], "C\021\021\000\000\000\000\000\000\000" +; ASM: .cv_def_range [[pad_left_tmp]] [[pad_left_tmp]], subfield_reg, 17, 0 ; OBJ-LABEL: GlobalProcIdSym { ; OBJ: Kind: S_GPROC32_ID (0x1147) @@ -193,10 +193,10 @@ ; ASM: .asciz "nested" # Function name ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "o" -; ASM: .cv_def_range .Lfunc_begin3 .Lfunc_end3, "E\021J\001\000\000\000\000\000\000" +; ASM: .cv_def_range .Lfunc_begin3 .Lfunc_end3, reg_rel, 330, 0, 0 ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "p" -; ASM: .cv_def_range [[p_start]] .Lfunc_end3, "C\021\021\000\000\000\004\000\000\000" +; ASM: .cv_def_range [[p_start]] .Lfunc_end3, subfield_reg, 17, 4 ; OBJ-LABEL: GlobalProcIdSym { ; OBJ: Kind: S_GPROC32_ID (0x1147) @@ -232,7 +232,7 @@ ; ASM: .asciz "bitpiece_spill" # Function name ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "o" -; ASM: .cv_def_range [[spill_o_x_start]] .Lfunc_end4, "E\021O\001A\000$\000\000\000" +; ASM: .cv_def_range [[spill_o_x_start]] .Lfunc_end4, reg_rel, 335, 65, 36 ; OBJ-LABEL: GlobalProcIdSym { ; OBJ: Kind: S_GPROC32_ID (0x1147) diff --git a/llvm/test/DebugInfo/COFF/register-variables.ll b/llvm/test/DebugInfo/COFF/register-variables.ll index d0a0d27fda046a..e67c62a7c5b929 100644 --- a/llvm/test/DebugInfo/COFF/register-variables.ll +++ b/llvm/test/DebugInfo/COFF/register-variables.ll @@ -58,25 +58,25 @@ ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "p" -; ASM: .cv_def_range .Lfunc_begin0 [[p_ecx_esi]], "A\021\022\000\000\000" -; ASM: .cv_def_range [[p_ecx_esi]] [[func_end]], "A\021\027\000\000\000" +; ASM: .cv_def_range .Lfunc_begin0 [[p_ecx_esi]], reg, 18 +; ASM: .cv_def_range [[p_ecx_esi]] [[func_end]], reg, 23 ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "c" -; ASM: .cv_def_range [[after_getint]] [[after_je]], "A\021\021\000\000\000" +; ASM: .cv_def_range [[after_getint]] [[after_je]], reg, 17 ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "a" -; ASM: .cv_def_range [[after_getint]] [[after_inc_eax]], "A\021\021\000\000\000" +; ASM: .cv_def_range [[after_getint]] [[after_inc_eax]], reg, 17 ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "b" -; ASM: .cv_def_range [[after_inc_eax]] [[after_if]], "A\021\021\000\000\000" +; ASM: .cv_def_range [[after_inc_eax]] [[after_if]], reg, 17 ; ASM: .short 4429 # Record kind: S_INLINESITE ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "a" -; ASM: .cv_def_range [[after_getint]] [[after_inc_eax]], "A\021\021\000\000\000" +; ASM: .cv_def_range [[after_getint]] [[after_inc_eax]], reg, 17 ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "b" -; ASM: .cv_def_range [[after_inc_eax]] [[after_if]], "A\021\021\000\000\000" +; ASM: .cv_def_range [[after_inc_eax]] [[after_if]], reg, 17 ; ASM: .short 4430 # Record kind: S_INLINESITE_END ; OBJ: Subsection [ diff --git a/llvm/test/MC/COFF/cv-def-range-align.s b/llvm/test/MC/COFF/cv-def-range-align.s index 57bd3bf2af547c..2b6c18ad346b06 100644 --- a/llvm/test/MC/COFF/cv-def-range-align.s +++ b/llvm/test/MC/COFF/cv-def-range-align.s @@ -97,7 +97,7 @@ max: # @max # BUG .p2align 2 .Ltmp13: - .cv_def_range .Ltmp0 .Ltmp1, "B\021\000\000\000\000" + .cv_def_range .Ltmp0 .Ltmp1, frame_ptr_rel, 8 .short .Ltmp15-.Ltmp14 # Record length .Ltmp14: .short 4414 # Record kind: S_LOCAL @@ -107,7 +107,7 @@ max: # @max # BUG .p2align 2 .Ltmp15: - .cv_def_range .Ltmp0 .Ltmp1, "B\021\004\000\000\000" + .cv_def_range .Ltmp0 .Ltmp1, frame_ptr_rel, 8 .short 2 # Record length .short 4431 # Record kind: S_PROC_ID_END .Ltmp7: diff --git a/llvm/test/MC/COFF/cv-def-range-errors.s b/llvm/test/MC/COFF/cv-def-range-errors.s new file mode 100644 index 00000000000000..1529bd16815442 --- /dev/null +++ b/llvm/test/MC/COFF/cv-def-range-errors.s @@ -0,0 +1,95 @@ +# RUN: not llvm-mc < %s -filetype=obj --triple=x86_64-windows -o /dev/null 2>&1 | FileCheck %s + +.cv_def_range .Ltmp1 .Ltmp2 +# CHECK: error: expected comma before def_range type in .cv_def_range directive +# CHECK: error: expected def_range type in directive + +.cv_def_range .Ltmp1 .Ltmp2, +# CHECK: error: expected def_range type in directive + +.cv_def_range .Ltmp1 .Ltmp2, subfield_reg +# CHECK: error: expected comma before register number in .cv_def_range directive +# CHECK: error: expected register number + +.cv_def_range .Ltmp1 .Ltmp2, subfield_reg, +# CHECK: error: unknown token in expression +# CHECK: error: expected register number + +.cv_def_range .Ltmp1 .Ltmp2, subfield_reg, 25 +# CHECK: error: expected comma before offset in .cv_def_range directive +# CHECK: error: expected offset value + +.cv_def_range .Ltmp1 .Ltmp2, subfield_reg, 25, +# CHECK: error: unknown token in expression +# CHECK: error: expected offset value + + + + +.cv_def_range .Ltmp1 .Ltmp2 +# CHECK: error: expected comma before def_range type in .cv_def_range directive +# CHECK: error: expected def_range type in directive + +.cv_def_range .Ltmp1 .Ltmp2, +# CHECK: error: expected def_range type in directive + +.cv_def_range .Ltmp1 .Ltmp2, reg +# CHECK: error: expected comma before register number in .cv_def_range directive +# CHECK: error: expected register number + +.cv_def_range .Ltmp1 .Ltmp2, reg, +# CHECK: error: unknown token in expression +# CHECK: error: expected register number + + + + +.cv_def_range .Ltmp1 .Ltmp2 +# CHECK: error: expected comma before def_range type in .cv_def_range directive +# CHECK: error: expected def_range type in directive + +.cv_def_range .Ltmp1 .Ltmp2, +# CHECK: error: expected def_range type in directive + +.cv_def_range .Ltmp1 .Ltmp2, frame_ptr_rel +# CHECK: error: expected comma before offset in .cv_def_range directive +# CHECK: error: expected offset value + +.cv_def_range .Ltmp1 .Ltmp2, frame_ptr_rel, +# CHECK: error: unknown token in expression +# CHECK: error: expected offset value + + + + + +.cv_def_range .Ltmp1 .Ltmp2 +# CHECK: error: expected comma before def_range type in .cv_def_range directive +# CHECK: error: expected def_range type in directive + +.cv_def_range .Ltmp1 .Ltmp2, +# CHECK: error: expected def_range type in directive + +.cv_def_range .Ltmp1 .Ltmp2, reg_rel +# CHECK: error: expected comma before register number in .cv_def_range directive +# CHECK: error: expected register value + +.cv_def_range .Ltmp1 .Ltmp2, reg_rel, +# CHECK: error: unknown token in expression +# CHECK: error: expected register value + +.cv_def_range .Ltmp1 .Ltmp2, reg_rel, 330 +# CHECK: error: expected comma before flag value in .cv_def_range directive +# CHECK: error: expected flag value + +.cv_def_range .Ltmp1 .Ltmp2, reg_rel, 330, +# CHECK: error: unknown token in expression +# CHECK: error: expected flag value + +.cv_def_range .Ltmp1 .Ltmp2, reg_rel, 330, 0 +# CHECK: error: expected comma before base pointer offset in .cv_def_range directive +# CHECK: error: expected base pointer offset value + +.cv_def_range .Ltmp1 .Ltmp2, reg_rel, 330, 0, +# CHECK: error: unknown token in expression +# CHECK: error: expected base pointer offset value diff --git a/llvm/test/MC/COFF/cv-def-range-gap.s b/llvm/test/MC/COFF/cv-def-range-gap.s index 877eaeef7e445d..1e3703a02a9077 100644 --- a/llvm/test/MC/COFF/cv-def-range-gap.s +++ b/llvm/test/MC/COFF/cv-def-range-gap.s @@ -120,8 +120,8 @@ f: # @f .short 0 # Flags .asciz "p" .Ltmp19: - .cv_def_range .Lbegin0 .Lend0 .Lbegin1 .Lend1 .Lbegin2 .Lend2 .Lbegin3 .Lend3, "A\021\027\000\000\000" - .cv_def_range .Lbegin4 .Lend4 .Lbegin5 .Lend5, "A\021\027\000\000\000" + .cv_def_range .Lbegin0 .Lend0 .Lbegin1 .Lend1 .Lbegin2 .Lend2 .Lbegin3 .Lend3, reg, 23 + .cv_def_range .Lbegin4 .Lend4 .Lbegin5 .Lend5, reg, 23 .short 2 # Record length .short 4431 # Record kind: S_PROC_ID_END .Ltmp15: diff --git a/llvm/test/MC/COFF/cv-def-range.s b/llvm/test/MC/COFF/cv-def-range.s index cbd62f3fe3bd29..7ce2e5fb455fff 100644 --- a/llvm/test/MC/COFF/cv-def-range.s +++ b/llvm/test/MC/COFF/cv-def-range.s @@ -75,7 +75,7 @@ Ltmp2: Ltmp3: .short 2 # Record length .short 4431 # Record kind: S_PROC_ID_END - .cv_def_range Lvar_begin0 Lvar_end0, "\102\021\374\377\377\377" + .cv_def_range Lvar_begin0 Lvar_end0, frame_ptr_rel, -4 # CHECK: DefRangeFramePointerRelSym { # CHECK: Offset: -4 diff --git a/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp b/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp index e5ae47050678d0..ebfa50625e767e 100644 --- a/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp +++ b/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp @@ -569,8 +569,9 @@ Error MinimalSymbolDumper::visitKnownRecord( Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, DefRangeFramePointerRelSym &Def) { AutoIndent Indent(P, 7); - P.formatLine("offset = {0}, range = {1}", Def.Offset, formatRange(Def.Range)); - P.formatLine("gaps = {2}", Def.Offset, + P.formatLine("offset = {0}, range = {1}", Def.Hdr.Offset, + formatRange(Def.Range)); + P.formatLine("gaps = {2}", Def.Hdr.Offset, formatGaps(P.getIndentLevel() + 9, Def.Gaps)); return Error::success(); }