mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-08 03:26:34 +00:00
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@259868 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
419c3d8a2f
commit
7ddc547ea9
@ -123,6 +123,8 @@ struct LocalVariableAddrGap {
|
||||
ulittle16_t Range;
|
||||
};
|
||||
|
||||
enum : uint16_t { MaxDefRange = 0xf000 };
|
||||
|
||||
// S_DEFRANGE
|
||||
struct DefRangeSym {
|
||||
ulittle32_t Program;
|
||||
|
@ -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);
|
||||
|
@ -166,6 +166,13 @@ public:
|
||||
void encodeInlineLineTable(MCAsmLayout &Layout,
|
||||
MCCVInlineLineTableFragment &F);
|
||||
|
||||
void
|
||||
emitDefRange(MCObjectStreamer &OS,
|
||||
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
||||
StringRef FixedSizePortion);
|
||||
|
||||
void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F);
|
||||
|
||||
/// Emits the string table substream.
|
||||
void emitStringTable(MCObjectStreamer &OS);
|
||||
|
||||
|
@ -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<std::pair<const MCSymbol *, const MCSymbol *>, 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<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
||||
StringRef FixedSizePortion, MCSection *Sec = nullptr)
|
||||
: MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec),
|
||||
Ranges(Ranges.begin(), Ranges.end()),
|
||||
FixedSizePortion(FixedSizePortion) {}
|
||||
|
||||
/// \name Accessors
|
||||
/// @{
|
||||
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> 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
|
||||
|
@ -131,6 +131,9 @@ public:
|
||||
unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
|
||||
const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
|
||||
ArrayRef<unsigned> SecondaryFunctionIds) override;
|
||||
void EmitCVDefRangeDirective(
|
||||
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
||||
StringRef FixedSizePortion) override;
|
||||
void EmitCVStringTableDirective() override;
|
||||
void EmitCVFileChecksumsDirective() override;
|
||||
void EmitGPRel32Value(const MCExpr *Value) override;
|
||||
|
@ -662,6 +662,12 @@ public:
|
||||
const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
|
||||
ArrayRef<unsigned> SecondaryFunctionIds);
|
||||
|
||||
/// \brief This implements the CodeView '.cv_def_range' assembler
|
||||
/// directive.
|
||||
virtual void EmitCVDefRangeDirective(
|
||||
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
||||
StringRef FixedSizePortion);
|
||||
|
||||
/// \brief This implements the CodeView '.cv_stringtable' assembler directive.
|
||||
virtual void EmitCVStringTableDirective() {}
|
||||
|
||||
|
@ -209,6 +209,9 @@ public:
|
||||
unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
|
||||
const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
|
||||
ArrayRef<unsigned> SecondaryFunctionIds) override;
|
||||
void EmitCVDefRangeDirective(
|
||||
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
||||
StringRef FixedSizePortion) override;
|
||||
void EmitCVStringTableDirective() override;
|
||||
void EmitCVFileChecksumsDirective() override;
|
||||
|
||||
@ -1038,6 +1041,22 @@ void MCAsmStreamer::EmitCVInlineLinetableDirective(
|
||||
SecondaryFunctionIds);
|
||||
}
|
||||
|
||||
void MCAsmStreamer::EmitCVDefRangeDirective(
|
||||
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
||||
StringRef FixedSizePortion) {
|
||||
OS << "\t.cv_def_range\t";
|
||||
for (std::pair<const MCSymbol *, const MCSymbol *> 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();
|
||||
|
@ -303,6 +303,8 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
|
||||
return cast<MCDwarfCallFrameFragment>(F).getContents().size();
|
||||
case MCFragment::FT_CVInlineLines:
|
||||
return cast<MCCVInlineLineTableFragment>(F).getContents().size();
|
||||
case MCFragment::FT_CVDefRange:
|
||||
return cast<MCCVDefRangeFragment>(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<MCCVDefRangeFragment>(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<MCEncodedFragment>(&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<MCCompactEncodedInstFragment>(F))
|
||||
if (isa<MCEncodedFragment>(&Frag) &&
|
||||
isa<MCCompactEncodedInstFragment>(&Frag))
|
||||
continue;
|
||||
if (!isa<MCEncodedFragment>(&Frag) && !isa<MCCVDefRangeFragment>(&Frag))
|
||||
continue;
|
||||
ArrayRef<MCFixup> Fixups;
|
||||
MutableArrayRef<char> Contents;
|
||||
if (auto *FragWithFixups = dyn_cast<MCDataFragment>(F)) {
|
||||
if (auto *FragWithFixups = dyn_cast<MCDataFragment>(&Frag)) {
|
||||
Fixups = FragWithFixups->getFixups();
|
||||
Contents = FragWithFixups->getContents();
|
||||
} else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(F)) {
|
||||
} else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(&Frag)) {
|
||||
Fixups = FragWithFixups->getFixups();
|
||||
Contents = FragWithFixups->getContents();
|
||||
} else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&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<MCCVInlineLineTableFragment>(I));
|
||||
break;
|
||||
case MCFragment::FT_CVDefRange:
|
||||
RelaxedFrag = relaxCVDefRange(Layout, *cast<MCCVDefRangeFragment>(I));
|
||||
break;
|
||||
}
|
||||
if (RelaxedFrag && !FirstRelaxedFragment)
|
||||
FirstRelaxedFragment = &*I;
|
||||
|
@ -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<std::pair<const MCSymbol *, const MCSymbol *>> 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<char> &Contents = Frag.getContents();
|
||||
Contents.clear();
|
||||
SmallVectorImpl<MCFixup> &Fixups = Frag.getFixups();
|
||||
Fixups.clear();
|
||||
raw_svector_ostream OS(Contents);
|
||||
|
||||
// Write down each range where the variable is defined.
|
||||
for (std::pair<const MCSymbol *, const MCSymbol *> 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<support::little>(OS).write<uint16_t>(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<support::little>(OS).write<uint16_t>(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
|
||||
|
@ -292,6 +292,9 @@ void MCFragment::destroy() {
|
||||
case FT_CVInlineLines:
|
||||
delete cast<MCCVInlineLineTableFragment>(this);
|
||||
return;
|
||||
case FT_CVDefRange:
|
||||
delete cast<MCCVDefRangeFragment>(this);
|
||||
return;
|
||||
case FT_Dummy:
|
||||
delete cast<MCDummyFragment>(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<MCCVDefRangeFragment>(this);
|
||||
OS << "\n ";
|
||||
for (std::pair<const MCSymbol *, const MCSymbol *> RangeStartEnd :
|
||||
F->getRanges()) {
|
||||
OS << " RangeStart:" << RangeStartEnd.first;
|
||||
OS << " RangeEnd:" << RangeStartEnd.second;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MCFragment::FT_Dummy:
|
||||
break;
|
||||
}
|
||||
|
@ -396,6 +396,13 @@ void MCObjectStreamer::EmitCVInlineLinetableDirective(
|
||||
SecondaryFunctionIds);
|
||||
}
|
||||
|
||||
void MCObjectStreamer::EmitCVDefRangeDirective(
|
||||
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
||||
StringRef FixedSizePortion) {
|
||||
getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion);
|
||||
this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
|
||||
}
|
||||
|
||||
void MCObjectStreamer::EmitCVStringTableDirective() {
|
||||
getContext().getCVContext().emitStringTable(*this);
|
||||
}
|
||||
|
@ -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<std::pair<const MCSymbol *, const MCSymbol *>> 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;
|
||||
|
@ -201,6 +201,10 @@ void MCStreamer::EmitCVInlineLinetableDirective(
|
||||
const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
|
||||
ArrayRef<unsigned> SecondaryFunctionIds) {}
|
||||
|
||||
void MCStreamer::EmitCVDefRangeDirective(
|
||||
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
||||
StringRef FixedSizePortion) {}
|
||||
|
||||
void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
|
||||
MCSymbol *EHSymbol) {
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
97
test/MC/COFF/cv-def-range.s
Normal file
97
test/MC/COFF/cv-def-range.s
Normal file
@ -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\\<stdin>"
|
||||
.cv_loc 0 1 3 0 is_stmt 0 # <stdin>: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 # <stdin>:4:7
|
||||
movl $0, -4(%ebp)
|
||||
.cv_loc 0 1 5 3 # <stdin>:5:3
|
||||
movl %eax, (%esp)
|
||||
calll _f
|
||||
.cv_loc 0 1 6 1 # <stdin>: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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user