1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

Enable llvm-pdbutil to list enumerations using native PDB reader

This extends the native reader to enable llvm-pdbutil to list the enums in a
PDB and it includes a simple test. It does not yet list the values in the
enumerations, which requires an actual implementation of
NativeEnumSymbol::FindChildren.

To exercise this code, use a command like:

    llvm-pdbutil pretty -native -enums foo.pdb

Differential Revision: https://reviews.llvm.org/D35738

llvm-svn: 310144
This commit is contained in:
Adrian McCarthy 2017-08-04 22:37:58 +00:00
parent 23bd4a9364
commit ee6fb7079a
11 changed files with 354 additions and 19 deletions

View File

@ -0,0 +1,60 @@
//===- NativeEnumSymbol.h - info about enum type ----------------*- 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_PDB_NATIVE_NATIVEENUMSYMBOL_H
#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
namespace llvm {
namespace pdb {
class NativeEnumSymbol : public NativeRawSymbol,
public codeview::TypeVisitorCallbacks {
public:
NativeEnumSymbol(NativeSession &Session, SymIndexId Id,
const codeview::CVType &CV);
~NativeEnumSymbol() override;
std::unique_ptr<NativeRawSymbol> clone() const override;
std::unique_ptr<IPDBEnumSymbols>
findChildren(PDB_SymType Type) const override;
Error visitKnownRecord(codeview::CVType &CVR,
codeview::EnumRecord &Record) override;
Error visitKnownMember(codeview::CVMemberRecord &CVM,
codeview::EnumeratorRecord &Record) override;
PDB_SymType getSymTag() const override;
uint32_t getClassParentId() const override;
uint32_t getUnmodifiedTypeId() const override;
bool hasConstructor() const override;
bool hasAssignmentOperator() const override;
bool hasCastOperator() const override;
uint64_t getLength() const override;
std::string getName() const override;
bool isNested() const override;
bool hasOverloadedOperator() const override;
bool isPacked() const override;
bool isScoped() const override;
uint32_t getTypeId() const override;
protected:
codeview::CVType CV;
codeview::EnumRecord Record;
};
} // namespace pdb
} // namespace llvm
#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H

View File

@ -0,0 +1,51 @@
//==- NativeEnumTypes.h - Native Type Enumerator impl ------------*- 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_PDB_NATIVE_NATIVEENUMTYPES_H
#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMTYPES_H
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
#include <vector>
namespace llvm {
namespace pdb {
class NativeSession;
class NativeEnumTypes : public IPDBEnumChildren<PDBSymbol> {
public:
NativeEnumTypes(NativeSession &Session,
codeview::LazyRandomTypeCollection &TypeCollection,
codeview::TypeLeafKind Kind);
uint32_t getChildCount() const override;
std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
std::unique_ptr<PDBSymbol> getNext() override;
void reset() override;
NativeEnumTypes *clone() const override;
private:
NativeEnumTypes(NativeSession &Session,
const std::vector<codeview::TypeIndex> &Matches,
codeview::TypeLeafKind Kind);
std::vector<codeview::TypeIndex> Matches;
uint32_t Index;
NativeSession &Session;
codeview::TypeLeafKind Kind;
};
} // namespace pdb
} // namespace llvm
#endif

View File

@ -39,6 +39,12 @@ public:
std::unique_ptr<PDBSymbolCompiland>
createCompilandSymbol(DbiModuleDescriptor MI);
std::unique_ptr<PDBSymbolTypeEnum>
createEnumSymbol(codeview::TypeIndex Index);
std::unique_ptr<IPDBEnumSymbols>
createTypeEnumerator(codeview::TypeLeafKind Kind);
SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
uint64_t getLoadAddress() const override;

View File

@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H
#define LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H
#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOL_H
#define LLVM_DEBUGINFO_PDB_PDBSYMBOL_H
#include "ConcreteSymbolEnumerator.h"
#include "IPDBRawSymbol.h"

View File

@ -44,6 +44,8 @@ add_pdb_impl_folder(Native
Native/NativeBuiltinSymbol.cpp
Native/NativeCompilandSymbol.cpp
Native/NativeEnumModules.cpp
Native/NativeEnumSymbol.cpp
Native/NativeEnumTypes.cpp
Native/NativeExeSymbol.cpp
Native/NativeRawSymbol.cpp
Native/NamedStreamMap.cpp

View File

@ -0,0 +1,108 @@
//===- NativeEnumSymbol.cpp - info about enum type --------------*- 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/NativeEnumSymbol.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include <cassert>
using namespace llvm;
using namespace llvm::pdb;
NativeEnumSymbol::NativeEnumSymbol(NativeSession &Session, SymIndexId Id,
const codeview::CVType &CVT)
: NativeRawSymbol(Session, Id), CV(CVT),
Record(codeview::TypeRecordKind::Enum) {
assert(CV.kind() == codeview::TypeLeafKind::LF_ENUM);
cantFail(visitTypeRecord(CV, *this));
}
NativeEnumSymbol::~NativeEnumSymbol() {}
std::unique_ptr<NativeRawSymbol> NativeEnumSymbol::clone() const {
return llvm::make_unique<NativeEnumSymbol>(Session, SymbolId, CV);
}
std::unique_ptr<IPDBEnumSymbols>
NativeEnumSymbol::findChildren(PDB_SymType Type) const {
switch (Type) {
case PDB_SymType::Data: {
// TODO(amccarth): Provide an actual implementation.
return nullptr;
}
default:
return nullptr;
}
}
Error NativeEnumSymbol::visitKnownRecord(codeview::CVType &CVR,
codeview::EnumRecord &ER) {
Record = ER;
return Error::success();
}
Error NativeEnumSymbol::visitKnownMember(codeview::CVMemberRecord &CVM,
codeview::EnumeratorRecord &R) {
return Error::success();
}
PDB_SymType NativeEnumSymbol::getSymTag() const { return PDB_SymType::Enum; }
uint32_t NativeEnumSymbol::getClassParentId() const { return 0xFFFFFFFF; }
uint32_t NativeEnumSymbol::getUnmodifiedTypeId() const { return 0; }
bool NativeEnumSymbol::hasConstructor() const {
return bool(Record.getOptions() &
codeview::ClassOptions::HasConstructorOrDestructor);
}
bool NativeEnumSymbol::hasAssignmentOperator() const {
return bool(Record.getOptions() &
codeview::ClassOptions::HasOverloadedAssignmentOperator);
}
bool NativeEnumSymbol::hasCastOperator() const {
return bool(Record.getOptions() &
codeview::ClassOptions::HasConversionOperator);
}
uint64_t NativeEnumSymbol::getLength() const {
const auto Id = Session.findSymbolByTypeIndex(Record.getUnderlyingType());
const auto UnderlyingType =
Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id);
return UnderlyingType ? UnderlyingType->getLength() : 0;
}
std::string NativeEnumSymbol::getName() const { return Record.getName(); }
bool NativeEnumSymbol::isNested() const {
return bool(Record.getOptions() & codeview::ClassOptions::Nested);
}
bool NativeEnumSymbol::hasOverloadedOperator() const {
return bool(Record.getOptions() &
codeview::ClassOptions::HasOverloadedOperator);
}
bool NativeEnumSymbol::isPacked() const {
return bool(Record.getOptions() & codeview::ClassOptions::Packed);
}
bool NativeEnumSymbol::isScoped() const {
return bool(Record.getOptions() & codeview::ClassOptions::Scoped);
}
uint32_t NativeEnumSymbol::getTypeId() const {
return Session.findSymbolByTypeIndex(Record.getUnderlyingType());
}

View File

@ -0,0 +1,59 @@
//==- NativeEnumTypes.cpp - Native Type Enumerator impl ----------*- 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/NativeEnumTypes.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
namespace llvm {
namespace pdb {
NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
codeview::LazyRandomTypeCollection &Types,
codeview::TypeLeafKind Kind)
: Matches(), Index(0), Session(PDBSession), Kind(Kind) {
for (auto Index = Types.getFirst(); Index;
Index = Types.getNext(Index.getValue())) {
if (Types.getType(Index.getValue()).kind() == Kind)
Matches.push_back(Index.getValue());
}
}
NativeEnumTypes::NativeEnumTypes(
NativeSession &PDBSession, const std::vector<codeview::TypeIndex> &Matches,
codeview::TypeLeafKind Kind)
: Matches(Matches), Index(0), Session(PDBSession), Kind(Kind) {}
uint32_t NativeEnumTypes::getChildCount() const {
return static_cast<uint32_t>(Matches.size());
}
std::unique_ptr<PDBSymbol>
NativeEnumTypes::getChildAtIndex(uint32_t Index) const {
if (Index < Matches.size())
return Session.createEnumSymbol(Matches[Index]);
return nullptr;
}
std::unique_ptr<PDBSymbol> NativeEnumTypes::getNext() {
return getChildAtIndex(Index++);
}
void NativeEnumTypes::reset() { Index = 0; }
NativeEnumTypes *NativeEnumTypes::clone() const {
return new NativeEnumTypes(Session, Matches, Kind);
}
} // namespace pdb
} // namespace llvm

View File

@ -13,7 +13,9 @@
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
namespace llvm {
namespace pdb {
@ -38,6 +40,8 @@ NativeExeSymbol::findChildren(PDB_SymType Type) const {
consumeError(Dbi.takeError());
break;
}
case PDB_SymType::Enum:
return Session.createTypeEnumerator(codeview::LF_ENUM);
default:
break;
}

View File

@ -16,11 +16,15 @@
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
#include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
#include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Error.h"
@ -28,6 +32,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include <algorithm>
#include <cassert>
#include <memory>
#include <utility>
@ -102,6 +107,25 @@ NativeSession::createCompilandSymbol(DbiModuleDescriptor MI) {
*this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));
}
std::unique_ptr<PDBSymbolTypeEnum>
NativeSession::createEnumSymbol(codeview::TypeIndex Index) {
const auto Id = findSymbolByTypeIndex(Index);
return llvm::make_unique<PDBSymbolTypeEnum>(
*this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));
}
std::unique_ptr<IPDBEnumSymbols>
NativeSession::createTypeEnumerator(codeview::TypeLeafKind Kind) {
auto Tpi = Pdb->getPDBTpiStream();
if (!Tpi) {
consumeError(Tpi.takeError());
return nullptr;
}
auto &Types = Tpi->typeCollection();
return std::unique_ptr<IPDBEnumSymbols>(
new NativeEnumTypes(*this, Types, codeview::LF_ENUM));
}
SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) {
// First see if it's already in our cache.
const auto Entry = TypeIndexToSymbolId.find(Index);
@ -129,9 +153,20 @@ SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) {
return Id;
}
// TODO: Look up PDB type by type index
return 0;
// We need to instantiate and cache the desired type symbol.
auto Tpi = Pdb->getPDBTpiStream();
if (!Tpi) {
consumeError(Tpi.takeError());
return 0;
}
auto &Types = Tpi->typeCollection();
const auto &I = Types.getType(Index);
const auto Id = static_cast<SymIndexId>(SymbolCache.size());
// TODO(amccarth): Make this handle all types, not just LF_ENUMs.
assert(I.kind() == codeview::LF_ENUM);
SymbolCache.emplace_back(llvm::make_unique<NativeEnumSymbol>(*this, Id, I));
TypeIndexToSymbolId[Index] = Id;
return Id;
}
uint64_t NativeSession::getLoadAddress() const { return 0; }

View File

@ -0,0 +1,6 @@
; Test that the native PDB reader can enumerate the enum types.
; RUN: llvm-pdbutil pretty -native -enums %p/../Inputs/every-type.pdb \
; RUN: | FileCheck -check-prefix=ENUMS %s
ENUMS: enum FooClass::NestedEnum {
ENUMS-NEXT: }

View File

@ -26,25 +26,29 @@ void EnumDumper::start(const PDBSymbolTypeEnum &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
if (!opts::pretty::NoEnumDefs) {
auto BuiltinType = Symbol.getUnderlyingType();
if (BuiltinType->getBuiltinType() != PDB_BuiltinType::Int ||
BuiltinType->getLength() != 4) {
auto UnderlyingType = Symbol.getUnderlyingType();
if (!UnderlyingType)
return;
if (UnderlyingType->getBuiltinType() != PDB_BuiltinType::Int ||
UnderlyingType->getLength() != 4) {
Printer << " : ";
BuiltinDumper Dumper(Printer);
Dumper.start(*BuiltinType);
Dumper.start(*UnderlyingType);
}
auto EnumValues = Symbol.findAllChildren<PDBSymbolData>();
Printer << " {";
Printer.Indent();
auto EnumValues = Symbol.findAllChildren<PDBSymbolData>();
while (auto EnumValue = EnumValues->getNext()) {
if (EnumValue->getDataKind() != PDB_DataKind::Constant)
continue;
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Identifier).get()
<< EnumValue->getName();
Printer << " = ";
WithColor(Printer, PDB_ColorItem::LiteralValue).get()
<< EnumValue->getValue();
if (EnumValues && EnumValues->getChildCount() > 0) {
while (auto EnumValue = EnumValues->getNext()) {
if (EnumValue->getDataKind() != PDB_DataKind::Constant)
continue;
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Identifier).get()
<< EnumValue->getName();
Printer << " = ";
WithColor(Printer, PDB_ColorItem::LiteralValue).get()
<< EnumValue->getValue();
}
}
Printer.Unindent();
Printer.NewLine();