From 408b5e660300f96d9a231ba0e18e75d8e69d17bb Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Fri, 5 Feb 2016 01:55:49 +0000 Subject: [PATCH] [MC] Add support for encoding CodeView variable definition ranges CodeView, like most other debug formats, represents the live range of a variable so that debuggers might print them out. They use a variety of records to represent how a particular variable might be available (in a register, in a frame pointer, etc.) along with a set of ranges where this debug information is relevant. However, the format only allows us to use ranges which are limited to a maximum of 0xF000 in size. This means that we need to split our debug information into chunks of 0xF000. Because the layout of code is not known until *very* late, we must use a new fragment to record the information we need until we can know *exactly* what the range is. llvm-svn: 259868 --- .../include/llvm/DebugInfo/CodeView/SymbolRecord.h | 2 + llvm/include/llvm/MC/MCAssembler.h | 1 + llvm/include/llvm/MC/MCCodeView.h | 7 ++ llvm/include/llvm/MC/MCFragment.h | 39 ++++++++- llvm/include/llvm/MC/MCObjectStreamer.h | 3 + llvm/include/llvm/MC/MCStreamer.h | 6 ++ llvm/lib/MC/MCAsmStreamer.cpp | 19 +++++ llvm/lib/MC/MCAssembler.cpp | 32 +++++-- llvm/lib/MC/MCCodeView.cpp | 63 ++++++++++++++ llvm/lib/MC/MCFragment.cpp | 14 ++++ llvm/lib/MC/MCObjectStreamer.cpp | 7 ++ llvm/lib/MC/MCParser/AsmParser.cpp | 43 +++++++++- llvm/lib/MC/MCStreamer.cpp | 4 + llvm/lib/MC/WinCOFFObjectWriter.cpp | 4 + llvm/test/MC/COFF/cv-def-range.s | 97 ++++++++++++++++++++++ llvm/test/MC/X86/reloc-directive.s | 4 +- 16 files changed, 332 insertions(+), 13 deletions(-) create mode 100644 llvm/test/MC/COFF/cv-def-range.s diff --git a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h index c01b7ba..5af97f5 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -123,6 +123,8 @@ struct LocalVariableAddrGap { ulittle16_t Range; }; +enum : uint16_t { MaxDefRange = 0xf000 }; + // S_DEFRANGE struct DefRangeSym { ulittle32_t Program; diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h index 3ad31dc..f15b9af 100644 --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/include/llvm/MC/MCAssembler.h @@ -191,6 +191,7 @@ private: MCDwarfCallFrameFragment &DF); bool relaxCVInlineLineTable(MCAsmLayout &Layout, MCCVInlineLineTableFragment &DF); + bool relaxCVDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &DF); /// finishLayout - Finalize a layout, including fragment lowering. void finishLayout(MCAsmLayout &Layout); diff --git a/llvm/include/llvm/MC/MCCodeView.h b/llvm/include/llvm/MC/MCCodeView.h index 22cf94f..d999ff5 100644 --- a/llvm/include/llvm/MC/MCCodeView.h +++ b/llvm/include/llvm/MC/MCCodeView.h @@ -166,6 +166,13 @@ public: void encodeInlineLineTable(MCAsmLayout &Layout, MCCVInlineLineTableFragment &F); + void + emitDefRange(MCObjectStreamer &OS, + ArrayRef> Ranges, + StringRef FixedSizePortion); + + void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F); + /// Emits the string table substream. void emitStringTable(MCObjectStreamer &OS); diff --git a/llvm/include/llvm/MC/MCFragment.h b/llvm/include/llvm/MC/MCFragment.h index a7548be..e0a2bfc 100644 --- a/llvm/include/llvm/MC/MCFragment.h +++ b/llvm/include/llvm/MC/MCFragment.h @@ -41,6 +41,7 @@ public: FT_LEB, FT_SafeSEH, FT_CVInlineLines, + FT_CVDefRange, FT_Dummy }; @@ -211,7 +212,8 @@ public: static bool classof(const MCFragment *F) { MCFragment::FragmentType Kind = F->getKind(); - return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data; + return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data || + Kind == MCFragment::FT_CVDefRange; } }; @@ -509,9 +511,7 @@ public: : MCFragment(FT_CVInlineLines, false, 0, Sec), SiteFuncId(SiteFuncId), StartFileId(StartFileId), StartLineNum(StartLineNum), FnStartSym(FnStartSym), FnEndSym(FnEndSym), - SecondaryFuncs(SecondaryFuncs.begin(), SecondaryFuncs.end()) { - Contents.push_back(0); - } + SecondaryFuncs(SecondaryFuncs.begin(), SecondaryFuncs.end()) {} /// \name Accessors /// @{ @@ -529,6 +529,37 @@ public: } }; +/// Fragment representing the .cv_def_range directive. +class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> { + SmallVector, 2> Ranges; + SmallString<32> FixedSizePortion; + + /// CodeViewContext has the real knowledge about this format, so let it access + /// our members. + friend class CodeViewContext; + +public: + MCCVDefRangeFragment( + ArrayRef> Ranges, + StringRef FixedSizePortion, MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec), + Ranges(Ranges.begin(), Ranges.end()), + FixedSizePortion(FixedSizePortion) {} + + /// \name Accessors + /// @{ + ArrayRef> getRanges() const { + return Ranges; + } + + StringRef getFixedSizePortion() const { return FixedSizePortion; } + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_CVDefRange; + } +}; + } // end namespace llvm #endif diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index 6a4ee8c..7123072 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -131,6 +131,9 @@ public: unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, ArrayRef SecondaryFunctionIds) override; + void EmitCVDefRangeDirective( + ArrayRef> Ranges, + StringRef FixedSizePortion) override; void EmitCVStringTableDirective() override; void EmitCVFileChecksumsDirective() override; void EmitGPRel32Value(const MCExpr *Value) override; diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 8c4d4ee..c0177c1 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -662,6 +662,12 @@ public: const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, ArrayRef SecondaryFunctionIds); + /// \brief This implements the CodeView '.cv_def_range' assembler + /// directive. + virtual void EmitCVDefRangeDirective( + ArrayRef> Ranges, + StringRef FixedSizePortion); + /// \brief This implements the CodeView '.cv_stringtable' assembler directive. virtual void EmitCVStringTableDirective() {} diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 9fcfcf7..c615752 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -209,6 +209,9 @@ public: unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, ArrayRef SecondaryFunctionIds) override; + void EmitCVDefRangeDirective( + ArrayRef> Ranges, + StringRef FixedSizePortion) override; void EmitCVStringTableDirective() override; void EmitCVFileChecksumsDirective() override; @@ -1038,6 +1041,22 @@ void MCAsmStreamer::EmitCVInlineLinetableDirective( SecondaryFunctionIds); } +void MCAsmStreamer::EmitCVDefRangeDirective( + ArrayRef> Ranges, + StringRef FixedSizePortion) { + OS << "\t.cv_def_range\t"; + for (std::pair Range : Ranges) { + OS << ' '; + Range.first->print(OS, MAI); + OS << ' '; + Range.second->print(OS, MAI); + } + OS << ", "; + PrintQuotedString(FixedSizePortion, OS); + EmitEOL(); + this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion); +} + void MCAsmStreamer::EmitCVStringTableDirective() { OS << "\t.cv_stringtable"; EmitEOL(); diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 9a55ef3..ca8ccb4 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -303,6 +303,8 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, return cast(F).getContents().size(); case MCFragment::FT_CVInlineLines: return cast(F).getContents().size(); + case MCFragment::FT_CVDefRange: + return cast(F).getContents().size(); case MCFragment::FT_Dummy: llvm_unreachable("Should not have been added"); } @@ -545,6 +547,11 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, OW->writeBytes(OF.getContents()); break; } + case MCFragment::FT_CVDefRange: { + const auto &DRF = cast(F); + OW->writeBytes(DRF.getContents()); + break; + } case MCFragment::FT_Dummy: llvm_unreachable("Should not have been added"); } @@ -673,19 +680,24 @@ void MCAssembler::layout(MCAsmLayout &Layout) { // Evaluate and apply the fixups, generating relocation entries as necessary. for (MCSection &Sec : *this) { for (MCFragment &Frag : Sec) { - MCEncodedFragment *F = dyn_cast(&Frag); // Data and relaxable fragments both have fixups. So only process // those here. // FIXME: Is there a better way to do this? MCEncodedFragmentWithFixups // being templated makes this tricky. - if (!F || isa(F)) + if (isa(&Frag) && + isa(&Frag)) + continue; + if (!isa(&Frag) && !isa(&Frag)) continue; ArrayRef Fixups; MutableArrayRef Contents; - if (auto *FragWithFixups = dyn_cast(F)) { + if (auto *FragWithFixups = dyn_cast(&Frag)) { + Fixups = FragWithFixups->getFixups(); + Contents = FragWithFixups->getContents(); + } else if (auto *FragWithFixups = dyn_cast(&Frag)) { Fixups = FragWithFixups->getFixups(); Contents = FragWithFixups->getContents(); - } else if (auto *FragWithFixups = dyn_cast(F)) { + } else if (auto *FragWithFixups = dyn_cast(&Frag)) { Fixups = FragWithFixups->getFixups(); Contents = FragWithFixups->getContents(); } else @@ -693,7 +705,7 @@ void MCAssembler::layout(MCAsmLayout &Layout) { for (const MCFixup &Fixup : Fixups) { uint64_t FixedValue; bool IsPCRel; - std::tie(FixedValue, IsPCRel) = handleFixup(Layout, *F, Fixup); + std::tie(FixedValue, IsPCRel) = handleFixup(Layout, Frag, Fixup); getBackend().applyFixup(Fixup, Contents.data(), Contents.size(), FixedValue, IsPCRel); } @@ -828,6 +840,13 @@ bool MCAssembler::relaxCVInlineLineTable(MCAsmLayout &Layout, return OldSize != F.getContents().size(); } +bool MCAssembler::relaxCVDefRange(MCAsmLayout &Layout, + MCCVDefRangeFragment &F) { + unsigned OldSize = F.getContents().size(); + getContext().getCVContext().encodeDefRange(Layout, F); + return OldSize != F.getContents().size(); +} + bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) { // Holds the first fragment which needed relaxing during this layout. It will // remain NULL if none were relaxed. @@ -863,6 +882,9 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) { RelaxedFrag = relaxCVInlineLineTable(Layout, *cast(I)); break; + case MCFragment::FT_CVDefRange: + RelaxedFrag = relaxCVDefRange(Layout, *cast(I)); + break; } if (RelaxedFrag && !FirstRelaxedFragment) FirstRelaxedFragment = &*I; diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp index f50fdab..029bab1 100644 --- a/llvm/lib/MC/MCCodeView.cpp +++ b/llvm/lib/MC/MCCodeView.cpp @@ -19,6 +19,7 @@ #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCValue.h" #include "llvm/Support/COFF.h" using namespace llvm; @@ -236,6 +237,16 @@ void CodeViewContext::emitInlineLineTableForFunction( SecondaryFunctionIds, OS.getCurrentSectionOnly()); } +void CodeViewContext::emitDefRange( + MCObjectStreamer &OS, + ArrayRef> Ranges, + StringRef FixedSizePortion) { + // Create and insert a fragment into the current section that will be encoded + // later. + new MCCVDefRangeFragment(Ranges, FixedSizePortion, + OS.getCurrentSectionOnly()); +} + static unsigned computeLabelDiff(MCAsmLayout &Layout, const MCSymbol *Begin, const MCSymbol *End) { MCContext &Ctx = Layout.getAssembler().getContext(); @@ -352,6 +363,58 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout, compressAnnotation(std::min(EndSymLength, LocAfterLength), Buffer); } +void CodeViewContext::encodeDefRange(MCAsmLayout &Layout, + MCCVDefRangeFragment &Frag) { + MCContext &Ctx = Layout.getAssembler().getContext(); + SmallVectorImpl &Contents = Frag.getContents(); + Contents.clear(); + SmallVectorImpl &Fixups = Frag.getFixups(); + Fixups.clear(); + raw_svector_ostream OS(Contents); + + // Write down each range where the variable is defined. + for (std::pair Range : Frag.getRanges()) { + unsigned RangeSize = computeLabelDiff(Layout, Range.first, Range.second); + unsigned Bias = 0; + // We must split the range into chunks of MaxDefRange, this is a fundamental + // limitation of the file format. + do { + uint16_t Chunk = std::min((uint32_t)MaxDefRange, RangeSize); + + const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Range.first, Ctx); + const MCBinaryExpr *BE = + MCBinaryExpr::createAdd(SRE, MCConstantExpr::create(Bias, Ctx), Ctx); + MCValue Res; + BE->evaluateAsRelocatable(Res, &Layout, /*Fixup=*/nullptr); + + // Each record begins with a 2-byte number indicating how large the record + // is. + StringRef FixedSizePortion = Frag.getFixedSizePortion(); + // Our record is a fixed sized prefix and a LocalVariableAddrRange that we + // are artificially constructing. + size_t RecordSize = + FixedSizePortion.size() + sizeof(LocalVariableAddrRange); + // Write out the recrod size. + support::endian::Writer(OS).write(RecordSize); + // Write out the fixed size prefix. + OS << FixedSizePortion; + // Make space for a fixup that will eventually have a section relative + // relocation pointing at the offset where the variable becomes live. + Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_4)); + Contents.resize(Contents.size() + 4); // Fixup for code start. + // Make space for a fixup that will record the section index for the code. + Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_2)); + Contents.resize(Contents.size() + 2); // Fixup for section index. + // Write down the range's extent. + support::endian::Writer(OS).write(Chunk); + + // Move on to the next range. + Bias += Chunk; + RangeSize -= Chunk; + } while (RangeSize > 0); + } +} + // // This is called when an instruction is assembled into the specified section // and if there is information from the last .cv_loc directive that has yet to have diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index bfadfda..b9889049 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -292,6 +292,9 @@ void MCFragment::destroy() { case FT_CVInlineLines: delete cast(this); return; + case FT_CVDefRange: + delete cast(this); + return; case FT_Dummy: delete cast(this); return; @@ -331,6 +334,7 @@ LLVM_DUMP_METHOD void MCFragment::dump() { case MCFragment::FT_LEB: OS << "MCLEBFragment"; break; case MCFragment::FT_SafeSEH: OS << "MCSafeSEHFragment"; break; case MCFragment::FT_CVInlineLines: OS << "MCCVInlineLineTableFragment"; break; + case MCFragment::FT_CVDefRange: OS << "MCCVDefRangeTableFragment"; break; case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break; } @@ -435,6 +439,16 @@ LLVM_DUMP_METHOD void MCFragment::dump() { OS << " Sym:" << *F->getFnStartSym(); break; } + case MCFragment::FT_CVDefRange: { + const auto *F = cast(this); + OS << "\n "; + for (std::pair RangeStartEnd : + F->getRanges()) { + OS << " RangeStart:" << RangeStartEnd.first; + OS << " RangeEnd:" << RangeStartEnd.second; + } + break; + } case MCFragment::FT_Dummy: break; } diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 40c2e8d..b90f0a8 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -396,6 +396,13 @@ void MCObjectStreamer::EmitCVInlineLinetableDirective( SecondaryFunctionIds); } +void MCObjectStreamer::EmitCVDefRangeDirective( + ArrayRef> Ranges, + StringRef FixedSizePortion) { + getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion); + this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion); +} + void MCObjectStreamer::EmitCVStringTableDirective() { getContext().getCVContext().emitStringTable(*this); } diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 2db7504..1332ef4 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -358,7 +358,7 @@ private: DK_IFNOTDEF, DK_ELSEIF, DK_ELSE, DK_ENDIF, DK_SPACE, DK_SKIP, DK_FILE, DK_LINE, DK_LOC, DK_STABS, DK_CV_FILE, DK_CV_LOC, DK_CV_LINETABLE, DK_CV_INLINE_LINETABLE, - DK_CV_STRINGTABLE, DK_CV_FILECHECKSUMS, + DK_CV_DEF_RANGE, DK_CV_STRINGTABLE, DK_CV_FILECHECKSUMS, DK_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA, DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET, DK_CFI_DEF_CFA_REGISTER, DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, DK_CFI_LSDA, @@ -396,11 +396,13 @@ private: bool parseDirectiveLoc(); bool parseDirectiveStabs(); - // ".cv_file", ".cv_loc", ".cv_linetable", "cv_inline_linetable" + // ".cv_file", ".cv_loc", ".cv_linetable", "cv_inline_linetable", + // ".cv_def_range" bool parseDirectiveCVFile(); bool parseDirectiveCVLoc(); bool parseDirectiveCVLinetable(); bool parseDirectiveCVInlineLinetable(); + bool parseDirectiveCVDefRange(); bool parseDirectiveCVStringTable(); bool parseDirectiveCVFileChecksums(); @@ -1656,6 +1658,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveCVLinetable(); case DK_CV_INLINE_LINETABLE: return parseDirectiveCVInlineLinetable(); + case DK_CV_DEF_RANGE: + return parseDirectiveCVDefRange(); case DK_CV_STRINGTABLE: return parseDirectiveCVStringTable(); case DK_CV_FILECHECKSUMS: @@ -3286,6 +3290,40 @@ bool AsmParser::parseDirectiveCVInlineLinetable() { return false; } +/// parseDirectiveCVDefRange +/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes* +bool AsmParser::parseDirectiveCVDefRange() { + SMLoc Loc; + std::vector> Ranges; + while (getLexer().is(AsmToken::Identifier)) { + Loc = getLexer().getLoc(); + StringRef GapStartName; + if (parseIdentifier(GapStartName)) + return Error(Loc, "expected identifier in directive"); + MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName); + + Loc = getLexer().getLoc(); + StringRef GapEndName; + if (parseIdentifier(GapEndName)) + return Error(Loc, "expected identifier in directive"); + MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName); + + Ranges.push_back({GapStartSym, GapEndSym}); + } + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + std::string FixedSizePortion; + if (parseEscapedString(FixedSizePortion)) + return true; + Lex(); + + getStreamer().EmitCVDefRangeDirective(Ranges, FixedSizePortion); + return false; +} + /// parseDirectiveCVStringTable /// ::= .cv_stringtable bool AsmParser::parseDirectiveCVStringTable() { @@ -4615,6 +4653,7 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".cv_loc"] = DK_CV_LOC; DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE; DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE; + DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE; DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE; DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS; DirectiveKindMap[".sleb128"] = DK_SLEB128; diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 8ee41261..663ed83 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -201,6 +201,10 @@ void MCStreamer::EmitCVInlineLinetableDirective( const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, ArrayRef SecondaryFunctionIds) {} +void MCStreamer::EmitCVDefRangeDirective( + ArrayRef> Ranges, + StringRef FixedSizePortion) {} + void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) { } diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp index 825e488..dd7adbf 100644 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -785,6 +785,10 @@ void WinCOFFObjectWriter::recordRelocation( } } + // The fixed value never makes sense for section indicies, ignore it. + if (Fixup.getKind() == FK_SecRel_2) + FixedValue = 0; + if (TargetObjectWriter->recordRelocation(Fixup)) coff_section->Relocations.push_back(Reloc); } diff --git a/llvm/test/MC/COFF/cv-def-range.s b/llvm/test/MC/COFF/cv-def-range.s new file mode 100644 index 0000000..781275d --- /dev/null +++ b/llvm/test/MC/COFF/cv-def-range.s @@ -0,0 +1,97 @@ +# RUN: llvm-mc -triple=i686-pc-win32 -filetype=obj < %s | llvm-readobj -codeview -codeview-subsection-bytes | FileCheck %s + .text + .def @feat.00; + .scl 3; + .type 0; + .endef + .globl @feat.00 +@feat.00 = 1 + .def _g; + .scl 2; + .type 32; + .endef + .globl _g + .p2align 4, 0x90 +_g: # @g +Lfunc_begin0: + .cv_file 1 "\\usr\\local\\google\\home\\majnemer\\llvm\\src\\" + .cv_loc 0 1 3 0 is_stmt 0 # :3:0 +# BB#0: # %entry + pushl %ebp + movl %esp, %ebp + subl $8, %esp + leal -4(%ebp), %eax +Lvar_begin0: + #DEBUG_VALUE: g:x <- %EAX + .cv_loc 0 1 4 7 # :4:7 + movl $0, -4(%ebp) + .cv_loc 0 1 5 3 # :5:3 + movl %eax, (%esp) + calll _f + .cv_loc 0 1 6 1 # :6:1 +Lvar_end0: + addl $8, %esp + popl %ebp + retl +Lfunc_end0: + + .section .debug$T,"dr" + .long 4 # Debug section magic + .short 6 # Type record length + .short 4609 # Leaf type: LF_ARGLIST + .long 0 # Number of arguments + .short 14 # Type record length + .short 4104 # Leaf type: LF_PROCEDURE + .long 3 # Return type index + .byte 0 # Calling convention + .byte 0 # Function options + .short 0 # # of parameters + .long 4096 # Argument list type index + .short 12 # Type record length + .short 5633 # Leaf type: LF_FUNC_ID + .long 0 # Scope type index + .long 4097 # Function type + .asciz "g" # Function name + .section .debug$S,"dr" + .long 4 # Debug section magic + .long 241 # Symbol subsection for g + .long Ltmp1-Ltmp0 # Subsection size +Ltmp0: + .short Ltmp3-Ltmp2 # Record length +Ltmp2: + .short 4423 # Record kind: S_GPROC32_ID + .long 0 # PtrParent + .long 0 # PtrEnd + .long 0 # PtrNext + .long Lfunc_end0-_g # Code size + .long 0 # Offset after prologue + .long 0 # Offset before epilogue + .long 0 # Function type index + .secrel32 _g # Function section relative address + .secidx _g # Function section index + .byte 0 # Flags + .asciz "g" # Function name +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" + +# CHECK: DefRangeFramePointerRel { +# CHECK: Offset: -4 +# CHECK: LocalVariableAddrRange { +# CHECK: OffsetStart: .text+0x9 +# CHECK: ISectStart: 0x0 +# CHECK: Range: 15 +# CHECK: } +# CHECK: } +# CHECK: BlockRelocations [ +# CHECK: 0x4 IMAGE_REL_I386_SECREL .text +# CHECK: 0x8 IMAGE_REL_I386_SECTION .text +# CHECK: ] + +Ltmp1: + .p2align 2 + .cv_linetable 0, _g, Lfunc_end0 + .cv_filechecksums # File index to string table offset subsection + .cv_stringtable # String table + diff --git a/llvm/test/MC/X86/reloc-directive.s b/llvm/test/MC/X86/reloc-directive.s index 0cc96b3..901427a 100644 --- a/llvm/test/MC/X86/reloc-directive.s +++ b/llvm/test/MC/X86/reloc-directive.s @@ -20,7 +20,7 @@ foo: .reloc 16, dir32, foo@imgrel # ASM: .reloc 16, dir32, foo@IMGREL # OBJ-32-LABEL: Name: .text -# OBJ-32: 0000: 04000000 00000000 08000000 +# OBJ-32: 0000: 04000000 00000000 00000000 # OBJ-32-LABEL: } # OBJ-32-LABEL: Relocations [ # OBJ-32: 0x4 IMAGE_REL_I386_DIR32 foo @@ -30,7 +30,7 @@ foo: # OBJ-32: 0x10 IMAGE_REL_I386_DIR32NB foo # OBJ-64-LABEL: Name: .text -# OBJ-64: 0000: 04000000 00000000 08000000 +# OBJ-64: 0000: 04000000 00000000 00000000 # OBJ-64-LABEL: } # OBJ-64-LABEL: Relocations [ # OBJ-64: 0x4 IMAGE_REL_AMD64_ADDR32 foo -- 2.7.4