diff options
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 113 |
1 files changed, 81 insertions, 32 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 7bded31271a..032f611f20e 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -182,6 +182,7 @@ void CodeViewDebug::endModule() { assert(Asm != nullptr); Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getCOFFDebugSymbolsSection()); + Asm->OutStreamer->AddComment("Debug section magic"); Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC); // The COFF .debug$S section consists of several subsections, each starting @@ -207,14 +208,11 @@ void CodeViewDebug::endModule() { clear(); } -template <typename T> static void emitRecord(MCStreamer &OS, const T &Rec) { - OS.EmitBytes(StringRef(reinterpret_cast<const char *>(&Rec), sizeof(Rec))); -} - void CodeViewDebug::emitTypeInformation() { // Start the .debug$T section with 0x4. Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getCOFFDebugTypesSection()); + Asm->OutStreamer->AddComment("Debug section magic"); Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC); NamedMDNode *CU_Nodes = @@ -226,34 +224,49 @@ void CodeViewDebug::emitTypeInformation() { // frame info. All functions are assigned a simple 'void ()' type. Emit that // type here. TypeIndex ArgListIdx = getNextTypeIndex(); + Asm->OutStreamer->AddComment("Type record length"); Asm->EmitInt16(2 + sizeof(ArgList)); + Asm->OutStreamer->AddComment("Leaf type: LF_ARGLIST"); Asm->EmitInt16(LF_ARGLIST); + Asm->OutStreamer->AddComment("Number of arguments"); Asm->EmitInt32(0); TypeIndex VoidProcIdx = getNextTypeIndex(); + Asm->OutStreamer->AddComment("Type record length"); Asm->EmitInt16(2 + sizeof(ProcedureType)); + Asm->OutStreamer->AddComment("Leaf type: LF_PROCEDURE"); Asm->EmitInt16(LF_PROCEDURE); - ProcedureType Proc{}; // Zero initialize. - Proc.ReturnType = TypeIndex::Void(); - Proc.CallConv = CallingConvention::NearC; - Proc.Options = FunctionOptions::None; - Proc.NumParameters = 0; - Proc.ArgListType = ArgListIdx; - emitRecord(*Asm->OutStreamer, Proc); + Asm->OutStreamer->AddComment("Return type index"); + Asm->EmitInt32(TypeIndex::Void().getIndex()); + Asm->OutStreamer->AddComment("Calling convention"); + Asm->EmitInt8(char(CallingConvention::NearC)); + Asm->OutStreamer->AddComment("Function options"); + Asm->EmitInt8(char(FunctionOptions::None)); + Asm->OutStreamer->AddComment("# of parameters"); + Asm->EmitInt16(0); + Asm->OutStreamer->AddComment("Argument list type index"); + Asm->EmitInt32(ArgListIdx.getIndex()); for (MDNode *N : CU_Nodes->operands()) { auto *CUNode = cast<DICompileUnit>(N); for (auto *SP : CUNode->getSubprograms()) { StringRef DisplayName = SP->getDisplayName(); + Asm->OutStreamer->AddComment("Type record length"); Asm->EmitInt16(2 + sizeof(FuncId) + DisplayName.size() + 1); + Asm->OutStreamer->AddComment("Leaf type: LF_FUNC_ID"); Asm->EmitInt16(LF_FUNC_ID); - FuncId Func{}; // Zero initialize. - Func.ParentScope = TypeIndex(); - Func.FunctionType = VoidProcIdx; - emitRecord(*Asm->OutStreamer, Func); - Asm->OutStreamer->EmitBytes(DisplayName); - Asm->EmitInt8(0); + Asm->OutStreamer->AddComment("Scope type index"); + Asm->EmitInt32(TypeIndex().getIndex()); + Asm->OutStreamer->AddComment("Function type"); + Asm->EmitInt32(VoidProcIdx.getIndex()); + { + SmallString<32> NullTerminatedString(DisplayName); + if (NullTerminatedString.empty() || NullTerminatedString.back() != '\0') + NullTerminatedString.push_back('\0'); + Asm->OutStreamer->AddComment("Function name"); + Asm->OutStreamer->EmitBytes(NullTerminatedString); + } TypeIndex FuncIdIdx = getNextTypeIndex(); SubprogramToFuncId.insert(std::make_pair(SP, FuncIdIdx)); @@ -271,23 +284,30 @@ void CodeViewDebug::emitInlineeLinesSubsection() { OS.AddComment("Inlinee lines subsection"); OS.EmitIntValue(unsigned(ModuleSubstreamKind::InlineeLines), 4); + OS.AddComment("Subsection size"); OS.emitAbsoluteSymbolDiff(InlineEnd, InlineBegin, 4); OS.EmitLabel(InlineBegin); // We don't provide any extra file info. // FIXME: Find out if debuggers use this info. + OS.AddComment("Inlinee lines signature"); OS.EmitIntValue(unsigned(InlineeLinesSignature::Normal), 4); for (const DISubprogram *SP : InlinedSubprograms) { + OS.AddBlankLine(); TypeIndex TypeId = SubprogramToFuncId[SP]; unsigned FileId = maybeRecordFile(SP->getFile()); OS.AddComment("Inlined function " + SP->getDisplayName() + " starts at " + SP->getFilename() + Twine(':') + Twine(SP->getLine())); + OS.AddBlankLine(); // The filechecksum table uses 8 byte entries for now, and file ids start at // 1. unsigned FileOffset = (FileId - 1) * 8; + OS.AddComment("Type index of inlined function"); OS.EmitIntValue(TypeId.getIndex(), 4); + OS.AddComment("Offset into filechecksum table"); OS.EmitIntValue(FileOffset, 4); + OS.AddComment("Starting line number"); OS.EmitIntValue(SP->getLine(), 4); } @@ -330,14 +350,18 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI, TypeIndex InlineeIdx = SubprogramToFuncId[Site.Inlinee]; // SymbolRecord + Asm->OutStreamer->AddComment("Record length"); EmitLabelDiff(OS, InlineBegin, InlineEnd, 2); // RecordLength OS.EmitLabel(InlineBegin); + Asm->OutStreamer->AddComment("Record kind: S_INLINESITE"); Asm->EmitInt16(SymbolRecordKind::S_INLINESITE); // RecordKind - InlineSiteSym SiteBytes{}; - SiteBytes.Inlinee = InlineeIdx; - Asm->OutStreamer->EmitBytes( - StringRef(reinterpret_cast<const char *>(&SiteBytes), sizeof(SiteBytes))); + Asm->OutStreamer->AddComment("PtrParent"); + Asm->OutStreamer->EmitIntValue(0, 4); + Asm->OutStreamer->AddComment("PtrEnd"); + Asm->OutStreamer->EmitIntValue(0, 4); + Asm->OutStreamer->AddComment("Inlinee type index"); + Asm->EmitInt32(InlineeIdx.getIndex()); unsigned FileId = maybeRecordFile(Site.Inlinee->getFile()); unsigned StartLineNum = Site.Inlinee->getLine(); @@ -358,7 +382,9 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI, } // Close the scope. + Asm->OutStreamer->AddComment("Record length"); Asm->EmitInt16(2); // RecordLength + Asm->OutStreamer->AddComment("Record kind: S_INLINESITE_END"); Asm->EmitInt16(SymbolRecordKind::S_INLINESITE_END); // RecordKind } @@ -382,30 +408,51 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, *SymbolsEnd = Asm->MMI->getContext().createTempSymbol(); Asm->OutStreamer->AddComment("Symbol subsection for " + Twine(FuncName)); Asm->EmitInt32(unsigned(ModuleSubstreamKind::Symbols)); + Asm->OutStreamer->AddComment("Subsection size"); EmitLabelDiff(*Asm->OutStreamer, SymbolsBegin, SymbolsEnd); Asm->OutStreamer->EmitLabel(SymbolsBegin); { - MCSymbol *ProcSegmentBegin = Asm->MMI->getContext().createTempSymbol(), - *ProcSegmentEnd = Asm->MMI->getContext().createTempSymbol(); - EmitLabelDiff(*Asm->OutStreamer, ProcSegmentBegin, ProcSegmentEnd, 2); - Asm->OutStreamer->EmitLabel(ProcSegmentBegin); + MCSymbol *ProcRecordBegin = Asm->MMI->getContext().createTempSymbol(), + *ProcRecordEnd = Asm->MMI->getContext().createTempSymbol(); + Asm->OutStreamer->AddComment("Record length"); + EmitLabelDiff(*Asm->OutStreamer, ProcRecordBegin, ProcRecordEnd, 2); + Asm->OutStreamer->EmitLabel(ProcRecordBegin); + Asm->OutStreamer->AddComment("Record kind: S_GPROC32_ID"); Asm->EmitInt16(unsigned(SymbolRecordKind::S_GPROC32_ID)); - // Some bytes of this segment don't seem to be required for basic debugging, - // so just fill them with zeroes. - Asm->OutStreamer->EmitFill(12, 0); + // These fields are filled in by tools like CVPACK which run after the fact. + Asm->OutStreamer->AddComment("PtrParent"); + Asm->OutStreamer->EmitIntValue(0, 4); + Asm->OutStreamer->AddComment("PtrEnd"); + Asm->OutStreamer->EmitIntValue(0, 4); + Asm->OutStreamer->AddComment("PtrNext"); + Asm->OutStreamer->EmitIntValue(0, 4); // This is the important bit that tells the debugger where the function // code is located and what's its size: + Asm->OutStreamer->AddComment("Code size"); EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End); - Asm->OutStreamer->EmitFill(12, 0); + Asm->OutStreamer->AddComment("Offset after prologue"); + Asm->OutStreamer->EmitIntValue(0, 4); + Asm->OutStreamer->AddComment("Offset before epilogue"); + Asm->OutStreamer->EmitIntValue(0, 4); + Asm->OutStreamer->AddComment("Function type index"); + Asm->OutStreamer->EmitIntValue(0, 4); + Asm->OutStreamer->AddComment("Function section relative address"); Asm->OutStreamer->EmitCOFFSecRel32(Fn); + Asm->OutStreamer->AddComment("Function section index"); Asm->OutStreamer->EmitCOFFSectionIndex(Fn); + Asm->OutStreamer->AddComment("Flags"); Asm->EmitInt8(0); // Emit the function display name as a null-terminated string. - Asm->OutStreamer->EmitBytes(FuncName); - Asm->EmitInt8(0); - Asm->OutStreamer->EmitLabel(ProcSegmentEnd); + Asm->OutStreamer->AddComment("Function name"); + { + SmallString<32> NullTerminatedString(FuncName); + if (NullTerminatedString.empty() || NullTerminatedString.back() != '\0') + NullTerminatedString.push_back('\0'); + Asm->OutStreamer->EmitBytes(NullTerminatedString); + } + Asm->OutStreamer->EmitLabel(ProcRecordEnd); // Emit inlined call site information. Only emit functions inlined directly // into the parent function. We'll emit the other sites recursively as part @@ -417,7 +464,9 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, } // We're done with this function. + Asm->OutStreamer->AddComment("Record length"); Asm->EmitInt16(0x0002); + Asm->OutStreamer->AddComment("Record kind: S_PROC_ID_END"); Asm->EmitInt16(unsigned(SymbolRecordKind::S_PROC_ID_END)); } Asm->OutStreamer->EmitLabel(SymbolsEnd); |