diff options
Diffstat (limited to 'llvm')
20 files changed, 663 insertions, 27 deletions
diff --git a/llvm/include/llvm/DebugInfo/CodeView/CodeView.h b/llvm/include/llvm/DebugInfo/CodeView/CodeView.h index 9890263ae2d..251c9d1ae62 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CodeView.h @@ -575,6 +575,24 @@ struct FrameData { }; }; +// 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) { diff --git a/llvm/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h b/llvm/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h new file mode 100644 index 00000000000..f755b23422c --- /dev/null +++ b/llvm/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h @@ -0,0 +1,64 @@ +//===- 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 diff --git a/llvm/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h b/llvm/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h new file mode 100644 index 00000000000..d9bb56e717c --- /dev/null +++ b/llvm/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h @@ -0,0 +1,88 @@ +//===- 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 diff --git a/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h b/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h index 55bef491c97..6fa62441e04 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h +++ b/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h @@ -20,6 +20,8 @@ namespace codeview { class DebugChecksumsSubsectionRef; class DebugSubsectionRecord; class DebugInlineeLinesSubsectionRef; +class DebugCrossModuleExportsSubsectionRef; +class DebugCrossModuleImportsSubsectionRef; class DebugLinesSubsectionRef; class DebugUnknownSubsectionRef; @@ -42,6 +44,16 @@ public: 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(); } }; diff --git a/llvm/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h b/llvm/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h index a6d4d404415..af9d05c7236 100644 --- a/llvm/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h +++ b/llvm/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h @@ -33,6 +33,11 @@ namespace detail { struct YAMLSubsectionBase; } +struct YAMLCrossModuleImport { + StringRef ModuleName; + std::vector<uint32_t> ImportIds; +}; + struct SourceLineEntry { uint32_t Offset; uint32_t LineStart; diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt index 410b89bc949..c543a6e9ae1 100644 --- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt @@ -3,11 +3,9 @@ add_llvm_library(LLVMDebugInfoCodeView 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 @@ -16,6 +14,10 @@ add_llvm_library(LLVMDebugInfoCodeView DebugSubsectionRecord.cpp DebugSubsectionVisitor.cpp DebugSymbolsSubsection.cpp + EnumTables.cpp + Formatters.cpp + LazyRandomTypeCollection.cpp + Line.cpp RecordSerialization.cpp SymbolRecordMapping.cpp SymbolDumper.cpp diff --git a/llvm/lib/DebugInfo/CodeView/DebugCrossExSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugCrossExSubsection.cpp new file mode 100644 index 00000000000..d8dca5d5c63 --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/DebugCrossExSubsection.cpp @@ -0,0 +1,49 @@ +//===- 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(); +} diff --git a/llvm/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp new file mode 100644 index 00000000000..e0ceefcd5fa --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp @@ -0,0 +1,91 @@ +//===- 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(); +} diff --git a/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp index cfd1c5d3ab0..0cf31846f25 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp @@ -38,6 +38,8 @@ Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream, case DebugSubsectionKind::FileChecksums: case DebugSubsectionKind::Lines: case DebugSubsectionKind::InlineeLines: + case DebugSubsectionKind::CrossScopeExports: + case DebugSubsectionKind::CrossScopeImports: break; default: llvm_unreachable("Unexpected debug fragment kind!"); diff --git a/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp b/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp index f2c4dea8685..93fe4e1914b 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp @@ -10,6 +10,8 @@ #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" @@ -44,6 +46,18 @@ Error llvm::codeview::visitDebugSubsection(const DebugSubsectionRecord &R, 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); diff --git a/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp b/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp index c4ff30011a1..4186f2eb6ba 100644 --- a/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp @@ -90,14 +90,14 @@ Error ModuleDebugStreamRef::commit() { return Error::success(); } 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; } diff --git a/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp b/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp index 58202577672..091ac67035d 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp @@ -105,10 +105,12 @@ Error PublicsStream::reload() { "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, diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp index 21d29835624..fc3d0ceaa15 100644 --- a/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp +++ b/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp @@ -18,6 +18,8 @@ #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" @@ -38,13 +40,19 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineBlock) 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) @@ -114,6 +122,35 @@ struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase { 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) { @@ -161,6 +198,17 @@ void MappingTraits<SourceLineBlock>::mapping(IO &IO, SourceLineBlock &Obj) { 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); @@ -196,6 +244,16 @@ void YAMLInlineeLinesSubsection::map(IO &IO) { 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()) { @@ -206,6 +264,12 @@ void MappingTraits<YAMLDebugSubsection>::mapping( 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!"); } @@ -213,14 +277,15 @@ void MappingTraits<YAMLDebugSubsection>::mapping( 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( @@ -285,6 +350,28 @@ YAMLInlineeLinesSubsection::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) { @@ -391,6 +478,31 @@ YAMLInlineeLinesSubsection::fromCodeViewSubsection( 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, @@ -400,11 +512,11 @@ llvm::CodeViewYAML::convertSubsectionList( 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. @@ -412,7 +524,8 @@ llvm::CodeViewYAML::convertSubsectionList( 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); @@ -429,6 +542,10 @@ struct SubsectionConversionVisitor : public DebugSubsectionVisitor { 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; @@ -470,6 +587,26 @@ Error SubsectionConversionVisitor::visitInlineeLines( 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( diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp index bd97af3a932..fa3f1e0b60a 100644 --- a/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp +++ b/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp @@ -47,6 +47,18 @@ LLVM_YAML_DECLARE_ENUM_TRAITS(RegisterId) 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(); @@ -264,6 +276,7 @@ template <> void SymbolRecordImpl<InlineSiteSym>::map(IO &IO) { template <> void SymbolRecordImpl<LocalSym>::map(IO &IO) { IO.mapRequired("Type", Symbol.Type); IO.mapRequired("Flags", Symbol.Flags); + IO.mapRequired("VarName", Symbol.Name); } diff --git a/llvm/test/DebugInfo/PDB/Inputs/cross-module-import-export.yaml b/llvm/test/DebugInfo/PDB/Inputs/cross-module-import-export.yaml new file mode 100644 index 00000000000..4c3f28c3102 --- /dev/null +++ b/llvm/test/DebugInfo/PDB/Inputs/cross-module-import-export.yaml @@ -0,0 +1,24 @@ +DbiStream:
+ Modules:
+ - Module: 'Foo.obj'
+ ObjFile: 'Foo.obj'
+ Subsections:
+ - !CrossModuleExports
+ Exports:
+ - LocalId: 4852
+ GlobalId: 9283
+ - LocalId: 2147487875
+ GlobalId: 9123
+ - Module: 'Bar.obj'
+ ObjFile: 'Bar.obj'
+ Subsections:
+ - !CrossModuleExports
+ Exports:
+ - LocalId: 4265
+ GlobalId: 6097
+ - LocalId: 4297
+ GlobalId: 4677
+ - !CrossModuleImports
+ Imports:
+ - Module: 'Foo.obj'
+ Imports: [ 4852, 2147487875 ]
diff --git a/llvm/test/DebugInfo/PDB/cross-module-import-export.test b/llvm/test/DebugInfo/PDB/cross-module-import-export.test new file mode 100644 index 00000000000..fda7495dd87 --- /dev/null +++ b/llvm/test/DebugInfo/PDB/cross-module-import-export.test @@ -0,0 +1,60 @@ +; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/cross-module-import-export.yaml
+
+; RUN: llvm-pdbdump pdb2yaml -all -no-file-headers %t.pdb | FileCheck --check-prefix=YAML %s
+; RUN: llvm-pdbdump raw -all %t.pdb | FileCheck --check-prefix=RAW %s
+
+YAML: Modules:
+YAML-NEXT: - Module: Foo.obj
+YAML-NEXT: ObjFile: Foo.obj
+YAML-NEXT: Subsections:
+YAML-NEXT: - !CrossModuleExports
+YAML-NEXT: Exports:
+YAML-NEXT: - LocalId: 4852
+YAML-NEXT: GlobalId: 9283
+YAML-NEXT: - LocalId: 2147487875
+YAML-NEXT: GlobalId: 9123
+YAML: - Module: Bar.obj
+YAML-NEXT: ObjFile: Bar.obj
+YAML-NEXT: Subsections:
+YAML-NEXT: - !CrossModuleExports
+YAML-NEXT: Exports:
+YAML-NEXT: - LocalId: 4265
+YAML-NEXT: GlobalId: 6097
+YAML-NEXT: - LocalId: 4297
+YAML-NEXT: GlobalId: 4677
+YAML-NEXT: - !CrossModuleImports
+YAML-NEXT: Imports:
+YAML-NEXT: - Module: Foo.obj
+YAML-NEXT: Imports: [ 4852, 2147487875 ]
+
+
+RAW: DBI Stream {
+RAW: Modules [
+RAW-NEXT: {
+RAW-NEXT: Name: Foo.obj
+RAW: LineInfo [
+RAW-NEXT: CrossModuleExports {
+RAW-NEXT: Local: 0x12F4
+RAW-NEXT: Global: 0x2443
+RAW-NEXT: Local: 0x80001083
+RAW-NEXT: Global: 0x23A3
+RAW-NEXT: }
+RAW-NEXT: ]
+RAW-NEXT: }
+RAW-NEXT: {
+RAW-NEXT: Name: Bar.obj
+RAW: LineInfo [
+RAW-NEXT: CrossModuleExports {
+RAW-NEXT: Local: 0x10A9
+RAW-NEXT: Global: 0x17D1
+RAW-NEXT: Local: 0x10C9
+RAW-NEXT: Global: 0x1245
+RAW-NEXT: }
+RAW-NEXT: CrossModuleImports {
+RAW-NEXT: Module: Foo.obj
+RAW-NEXT: Imports: [0x12F4, 0x80001083]
+RAW-NEXT: }
+RAW-NEXT: ]
+RAW-NEXT: }
+RAW-NEXT: ]
+RAW-NEXT: }
\ No newline at end of file diff --git a/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp b/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp index 78971eb5879..3113a3250f0 100644 --- a/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp +++ b/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp @@ -10,6 +10,8 @@ #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" @@ -48,18 +50,34 @@ Error C13DebugFragmentVisitor::visitInlineeLines( 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(); diff --git a/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.h b/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.h index a12f282c4c5..1865295da38 100644 --- a/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.h +++ b/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.h @@ -38,12 +38,20 @@ public: 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); @@ -51,6 +59,8 @@ protected: 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; }; diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp index 31c342cd0f5..cd5bf8a095d 100644 --- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -16,6 +16,8 @@ #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" @@ -174,6 +176,32 @@ public: 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); diff --git a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp index ee72b90b12d..c28885104ca 100644 --- a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -17,7 +17,6 @@ #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" |

