summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2018-09-17 21:08:11 +0000
committerZachary Turner <zturner@google.com>2018-09-17 21:08:11 +0000
commitbdf0381e216e2aaa1aa736fd288d94786e4447e0 (patch)
treec3aa3cf7b6a308538953cf7a6623ca21c7b4d146 /llvm/lib/DebugInfo
parent4727ac23947013a1f1cdd1f8ced7002f3bc06c72 (diff)
downloadbcm5719-llvm-bdf0381e216e2aaa1aa736fd288d94786e4447e0.tar.gz
bcm5719-llvm-bdf0381e216e2aaa1aa736fd288d94786e4447e0.zip
[PDB] Make the native reader support enumerators.
Previously we would dump the names of enum types, but not their enumerator values. This adds support for enumerator values. In doing so, we have to introduce a general purpose mechanism for caching symbol indices of field list members. Unlike global types, FieldList members do not have a TypeIndex. So instead, we identify them by the pair {TypeIndexOfFieldList, IndexInFieldList}. llvm-svn: 342415
Diffstat (limited to 'llvm/lib/DebugInfo')
-rw-r--r--llvm/lib/DebugInfo/PDB/CMakeLists.txt1
-rw-r--r--llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp17
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp116
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp123
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp7
-rw-r--r--llvm/lib/DebugInfo/PDB/PDBExtras.cpp2
6 files changed, 254 insertions, 12 deletions
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
index 5e52515268e..8bf16c505cb 100644
--- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
@@ -51,6 +51,7 @@ add_pdb_impl_folder(Native
Native/NativeEnumTypes.cpp
Native/NativeExeSymbol.cpp
Native/NativeRawSymbol.cpp
+ Native/NativeSymbolEnumerator.cpp
Native/NativeTypeBuiltin.cpp
Native/NativeTypeEnum.cpp
Native/NativeTypePointer.cpp
diff --git a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
index 95aab9f1506..0b4b127736a 100644
--- a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
@@ -141,6 +141,15 @@ PrivateGetDIAValue(IDiaSymbol *Symbol,
return IdResult;
}
+template <typename PrintType, typename ArgType>
+void DumpDIAValueAs(llvm::raw_ostream &OS, int Indent, StringRef Name,
+ IDiaSymbol *Symbol,
+ HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) {
+ ArgType Value;
+ if (S_OK == (Symbol->*Method)(&Value))
+ dumpSymbolField(OS, Name, static_cast<PrintType>(Value), Indent);
+}
+
template <typename ArgType>
void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name,
IDiaSymbol *Symbol,
@@ -194,6 +203,10 @@ DIARawSymbol::DIARawSymbol(const DIASession &PDBSession,
DumpDIAValue(Stream, Indent, StringRef{#Method}, Symbol, \
&IDiaSymbol::get_##Method);
+#define RAW_METHOD_DUMP_AS(Stream, Method, Type) \
+ DumpDIAValueAs<Type>(Stream, Indent, StringRef{#Method}, Symbol, \
+ &IDiaSymbol::get_##Method);
+
void DIARawSymbol::dump(raw_ostream &OS, int Indent) const {
RAW_METHOD_DUMP(OS, symIndexId);
RAW_METHOD_DUMP(OS, symTag);
@@ -267,12 +280,12 @@ void DIARawSymbol::dump(raw_ostream &OS, int Indent) const {
RAW_METHOD_DUMP(OS, virtualBaseDispIndex);
RAW_METHOD_DUMP(OS, virtualBaseOffset);
RAW_METHOD_DUMP(OS, virtualTableShapeId);
- RAW_METHOD_DUMP(OS, dataKind);
+ RAW_METHOD_DUMP_AS(OS, dataKind, PDB_DataKind);
RAW_METHOD_DUMP(OS, guid);
RAW_METHOD_DUMP(OS, offset);
RAW_METHOD_DUMP(OS, thisAdjust);
RAW_METHOD_DUMP(OS, virtualBasePointerOffset);
- RAW_METHOD_DUMP(OS, locationType);
+ RAW_METHOD_DUMP_AS(OS, locationType, PDB_LocType);
RAW_METHOD_DUMP(OS, machineType);
RAW_METHOD_DUMP(OS, thunkOrdinal);
RAW_METHOD_DUMP(OS, length);
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
new file mode 100644
index 00000000000..18b13b07607
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
@@ -0,0 +1,116 @@
+//===- NativeSymbolEnumerator.cpp - info about enumerators ------*- 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/PDB/Native/NativeSymbolEnumerator.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeSymbolEnumerator::NativeSymbolEnumerator(
+ NativeSession &Session, SymIndexId Id, const NativeTypeEnum &Parent,
+ codeview::EnumeratorRecord Record)
+ : NativeRawSymbol(Session, PDB_SymType::Data, Id), Parent(Parent),
+ Record(std::move(Record)) {}
+
+NativeSymbolEnumerator::~NativeSymbolEnumerator() {}
+
+void NativeSymbolEnumerator::dump(raw_ostream &OS, int Indent) const {
+ NativeRawSymbol::dump(OS, Indent);
+ dumpSymbolField(OS, "classParentId", getClassParentId(), Indent);
+ dumpSymbolField(OS, "lexicalParentId", getLexicalParentId(), Indent);
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolField(OS, "typeId", getTypeId(), Indent);
+ dumpSymbolField(OS, "dataKind", getDataKind(), Indent);
+ dumpSymbolField(OS, "locationType", getLocationType(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+ dumpSymbolField(OS, "value", getValue(), Indent);
+}
+
+SymIndexId NativeSymbolEnumerator::getClassParentId() const {
+ return Parent.getSymIndexId();
+}
+
+SymIndexId NativeSymbolEnumerator::getLexicalParentId() const { return 0; }
+
+std::string NativeSymbolEnumerator::getName() const { return Record.Name; }
+
+SymIndexId NativeSymbolEnumerator::getTypeId() const {
+ return Parent.getTypeId();
+}
+
+PDB_DataKind NativeSymbolEnumerator::getDataKind() const {
+ return PDB_DataKind::Constant;
+}
+
+PDB_LocType NativeSymbolEnumerator::getLocationType() const {
+ return PDB_LocType::Constant;
+}
+
+bool NativeSymbolEnumerator::isConstType() const { return false; }
+
+bool NativeSymbolEnumerator::isVolatileType() const { return false; }
+
+bool NativeSymbolEnumerator::isUnalignedType() const { return false; }
+
+Variant NativeSymbolEnumerator::getValue() const {
+ const NativeTypeBuiltin &BT = Parent.getUnderlyingBuiltinType();
+
+ switch (BT.getBuiltinType()) {
+ case PDB_BuiltinType::Int:
+ case PDB_BuiltinType::Long:
+ case PDB_BuiltinType::Char: {
+ assert(Record.Value.isSignedIntN(BT.getLength() * 8));
+ int64_t N = Record.Value.getSExtValue();
+ switch (BT.getLength()) {
+ case 1:
+ return Variant{static_cast<int8_t>(N)};
+ case 2:
+ return Variant{static_cast<int16_t>(N)};
+ case 4:
+ return Variant{static_cast<int32_t>(N)};
+ case 8:
+ return Variant{static_cast<int64_t>(N)};
+ }
+ break;
+ }
+ case PDB_BuiltinType::UInt:
+ case PDB_BuiltinType::ULong: {
+ assert(Record.Value.isIntN(BT.getLength() * 8));
+ uint64_t U = Record.Value.getZExtValue();
+ switch (BT.getLength()) {
+ case 1:
+ return Variant{static_cast<uint8_t>(U)};
+ case 2:
+ return Variant{static_cast<uint16_t>(U)};
+ case 4:
+ return Variant{static_cast<uint32_t>(U)};
+ case 8:
+ return Variant{static_cast<uint64_t>(U)};
+ }
+ break;
+ }
+ case PDB_BuiltinType::Bool: {
+ assert(Record.Value.isIntN(BT.getLength() * 8));
+ uint64_t U = Record.Value.getZExtValue();
+ return Variant{static_cast<bool>(U)};
+ }
+ default:
+ assert(false && "Invalid enumeration type");
+ break;
+ }
+
+ return Variant{Record.Value.getSExtValue()};
+}
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
index cfc767f4422..e833b6dddd9 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
@@ -12,7 +12,11 @@
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include "llvm/Support/FormatVariadic.h"
@@ -23,6 +27,95 @@ using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;
+namespace {
+// Yea, this is a pretty terrible class name. But if we have an enum:
+//
+// enum Foo {
+// A,
+// B
+// };
+//
+// then A and B are the "enumerators" of the "enum" Foo. And we need
+// to enumerate them.
+class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks {
+public:
+ NativeEnumEnumEnumerators(NativeSession &Session,
+ const NativeTypeEnum &ClassParent,
+ const codeview::EnumRecord &CVEnum);
+
+ uint32_t getChildCount() const override;
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+ std::unique_ptr<PDBSymbol> getNext() override;
+ void reset() override;
+
+private:
+ Error visitKnownMember(CVMemberRecord &CVM,
+ EnumeratorRecord &Record) override;
+ Error visitKnownMember(CVMemberRecord &CVM,
+ ListContinuationRecord &Record) override;
+
+ NativeSession &Session;
+ const NativeTypeEnum &ClassParent;
+ const codeview::EnumRecord &CVEnum;
+ std::vector<EnumeratorRecord> Enumerators;
+ Optional<TypeIndex> ContinuationIndex;
+ uint32_t Index = 0;
+};
+} // namespace
+
+NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
+ NativeSession &Session, const NativeTypeEnum &ClassParent,
+ const codeview::EnumRecord &CVEnum)
+ : Session(Session), ClassParent(ClassParent), CVEnum(CVEnum) {
+ TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
+ LazyRandomTypeCollection &Types = Tpi.typeCollection();
+
+ ContinuationIndex = CVEnum.FieldList;
+ while (ContinuationIndex) {
+ CVType FieldList = Types.getType(*ContinuationIndex);
+ assert(FieldList.kind() == LF_FIELDLIST);
+ ContinuationIndex.reset();
+ cantFail(visitMemberRecordStream(FieldList.data(), *this));
+ }
+}
+
+Error NativeEnumEnumEnumerators::visitKnownMember(CVMemberRecord &CVM,
+ EnumeratorRecord &Record) {
+ Enumerators.push_back(Record);
+ return Error::success();
+}
+
+Error NativeEnumEnumEnumerators::visitKnownMember(
+ CVMemberRecord &CVM, ListContinuationRecord &Record) {
+ ContinuationIndex = Record.ContinuationIndex;
+ return Error::success();
+}
+
+uint32_t NativeEnumEnumEnumerators::getChildCount() const {
+ return Enumerators.size();
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
+ if (Index >= getChildCount())
+ return nullptr;
+
+ SymIndexId Id =
+ Session.getSymbolCache()
+ .getOrCreateFieldListMember<NativeSymbolEnumerator>(
+ CVEnum.FieldList, Index, ClassParent, Enumerators[Index]);
+ return Session.getSymbolCache().getSymbolById(Id);
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() {
+ if (Index >= getChildCount())
+ return nullptr;
+
+ return getChildAtIndex(Index++);
+}
+
+void NativeEnumEnumEnumerators::reset() { Index = 0; }
+
NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
TypeIndex Index, EnumRecord Record)
: NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
@@ -67,14 +160,20 @@ void NativeTypeEnum::dump(raw_ostream &OS, int Indent) const {
std::unique_ptr<IPDBEnumSymbols>
NativeTypeEnum::findChildren(PDB_SymType Type) const {
- switch (Type) {
- case PDB_SymType::Data: {
- // TODO(amccarth) : Provide an actual implementation.
- return nullptr;
- }
- default:
- return nullptr;
+ if (Type != PDB_SymType::Data)
+ return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+
+ const NativeTypeEnum *ClassParent = nullptr;
+ if (!Modifiers)
+ ClassParent = this;
+ else {
+ NativeRawSymbol &NRS =
+ Session.getSymbolCache().getNativeSymbolById(getUnmodifiedTypeId());
+ assert(NRS.getSymTag() == PDB_SymType::Enum);
+ ClassParent = static_cast<NativeTypeEnum *>(&NRS);
}
+ return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent,
+ Record);
}
PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
@@ -86,8 +185,9 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
// This indicates a corrupt record.
if (!Underlying.isSimple() ||
- Underlying.getSimpleMode() != SimpleTypeMode::Direct)
+ Underlying.getSimpleMode() != SimpleTypeMode::Direct) {
return PDB_BuiltinType::None;
+ }
switch (Underlying.getSimpleKind()) {
case SimpleTypeKind::Boolean128:
@@ -98,6 +198,7 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
return PDB_BuiltinType::Bool;
case SimpleTypeKind::NarrowCharacter:
case SimpleTypeKind::UnsignedCharacter:
+ case SimpleTypeKind::SignedCharacter:
return PDB_BuiltinType::Char;
case SimpleTypeKind::WideCharacter:
return PDB_BuiltinType::WCharT;
@@ -149,6 +250,7 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
if (!Modifiers)
return 0;
+
return Session.getSymbolCache().findSymbolByTypeIndex(
Modifiers->ModifiedType);
}
@@ -235,3 +337,8 @@ bool NativeTypeEnum::isUnalignedType() const {
return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
ModifierOptions::None);
}
+
+const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
+ return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
+ getTypeId());
+}
diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
index d8b4d591a97..a4b1ecfb770 100644
--- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
@@ -26,14 +26,17 @@ static const struct BuiltinTypeEntry {
PDB_BuiltinType Type;
uint32_t Size;
} BuiltinTypes[] = {
+ {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
+ {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
{codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
{codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
+ {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
{codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
+ {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
{codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
{codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
{codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
{codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
- {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
{codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}
// This table can be grown as necessary, but these are the only types we've
// needed so far.
@@ -169,6 +172,8 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
std::unique_ptr<PDBSymbol>
SymbolCache::getSymbolById(SymIndexId SymbolId) const {
+ assert(SymbolId < Cache.size());
+
// Id 0 is reserved.
if (SymbolId == 0)
return nullptr;
diff --git a/llvm/lib/DebugInfo/PDB/PDBExtras.cpp b/llvm/lib/DebugInfo/PDB/PDBExtras.cpp
index a4e316417f9..0c5fa42733c 100644
--- a/llvm/lib/DebugInfo/PDB/PDBExtras.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBExtras.cpp
@@ -293,7 +293,7 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const Variant &Value) {
OS << Value.Value.Single;
break;
case PDB_VariantType::UInt16:
- OS << Value.Value.Double;
+ OS << Value.Value.UInt16;
break;
case PDB_VariantType::UInt32:
OS << Value.Value.UInt32;
OpenPOWER on IntegriCloud