diff options
author | Zachary Turner <zturner@google.com> | 2018-09-17 21:08:11 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2018-09-17 21:08:11 +0000 |
commit | bdf0381e216e2aaa1aa736fd288d94786e4447e0 (patch) | |
tree | c3aa3cf7b6a308538953cf7a6623ca21c7b4d146 /llvm/lib/DebugInfo | |
parent | 4727ac23947013a1f1cdd1f8ced7002f3bc06c72 (diff) | |
download | bcm5719-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.txt | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp | 116 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp | 123 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/PDBExtras.cpp | 2 |
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; |