bool valid() const { return Stream.valid(); }
+ BinaryStreamRef getBuffer() const { return Stream; }
+
private:
BinaryStreamRef Stream;
};
DebugSubsectionRecordBuilder(std::unique_ptr<DebugSubsection> Subsection,
CodeViewContainer Container);
uint32_t calculateSerializedLength();
- Error commit(BinaryStreamWriter &Writer);
+ Error commit(BinaryStreamWriter &Writer) const;
private:
std::unique_ptr<DebugSubsection> Subsection;
static Error extract(BinaryStreamRef Stream, uint32_t &Length,
codeview::DebugSubsectionRecord &Info) {
- // FIXME: We need to pass the container type through to this function, but
- // VarStreamArray doesn't easily support stateful contexts. In practice
- // this isn't super important since the subsection header describes its
- // length and we can just skip it. It's more important when writing.
if (auto EC = codeview::DebugSubsectionRecord::initialize(
Stream, Info, codeview::CodeViewContainer::Pdb))
return EC;
- Length = Info.getRecordLength();
+ Length = alignTo(Info.getRecordLength(), 4);
return Error::success();
}
};
class DebugInlineeLinesSubsectionRef;
class DebugCrossModuleExportsSubsectionRef;
class DebugCrossModuleImportsSubsectionRef;
+class DebugFrameDataSubsectionRef;
class DebugLinesSubsectionRef;
class DebugStringTableSubsectionRef;
+class DebugSymbolsSubsectionRef;
class DebugUnknownSubsectionRef;
struct DebugSubsectionState {
virtual Error
visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE,
const DebugSubsectionState &State) = 0;
+
+ virtual Error visitStringTable(DebugStringTableSubsectionRef &ST,
+ const DebugSubsectionState &State) = 0;
+
+ virtual Error visitSymbols(DebugSymbolsSubsectionRef &CSE,
+ const DebugSubsectionState &State) = 0;
+
+ virtual Error visitFrameData(DebugFrameDataSubsectionRef &FD,
+ const DebugSubsectionState &State) = 0;
};
Error visitDebugSubsection(const DebugSubsectionRecord &R,
Error initialize(BinaryStreamReader Reader);
+ CVSymbolArray::Iterator begin() const { return Records.begin(); }
+ CVSymbolArray::Iterator end() const { return Records.end(); }
+
private:
CVSymbolArray Records;
};
void reset();
+ BumpPtrAllocator &getAllocator() { return RecordStorage; }
+
ArrayRef<ArrayRef<uint8_t>> records() const;
TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record);
TypeIndex insertRecord(const RemappedType &Record);
TypeSerializer Serializer;
public:
- explicit TypeTableBuilder(BumpPtrAllocator &Allocator)
- : Allocator(Allocator), Serializer(Allocator) {}
+ explicit TypeTableBuilder(BumpPtrAllocator &Allocator,
+ bool WriteUnique = true)
+ : Allocator(Allocator), Serializer(Allocator, WriteUnique) {}
TypeTableBuilder(const TypeTableBuilder &) = delete;
TypeTableBuilder &operator=(const TypeTableBuilder &) = delete;
class DebugStringTableSubsection;
class DebugStringTableSubsectionRef;
class DebugChecksumsSubsectionRef;
+class DebugStringTableSubsection;
+class DebugChecksumsSubsection;
}
namespace CodeViewYAML {
struct YAMLSubsectionBase;
}
+struct YAMLFrameData {
+ uint32_t RvaStart;
+ uint32_t CodeSize;
+ uint32_t LocalSize;
+ uint32_t ParamsSize;
+ uint32_t MaxStackSize;
+ StringRef FrameFunc;
+ uint32_t PrologSize;
+ uint32_t SavedRegsSize;
+ uint32_t Flags;
+};
+
struct YAMLCrossModuleImport {
StringRef ModuleName;
std::vector<uint32_t> ImportIds;
};
Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>>
-convertSubsectionList(ArrayRef<YAMLDebugSubsection> Subsections,
- codeview::DebugStringTableSubsection &Strings);
+toCodeViewSubsectionList(BumpPtrAllocator &Allocator,
+ ArrayRef<YAMLDebugSubsection> Subsections,
+ codeview::DebugStringTableSubsection &Strings);
+Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>>
+toCodeViewSubsectionList(
+ BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
+ std::unique_ptr<codeview::DebugStringTableSubsection> &TakeStrings,
+ codeview::DebugStringTableSubsection *StringsRef);
+
+std::unique_ptr<codeview::DebugStringTableSubsection>
+findStringTable(ArrayRef<YAMLDebugSubsection> Sections);
} // namespace CodeViewYAML
} // namespace llvm
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/ObjectYAML/YAML.h"
+#include "llvm/Support/Allocator.h"
namespace llvm {
+namespace codeview {
+class TypeTableBuilder;
+}
namespace CodeViewYAML {
namespace detail {
struct LeafRecordBase;
std::shared_ptr<detail::LeafRecordBase> Leaf;
codeview::CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const;
+ codeview::CVType toCodeViewRecord(codeview::TypeTableBuilder &TS) const;
static Expected<LeafRecord> fromCodeViewRecord(codeview::CVType Type);
};
} // namespace CodeViewYAML
return Error::success();
}
Error DebugStringTableSubsectionRef::initialize(BinaryStreamReader &Reader) {
- return Reader.readStreamRef(Stream, Reader.bytesRemaining());
+ return Reader.readStreamRef(Stream);
}
Expected<StringRef>
}
Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const {
- assert(Writer.bytesRemaining() == StringSize);
- uint32_t MaxOffset = 1;
+ uint32_t Begin = Writer.getOffset();
+ uint32_t End = Begin + StringSize;
for (auto &Pair : Strings) {
StringRef S = Pair.getKey();
- uint32_t Offset = Pair.getValue();
+ uint32_t Offset = Begin + Pair.getValue();
Writer.setOffset(Offset);
if (auto EC = Writer.writeCString(S))
return EC;
- MaxOffset = std::max<uint32_t>(MaxOffset, Offset + S.size() + 1);
+ assert(Writer.getOffset() <= End);
}
- Writer.setOffset(MaxOffset);
- assert(Writer.bytesRemaining() == 0);
+ Writer.setOffset(End);
return Error::success();
}
case DebugSubsectionKind::InlineeLines:
case DebugSubsectionKind::CrossScopeExports:
case DebugSubsectionKind::CrossScopeImports:
+ case DebugSubsectionKind::Symbols:
+ case DebugSubsectionKind::StringTable:
+ case DebugSubsectionKind::FrameData:
break;
default:
llvm_unreachable("Unexpected debug fragment kind!");
}
uint32_t DebugSubsectionRecord::getRecordLength() const {
- uint32_t Result = sizeof(DebugSubsectionHeader) + Data.getLength();
- assert(Result % alignOf(Container) == 0);
- return Result;
+ return sizeof(DebugSubsectionHeader) + Data.getLength();
}
DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
: Subsection(std::move(Subsection)), Container(Container) {}
uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
- uint32_t Size =
- sizeof(DebugSubsectionHeader) +
- alignTo(Subsection->calculateSerializedSize(), alignOf(Container));
+ // The length of the entire subsection is always padded to 4 bytes, regardless
+ // of the container kind.
+ uint32_t Size = sizeof(DebugSubsectionHeader) +
+ alignTo(Subsection->calculateSerializedSize(), 4);
return Size;
}
-Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) {
+Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const {
assert(Writer.getOffset() % alignOf(Container) == 0 &&
"Debug Subsection not properly aligned");
DebugSubsectionHeader Header;
Header.Kind = uint32_t(Subsection->kind());
- Header.Length = calculateSerializedLength() - sizeof(DebugSubsectionHeader);
+ // The value written into the Header's Length field is only padded to the
+ // container's alignment
+ Header.Length =
+ alignTo(Subsection->calculateSerializedSize(), alignOf(Container));
if (auto EC = Writer.writeObject(Header))
return EC;
if (auto EC = Subsection->commit(Writer))
return EC;
- if (auto EC = Writer.padToAlignment(alignOf(Container)))
+ if (auto EC = Writer.padToAlignment(4))
return EC;
return Error::success();
-//===- DebugSubsectionVisitor.cpp ---------------------------*- C++ -*-===//
+//===- DebugSubsectionVisitor.cpp -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/BinaryStreamRef.h"
return EC;
return V.visitCrossModuleImports(Section, State);
}
+ case DebugSubsectionKind::Symbols: {
+ DebugSymbolsSubsectionRef Section;
+ if (auto EC = Section.initialize(Reader))
+ return EC;
+ return V.visitSymbols(Section, State);
+ }
+ case DebugSubsectionKind::StringTable: {
+ DebugStringTableSubsectionRef Section;
+ if (auto EC = Section.initialize(Reader))
+ return EC;
+ return V.visitStringTable(Section, State);
+ }
+ case DebugSubsectionKind::FrameData: {
+ DebugFrameDataSubsectionRef Section;
+ if (auto EC = Section.initialize(Reader))
+ return EC;
+ return V.visitFrameData(Section, State);
+ }
default: {
DebugUnknownSubsectionRef Fragment(R.kind(), R.getRecordData());
return V.visitUnknown(Fragment);
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.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/DebugSymbolsSubsection.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-
+#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
+#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
+#include "llvm/Support/BinaryStreamWriter.h"
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::CodeViewYAML;
LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModuleExport)
LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLCrossModuleImport)
LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
+LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLFrameData)
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, false)
LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags)
LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleExport)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLFrameData)
LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLCrossModuleImport)
LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleImportItem)
LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry)
virtual void map(IO &IO) = 0;
virtual std::unique_ptr<DebugSubsection>
- toCodeViewSubsection(DebugStringTableSubsection *UseStrings,
+ toCodeViewSubsection(BumpPtrAllocator &Allocator,
+ DebugStringTableSubsection *UseStrings,
DebugChecksumsSubsection *UseChecksums) const = 0;
};
}
void map(IO &IO) override;
std::unique_ptr<DebugSubsection>
- toCodeViewSubsection(DebugStringTableSubsection *Strings,
+ toCodeViewSubsection(BumpPtrAllocator &Allocator,
+ DebugStringTableSubsection *Strings,
DebugChecksumsSubsection *Checksums) const override;
static Expected<std::shared_ptr<YAMLChecksumsSubsection>>
fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
void map(IO &IO) override;
std::unique_ptr<DebugSubsection>
- toCodeViewSubsection(DebugStringTableSubsection *Strings,
+ toCodeViewSubsection(BumpPtrAllocator &Allocator,
+ DebugStringTableSubsection *Strings,
DebugChecksumsSubsection *Checksums) const override;
static Expected<std::shared_ptr<YAMLLinesSubsection>>
fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
void map(IO &IO) override;
std::unique_ptr<DebugSubsection>
- toCodeViewSubsection(DebugStringTableSubsection *Strings,
+ toCodeViewSubsection(BumpPtrAllocator &Allocator,
+ DebugStringTableSubsection *Strings,
DebugChecksumsSubsection *Checksums) const override;
static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
void map(IO &IO) override;
std::unique_ptr<DebugSubsection>
- toCodeViewSubsection(DebugStringTableSubsection *Strings,
+ toCodeViewSubsection(BumpPtrAllocator &Allocator,
+ DebugStringTableSubsection *Strings,
DebugChecksumsSubsection *Checksums) const override;
static Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports);
void map(IO &IO) override;
std::unique_ptr<DebugSubsection>
- toCodeViewSubsection(DebugStringTableSubsection *Strings,
+ toCodeViewSubsection(BumpPtrAllocator &Allocator,
+ DebugStringTableSubsection *Strings,
DebugChecksumsSubsection *Checksums) const override;
static Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
std::vector<YAMLCrossModuleImport> Imports;
};
+
+struct YAMLSymbolsSubsection : public YAMLSubsectionBase {
+ YAMLSymbolsSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Symbols) {}
+
+ void map(IO &IO) override;
+ std::unique_ptr<DebugSubsection>
+ toCodeViewSubsection(BumpPtrAllocator &Allocator,
+ DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const override;
+ static Expected<std::shared_ptr<YAMLSymbolsSubsection>>
+ fromCodeViewSubsection(const DebugSymbolsSubsectionRef &Symbols);
+
+ std::vector<CodeViewYAML::SymbolRecord> Symbols;
+};
+
+struct YAMLStringTableSubsection : public YAMLSubsectionBase {
+ YAMLStringTableSubsection()
+ : YAMLSubsectionBase(DebugSubsectionKind::StringTable) {}
+
+ void map(IO &IO) override;
+ std::unique_ptr<DebugSubsection>
+ toCodeViewSubsection(BumpPtrAllocator &Allocator,
+ DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const override;
+ static Expected<std::shared_ptr<YAMLStringTableSubsection>>
+ fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings);
+
+ std::vector<StringRef> Strings;
+};
+
+struct YAMLFrameDataSubsection : public YAMLSubsectionBase {
+ YAMLFrameDataSubsection()
+ : YAMLSubsectionBase(DebugSubsectionKind::FrameData) {}
+
+ void map(IO &IO) override;
+ std::unique_ptr<DebugSubsection>
+ toCodeViewSubsection(BumpPtrAllocator &Allocator,
+ DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const override;
+ static Expected<std::shared_ptr<YAMLFrameDataSubsection>>
+ fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
+ const DebugFrameDataSubsectionRef &Frames);
+
+ std::vector<YAMLFrameData> Frames;
+};
}
void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) {
IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
}
+void MappingTraits<YAMLFrameData>::mapping(IO &IO, YAMLFrameData &Obj) {
+ IO.mapRequired("CodeSize", Obj.CodeSize);
+ IO.mapRequired("FrameFunc", Obj.FrameFunc);
+ IO.mapRequired("LocalSize", Obj.LocalSize);
+ IO.mapOptional("MaxStackSize", Obj.MaxStackSize);
+ IO.mapOptional("ParamsSize", Obj.ParamsSize);
+ IO.mapOptional("PrologSize", Obj.PrologSize);
+ IO.mapOptional("RvaStart", Obj.RvaStart);
+ IO.mapOptional("SavedRegsSize", Obj.SavedRegsSize);
+}
+
void YAMLChecksumsSubsection::map(IO &IO) {
IO.mapTag("!FileChecksums", true);
IO.mapRequired("Checksums", Checksums);
IO.mapOptional("Imports", Imports);
}
+void YAMLSymbolsSubsection::map(IO &IO) {
+ IO.mapTag("!Symbols", true);
+ IO.mapRequired("Records", Symbols);
+}
+
+void YAMLStringTableSubsection::map(IO &IO) {
+ IO.mapTag("!StringTable", true);
+ IO.mapRequired("Strings", Strings);
+}
+
+void YAMLFrameDataSubsection::map(IO &IO) {
+ IO.mapTag("!FrameData", true);
+ IO.mapRequired("Frames", Frames);
+}
+
void MappingTraits<YAMLDebugSubsection>::mapping(
IO &IO, YAMLDebugSubsection &Subsection) {
if (!IO.outputting()) {
} else if (IO.mapTag("!CrossModuleImports")) {
Subsection.Subsection =
std::make_shared<YAMLCrossModuleImportsSubsection>();
+ } else if (IO.mapTag("!Symbols")) {
+ Subsection.Subsection = std::make_shared<YAMLSymbolsSubsection>();
+ } else if (IO.mapTag("!StringTable")) {
+ Subsection.Subsection = std::make_shared<YAMLStringTableSubsection>();
+ } else if (IO.mapTag("!FrameData")) {
+ Subsection.Subsection = std::make_shared<YAMLFrameDataSubsection>();
} else {
llvm_unreachable("Unexpected subsection tag!");
}
}
std::unique_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
- DebugStringTableSubsection *UseStrings,
+ BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
DebugChecksumsSubsection *UseChecksums) const {
assert(UseStrings && !UseChecksums);
auto Result = llvm::make_unique<DebugChecksumsSubsection>(*UseStrings);
}
std::unique_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection(
- DebugStringTableSubsection *UseStrings,
+ BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
DebugChecksumsSubsection *UseChecksums) const {
assert(UseStrings && UseChecksums);
auto Result =
std::unique_ptr<DebugSubsection>
YAMLInlineeLinesSubsection::toCodeViewSubsection(
- DebugStringTableSubsection *UseStrings,
+ BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
DebugChecksumsSubsection *UseChecksums) const {
assert(UseChecksums);
auto Result = llvm::make_unique<DebugInlineeLinesSubsection>(
std::unique_ptr<DebugSubsection>
YAMLCrossModuleExportsSubsection::toCodeViewSubsection(
- DebugStringTableSubsection *Strings,
+ BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
DebugChecksumsSubsection *Checksums) const {
auto Result = llvm::make_unique<DebugCrossModuleExportsSubsection>();
for (const auto &M : Exports)
std::unique_ptr<DebugSubsection>
YAMLCrossModuleImportsSubsection::toCodeViewSubsection(
- DebugStringTableSubsection *Strings,
+ BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
DebugChecksumsSubsection *Checksums) const {
auto Result = llvm::make_unique<DebugCrossModuleImportsSubsection>(*Strings);
for (const auto &M : Imports) {
return llvm::cast<DebugSubsection>(std::move(Result));
}
+std::unique_ptr<DebugSubsection> YAMLSymbolsSubsection::toCodeViewSubsection(
+ BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const {
+ auto Result = llvm::make_unique<DebugSymbolsSubsection>();
+ for (const auto &Sym : Symbols)
+ Result->addSymbol(
+ Sym.toCodeViewSymbol(Allocator, CodeViewContainer::ObjectFile));
+ return std::move(Result);
+}
+
+std::unique_ptr<DebugSubsection>
+YAMLStringTableSubsection::toCodeViewSubsection(
+ BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const {
+ auto Result = llvm::make_unique<DebugStringTableSubsection>();
+ for (const auto &Str : this->Strings)
+ Result->insert(Str);
+ return std::move(Result);
+}
+
+std::unique_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection(
+ BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
+ DebugChecksumsSubsection *Checksums) const {
+ assert(Strings);
+ auto Result = llvm::make_unique<DebugFrameDataSubsection>();
+ for (const auto &YF : Frames) {
+ codeview::FrameData F;
+ F.CodeSize = YF.CodeSize;
+ F.Flags = YF.Flags;
+ F.LocalSize = YF.LocalSize;
+ F.MaxStackSize = YF.MaxStackSize;
+ F.ParamsSize = YF.ParamsSize;
+ F.PrologSize = YF.PrologSize;
+ F.RvaStart = YF.RvaStart;
+ F.SavedRegsSize = YF.SavedRegsSize;
+ F.FrameFunc = Strings->insert(YF.FrameFunc);
+ Result->addFrameData(F);
+ }
+ return std::move(Result);
+}
+
static Expected<SourceFileChecksumEntry>
convertOneChecksum(const DebugStringTableSubsectionRef &Strings,
const FileChecksumEntry &CS) {
return Result;
}
+Expected<std::shared_ptr<YAMLSymbolsSubsection>>
+YAMLSymbolsSubsection::fromCodeViewSubsection(
+ const DebugSymbolsSubsectionRef &Symbols) {
+ auto Result = std::make_shared<YAMLSymbolsSubsection>();
+ for (const auto &Sym : Symbols) {
+ auto S = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym);
+ if (!S)
+ return joinErrors(make_error<CodeViewError>(
+ cv_error_code::corrupt_record,
+ "Invalid CodeView Symbol Record in SymbolRecord "
+ "subsection of .debug$S while converting to YAML!"),
+ S.takeError());
+
+ Result->Symbols.push_back(*S);
+ }
+ return Result;
+}
+
+Expected<std::shared_ptr<YAMLStringTableSubsection>>
+YAMLStringTableSubsection::fromCodeViewSubsection(
+ const DebugStringTableSubsectionRef &Strings) {
+ auto Result = std::make_shared<YAMLStringTableSubsection>();
+ BinaryStreamReader Reader(Strings.getBuffer());
+ StringRef S;
+ // First item is a single null string, skip it.
+ if (auto EC = Reader.readCString(S))
+ return std::move(EC);
+ assert(S.empty());
+ while (Reader.bytesRemaining() > 0) {
+ if (auto EC = Reader.readCString(S))
+ return std::move(EC);
+ Result->Strings.push_back(S);
+ }
+ return Result;
+}
+
+Expected<std::shared_ptr<YAMLFrameDataSubsection>>
+YAMLFrameDataSubsection::fromCodeViewSubsection(
+ const DebugStringTableSubsectionRef &Strings,
+ const DebugFrameDataSubsectionRef &Frames) {
+ auto Result = std::make_shared<YAMLFrameDataSubsection>();
+ for (const auto &F : Frames) {
+ YAMLFrameData YF;
+ YF.CodeSize = F.CodeSize;
+ YF.Flags = F.Flags;
+ YF.LocalSize = F.LocalSize;
+ YF.MaxStackSize = F.MaxStackSize;
+ YF.ParamsSize = F.ParamsSize;
+ YF.PrologSize = F.PrologSize;
+ YF.RvaStart = F.RvaStart;
+ YF.SavedRegsSize = F.SavedRegsSize;
+
+ auto ES = Strings.getString(F.FrameFunc);
+ if (!ES)
+ return joinErrors(
+ make_error<CodeViewError>(
+ cv_error_code::no_records,
+ "Could not find string for string id while mapping FrameData!"),
+ ES.takeError());
+ YF.FrameFunc = *ES;
+ Result->Frames.push_back(YF);
+ }
+ return Result;
+}
+
Expected<std::vector<std::unique_ptr<DebugSubsection>>>
-llvm::CodeViewYAML::convertSubsectionList(
- ArrayRef<YAMLDebugSubsection> Subsections,
+llvm::CodeViewYAML::toCodeViewSubsectionList(
+ BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
DebugStringTableSubsection &Strings) {
std::vector<std::unique_ptr<DebugSubsection>> Result;
if (Subsections.empty())
auto Checksums = findChecksums(Subsections);
std::unique_ptr<DebugSubsection> ChecksumsBase;
if (Checksums)
- ChecksumsBase = Checksums->toCodeViewSubsection(&Strings, nullptr);
+ ChecksumsBase =
+ Checksums->toCodeViewSubsection(Allocator, &Strings, nullptr);
DebugChecksumsSubsection *CS =
static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get());
for (const auto &SS : Subsections) {
if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
CVS = std::move(ChecksumsBase);
else
- CVS = SS.Subsection->toCodeViewSubsection(&Strings, CS);
+ CVS = SS.Subsection->toCodeViewSubsection(Allocator, &Strings, CS);
+ assert(CVS != nullptr);
+ Result.push_back(std::move(CVS));
+ }
+ return std::move(Result);
+}
+
+Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>>
+llvm::CodeViewYAML::toCodeViewSubsectionList(
+ BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
+ std::unique_ptr<DebugStringTableSubsection> &TakeStrings,
+ DebugStringTableSubsection *StringsRef) {
+ std::vector<std::unique_ptr<DebugSubsection>> Result;
+ if (Subsections.empty())
+ return std::move(Result);
+
+ auto Checksums = findChecksums(Subsections);
+
+ std::unique_ptr<DebugSubsection> ChecksumsBase;
+ if (Checksums)
+ ChecksumsBase =
+ Checksums->toCodeViewSubsection(Allocator, StringsRef, nullptr);
+ DebugChecksumsSubsection *CS =
+ static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get());
+ for (const auto &SS : Subsections) {
+ // We've already converted the checksums and string table subsection, don't
+ // do it twice.
+ std::unique_ptr<DebugSubsection> CVS;
+ if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
+ CVS = std::move(ChecksumsBase);
+ else if (SS.Subsection->Kind == DebugSubsectionKind::StringTable) {
+ assert(TakeStrings && "No string table!");
+ CVS = std::move(TakeStrings);
+ } else
+ CVS = SS.Subsection->toCodeViewSubsection(Allocator, StringsRef, CS);
assert(CVS != nullptr);
Result.push_back(std::move(CVS));
}
const DebugSubsectionState &State) override;
Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees,
const DebugSubsectionState &State) override;
+ Error visitStringTable(DebugStringTableSubsectionRef &ST,
+ const DebugSubsectionState &State) override;
+ Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
+ const DebugSubsectionState &State) override;
+ Error visitFrameData(DebugFrameDataSubsectionRef &Symbols,
+ const DebugSubsectionState &State) override;
YAMLDebugSubsection Subsection;
};
Subsection.Subsection = *Result;
return Error::success();
}
+
+Error SubsectionConversionVisitor::visitStringTable(
+ DebugStringTableSubsectionRef &Strings, const DebugSubsectionState &State) {
+ auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings);
+ if (!Result)
+ return Result.takeError();
+ Subsection.Subsection = *Result;
+ return Error::success();
+}
+
+Error SubsectionConversionVisitor::visitSymbols(
+ DebugSymbolsSubsectionRef &Symbols, const DebugSubsectionState &State) {
+ auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols);
+ if (!Result)
+ return Result.takeError();
+ Subsection.Subsection = *Result;
+ return Error::success();
+}
+
+Error SubsectionConversionVisitor::visitFrameData(
+ DebugFrameDataSubsectionRef &Frames, const DebugSubsectionState &State) {
+ auto Result =
+ YAMLFrameDataSubsection::fromCodeViewSubsection(State.strings(), Frames);
+ if (!Result)
+ return Result.takeError();
+ Subsection.Subsection = *Result;
+ return Error::success();
+}
}
Expected<YAMLDebugSubsection> YAMLDebugSubsection::fromCodeViewSubection(
return V.Subsection;
}
+
+std::unique_ptr<DebugStringTableSubsection>
+llvm::CodeViewYAML::findStringTable(ArrayRef<YAMLDebugSubsection> Sections) {
+ for (const auto &SS : Sections) {
+ if (SS.Subsection->Kind != DebugSubsectionKind::StringTable)
+ continue;
+
+ // String Table doesn't use the allocator.
+ BumpPtrAllocator Allocator;
+ auto Result =
+ SS.Subsection->toCodeViewSubsection(Allocator, nullptr, nullptr);
+ return llvm::cast<DebugStringTableSubsection>(std::move(Result));
+ }
+ return nullptr;
+}
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+#include "llvm/Support/BinaryStreamWriter.h"
using namespace llvm;
using namespace llvm::codeview;
virtual ~LeafRecordBase() {}
virtual void map(yaml::IO &io) = 0;
- virtual CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const = 0;
+ virtual CVType toCodeViewRecord(TypeTableBuilder &TTB) const = 0;
virtual Error fromCodeViewRecord(CVType Type) = 0;
};
return TypeDeserializer::deserializeAs<T>(Type, Record);
}
- CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const override {
- TypeTableBuilder Table(Allocator);
- Table.writeKnownType(Record);
- return CVType(Kind, Table.records().front());
+ CVType toCodeViewRecord(TypeTableBuilder &TTB) const override {
+ TTB.writeKnownType(Record);
+ return CVType(Kind, TTB.records().back());
}
mutable T Record;
explicit LeafRecordImpl(TypeLeafKind K) : LeafRecordBase(K) {}
void map(yaml::IO &io) override;
- CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const override;
+ CVType toCodeViewRecord(TypeTableBuilder &TTB) const override;
Error fromCodeViewRecord(CVType Type) override;
std::vector<MemberRecord> Members;
return visitMemberRecordStream(Type.content(), V);
}
-CVType LeafRecordImpl<FieldListRecord>::toCodeViewRecord(
- BumpPtrAllocator &Allocator) const {
- TypeTableBuilder TTB(Allocator);
+CVType
+LeafRecordImpl<FieldListRecord>::toCodeViewRecord(TypeTableBuilder &TTB) const {
FieldListRecordBuilder FLRB(TTB);
FLRB.begin();
for (const auto &Member : Members) {
Member.Member->writeTo(FLRB);
}
FLRB.end(true);
- return CVType(Kind, TTB.records().front());
+ return CVType(Kind, TTB.records().back());
}
void MappingTraits<OneMethodRecord>::mapping(IO &io, OneMethodRecord &Record) {
return make_error<CodeViewError>(cv_error_code::corrupt_record);
}
-CVType LeafRecord::toCodeViewRecord(BumpPtrAllocator &Allocator) const {
- return Leaf->toCodeViewRecord(Allocator);
+CVType LeafRecord::toCodeViewRecord(BumpPtrAllocator &Alloc) const {
+ TypeTableBuilder TTB(Alloc);
+ return Leaf->toCodeViewRecord(TTB);
+}
+
+CVType LeafRecord::toCodeViewRecord(TypeTableBuilder &TTB) const {
+ return Leaf->toCodeViewRecord(TTB);
}
namespace llvm {
- FileName: 'f:\dd\externalapis\windows\10\sdk\inc\winerror.h'
LineNum: 26950
Inlinee: 22767
+ # The following subsections don't normally appear in PDB files, but we test
+ # them anyway
+ - Module: 'ObjFileSubsections'
+ ObjFile: 'ObjFileSubsections'
+ Subsections:
+ - !StringTable
+ Strings:
+ - 'String1'
+ - 'String2'
+ - 'String3'
+ - !Symbols
+ Records:
+ - Kind: S_OBJNAME
+ ObjNameSym:
+ Signature: 0
+ ObjectName: 'ObjFileSubsections'
+ - !FrameData
+ Frames:
+ - CodeSize: 1
+ FrameFunc: 'MyFunc'
+ LocalSize: 2
+ MaxStackSize: 3
+ ParamsSize: 4
+ PrologSize: 5
+ RvaStart: 6
+ SavedRegsSize: 7
+...
; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/debug-subsections.yaml
-
; RUN: llvm-pdbdump pdb2yaml -all -no-file-headers %t.pdb | FileCheck --check-prefix=YAML %s
; RUN: llvm-pdbdump raw -subsections=all %t.pdb | FileCheck --check-prefix=RAW %s
RAW-NEXT: ]
RAW-NEXT: ]
RAW-NEXT: }
-RAW-NEXT: {
-RAW-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-RAW: Subsections [
-RAW-NEXT: FileChecksums {
-RAW-NEXT: Checksum {
-RAW-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
-RAW-NEXT: Kind: MD5 (0x1)
-RAW-NEXT: Checksum (
-RAW-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...|
-RAW-NEXT: )
-RAW-NEXT: }
-RAW-NEXT: Checksum {
-RAW-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
-RAW-NEXT: Kind: MD5 (0x1)
-RAW-NEXT: Checksum (
-RAW-NEXT: 0000: 1154D69F 5B265019 6E1FC34F 4134E56B |.T..[&P.n..OA4.k|
-RAW-NEXT: )
-RAW-NEXT: }
-RAW-NEXT: }
-RAW-NEXT: Lines {
-RAW-NEXT: RelocSegment: 1
-RAW-NEXT: RelocOffset: 16
-RAW-NEXT: CodeSize: 10
-RAW-NEXT: HasColumns: No
-RAW-NEXT: FileEntry {
-RAW-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
-RAW-NEXT: Line {
-RAW-NEXT: Offset: 0
-RAW-NEXT: LineNumberStart: 5
-RAW-NEXT: EndDelta: 0
-RAW-NEXT: IsStatement: Yes
-RAW-NEXT: }
-RAW-NEXT: Line {
-RAW-NEXT: Offset: 3
-RAW-NEXT: LineNumberStart: 6
-RAW-NEXT: EndDelta: 0
-RAW-NEXT: IsStatement: Yes
-RAW-NEXT: }
-RAW-NEXT: Line {
-RAW-NEXT: Offset: 8
-RAW-NEXT: LineNumberStart: 7
-RAW-NEXT: EndDelta: 0
-RAW-NEXT: IsStatement: Yes
-RAW-NEXT: }
-RAW-NEXT: }
-RAW-NEXT: }
-RAW-NEXT: InlineeLines {
-RAW-NEXT: HasExtraFiles: No
-RAW-NEXT: Lines [
-RAW-NEXT: Inlinee {
-RAW-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
-RAW-NEXT: Function {
-RAW-NEXT: Index: 0x58ef (unknown function)
-RAW-NEXT: }
-RAW-NEXT: SourceLine: 26950
-RAW-NEXT: }
-RAW-NEXT: ]
-RAW-NEXT: }
-RAW-NEXT: ]
-RAW-NEXT: }
-RAW-NEXT: ]
-RAW-NEXT:}
+RAW-NEXT: {
+RAW-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
+RAW: Subsections [
+RAW-NEXT: FileChecksums {
+RAW-NEXT: Checksum {
+RAW-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
+RAW-NEXT: Kind: MD5 (0x1)
+RAW-NEXT: Checksum (
+RAW-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...|
+RAW-NEXT: )
+RAW-NEXT: }
+RAW-NEXT: Checksum {
+RAW-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
+RAW-NEXT: Kind: MD5 (0x1)
+RAW-NEXT: Checksum (
+RAW-NEXT: 0000: 1154D69F 5B265019 6E1FC34F 4134E56B |.T..[&P.n..OA4.k|
+RAW-NEXT: )
+RAW-NEXT: }
+RAW-NEXT: }
+RAW-NEXT: Lines {
+RAW-NEXT: RelocSegment: 1
+RAW-NEXT: RelocOffset: 16
+RAW-NEXT: CodeSize: 10
+RAW-NEXT: HasColumns: No
+RAW-NEXT: FileEntry {
+RAW-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
+RAW-NEXT: Line {
+RAW-NEXT: Offset: 0
+RAW-NEXT: LineNumberStart: 5
+RAW-NEXT: EndDelta: 0
+RAW-NEXT: IsStatement: Yes
+RAW-NEXT: }
+RAW-NEXT: Line {
+RAW-NEXT: Offset: 3
+RAW-NEXT: LineNumberStart: 6
+RAW-NEXT: EndDelta: 0
+RAW-NEXT: IsStatement: Yes
+RAW-NEXT: }
+RAW-NEXT: Line {
+RAW-NEXT: Offset: 8
+RAW-NEXT: LineNumberStart: 7
+RAW-NEXT: EndDelta: 0
+RAW-NEXT: IsStatement: Yes
+RAW-NEXT: }
+RAW-NEXT: }
+RAW-NEXT: }
+RAW-NEXT: InlineeLines {
+RAW-NEXT: HasExtraFiles: No
+RAW-NEXT: Lines [
+RAW-NEXT: Inlinee {
+RAW-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
+RAW-NEXT: Function {
+RAW-NEXT: Index: 0x58ef (unknown function)
+RAW-NEXT: }
+RAW-NEXT: SourceLine: 26950
+RAW-NEXT: }
+RAW-NEXT: ]
+RAW-NEXT: }
+RAW-NEXT: ]
+RAW-NEXT: }
+RAW-NEXT: {
+RAW-NEXT: Name: ObjFileSubsections
+RAW-NEXT: Debug Stream Index: 11
+RAW-NEXT: Object File Name: ObjFileSubsections
+RAW-NEXT: Num Files: 0
+RAW-NEXT: Source File Name Idx: 0
+RAW-NEXT: Pdb File Name Idx: 0
+RAW-NEXT: Line Info Byte Size: 0
+RAW-NEXT: C13 Line Info Byte Size: 116
+RAW-NEXT: Symbol Byte Size: 4
+RAW-NEXT: Type Server Index: 0
+RAW-NEXT: Has EC Info: No
+RAW-NEXT: Subsections [
+RAW-NEXT: String Table [
+RAW-NEXT: String1
+RAW-NEXT: String2
+RAW-NEXT: String3
+RAW-NEXT: ]
+RAW-NEXT: Symbols [
+RAW-NEXT: {
+RAW-NEXT: ObjectName {
+RAW-NEXT: Signature: 0x0
+RAW-NEXT: ObjectName: ObjFileSubsections
+RAW-NEXT: }
+RAW-NEXT: }
+RAW-NEXT: ]
+RAW-NEXT: FrameData [
+RAW-NEXT: Frame {
+RAW-NEXT: Rva: 6
+RAW-NEXT: CodeSize: 1
+RAW-NEXT: LocalSize: 2
+RAW-NEXT: ParamsSize: 4
+RAW-NEXT: MaxStackSize: 3
+RAW-NEXT: FrameFunc: MyFunc
+RAW-NEXT: PrologSize: 5
+RAW-NEXT: SavedRegsSize: 7
+RAW-NEXT: Flags: 0
+RAW-NEXT: }
+RAW-NEXT: ]
+RAW-NEXT: ]
+RAW-NEXT: }
+RAW-NEXT: ]
+RAW-NEXT: }
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.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/DebugSymbolsSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
class C13RawVisitor : public DebugSubsectionVisitor {
public:
- C13RawVisitor(ScopedPrinter &P, LazyRandomTypeCollection &IPI)
- : P(P), IPI(IPI) {}
+ C13RawVisitor(ScopedPrinter &P, LazyRandomTypeCollection &TPI,
+ LazyRandomTypeCollection &IPI)
+ : P(P), TPI(TPI), IPI(IPI) {}
Error visitLines(DebugLinesSubsectionRef &Lines,
const DebugSubsectionState &State) override {
return Error::success();
}
+ Error visitFrameData(DebugFrameDataSubsectionRef &FD,
+ const DebugSubsectionState &State) override {
+ if (!opts::checkModuleSubsection(opts::ModuleSubsection::FrameData))
+ return Error::success();
+
+ ListScope L(P, "FrameData");
+ for (const auto &Frame : FD) {
+ DictScope D(P, "Frame");
+ auto Name = getNameFromStringTable(Frame.FrameFunc, State);
+ if (!Name)
+ return joinErrors(make_error<RawError>(raw_error_code::invalid_format,
+ "Invalid Frame.FrameFunc index"),
+ std::move(Name.takeError()));
+ P.printNumber("Rva", Frame.RvaStart);
+ P.printNumber("CodeSize", Frame.CodeSize);
+ P.printNumber("LocalSize", Frame.LocalSize);
+ P.printNumber("ParamsSize", Frame.ParamsSize);
+ P.printNumber("MaxStackSize", Frame.MaxStackSize);
+ P.printString("FrameFunc", *Name);
+ P.printNumber("PrologSize", Frame.PrologSize);
+ P.printNumber("SavedRegsSize", Frame.SavedRegsSize);
+ P.printNumber("Flags", Frame.Flags);
+ }
+ return Error::success();
+ }
+
+ Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
+ const DebugSubsectionState &State) override {
+ if (!opts::checkModuleSubsection(opts::ModuleSubsection::Symbols))
+ return Error::success();
+ ListScope L(P, "Symbols");
+
+ // This section should not actually appear in a PDB file, it really only
+ // appears in object files. But we support it here for testing. So we
+ // specify the Object File container type.
+ codeview::CVSymbolDumper SD(P, TPI, CodeViewContainer::ObjectFile, nullptr,
+ false);
+ for (auto S : Symbols) {
+ DictScope LL(P, "");
+ if (auto EC = SD.dump(S)) {
+ return make_error<RawError>(
+ raw_error_code::corrupt_file,
+ "DEBUG_S_SYMBOLS subsection contained corrupt symbol record");
+ }
+ }
+ return Error::success();
+ }
+
+ Error visitStringTable(DebugStringTableSubsectionRef &Strings,
+ const DebugSubsectionState &State) override {
+ if (!opts::checkModuleSubsection(opts::ModuleSubsection::StringTable))
+ return Error::success();
+
+ ListScope D(P, "String Table");
+ BinaryStreamReader Reader(Strings.getBuffer());
+ StringRef S;
+ consumeError(Reader.readCString(S));
+ while (Reader.bytesRemaining() > 0) {
+ consumeError(Reader.readCString(S));
+ if (S.empty() && Reader.bytesRemaining() < 4)
+ break;
+ P.printString(S);
+ }
+ return Error::success();
+ }
+
private:
Error dumpTypeRecord(StringRef Label, TypeIndex Index) {
CompactTypeDumpVisitor CTDV(IPI, Index, &P);
}
ScopedPrinter &P;
+ LazyRandomTypeCollection &TPI;
LazyRandomTypeCollection &IPI;
};
}
if (auto EC = ModS.reload())
return EC;
+ auto ExpectedTpi = initializeTypeDatabase(StreamTPI);
+ if (!ExpectedTpi)
+ return ExpectedTpi.takeError();
+ auto &Tpi = *ExpectedTpi;
if (ShouldDumpSymbols) {
- auto ExpectedTypes = initializeTypeDatabase(StreamTPI);
- if (!ExpectedTypes)
- return ExpectedTypes.takeError();
- auto &Types = *ExpectedTypes;
ListScope SS(P, "Symbols");
- codeview::CVSymbolDumper SD(P, Types, CodeViewContainer::Pdb, nullptr,
+ codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr,
false);
bool HadError = false;
for (auto S : ModS.symbols(&HadError)) {
}
if (!opts::shared::DumpModuleSubsections.empty()) {
ListScope SS(P, "Subsections");
- auto ExpectedTypes = initializeTypeDatabase(StreamIPI);
- if (!ExpectedTypes)
- return ExpectedTypes.takeError();
- auto &IpiItems = *ExpectedTypes;
+ auto ExpectedIpi = initializeTypeDatabase(StreamIPI);
+ if (!ExpectedIpi)
+ return ExpectedIpi.takeError();
+ auto &Ipi = *ExpectedIpi;
auto ExpectedStrings = File.getStringTable();
if (!ExpectedStrings)
return joinErrors(
"Could not get string table!"),
std::move(ExpectedStrings.takeError()));
- C13RawVisitor V(P, IpiItems);
+ C13RawVisitor V(P, Tpi, Ipi);
if (auto EC = codeview::visitDebugSubsections(
ModS.subsections(), V, ExpectedStrings->getStringTable()))
return EC;
return opts::ModuleSubsection::InlineeLines;
case DebugSubsectionKind::Lines:
return opts::ModuleSubsection::Lines;
+ case DebugSubsectionKind::Symbols:
+ return opts::ModuleSubsection::Symbols;
+ case DebugSubsectionKind::StringTable:
+ return opts::ModuleSubsection::StringTable;
+ case DebugSubsectionKind::FrameData:
+ return opts::ModuleSubsection::FrameData;
default:
return opts::ModuleSubsection::Unknown;
}
"Inlinee lines (DEBUG_S_INLINEELINES subsection)"),
clEnumValN(ModuleSubsection::Lines, "lines",
"Lines (DEBUG_S_LINES subsection)"),
+ clEnumValN(ModuleSubsection::StringTable, "strings",
+ "String Table (DEBUG_S_STRINGTABLE subsection) (not "
+ "typically present in PDB file)"),
+ clEnumValN(ModuleSubsection::FrameData, "frames",
+ "Frame Data (DEBUG_S_FRAMEDATA subsection)"),
+ clEnumValN(ModuleSubsection::Symbols, "symbols",
+ "Symbols (DEBUG_S_SYMBOLS subsection) (not typically "
+ "present in PDB file)"),
clEnumValN(ModuleSubsection::All, "all", "All known subsections")),
cl::cat(FileOptions), cl::sub(RawSubcommand), cl::sub(PdbToYamlSubcommand));
cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
}
}
- auto CodeViewSubsections =
- ExitOnErr(CodeViewYAML::convertSubsectionList(MI.Subsections, Strings));
+ auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList(
+ Allocator, MI.Subsections, Strings));
for (auto &SS : CodeViewSubsections) {
ModiBuilder.addDebugSubsection(std::move(SS));
}
InlineeLines,
CrossScopeImports,
CrossScopeExports,
+ StringTable,
+ Symbols,
+ FrameData,
All
};