diff options
author | David Majnemer <david.majnemer@gmail.com> | 2016-02-05 01:55:49 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2016-02-05 01:55:49 +0000 |
commit | 408b5e660300f96d9a231ba0e18e75d8e69d17bb (patch) | |
tree | e9209cea4a29570a15cbcdb349cf6413b453e3aa /llvm/lib/MC/MCCodeView.cpp | |
parent | adc2376375f32b96daa8c548b11237738945f623 (diff) | |
download | bcm5719-llvm-408b5e660300f96d9a231ba0e18e75d8e69d17bb.tar.gz bcm5719-llvm-408b5e660300f96d9a231ba0e18e75d8e69d17bb.zip |
[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
Diffstat (limited to 'llvm/lib/MC/MCCodeView.cpp')
-rw-r--r-- | llvm/lib/MC/MCCodeView.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp index f50fdab8dfa..029bab1f7f8 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<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 |