diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 49 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp | 15 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp | 126 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp | 19 |
4 files changed, 177 insertions, 32 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 9f8ed86b50e..61fe6984338 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -51,6 +51,7 @@ #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeTableCollection.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfoMetadata.h" @@ -94,6 +95,24 @@ using namespace llvm; using namespace llvm::codeview; +namespace { +class CVMCAdapter : public CodeViewRecordStreamer { +public: + CVMCAdapter(MCStreamer &OS) : OS(&OS) {} + + void EmitBytes(StringRef Data) { OS->EmitBytes(Data); } + + void EmitIntValue(uint64_t Value, unsigned Size) { + OS->EmitIntValue(Value, Size); + } + + void EmitBinaryData(StringRef Data) { OS->EmitBinaryData(Data); } + +private: + MCStreamer *OS = nullptr; +}; +} // namespace + static CPUType mapArchToCVCPUType(Triple::ArchType Type) { switch (Type) { case Triple::ArchType::x86: @@ -617,26 +636,40 @@ void CodeViewDebug::emitTypeInformation() { // This will fail if the record data is invalid. CVType Record = Table.getType(*B); + TypeVisitorCallbackPipeline Pipeline; + CVMCAdapter CVMCOS(OS); + TypeRecordMapping typeMapping(CVMCOS); + SmallString<512> CommentBlock; + raw_svector_ostream CommentOS(CommentBlock); + if (OS.isVerboseAsm()) { // Emit a block comment describing the type record for readability. - SmallString<512> CommentBlock; - raw_svector_ostream CommentOS(CommentBlock); ScopedPrinter SP(CommentOS); SP.setPrefix(CommentPrefix); TypeDumpVisitor TDV(Table, &SP, false); + Pipeline.addCallbackToPipeline(TDV); + } + Pipeline.addCallbackToPipeline(typeMapping); - Error E = codeview::visitTypeRecord(Record, *B, TDV); - if (E) { - logAllUnhandledErrors(std::move(E), errs(), "error: "); - llvm_unreachable("produced malformed type record"); - } + auto RecordLen = Record.length(); + auto RecordKind = Record.kind(); + OS.EmitIntValue(RecordLen - 2, 2); + OS.EmitIntValue(RecordKind, sizeof(RecordKind)); + + Error E = codeview::visitTypeRecord(Record, *B, Pipeline); + + if (E) { + logAllUnhandledErrors(std::move(E), errs(), "error: "); + llvm_unreachable("produced malformed type record"); + } + + if (OS.isVerboseAsm()) { // emitRawComment will insert its own tab and comment string before // the first line, so strip off our first one. It also prints its own // newline. OS.emitRawComment( CommentOS.str().drop_front(CommentPrefix.size() - 1).rtrim()); } - OS.EmitBinaryData(Record.str_data()); B = Table.getNext(*B); } } diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp index dd6f75f97a4..ec4773d571c 100644 --- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -209,6 +209,14 @@ struct VisitHelper { } } + VisitHelper(TypeVisitorCallbackPipeline &Callbacks, VisitorDataSource Source) + : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) { + if (Source == VDS_BytesPresent) { + Pipeline = Callbacks; + Pipeline.addCallbackToPipelineFront(Deserializer); + } + } + TypeDeserializer Deserializer; TypeVisitorCallbackPipeline Pipeline; CVTypeVisitor Visitor; @@ -222,6 +230,13 @@ Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index, return V.Visitor.visitTypeRecord(Record, Index); } +Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index, + TypeVisitorCallbackPipeline &Callbacks, + VisitorDataSource Source) { + VisitHelper V(Callbacks, Source); + return V.Visitor.visitTypeRecord(Record, Index); +} + Error llvm::codeview::visitTypeRecord(CVType &Record, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source) { diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp index 92c795ab8fa..2b69a1e0768 100644 --- a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp +++ b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp @@ -20,6 +20,7 @@ Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) { Limit.MaxLength = MaxLength; Limit.BeginOffset = getCurrentOffset(); Limits.push_back(Limit); + resetStreamedLen(); return Error::success(); } @@ -34,10 +35,29 @@ Error CodeViewRecordIO::endRecord() { // we don't know how big the record is until we're finished writing it, so // even though we don't commit the extraneous data, we still can't guarantee // we're at the end of the allocated data. + + if (isStreaming()) { + // For streaming mode, add padding to align with 4 byte boundaries for each + // record + uint32_t Align = getStreamedLen() % 4; + if (Align == 0) + return Error::success(); + + int PaddingBytes = 4 - Align; + while (PaddingBytes > 0) { + char Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes); + StringRef BytesSR = StringRef(&Pad, sizeof(Pad)); + Streamer->EmitBytes(BytesSR); + --PaddingBytes; + } + } return Error::success(); } uint32_t CodeViewRecordIO::maxFieldLength() const { + if (isStreaming()) + return 0; + assert(!Limits.empty() && "Not in a record!"); // The max length of the next field is the minimum of all lengths that would @@ -78,7 +98,10 @@ Error CodeViewRecordIO::skipPadding() { } Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) { - if (isWriting()) { + if (isStreaming()) { + Streamer->EmitBinaryData(toStringRef(Bytes)); + incrStreamedLen(Bytes.size()); + } else if (isWriting()) { if (auto EC = Writer->writeBytes(Bytes)) return EC; } else { @@ -99,21 +122,28 @@ Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes) { } Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) { - if (isWriting()) { + if (isStreaming()) { + Streamer->EmitIntValue(TypeInd.getIndex(), sizeof(TypeInd.getIndex())); + incrStreamedLen(sizeof(TypeInd.getIndex())); + } else if (isWriting()) { if (auto EC = Writer->writeInteger(TypeInd.getIndex())) return EC; - return Error::success(); + } else { + uint32_t I; + if (auto EC = Reader->readInteger(I)) + return EC; + TypeInd.setIndex(I); } - - uint32_t I; - if (auto EC = Reader->readInteger(I)) - return EC; - TypeInd.setIndex(I); return Error::success(); } Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) { - if (isWriting()) { + if (isStreaming()) { + if (Value >= 0) + emitEncodedUnsignedInteger(static_cast<uint64_t>(Value)); + else + emitEncodedSignedInteger(Value); + } else if (isWriting()) { if (Value >= 0) { if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value))) return EC; @@ -132,7 +162,9 @@ Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) { } Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) { - if (isWriting()) { + if (isStreaming()) + emitEncodedUnsignedInteger(Value); + else if (isWriting()) { if (auto EC = writeEncodedUnsignedInteger(Value)) return EC; } else { @@ -145,17 +177,26 @@ Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) { } Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) { - if (isWriting()) { + if (isStreaming()) { + if (Value.isSigned()) + emitEncodedSignedInteger(Value.getSExtValue()); + else + emitEncodedUnsignedInteger(Value.getZExtValue()); + } else if (isWriting()) { if (Value.isSigned()) return writeEncodedSignedInteger(Value.getSExtValue()); return writeEncodedUnsignedInteger(Value.getZExtValue()); - } - - return consume(*Reader, Value); + } else + return consume(*Reader, Value); + return Error::success(); } Error CodeViewRecordIO::mapStringZ(StringRef &Value) { - if (isWriting()) { + if (isStreaming()) { + auto NullTerminatedString = StringRef(Value.data(), Value.size() + 1); + Streamer->EmitBytes(NullTerminatedString); + incrStreamedLen(NullTerminatedString.size()); + } else if (isWriting()) { // Truncate if we attempt to write too much. StringRef S = Value.take_front(maxFieldLength() - 1); if (auto EC = Writer->writeCString(S)) @@ -169,6 +210,15 @@ Error CodeViewRecordIO::mapStringZ(StringRef &Value) { Error CodeViewRecordIO::mapGuid(GUID &Guid) { constexpr uint32_t GuidSize = 16; + + if (isStreaming()) { + StringRef GuidSR = + StringRef((reinterpret_cast<const char *>(&Guid)), GuidSize); + Streamer->EmitBytes(GuidSR); + incrStreamedLen(GuidSize); + return Error::success(); + } + if (maxFieldLength() < GuidSize) return make_error<CodeViewError>(cv_error_code::insufficient_buffer); @@ -185,12 +235,14 @@ Error CodeViewRecordIO::mapGuid(GUID &Guid) { } Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) { - if (isWriting()) { + + if (!isReading()) { for (auto V : Value) { if (auto EC = mapStringZ(V)) return EC; } - if (auto EC = Writer->writeInteger<uint8_t>(0)) + uint8_t FinalZero = 0; + if (auto EC = mapInteger(FinalZero)) return EC; } else { StringRef S; @@ -205,6 +257,46 @@ Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) { return Error::success(); } +void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value) { + assert(Value < 0 && "Encoded integer is not signed!"); + if (Value >= std::numeric_limits<int8_t>::min()) { + Streamer->EmitIntValue(LF_CHAR, 2); + Streamer->EmitIntValue(Value, 1); + incrStreamedLen(3); + } else if (Value >= std::numeric_limits<int16_t>::min()) { + Streamer->EmitIntValue(LF_SHORT, 2); + Streamer->EmitIntValue(Value, 2); + incrStreamedLen(4); + } else if (Value >= std::numeric_limits<int32_t>::min()) { + Streamer->EmitIntValue(LF_LONG, 2); + Streamer->EmitIntValue(Value, 4); + incrStreamedLen(6); + } else { + Streamer->EmitIntValue(LF_QUADWORD, 2); + Streamer->EmitIntValue(Value, 4); + incrStreamedLen(6); + } +} + +void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value) { + if (Value < LF_NUMERIC) { + Streamer->EmitIntValue(Value, 2); + incrStreamedLen(2); + } else if (Value <= std::numeric_limits<uint16_t>::max()) { + Streamer->EmitIntValue(LF_USHORT, 2); + Streamer->EmitIntValue(Value, 2); + incrStreamedLen(4); + } else if (Value <= std::numeric_limits<uint32_t>::max()) { + Streamer->EmitIntValue(LF_ULONG, 2); + Streamer->EmitIntValue(Value, 4); + incrStreamedLen(6); + } else { + Streamer->EmitIntValue(LF_UQUADWORD, 2); + Streamer->EmitIntValue(Value, 8); + incrStreamedLen(6); + } +} + Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { assert(Value < 0 && "Encoded integer is not signed!"); if (Value >= std::numeric_limits<int8_t>::min()) { diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp index 12fb50d6ddc..104e310d41b 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp @@ -29,7 +29,7 @@ struct MapOneMethodRecord { error(IO.mapInteger(Method.Type)); if (Method.isIntroducingVirtual()) { error(IO.mapInteger(Method.VFTableOffset)); - } else if (!IO.isWriting()) + } else if (IO.isReading()) Method.VFTableOffset = -1; if (!IsFromOverloadList) @@ -72,6 +72,9 @@ static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name, error(IO.mapStringZ(N)); } } else { + // Reading & Streaming mode come after writing mode is executed for each + // record. Truncating large names are done during writing, so its not + // necessary to do it while reading or streaming. error(IO.mapStringZ(Name)); if (HasUniqueName) error(IO.mapStringZ(UniqueName)); @@ -96,6 +99,10 @@ Error TypeRecordMapping::visitTypeBegin(CVType &CVR) { return Error::success(); } +Error TypeRecordMapping::visitTypeBegin(CVType &CVR, TypeIndex Index) { + return visitTypeBegin(CVR); +} + Error TypeRecordMapping::visitTypeEnd(CVType &Record) { assert(TypeKind.hasValue() && "Not in a type mapping!"); assert(!MemberKind.hasValue() && "Still in a member mapping!"); @@ -126,7 +133,7 @@ Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) { assert(TypeKind.hasValue() && "Not in a type mapping!"); assert(MemberKind.hasValue() && "Not in a member mapping!"); - if (!IO.isWriting()) { + if (IO.isReading()) { if (auto EC = IO.skipPadding()) return EC; } @@ -139,7 +146,6 @@ Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) { Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) { error(IO.mapInteger(Record.ModifiedType)); error(IO.mapEnum(Record.Modifiers)); - return Error::success(); } @@ -172,7 +178,6 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) { error(IO.mapVectorN<uint32_t>( Record.ArgIndices, [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); })); - return Error::success(); } @@ -190,7 +195,7 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) { error(IO.mapInteger(Record.Attrs)); if (Record.isPointerToMember()) { - if (!IO.isWriting()) + if (IO.isReading()) Record.MemberInfo.emplace(); MemberPointerInfo &M = *Record.MemberInfo; @@ -260,7 +265,7 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) { Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableShapeRecord &Record) { uint16_t Size; - if (IO.isWriting()) { + if (!IO.isReading()) { ArrayRef<VFTableSlotKind> Slots = Record.getSlots(); Size = Slots.size(); error(IO.mapInteger(Size)); @@ -291,7 +296,7 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) { error(IO.mapInteger(Record.OverriddenVFTable)); error(IO.mapInteger(Record.VFPtrOffset)); uint32_t NamesLen = 0; - if (IO.isWriting()) { + if (!IO.isReading()) { for (auto Name : Record.MethodNames) NamesLen += Name.size() + 1; } |