summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2017-06-02 19:49:14 +0000
committerZachary Turner <zturner@google.com>2017-06-02 19:49:14 +0000
commit92dcdda623326bfd97a5833544e396fa739e2a29 (patch)
tree26ab0c07be6f8c1f067a59c4091d7a43f19f2fb5 /llvm/lib
parent3440bc37ffc9221a21e9bae540d410279ced283b (diff)
downloadbcm5719-llvm-92dcdda623326bfd97a5833544e396fa739e2a29.tar.gz
bcm5719-llvm-92dcdda623326bfd97a5833544e396fa739e2a29.zip
[CodeView] Support CodeView subsections in any order.
Previously we would expect certain subsections to appear in a certain order because some subsections would reference other subsections, but in practice we need to support arbitrary orderings since some object file and PDB file producers generate them this way. This also paves the way for supporting Yaml <-> Object File conversion of CodeView, since Object Files typically have quite a large number of subsections in their debug info. Differential Revision: https://reviews.llvm.org/D33807 llvm-svn: 304588
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp6
-rw-r--r--llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp14
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp41
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp28
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp4
-rw-r--r--llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp407
6 files changed, 421 insertions, 79 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
index b8741eb0b67..2e72242181b 100644
--- a/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
+++ b/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
@@ -72,7 +72,7 @@ Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const {
uint32_t DebugStringTableSubsection::size() const { return Strings.size(); }
uint32_t DebugStringTableSubsection::getStringId(StringRef S) const {
- auto P = Strings.find(S);
- assert(P != Strings.end());
- return P->second;
+ auto Iter = Strings.find(S);
+ assert(Iter != Strings.end());
+ return Iter->second;
}
diff --git a/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp
index 5ecfaf2f23a..cfd1c5d3ab0 100644
--- a/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp
+++ b/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp
@@ -60,13 +60,13 @@ DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
- DebugSubsectionKind Kind, DebugSubsection &Frag,
- CodeViewContainer Container)
- : Container(Container), Kind(Kind), Frag(Frag) {}
+ std::unique_ptr<DebugSubsection> Subsection, CodeViewContainer Container)
+ : Subsection(std::move(Subsection)), Container(Container) {}
uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
- uint32_t Size = sizeof(DebugSubsectionHeader) +
- alignTo(Frag.calculateSerializedSize(), alignOf(Container));
+ uint32_t Size =
+ sizeof(DebugSubsectionHeader) +
+ alignTo(Subsection->calculateSerializedSize(), alignOf(Container));
return Size;
}
@@ -75,12 +75,12 @@ Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) {
"Debug Subsection not properly aligned");
DebugSubsectionHeader Header;
- Header.Kind = uint32_t(Kind);
+ Header.Kind = uint32_t(Subsection->kind());
Header.Length = calculateSerializedLength() - sizeof(DebugSubsectionHeader);
if (auto EC = Writer.writeObject(Header))
return EC;
- if (auto EC = Frag.commit(Writer))
+ if (auto EC = Subsection->commit(Writer))
return EC;
if (auto EC = Writer.padToAlignment(alignOf(Container)))
return EC;
diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
index bf3f83741ae..9aea4acb74a 100644
--- a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
@@ -174,42 +174,9 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
return Error::success();
}
-void DbiModuleDescriptorBuilder::addC13Fragment(
- std::unique_ptr<DebugLinesSubsection> Lines) {
- DebugLinesSubsection &Frag = *Lines;
-
- // File Checksums have to come first, so push an empty entry on if this
- // is the first.
- if (C13Builders.empty())
- C13Builders.push_back(nullptr);
-
- this->LineInfo.push_back(std::move(Lines));
+void DbiModuleDescriptorBuilder::addDebugSubsection(
+ std::unique_ptr<DebugSubsection> Subsection) {
+ assert(Subsection);
C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>(
- Frag.kind(), Frag, CodeViewContainer::Pdb));
-}
-
-void DbiModuleDescriptorBuilder::addC13Fragment(
- std::unique_ptr<codeview::DebugInlineeLinesSubsection> Inlinees) {
- DebugInlineeLinesSubsection &Frag = *Inlinees;
-
- // File Checksums have to come first, so push an empty entry on if this
- // is the first.
- if (C13Builders.empty())
- C13Builders.push_back(nullptr);
-
- this->Inlinees.push_back(std::move(Inlinees));
- C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>(
- Frag.kind(), Frag, CodeViewContainer::Pdb));
-}
-
-void DbiModuleDescriptorBuilder::setC13FileChecksums(
- std::unique_ptr<DebugChecksumsSubsection> Checksums) {
- assert(!ChecksumInfo && "Can't have more than one checksum info!");
-
- if (C13Builders.empty())
- C13Builders.push_back(nullptr);
-
- ChecksumInfo = std::move(Checksums);
- C13Builders[0] = llvm::make_unique<DebugSubsectionRecordBuilder>(
- ChecksumInfo->kind(), *ChecksumInfo, CodeViewContainer::Pdb);
+ std::move(Subsection), CodeViewContainer::Pdb));
}
diff --git a/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp b/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
index d7a203746a0..c4ff30011a1 100644
--- a/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
@@ -55,9 +55,9 @@ Error ModuleDebugStreamRef::reload() {
if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size))
return EC;
- BinaryStreamReader LineReader(C13LinesSubstream);
- if (auto EC =
- LineReader.readArray(LinesAndChecksums, LineReader.bytesRemaining()))
+ BinaryStreamReader SubsectionsReader(C13LinesSubstream);
+ if (auto EC = SubsectionsReader.readArray(Subsections,
+ SubsectionsReader.bytesRemaining()))
return EC;
uint32_t GlobalRefsSize;
@@ -77,13 +77,27 @@ ModuleDebugStreamRef::symbols(bool *HadError) const {
return make_range(SymbolsSubstream.begin(HadError), SymbolsSubstream.end());
}
-llvm::iterator_range<ModuleDebugStreamRef::LinesAndChecksumsIterator>
-ModuleDebugStreamRef::linesAndChecksums() const {
- return make_range(LinesAndChecksums.begin(), LinesAndChecksums.end());
+llvm::iterator_range<ModuleDebugStreamRef::DebugSubsectionIterator>
+ModuleDebugStreamRef::subsections() const {
+ return make_range(Subsections.begin(), Subsections.end());
}
-bool ModuleDebugStreamRef::hasLineInfo() const {
+bool ModuleDebugStreamRef::hasDebugSubsections() const {
return C13LinesSubstream.getLength() > 0;
}
Error ModuleDebugStreamRef::commit() { return Error::success(); }
+
+Expected<codeview::DebugChecksumsSubsectionRef>
+ModuleDebugStreamRef::findChecksumsSubsection() const {
+ for (const auto &SS : subsections()) {
+ if (SS.kind() != DebugSubsectionKind::FileChecksums)
+ continue;
+
+ codeview::DebugChecksumsSubsectionRef Result;
+ if (auto EC = Result.initialize(SS.getRecordData()))
+ return std::move(EC);
+ return Result;
+ }
+ return make_error<RawError>(raw_error_code::no_entry);
+}
diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
index e84573fe07b..6013c342cf0 100644
--- a/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
@@ -56,6 +56,10 @@ Error PDBStringTable::readStrings(BinaryStreamReader &Reader) {
return Error::success();
}
+codeview::DebugStringTableSubsectionRef PDBStringTable::getStringTable() const {
+ return Strings;
+}
+
Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) {
const support::ulittle32_t *HashCount;
if (auto EC = Reader.readObject(HashCount))
diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
index f652ff57f30..1d62d1b2621 100644
--- a/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
+++ b/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
@@ -17,6 +17,11 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
@@ -36,16 +41,80 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo)
LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, false)
+LLVM_YAML_DECLARE_ENUM_TRAITS(DebugSubsectionKind)
LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind)
LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags)
-LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceLineEntry)
-LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceColumnEntry)
-LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceFileChecksumEntry)
-LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceLineInfo)
-LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::SourceLineBlock)
-LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::InlineeInfo)
-LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::InlineeSite)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceColumnEntry)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceFileChecksumEntry)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineBlock)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(InlineeSite)
+
+namespace llvm {
+namespace CodeViewYAML {
+namespace detail {
+struct YAMLSubsectionBase {
+ explicit YAMLSubsectionBase(DebugSubsectionKind Kind) : Kind(Kind) {}
+ DebugSubsectionKind Kind;
+ virtual ~YAMLSubsectionBase() {}
+
+ virtual void map(IO &IO) = 0;
+ virtual std::unique_ptr<DebugSubsection>
+ toCodeViewSubsection(DebugStringTableSubsection *UseStrings,
+ DebugChecksumsSubsection *UseChecksums) const = 0;
+};
+}
+}
+}
+
+namespace {
+struct YAMLChecksumsSubsection : public YAMLSubsectionBase {
+ YAMLChecksumsSubsection()
+ : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {}
+
+ void map(IO &IO) override;
+ std::unique_ptr<DebugSubsection>
+ toCodeViewSubsection(DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const override;
+ static Expected<std::shared_ptr<YAMLChecksumsSubsection>>
+ fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &FC);
+
+ std::vector<SourceFileChecksumEntry> Checksums;
+};
+
+struct YAMLLinesSubsection : public YAMLSubsectionBase {
+ YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {}
+
+ void map(IO &IO) override;
+ std::unique_ptr<DebugSubsection>
+ toCodeViewSubsection(DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const override;
+ static Expected<std::shared_ptr<YAMLLinesSubsection>>
+ fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &Checksums,
+ const DebugLinesSubsectionRef &Lines);
+
+ SourceLineInfo Lines;
+};
+
+struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase {
+ YAMLInlineeLinesSubsection()
+ : YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {}
+
+ void map(IO &IO) override;
+ std::unique_ptr<DebugSubsection>
+ toCodeViewSubsection(DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const override;
+ static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
+ fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &Checksums,
+ const DebugInlineeLinesSubsectionRef &Lines);
+
+ InlineeInfo InlineeLines;
+};
+}
void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) {
io.bitSetCase(Flags, "HasColumnInfo", LF_HaveColumns);
@@ -99,21 +168,6 @@ void MappingTraits<SourceFileChecksumEntry>::mapping(
IO.mapRequired("Checksum", Obj.ChecksumBytes);
}
-void MappingTraits<SourceLineInfo>::mapping(IO &IO, SourceLineInfo &Obj) {
- IO.mapRequired("CodeSize", Obj.CodeSize);
-
- IO.mapRequired("Flags", Obj.Flags);
- IO.mapRequired("RelocOffset", Obj.RelocOffset);
- IO.mapRequired("RelocSegment", Obj.RelocSegment);
- IO.mapRequired("Blocks", Obj.Blocks);
-}
-
-void MappingTraits<SourceFileInfo>::mapping(IO &IO, SourceFileInfo &Obj) {
- IO.mapOptional("Checksums", Obj.FileChecksums);
- IO.mapOptional("Lines", Obj.LineFragments);
- IO.mapOptional("InlineeLines", Obj.Inlinees);
-}
-
void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) {
IO.mapRequired("FileName", Obj.FileName);
IO.mapRequired("LineNum", Obj.SourceLineNum);
@@ -121,7 +175,310 @@ void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) {
IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
}
-void MappingTraits<InlineeInfo>::mapping(IO &IO, InlineeInfo &Obj) {
- IO.mapRequired("HasExtraFiles", Obj.HasExtraFiles);
- IO.mapRequired("Sites", Obj.Sites);
+void YAMLChecksumsSubsection::map(IO &IO) {
+ IO.mapTag("!FileChecksums", true);
+ IO.mapRequired("Checksums", Checksums);
+}
+
+void YAMLLinesSubsection::map(IO &IO) {
+ IO.mapTag("!Lines", true);
+ IO.mapRequired("CodeSize", Lines.CodeSize);
+
+ IO.mapRequired("Flags", Lines.Flags);
+ IO.mapRequired("RelocOffset", Lines.RelocOffset);
+ IO.mapRequired("RelocSegment", Lines.RelocSegment);
+ IO.mapRequired("Blocks", Lines.Blocks);
+}
+
+void YAMLInlineeLinesSubsection::map(IO &IO) {
+ IO.mapTag("!InlineeLines", true);
+ IO.mapRequired("HasExtraFiles", InlineeLines.HasExtraFiles);
+ IO.mapRequired("Sites", InlineeLines.Sites);
+}
+
+void MappingTraits<YAMLDebugSubsection>::mapping(
+ IO &IO, YAMLDebugSubsection &Subsection) {
+ if (!IO.outputting()) {
+ if (IO.mapTag("!FileChecksums")) {
+ auto SS = std::make_shared<YAMLChecksumsSubsection>();
+ Subsection.Subsection = SS;
+ } else if (IO.mapTag("!Lines")) {
+ Subsection.Subsection = std::make_shared<YAMLLinesSubsection>();
+ } else if (IO.mapTag("!InlineeLines")) {
+ Subsection.Subsection = std::make_shared<YAMLInlineeLinesSubsection>();
+ } else {
+ llvm_unreachable("Unexpected subsection tag!");
+ }
+ }
+ Subsection.Subsection->map(IO);
+}
+
+static Expected<const YAMLChecksumsSubsection &>
+findChecksums(ArrayRef<YAMLDebugSubsection> Subsections) {
+ for (const auto &SS : Subsections) {
+ if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) {
+ return static_cast<const YAMLChecksumsSubsection &>(*SS.Subsection);
+ }
+ }
+ return make_error<CodeViewError>(cv_error_code::no_records);
+}
+
+std::unique_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
+ DebugStringTableSubsection *UseStrings,
+ DebugChecksumsSubsection *UseChecksums) const {
+ assert(UseStrings && !UseChecksums);
+ auto Result = llvm::make_unique<DebugChecksumsSubsection>(*UseStrings);
+ for (const auto &CS : Checksums) {
+ Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes);
+ }
+ return std::move(Result);
+}
+
+std::unique_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection(
+ DebugStringTableSubsection *UseStrings,
+ DebugChecksumsSubsection *UseChecksums) const {
+ assert(UseStrings && UseChecksums);
+ auto Result =
+ llvm::make_unique<DebugLinesSubsection>(*UseChecksums, *UseStrings);
+ Result->setCodeSize(Lines.CodeSize);
+ Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset);
+ Result->setFlags(Lines.Flags);
+ for (const auto &LC : Lines.Blocks) {
+ Result->createBlock(LC.FileName);
+ if (Result->hasColumnInfo()) {
+ for (const auto &Item : zip(LC.Lines, LC.Columns)) {
+ auto &L = std::get<0>(Item);
+ auto &C = std::get<1>(Item);
+ uint32_t LE = L.LineStart + L.EndDelta;
+ Result->addLineAndColumnInfo(L.Offset,
+ LineInfo(L.LineStart, LE, L.IsStatement),
+ C.StartColumn, C.EndColumn);
+ }
+ } else {
+ for (const auto &L : LC.Lines) {
+ uint32_t LE = L.LineStart + L.EndDelta;
+ Result->addLineInfo(L.Offset, LineInfo(L.LineStart, LE, L.IsStatement));
+ }
+ }
+ }
+ return Result;
+}
+
+std::unique_ptr<DebugSubsection>
+YAMLInlineeLinesSubsection::toCodeViewSubsection(
+ DebugStringTableSubsection *UseStrings,
+ DebugChecksumsSubsection *UseChecksums) const {
+ assert(UseChecksums);
+ auto Result = llvm::make_unique<DebugInlineeLinesSubsection>(
+ *UseChecksums, InlineeLines.HasExtraFiles);
+
+ for (const auto &Site : InlineeLines.Sites) {
+ Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName,
+ Site.SourceLineNum);
+ if (!InlineeLines.HasExtraFiles)
+ continue;
+
+ for (auto EF : Site.ExtraFiles) {
+ Result->addExtraFile(EF);
+ }
+ }
+ return Result;
+}
+
+static Expected<SourceFileChecksumEntry>
+convertOneChecksum(const DebugStringTableSubsectionRef &Strings,
+ const FileChecksumEntry &CS) {
+ auto ExpectedString = Strings.getString(CS.FileNameOffset);
+ if (!ExpectedString)
+ return ExpectedString.takeError();
+
+ SourceFileChecksumEntry Result;
+ Result.ChecksumBytes.Bytes = CS.Checksum;
+ Result.Kind = CS.Kind;
+ Result.FileName = *ExpectedString;
+ return Result;
+}
+
+static Expected<StringRef>
+getFileName(const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
+ auto Iter = Checksums.getArray().at(FileID);
+ if (Iter == Checksums.getArray().end())
+ return make_error<CodeViewError>(cv_error_code::no_records);
+ uint32_t Offset = Iter->FileNameOffset;
+ return Strings.getString(Offset);
+}
+
+Expected<std::shared_ptr<YAMLChecksumsSubsection>>
+YAMLChecksumsSubsection::fromCodeViewSubsection(
+ const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &FC) {
+ auto Result = std::make_shared<YAMLChecksumsSubsection>();
+
+ for (const auto &CS : FC) {
+ auto ConvertedCS = convertOneChecksum(Strings, CS);
+ if (!ConvertedCS)
+ return ConvertedCS.takeError();
+ Result->Checksums.push_back(*ConvertedCS);
+ }
+ return Result;
+}
+
+Expected<std::shared_ptr<YAMLLinesSubsection>>
+YAMLLinesSubsection::fromCodeViewSubsection(
+ const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &Checksums,
+ const DebugLinesSubsectionRef &Lines) {
+ auto Result = std::make_shared<YAMLLinesSubsection>();
+ Result->Lines.CodeSize = Lines.header()->CodeSize;
+ Result->Lines.RelocOffset = Lines.header()->RelocOffset;
+ Result->Lines.RelocSegment = Lines.header()->RelocSegment;
+ Result->Lines.Flags = static_cast<LineFlags>(uint16_t(Lines.header()->Flags));
+ for (const auto &L : Lines) {
+ SourceLineBlock Block;
+ auto EF = getFileName(Strings, Checksums, L.NameIndex);
+ if (!EF)
+ return EF.takeError();
+ Block.FileName = *EF;
+ if (Lines.hasColumnInfo()) {
+ for (const auto &C : L.Columns) {
+ SourceColumnEntry SCE;
+ SCE.EndColumn = C.EndColumn;
+ SCE.StartColumn = C.StartColumn;
+ Block.Columns.push_back(SCE);
+ }
+ }
+ for (const auto &LN : L.LineNumbers) {
+ SourceLineEntry SLE;
+ LineInfo LI(LN.Flags);
+ SLE.Offset = LN.Offset;
+ SLE.LineStart = LI.getStartLine();
+ SLE.EndDelta = LI.getLineDelta();
+ SLE.IsStatement = LI.isStatement();
+ Block.Lines.push_back(SLE);
+ }
+ Result->Lines.Blocks.push_back(Block);
+ }
+ return Result;
+}
+
+Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
+YAMLInlineeLinesSubsection::fromCodeViewSubsection(
+ const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &Checksums,
+ const DebugInlineeLinesSubsectionRef &Lines) {
+ auto Result = std::make_shared<YAMLInlineeLinesSubsection>();
+
+ Result->InlineeLines.HasExtraFiles = Lines.hasExtraFiles();
+ for (const auto &IL : Lines) {
+ InlineeSite Site;
+ auto ExpF = getFileName(Strings, Checksums, IL.Header->FileID);
+ if (!ExpF)
+ return ExpF.takeError();
+ Site.FileName = *ExpF;
+ Site.Inlinee = IL.Header->Inlinee.getIndex();
+ Site.SourceLineNum = IL.Header->SourceLineNum;
+ if (Lines.hasExtraFiles()) {
+ for (const auto EF : IL.ExtraFiles) {
+ auto ExpF2 = getFileName(Strings, Checksums, EF);
+ if (!ExpF2)
+ return ExpF2.takeError();
+ Site.ExtraFiles.push_back(*ExpF2);
+ }
+ }
+ Result->InlineeLines.Sites.push_back(Site);
+ }
+ return Result;
+}
+
+Expected<std::vector<std::unique_ptr<DebugSubsection>>>
+llvm::CodeViewYAML::convertSubsectionList(
+ ArrayRef<YAMLDebugSubsection> Subsections,
+ DebugStringTableSubsection &Strings) {
+ std::vector<std::unique_ptr<DebugSubsection>> Result;
+ if (Subsections.empty())
+ return Result;
+
+ auto Checksums = findChecksums(Subsections);
+ if (!Checksums)
+ return Checksums.takeError();
+ auto ChecksumsBase = Checksums->toCodeViewSubsection(&Strings, nullptr);
+ DebugChecksumsSubsection &CS =
+ llvm::cast<DebugChecksumsSubsection>(*ChecksumsBase);
+ for (const auto &SS : Subsections) {
+ // We've already converted the checksums subsection, don't do it
+ // twice.
+ std::unique_ptr<DebugSubsection> CVS;
+ if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
+ CVS = std::move(ChecksumsBase);
+ else
+ CVS = SS.Subsection->toCodeViewSubsection(&Strings, &CS);
+ Result.push_back(std::move(CVS));
+ }
+ return std::move(Result);
+}
+
+namespace {
+struct SubsectionConversionVisitor : public DebugSubsectionVisitor {
+ explicit SubsectionConversionVisitor(
+ const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &Checksums)
+ : Strings(Strings), Checksums(Checksums) {}
+
+ Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override;
+ Error visitLines(DebugLinesSubsectionRef &Lines) override;
+ Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums) override;
+ Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees) override;
+
+ YAMLDebugSubsection Subsection;
+
+private:
+ const DebugStringTableSubsectionRef &Strings;
+ const DebugChecksumsSubsectionRef &Checksums;
+};
+
+Error SubsectionConversionVisitor::visitUnknown(
+ DebugUnknownSubsectionRef &Unknown) {
+ return make_error<CodeViewError>(cv_error_code::operation_unsupported);
+}
+
+Error SubsectionConversionVisitor::visitLines(DebugLinesSubsectionRef &Lines) {
+ auto Result =
+ YAMLLinesSubsection::fromCodeViewSubsection(Strings, Checksums, Lines);
+ if (!Result)
+ return Result.takeError();
+ Subsection.Subsection = *Result;
+ return Error::success();
+}
+
+Error SubsectionConversionVisitor::visitFileChecksums(
+ DebugChecksumsSubsectionRef &Checksums) {
+ auto Result =
+ YAMLChecksumsSubsection::fromCodeViewSubsection(Strings, Checksums);
+ if (!Result)
+ return Result.takeError();
+ Subsection.Subsection = *Result;
+ return Error::success();
+}
+
+Error SubsectionConversionVisitor::visitInlineeLines(
+ DebugInlineeLinesSubsectionRef &Inlinees) {
+ auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection(
+ Strings, Checksums, Inlinees);
+ if (!Result)
+ return Result.takeError();
+ Subsection.Subsection = *Result;
+ return Error::success();
+}
+}
+
+Expected<YAMLDebugSubsection> YAMLDebugSubsection::fromCodeViewSubection(
+ const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &Checksums,
+ const DebugSubsectionRecord &SS) {
+ SubsectionConversionVisitor V(Strings, Checksums);
+ if (auto EC = visitDebugSubsection(SS, V))
+ return std::move(EC);
+
+ return V.Subsection;
}
OpenPOWER on IntegriCloud