};
};
+// Corresponds to LocalIdAndGlobalIdPair structure.
+// This structure information allows cross-referencing between PDBs. For
+// example, when a PDB is being built during compilation it is not yet known
+// what other modules may end up in the PDB at link time. So certain types of
+// IDs may clash between the various compile time PDBs. For each affected
+// module, a subsection would be put into the PDB containing a mapping from its
+// local IDs to a single ID namespace for all items in the PDB file.
+struct CrossModuleExport {
+ support::ulittle32_t Local;
+ support::ulittle32_t Global;
+};
+
+struct CrossModuleImport {
+ support::ulittle32_t ModuleNameOffset;
+ support::ulittle32_t Count; // Number of elements
+ // support::ulittle32_t ids[Count]; // id from referenced module
+};
+
enum class CodeViewContainer { ObjectFile, Pdb };
inline uint32_t alignOf(CodeViewContainer Container) {
--- /dev/null
+//===- DebugCrossExSubsection.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSEXSUBSECTION_H
+#define LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSEXSUBSECTION_H
+
+#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+
+#include <map>
+
+namespace llvm {
+namespace codeview {
+class DebugCrossModuleExportsSubsectionRef final : public DebugSubsectionRef {
+ typedef FixedStreamArray<CrossModuleExport> ReferenceArray;
+ typedef ReferenceArray::Iterator Iterator;
+
+public:
+ DebugCrossModuleExportsSubsectionRef()
+ : DebugSubsectionRef(DebugSubsectionKind::CrossScopeExports) {}
+
+ static bool classof(const DebugSubsectionRef *S) {
+ return S->kind() == DebugSubsectionKind::CrossScopeExports;
+ }
+
+ Error initialize(BinaryStreamReader Reader);
+ Error initialize(BinaryStreamRef Stream);
+
+ Iterator begin() const { return References.begin(); }
+ Iterator end() const { return References.end(); }
+
+private:
+ FixedStreamArray<CrossModuleExport> References;
+};
+
+class DebugCrossModuleExportsSubsection final : public DebugSubsection {
+public:
+ DebugCrossModuleExportsSubsection()
+ : DebugSubsection(DebugSubsectionKind::CrossScopeExports) {}
+
+ static bool classof(const DebugSubsection *S) {
+ return S->kind() == DebugSubsectionKind::CrossScopeExports;
+ }
+
+ void addMapping(uint32_t Local, uint32_t Global);
+
+ uint32_t calculateSerializedSize() const override;
+ Error commit(BinaryStreamWriter &Writer) const override;
+
+private:
+ std::map<uint32_t, uint32_t> Mappings;
+};
+}
+}
+
+#endif
--- /dev/null
+//===- DebugCrossExSubsection.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSIMPSUBSECTION_H
+#define LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSIMPSUBSECTION_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+namespace codeview {
+
+struct CrossModuleImportItem {
+ const CrossModuleImport *Header = nullptr;
+ llvm::FixedStreamArray<support::ulittle32_t> Imports;
+};
+}
+}
+
+namespace llvm {
+template <> struct VarStreamArrayExtractor<codeview::CrossModuleImportItem> {
+public:
+ typedef void ContextType;
+
+ static Error extract(BinaryStreamRef Stream, uint32_t &Len,
+ codeview::CrossModuleImportItem &Item);
+};
+}
+
+namespace llvm {
+namespace codeview {
+class DebugStringTableSubsection;
+
+class DebugCrossModuleImportsSubsectionRef final : public DebugSubsectionRef {
+ typedef VarStreamArray<CrossModuleImportItem> ReferenceArray;
+ typedef ReferenceArray::Iterator Iterator;
+
+public:
+ DebugCrossModuleImportsSubsectionRef()
+ : DebugSubsectionRef(DebugSubsectionKind::CrossScopeImports) {}
+
+ static bool classof(const DebugSubsectionRef *S) {
+ return S->kind() == DebugSubsectionKind::CrossScopeImports;
+ }
+
+ Error initialize(BinaryStreamReader Reader);
+ Error initialize(BinaryStreamRef Stream);
+
+ Iterator begin() const { return References.begin(); }
+ Iterator end() const { return References.end(); }
+
+private:
+ ReferenceArray References;
+};
+
+class DebugCrossModuleImportsSubsection final : public DebugSubsection {
+public:
+ explicit DebugCrossModuleImportsSubsection(
+ DebugStringTableSubsection &Strings)
+ : DebugSubsection(DebugSubsectionKind::CrossScopeImports),
+ Strings(Strings) {}
+
+ static bool classof(const DebugSubsection *S) {
+ return S->kind() == DebugSubsectionKind::CrossScopeImports;
+ }
+
+ void addImport(StringRef Module, uint32_t ImportId);
+
+ uint32_t calculateSerializedSize() const override;
+ Error commit(BinaryStreamWriter &Writer) const override;
+
+private:
+ DebugStringTableSubsection &Strings;
+ StringMap<std::vector<support::ulittle32_t>> Mappings;
+};
+}
+}
+
+#endif
class DebugChecksumsSubsectionRef;
class DebugSubsectionRecord;
class DebugInlineeLinesSubsectionRef;
+class DebugCrossModuleExportsSubsectionRef;
+class DebugCrossModuleImportsSubsectionRef;
class DebugLinesSubsectionRef;
class DebugUnknownSubsectionRef;
return Error::success();
}
+ virtual Error
+ visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE) {
+ return Error::success();
+ }
+
+ virtual Error
+ visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE) {
+ return Error::success();
+ }
+
virtual Error finished() { return Error::success(); }
};
struct YAMLSubsectionBase;
}
+struct YAMLCrossModuleImport {
+ StringRef ModuleName;
+ std::vector<uint32_t> ImportIds;
+};
+
struct SourceLineEntry {
uint32_t Offset;
uint32_t LineStart;
CodeViewRecordIO.cpp
CVSymbolVisitor.cpp
CVTypeVisitor.cpp
- EnumTables.cpp
- Formatters.cpp
- LazyRandomTypeCollection.cpp
- Line.cpp
DebugChecksumsSubsection.cpp
+ DebugCrossExSubsection.cpp
+ DebugCrossImpSubsection.cpp
DebugFrameDataSubsection.cpp
DebugInlineeLinesSubsection.cpp
DebugLinesSubsection.cpp
DebugSubsectionRecord.cpp
DebugSubsectionVisitor.cpp
DebugSymbolsSubsection.cpp
+ EnumTables.cpp
+ Formatters.cpp
+ LazyRandomTypeCollection.cpp
+ Line.cpp
RecordSerialization.cpp
SymbolRecordMapping.cpp
SymbolDumper.cpp
--- /dev/null
+//===- DebugCrossExSubsection.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error DebugCrossModuleExportsSubsectionRef::initialize(
+ BinaryStreamReader Reader) {
+ if (Reader.bytesRemaining() % sizeof(CrossModuleExport) != 0)
+ return make_error<CodeViewError>(
+ cv_error_code::corrupt_record,
+ "Cross Scope Exports section is an invalid size!");
+
+ uint32_t Size = Reader.bytesRemaining() / sizeof(CrossModuleExport);
+ return Reader.readArray(References, Size);
+}
+
+Error DebugCrossModuleExportsSubsectionRef::initialize(BinaryStreamRef Stream) {
+ BinaryStreamReader Reader(Stream);
+ return initialize(Reader);
+}
+
+void DebugCrossModuleExportsSubsection::addMapping(uint32_t Local,
+ uint32_t Global) {
+ Mappings[Local] = Global;
+}
+
+uint32_t DebugCrossModuleExportsSubsection::calculateSerializedSize() const {
+ return Mappings.size() * sizeof(CrossModuleExport);
+}
+
+Error DebugCrossModuleExportsSubsection::commit(
+ BinaryStreamWriter &Writer) const {
+ for (const auto &M : Mappings) {
+ if (auto EC = Writer.writeObject(M))
+ return EC;
+ }
+ return Error::success();
+}
--- /dev/null
+//===- DebugCrossImpSubsection.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+namespace llvm {
+Error VarStreamArrayExtractor<CrossModuleImportItem>::extract(
+ BinaryStreamRef Stream, uint32_t &Len,
+ codeview::CrossModuleImportItem &Item) {
+ BinaryStreamReader Reader(Stream);
+ if (Reader.bytesRemaining() < sizeof(CrossModuleImport))
+ return make_error<CodeViewError>(
+ cv_error_code::insufficient_buffer,
+ "Not enough bytes for a Cross Module Import Header!");
+ if (auto EC = Reader.readObject(Item.Header))
+ return EC;
+ if (Reader.bytesRemaining() < Item.Header->Count * sizeof(uint32_t))
+ return make_error<CodeViewError>(
+ cv_error_code::insufficient_buffer,
+ "Not enough to read specified number of Cross Module References!");
+ if (auto EC = Reader.readArray(Item.Imports, Item.Header->Count))
+ return EC;
+ return Error::success();
+}
+}
+
+Error DebugCrossModuleImportsSubsectionRef::initialize(
+ BinaryStreamReader Reader) {
+ return Reader.readArray(References, Reader.bytesRemaining());
+}
+
+Error DebugCrossModuleImportsSubsectionRef::initialize(BinaryStreamRef Stream) {
+ BinaryStreamReader Reader(Stream);
+ return initialize(Reader);
+}
+
+void DebugCrossModuleImportsSubsection::addImport(StringRef Module,
+ uint32_t ImportId) {
+ Strings.insert(Module);
+ std::vector<support::ulittle32_t> Targets = {support::ulittle32_t(ImportId)};
+ auto Result = Mappings.insert(std::make_pair(Module, Targets));
+ if (!Result.second)
+ Result.first->getValue().push_back(Targets[0]);
+}
+
+uint32_t DebugCrossModuleImportsSubsection::calculateSerializedSize() const {
+ uint32_t Size = 0;
+ for (const auto &Item : Mappings) {
+ Size += sizeof(CrossModuleImport);
+ Size += sizeof(support::ulittle32_t) * Item.second.size();
+ }
+ return Size;
+}
+
+Error DebugCrossModuleImportsSubsection::commit(
+ BinaryStreamWriter &Writer) const {
+ using T = decltype(&*Mappings.begin());
+ std::vector<T> Ids;
+ Ids.reserve(Mappings.size());
+
+ for (const auto &M : Mappings)
+ Ids.push_back(&M);
+
+ std::sort(Ids.begin(), Ids.end(), [this](const T &L1, const T &L2) {
+ return Strings.getStringId(L1->getKey()) <
+ Strings.getStringId(L2->getKey());
+ });
+
+ for (const auto &Item : Ids) {
+ CrossModuleImport Imp;
+ Imp.ModuleNameOffset = Strings.getStringId(Item->getKey());
+ Imp.Count = Item->getValue().size();
+ if (auto EC = Writer.writeObject(Imp))
+ return EC;
+ if (auto EC = Writer.writeArray(makeArrayRef(Item->getValue())))
+ return EC;
+ }
+ return Error::success();
+}
case DebugSubsectionKind::FileChecksums:
case DebugSubsectionKind::Lines:
case DebugSubsectionKind::InlineeLines:
+ case DebugSubsectionKind::CrossScopeExports:
+ case DebugSubsectionKind::CrossScopeImports:
break;
default:
llvm_unreachable("Unexpected debug fragment kind!");
#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
return EC;
return V.visitInlineeLines(Fragment);
}
+ case DebugSubsectionKind::CrossScopeExports: {
+ DebugCrossModuleExportsSubsectionRef Section;
+ if (auto EC = Section.initialize(Reader))
+ return EC;
+ return V.visitCrossModuleExports(Section);
+ }
+ case DebugSubsectionKind::CrossScopeImports: {
+ DebugCrossModuleImportsSubsectionRef Section;
+ if (auto EC = Section.initialize(Reader))
+ return EC;
+ return V.visitCrossModuleImports(Section);
+ }
default: {
DebugUnknownSubsectionRef Fragment(R.kind(), R.getRecordData());
return V.visitUnknown(Fragment);
Expected<codeview::DebugChecksumsSubsectionRef>
ModuleDebugStreamRef::findChecksumsSubsection() const {
+ codeview::DebugChecksumsSubsectionRef Result;
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);
+ return Result;
}
"Could not read a thunk map."));
// Something called "section map" follows.
- if (auto EC = Reader.readArray(SectionOffsets, Header->NumSections))
- return joinErrors(std::move(EC),
- make_error<RawError>(raw_error_code::corrupt_file,
- "Could not read a section map."));
+ if (Reader.bytesRemaining() > 0) {
+ if (auto EC = Reader.readArray(SectionOffsets, Header->NumSections))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Could not read a section map."));
+ }
if (Reader.bytesRemaining() > 0)
return make_error<RawError>(raw_error_code::corrupt_file,
#include "llvm/ADT/StringSwitch.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineInfo)
LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeSite)
LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModuleExport)
+LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLCrossModuleImport)
LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
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(CrossModuleExport)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLCrossModuleImport)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleImportItem)
LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry)
LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceColumnEntry)
LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceFileChecksumEntry)
InlineeInfo InlineeLines;
};
+
+struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase {
+ YAMLCrossModuleExportsSubsection()
+ : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeExports) {}
+
+ void map(IO &IO) override;
+ std::unique_ptr<DebugSubsection>
+ toCodeViewSubsection(DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const override;
+ static Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
+ fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports);
+
+ std::vector<CrossModuleExport> Exports;
+};
+
+struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase {
+ YAMLCrossModuleImportsSubsection()
+ : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeImports) {}
+
+ void map(IO &IO) override;
+ std::unique_ptr<DebugSubsection>
+ toCodeViewSubsection(DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const override;
+ static Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
+ fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
+ const DebugCrossModuleImportsSubsectionRef &Imports);
+
+ std::vector<YAMLCrossModuleImport> Imports;
+};
}
void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) {
IO.mapRequired("Columns", Obj.Columns);
}
+void MappingTraits<CrossModuleExport>::mapping(IO &IO, CrossModuleExport &Obj) {
+ IO.mapRequired("LocalId", Obj.Local);
+ IO.mapRequired("GlobalId", Obj.Global);
+}
+
+void MappingTraits<YAMLCrossModuleImport>::mapping(IO &IO,
+ YAMLCrossModuleImport &Obj) {
+ IO.mapRequired("Module", Obj.ModuleName);
+ IO.mapRequired("Imports", Obj.ImportIds);
+}
+
void MappingTraits<SourceFileChecksumEntry>::mapping(
IO &IO, SourceFileChecksumEntry &Obj) {
IO.mapRequired("FileName", Obj.FileName);
IO.mapRequired("Sites", InlineeLines.Sites);
}
+void YAMLCrossModuleExportsSubsection::map(IO &IO) {
+ IO.mapTag("!CrossModuleExports", true);
+ IO.mapOptional("Exports", Exports);
+}
+
+void YAMLCrossModuleImportsSubsection::map(IO &IO) {
+ IO.mapTag("!CrossModuleImports", true);
+ IO.mapOptional("Imports", Imports);
+}
+
void MappingTraits<YAMLDebugSubsection>::mapping(
IO &IO, YAMLDebugSubsection &Subsection) {
if (!IO.outputting()) {
Subsection.Subsection = std::make_shared<YAMLLinesSubsection>();
} else if (IO.mapTag("!InlineeLines")) {
Subsection.Subsection = std::make_shared<YAMLInlineeLinesSubsection>();
+ } else if (IO.mapTag("!CrossModuleExports")) {
+ Subsection.Subsection =
+ std::make_shared<YAMLCrossModuleExportsSubsection>();
+ } else if (IO.mapTag("!CrossModuleImports")) {
+ Subsection.Subsection =
+ std::make_shared<YAMLCrossModuleImportsSubsection>();
} else {
llvm_unreachable("Unexpected subsection tag!");
}
Subsection.Subsection->map(IO);
}
-static Expected<const YAMLChecksumsSubsection &>
+static std::shared_ptr<YAMLChecksumsSubsection>
findChecksums(ArrayRef<YAMLDebugSubsection> Subsections) {
for (const auto &SS : Subsections) {
if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) {
- return static_cast<const YAMLChecksumsSubsection &>(*SS.Subsection);
+ return std::static_pointer_cast<YAMLChecksumsSubsection>(SS.Subsection);
}
}
- return make_error<CodeViewError>(cv_error_code::no_records);
+
+ return nullptr;
}
std::unique_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
return llvm::cast<DebugSubsection>(std::move(Result));
}
+std::unique_ptr<DebugSubsection>
+YAMLCrossModuleExportsSubsection::toCodeViewSubsection(
+ DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const {
+ auto Result = llvm::make_unique<DebugCrossModuleExportsSubsection>();
+ for (const auto &M : Exports)
+ Result->addMapping(M.Local, M.Global);
+ return llvm::cast<DebugSubsection>(std::move(Result));
+}
+
+std::unique_ptr<DebugSubsection>
+YAMLCrossModuleImportsSubsection::toCodeViewSubsection(
+ DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const {
+ auto Result = llvm::make_unique<DebugCrossModuleImportsSubsection>(*Strings);
+ for (const auto &M : Imports) {
+ for (const auto Id : M.ImportIds)
+ Result->addImport(M.ModuleName, Id);
+ }
+ return llvm::cast<DebugSubsection>(std::move(Result));
+}
+
static Expected<SourceFileChecksumEntry>
convertOneChecksum(const DebugStringTableSubsectionRef &Strings,
const FileChecksumEntry &CS) {
return Result;
}
+Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
+YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(
+ const DebugCrossModuleExportsSubsectionRef &Exports) {
+ auto Result = std::make_shared<YAMLCrossModuleExportsSubsection>();
+ Result->Exports.assign(Exports.begin(), Exports.end());
+ return Result;
+}
+
+Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
+YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
+ const DebugStringTableSubsectionRef &Strings,
+ const DebugCrossModuleImportsSubsectionRef &Imports) {
+ auto Result = std::make_shared<YAMLCrossModuleImportsSubsection>();
+ for (const auto &CMI : Imports) {
+ YAMLCrossModuleImport YCMI;
+ auto ExpectedStr = Strings.getString(CMI.Header->ModuleNameOffset);
+ if (!ExpectedStr)
+ return ExpectedStr.takeError();
+ YCMI.ModuleName = *ExpectedStr;
+ YCMI.ImportIds.assign(CMI.Imports.begin(), CMI.Imports.end());
+ Result->Imports.push_back(YCMI);
+ }
+ return Result;
+}
+
Expected<std::vector<std::unique_ptr<DebugSubsection>>>
llvm::CodeViewYAML::convertSubsectionList(
ArrayRef<YAMLDebugSubsection> Subsections,
return std::move(Result);
auto Checksums = findChecksums(Subsections);
- if (!Checksums)
- return Checksums.takeError();
- auto ChecksumsBase = Checksums->toCodeViewSubsection(&Strings, nullptr);
- DebugChecksumsSubsection &CS =
- llvm::cast<DebugChecksumsSubsection>(*ChecksumsBase);
+ std::unique_ptr<DebugSubsection> ChecksumsBase;
+ if (Checksums)
+ ChecksumsBase = Checksums->toCodeViewSubsection(&Strings, nullptr);
+ DebugChecksumsSubsection *CS =
+ static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get());
for (const auto &SS : Subsections) {
// We've already converted the checksums subsection, don't do it
// twice.
if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
CVS = std::move(ChecksumsBase);
else
- CVS = SS.Subsection->toCodeViewSubsection(&Strings, &CS);
+ CVS = SS.Subsection->toCodeViewSubsection(&Strings, CS);
+ assert(CVS != nullptr);
Result.push_back(std::move(CVS));
}
return std::move(Result);
Error visitLines(DebugLinesSubsectionRef &Lines) override;
Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums) override;
Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees) override;
+ Error visitCrossModuleExports(
+ DebugCrossModuleExportsSubsectionRef &Checksums) override;
+ Error visitCrossModuleImports(
+ DebugCrossModuleImportsSubsectionRef &Inlinees) override;
YAMLDebugSubsection Subsection;
Subsection.Subsection = *Result;
return Error::success();
}
+
+Error SubsectionConversionVisitor::visitCrossModuleExports(
+ DebugCrossModuleExportsSubsectionRef &Exports) {
+ auto Result =
+ YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports);
+ if (!Result)
+ return Result.takeError();
+ Subsection.Subsection = *Result;
+ return Error::success();
+}
+
+Error SubsectionConversionVisitor::visitCrossModuleImports(
+ DebugCrossModuleImportsSubsectionRef &Imports) {
+ auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
+ Strings, Imports);
+ if (!Result)
+ return Result.takeError();
+ Subsection.Subsection = *Result;
+ return Error::success();
+}
}
Expected<YAMLDebugSubsection> YAMLDebugSubsection::fromCodeViewSubection(
LLVM_YAML_DECLARE_ENUM_TRAITS(TrampolineType)
LLVM_YAML_DECLARE_ENUM_TRAITS(ThunkOrdinal)
+LLVM_YAML_STRONG_TYPEDEF(llvm::StringRef, TypeName)
+
+LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeName, true)
+
+StringRef ScalarTraits<TypeName>::input(StringRef S, void *V, TypeName &T) {
+ return ScalarTraits<StringRef>::input(S, V, T.value);
+}
+void ScalarTraits<TypeName>::output(const TypeName &T, void *V,
+ llvm::raw_ostream &R) {
+ ScalarTraits<StringRef>::output(T.value, V, R);
+}
+
void ScalarEnumerationTraits<SymbolKind>::enumeration(IO &io,
SymbolKind &Value) {
auto SymbolNames = getSymbolTypeNames();
template <> void SymbolRecordImpl<LocalSym>::map(IO &IO) {
IO.mapRequired("Type", Symbol.Type);
IO.mapRequired("Flags", Symbol.Flags);
+
IO.mapRequired("VarName", Symbol.Name);
}
--- /dev/null
+DbiStream: \r
+ Modules: \r
+ - Module: 'Foo.obj'\r
+ ObjFile: 'Foo.obj'\r
+ Subsections: \r
+ - !CrossModuleExports\r
+ Exports: \r
+ - LocalId: 4852\r
+ GlobalId: 9283\r
+ - LocalId: 2147487875\r
+ GlobalId: 9123\r
+ - Module: 'Bar.obj'\r
+ ObjFile: 'Bar.obj'\r
+ Subsections: \r
+ - !CrossModuleExports\r
+ Exports: \r
+ - LocalId: 4265\r
+ GlobalId: 6097\r
+ - LocalId: 4297\r
+ GlobalId: 4677\r
+ - !CrossModuleImports\r
+ Imports: \r
+ - Module: 'Foo.obj'\r
+ Imports: [ 4852, 2147487875 ]\r
--- /dev/null
+; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/cross-module-import-export.yaml\r
+\r
+; RUN: llvm-pdbdump pdb2yaml -all -no-file-headers %t.pdb | FileCheck --check-prefix=YAML %s\r
+; RUN: llvm-pdbdump raw -all %t.pdb | FileCheck --check-prefix=RAW %s\r
+\r
+YAML: Modules:\r
+YAML-NEXT: - Module: Foo.obj\r
+YAML-NEXT: ObjFile: Foo.obj\r
+YAML-NEXT: Subsections:\r
+YAML-NEXT: - !CrossModuleExports\r
+YAML-NEXT: Exports:\r
+YAML-NEXT: - LocalId: 4852\r
+YAML-NEXT: GlobalId: 9283\r
+YAML-NEXT: - LocalId: 2147487875\r
+YAML-NEXT: GlobalId: 9123\r
+YAML: - Module: Bar.obj\r
+YAML-NEXT: ObjFile: Bar.obj\r
+YAML-NEXT: Subsections:\r
+YAML-NEXT: - !CrossModuleExports\r
+YAML-NEXT: Exports:\r
+YAML-NEXT: - LocalId: 4265\r
+YAML-NEXT: GlobalId: 6097\r
+YAML-NEXT: - LocalId: 4297\r
+YAML-NEXT: GlobalId: 4677\r
+YAML-NEXT: - !CrossModuleImports\r
+YAML-NEXT: Imports:\r
+YAML-NEXT: - Module: Foo.obj\r
+YAML-NEXT: Imports: [ 4852, 2147487875 ]\r
+\r
+\r
+RAW: DBI Stream {\r
+RAW: Modules [\r
+RAW-NEXT: {\r
+RAW-NEXT: Name: Foo.obj\r
+RAW: LineInfo [\r
+RAW-NEXT: CrossModuleExports {\r
+RAW-NEXT: Local: 0x12F4\r
+RAW-NEXT: Global: 0x2443\r
+RAW-NEXT: Local: 0x80001083\r
+RAW-NEXT: Global: 0x23A3\r
+RAW-NEXT: }\r
+RAW-NEXT: ]\r
+RAW-NEXT: }\r
+RAW-NEXT: {\r
+RAW-NEXT: Name: Bar.obj\r
+RAW: LineInfo [\r
+RAW-NEXT: CrossModuleExports {\r
+RAW-NEXT: Local: 0x10A9\r
+RAW-NEXT: Global: 0x17D1\r
+RAW-NEXT: Local: 0x10C9\r
+RAW-NEXT: Global: 0x1245\r
+RAW-NEXT: }\r
+RAW-NEXT: CrossModuleImports {\r
+RAW-NEXT: Module: Foo.obj\r
+RAW-NEXT: Imports: [0x12F4, 0x80001083]\r
+RAW-NEXT: }\r
+RAW-NEXT: ]\r
+RAW-NEXT: }\r
+RAW-NEXT: ]\r
+RAW-NEXT: }
\ No newline at end of file
#include "C13DebugFragmentVisitor.h"
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
return Error::success();
}
+Error C13DebugFragmentVisitor::visitCrossModuleExports(
+ codeview::DebugCrossModuleExportsSubsectionRef &Exports) {
+ this->CrossExports.push_back(Exports);
+ return Error::success();
+}
+
+Error C13DebugFragmentVisitor::visitCrossModuleImports(
+ codeview::DebugCrossModuleImportsSubsectionRef &Imports) {
+ this->CrossImports.push_back(Imports);
+ return Error::success();
+}
+
Error C13DebugFragmentVisitor::finished() {
- if (!Checksums.hasValue()) {
- assert(Lines.empty());
- return Error::success();
+ if (Checksums.hasValue()) {
+ if (auto EC = handleFileChecksums())
+ return EC;
+
+ if (auto EC = handleLines())
+ return EC;
+
+ if (auto EC = handleInlineeLines())
+ return EC;
}
- if (auto EC = handleFileChecksums())
- return EC;
- if (auto EC = handleLines())
+ if (auto EC = handleCrossModuleExports())
return EC;
- if (auto EC = handleInlineeLines())
+ if (auto EC = handleCrossModuleImports())
return EC;
return Error::success();
Error
visitInlineeLines(codeview::DebugInlineeLinesSubsectionRef &Lines) final;
+ Error visitCrossModuleExports(
+ codeview::DebugCrossModuleExportsSubsectionRef &Lines) final;
+
+ Error visitCrossModuleImports(
+ codeview::DebugCrossModuleImportsSubsectionRef &Imports) final;
+
Error finished() final;
protected:
virtual Error handleFileChecksums() { return Error::success(); }
virtual Error handleLines() { return Error::success(); }
virtual Error handleInlineeLines() { return Error::success(); }
+ virtual Error handleCrossModuleExports() { return Error::success(); }
+ virtual Error handleCrossModuleImports() { return Error::success(); }
Expected<StringRef> getNameFromStringTable(uint32_t Offset);
Expected<StringRef> getNameFromChecksumsBuffer(uint32_t Offset);
Optional<codeview::DebugChecksumsSubsectionRef> Checksums;
std::vector<codeview::DebugInlineeLinesSubsectionRef> InlineeLines;
std::vector<codeview::DebugLinesSubsectionRef> Lines;
+ std::vector<codeview::DebugCrossModuleExportsSubsectionRef> CrossExports;
+ std::vector<codeview::DebugCrossModuleImportsSubsectionRef> CrossImports;
PDBFile &F;
};
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
return Error::success();
}
+ Error handleCrossModuleExports() override {
+ for (const auto &M : CrossExports) {
+ DictScope D(P, "CrossModuleExports");
+ for (const auto &E : M) {
+ P.printHex("Local", E.Local);
+ P.printHex("Global", E.Global);
+ }
+ }
+ return Error::success();
+ }
+
+ Error handleCrossModuleImports() override {
+ for (const auto &M : CrossImports) {
+ DictScope D(P, "CrossModuleImports");
+ for (const auto &ImportGroup : M) {
+ auto Name =
+ getNameFromStringTable(ImportGroup.Header->ModuleNameOffset);
+ if (!Name)
+ return Name.takeError();
+ P.printString("Module", *Name);
+ P.printHexList("Imports", ImportGroup.Imports);
+ }
+ }
+ return Error::success();
+ }
+
private:
Error dumpTypeRecord(StringRef Label, TypeIndex Index) {
CompactTypeDumpVisitor CTDV(IPI, Index, &P);
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"