Skip to content

Commit

Permalink
[llvm-pdbutil] rewrite the "raw" output style.
Browse files Browse the repository at this point in the history
After some internal discussions, we agreed that the raw output style had
outlived its usefulness. It was originally created before we had even
thought of dumping to YAML, and it was intended to give us some insight
into the internals of a PDB file. Now we have YAML mode which does
almost exactly this but is more powerful in that it can round-trip back
to a PDB, which the raw mode could not do. So the raw mode had become
purely a maintenance burden.

One option was to just delete it. However, its original goal was to be
as readable as possible while staying close to the "metal" - i.e.
presenting the output in a way that maps directly to the underlying file
format. We don't actually need that last requirement anymore since it's
covered by the yaml mode, so we could repurpose "raw" mode to actually
just be as readable as possible.

This patch implements about 80% of the functionality previously in raw
mode, but in a completely different style that is more akin to what
cvdump outputs. Records are very compressed, often times appearing on
just one line. One nice thing about this is that it makes full record
matching easier, because you can grep for indices, names, and leaf types
on a single line often.

See the tests for some examples of what the new output looks like.

Note that this patch actually regresses the functionality of raw mode in
a few areas, but only because the patch was already unreasonably large
and going 100% would have been even worse. Specifically, this patch is
missing:

The ability to dump module debug subsections (checksums, lines, etc)
The ability to dump section headers
Aside from that everything is here. While goign through the tests fixing
them all up, I found many duplicate tests. They've been deleted. In
subsequent patches I will go through and re-add the missing
functionality.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305495 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Zachary Turner committed Jun 15, 2017
1 parent 7807f69 commit 0f6dce0
Show file tree
Hide file tree
Showing 41 changed files with 3,823 additions and 4,818 deletions.
5 changes: 5 additions & 0 deletions include/llvm/DebugInfo/CodeView/CodeView.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,8 @@ CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ProcSymFlags)

/// Corresponds to COMPILESYM2::Flags bitfield.
enum class CompileSym2Flags : uint32_t {
None = 0,
SourceLanguageMask = 0xFF,
EC = 1 << 8,
NoDbgInfo = 1 << 9,
LTCG = 1 << 10,
Expand All @@ -432,6 +434,8 @@ CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(CompileSym2Flags)

/// Corresponds to COMPILESYM3::Flags bitfield.
enum class CompileSym3Flags : uint32_t {
None = 0,
SourceLanguageMask = 0xFF,
EC = 1 << 8,
NoDbgInfo = 1 << 9,
LTCG = 1 << 10,
Expand All @@ -448,6 +452,7 @@ enum class CompileSym3Flags : uint32_t {
CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(CompileSym3Flags)

enum class ExportFlags : uint16_t {
None = 0,
IsConstant = 1 << 0,
IsData = 1 << 1,
IsPrivate = 1 << 2,
Expand Down
17 changes: 17 additions & 0 deletions include/llvm/DebugInfo/CodeView/Formatters.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"

namespace llvm {
namespace codeview {
Expand All @@ -35,6 +38,20 @@ inline detail::GuidAdapter fmt_guid(ArrayRef<uint8_t> Item) {
return detail::GuidAdapter(Item);
}
}

template <> struct format_provider<codeview::TypeIndex> {
public:
static void format(const codeview::TypeIndex &V, llvm::raw_ostream &Stream,
StringRef Style) {
if (V.isNoneType())
Stream << "<no type>";
else {
Stream << formatv("{0:X+4}", V.getIndex());
if (V.isSimple())
Stream << " (" << codeview::TypeIndex::simpleTypeName(V) << ")";
}
}
};
}

#endif
10 changes: 5 additions & 5 deletions include/llvm/DebugInfo/CodeView/SymbolRecord.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ class PublicSym32 : public SymbolRecord {
: SymbolRecord(SymbolRecordKind::PublicSym32),
RecordOffset(RecordOffset) {}

uint32_t Index;
TypeIndex Index;
uint32_t Offset;
uint16_t Segment;
StringRef Name;
Expand All @@ -379,7 +379,7 @@ class RegisterSym : public SymbolRecord {
: SymbolRecord(SymbolRecordKind::RegisterSym),
RecordOffset(RecordOffset) {}

uint32_t Index;
TypeIndex Index;
RegisterId Register;
StringRef Name;

Expand Down Expand Up @@ -679,7 +679,7 @@ class FileStaticSym : public SymbolRecord {
: SymbolRecord(SymbolRecordKind::FileStaticSym),
RecordOffset(RecordOffset) {}

uint32_t Index;
TypeIndex Index;
uint32_t ModFilenameOffset;
LocalSymFlags Flags;
StringRef Name;
Expand Down Expand Up @@ -814,7 +814,7 @@ class FrameCookieSym : public SymbolRecord {

uint32_t CodeOffset;
uint16_t Register;
uint8_t CookieKind;
FrameCookieKind CookieKind;
uint8_t Flags;

uint32_t RecordOffset;
Expand Down Expand Up @@ -871,7 +871,7 @@ class RegRelativeSym : public SymbolRecord {

uint32_t Offset;
TypeIndex Type;
uint16_t Register;
RegisterId Register;
StringRef Name;

uint32_t RecordOffset;
Expand Down
2 changes: 2 additions & 0 deletions include/llvm/DebugInfo/CodeView/TypeIndex.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ class TypeIndex {
return A.toArrayIndex() - B.toArrayIndex();
}

static StringRef simpleTypeName(TypeIndex TI);

private:
support::ulittle32_t Index;
};
Expand Down
4 changes: 4 additions & 0 deletions include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class ModuleDebugStreamRef {
iterator_range<codeview::CVSymbolArray::Iterator>
symbols(bool *HadError) const;

const codeview::CVSymbolArray &getSymbolArray() const {
return SymbolsSubstream;
}

llvm::iterator_range<DebugSubsectionIterator> subsections() const;

bool hasDebugSubsections() const;
Expand Down
1 change: 1 addition & 0 deletions include/llvm/DebugInfo/PDB/Native/PublicsStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class PublicsStream {
uint32_t getSymHash() const;
uint32_t getAddrMap() const;
uint32_t getNumBuckets() const { return NumBuckets; }
Expected<const codeview::CVSymbolArray &> getSymbolArray() const;
iterator_range<codeview::CVSymbolArray::Iterator>
getSymbols(bool *HadError) const;
FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
Expand Down
6 changes: 5 additions & 1 deletion include/llvm/DebugInfo/PDB/Native/RawConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,19 @@ enum class DbgHeaderType : uint16_t {
};

enum class OMFSegDescFlags : uint16_t {
None = 0,
Read = 1 << 0, // Segment is readable.
Write = 1 << 1, // Segment is writable.
Execute = 1 << 2, // Segment is executable.
AddressIs32Bit = 1 << 3, // Descriptor describes a 32-bit linear address.
IsSelector = 1 << 8, // Frame represents a selector.
IsAbsoluteAddress = 1 << 9, // Frame represents an absolute address.
IsGroup = 1 << 10 // If set, descriptor represents a group.
IsGroup = 1 << 10, // If set, descriptor represents a group.
LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IsGroup)
};

LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();

} // end namespace pdb
} // end namespace llvm

Expand Down
4 changes: 4 additions & 0 deletions include/llvm/DebugInfo/PDB/Native/SymbolStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ class SymbolStream {
~SymbolStream();
Error reload();

const codeview::CVSymbolArray &getSymbolArray() const {
return SymbolRecords;
}

iterator_range<codeview::CVSymbolArray::Iterator>
getSymbols(bool *HadError) const;

Expand Down
6 changes: 6 additions & 0 deletions include/llvm/Support/BinaryStreamArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,12 @@ template <typename T> class FixedStreamArray {
return FixedStreamArrayIterator<T>(*this, size());
}

const T &front() const { return *begin(); }
const T &back() const {
FixedStreamArrayIterator<T> I = end();
return *(--I);
}

BinaryStreamRef getUnderlyingStream() const { return Stream; }

private:
Expand Down
14 changes: 14 additions & 0 deletions include/llvm/Support/FormatProviders.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FormatVariadicDetails.h"
#include "llvm/Support/NativeFormatting.h"

Expand Down Expand Up @@ -150,6 +151,19 @@ struct format_provider<
}
};

template <typename T, llvm::support::endianness E, int alignment>
struct format_provider<
support::detail::packed_endian_specific_integral<T, E, alignment>> {
using Type =
support::detail::packed_endian_specific_integral<T, E, alignment>;

public:
static void format(const Type &V, llvm::raw_ostream &Stream,
StringRef Style) {
format_provider<T>::format(static_cast<T>(V), Stream, Style);
}
};

/// Implementation of format_provider<T> for integral pointer types.
///
/// The options string of a pointer type has the grammar:
Expand Down
8 changes: 4 additions & 4 deletions lib/DebugInfo/CodeView/SymbolDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
FileStaticSym &FileStatic) {
DictScope S(W, "FileStatic");
W.printNumber("Index", FileStatic.Index);
printTypeIndex("Index", FileStatic.Index);
W.printNumber("ModFilenameOffset", FileStatic.ModFilenameOffset);
W.printFlags("Flags", uint16_t(FileStatic.Flags), getLocalFlagNames());
W.printString("Name", FileStatic.Name);
Expand Down Expand Up @@ -516,15 +516,15 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
RegisterSym &Register) {
DictScope S(W, "RegisterSym");
W.printNumber("Type", Register.Index);
printTypeIndex("Type", Register.Index);
W.printEnum("Seg", uint16_t(Register.Register), getRegisterNames());
W.printString("Name", Register.Name);
return Error::success();
}

Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) {
DictScope S(W, "PublicSym");
W.printNumber("Type", Public.Index);
printTypeIndex("Type", Public.Index);
W.printNumber("Seg", Public.Segment);
W.printNumber("Off", Public.Offset);
W.printString("Name", Public.Name);
Expand Down Expand Up @@ -631,7 +631,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,

W.printHex("Offset", RegRel.Offset);
printTypeIndex("Type", RegRel.Type);
W.printHex("Register", RegRel.Register);
W.printEnum("Register", uint16_t(RegRel.Register), getRegisterNames());
W.printString("VarName", RegRel.Name);
return Error::success();
}
Expand Down
4 changes: 2 additions & 2 deletions lib/DebugInfo/CodeView/SymbolRecordMapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,

error(IO.mapInteger(FrameCookie.CodeOffset));
error(IO.mapInteger(FrameCookie.Register));
error(IO.mapInteger(FrameCookie.CookieKind));
error(IO.mapEnum(FrameCookie.CookieKind));
error(IO.mapInteger(FrameCookie.Flags));

return Error::success();
Expand Down Expand Up @@ -439,7 +439,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,

error(IO.mapInteger(RegRel.Offset));
error(IO.mapInteger(RegRel.Type));
error(IO.mapInteger(RegRel.Register));
error(IO.mapEnum(RegRel.Register));
error(IO.mapStringZ(RegRel.Name));

return Error::success();
Expand Down
71 changes: 2 additions & 69 deletions lib/DebugInfo/CodeView/TypeDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,59 +12,6 @@
using namespace llvm;
using namespace llvm::codeview;

namespace {
struct SimpleTypeEntry {
StringRef Name;
SimpleTypeKind Kind;
};
}

/// The names here all end in "*". If the simple type is a pointer type, we
/// return the whole name. Otherwise we lop off the last character in our
/// StringRef.
static const SimpleTypeEntry SimpleTypeNames[] = {
{"void*", SimpleTypeKind::Void},
{"<not translated>*", SimpleTypeKind::NotTranslated},
{"HRESULT*", SimpleTypeKind::HResult},
{"signed char*", SimpleTypeKind::SignedCharacter},
{"unsigned char*", SimpleTypeKind::UnsignedCharacter},
{"char*", SimpleTypeKind::NarrowCharacter},
{"wchar_t*", SimpleTypeKind::WideCharacter},
{"char16_t*", SimpleTypeKind::Character16},
{"char32_t*", SimpleTypeKind::Character32},
{"__int8*", SimpleTypeKind::SByte},
{"unsigned __int8*", SimpleTypeKind::Byte},
{"short*", SimpleTypeKind::Int16Short},
{"unsigned short*", SimpleTypeKind::UInt16Short},
{"__int16*", SimpleTypeKind::Int16},
{"unsigned __int16*", SimpleTypeKind::UInt16},
{"long*", SimpleTypeKind::Int32Long},
{"unsigned long*", SimpleTypeKind::UInt32Long},
{"int*", SimpleTypeKind::Int32},
{"unsigned*", SimpleTypeKind::UInt32},
{"__int64*", SimpleTypeKind::Int64Quad},
{"unsigned __int64*", SimpleTypeKind::UInt64Quad},
{"__int64*", SimpleTypeKind::Int64},
{"unsigned __int64*", SimpleTypeKind::UInt64},
{"__int128*", SimpleTypeKind::Int128},
{"unsigned __int128*", SimpleTypeKind::UInt128},
{"__half*", SimpleTypeKind::Float16},
{"float*", SimpleTypeKind::Float32},
{"float*", SimpleTypeKind::Float32PartialPrecision},
{"__float48*", SimpleTypeKind::Float48},
{"double*", SimpleTypeKind::Float64},
{"long double*", SimpleTypeKind::Float80},
{"__float128*", SimpleTypeKind::Float128},
{"_Complex float*", SimpleTypeKind::Complex32},
{"_Complex double*", SimpleTypeKind::Complex64},
{"_Complex long double*", SimpleTypeKind::Complex80},
{"_Complex __float128*", SimpleTypeKind::Complex128},
{"bool*", SimpleTypeKind::Boolean8},
{"__bool16*", SimpleTypeKind::Boolean16},
{"__bool32*", SimpleTypeKind::Boolean32},
{"__bool64*", SimpleTypeKind::Boolean64},
};

TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) {
CVUDTNames.resize(Capacity);
TypeRecords.resize(Capacity);
Expand Down Expand Up @@ -103,22 +50,8 @@ StringRef TypeDatabase::saveTypeName(StringRef TypeName) {
}

StringRef TypeDatabase::getTypeName(TypeIndex Index) const {
if (Index.isNoneType())
return "<no type>";

if (Index.isSimple()) {
// This is a simple type.
for (const auto &SimpleTypeName : SimpleTypeNames) {
if (SimpleTypeName.Kind == Index.getSimpleKind()) {
if (Index.getSimpleMode() == SimpleTypeMode::Direct)
return SimpleTypeName.Name.drop_back(1);
// Otherwise, this is a pointer type. We gloss over the distinction
// between near, far, 64, 32, etc, and just give a pointer type.
return SimpleTypeName.Name;
}
}
return "<unknown simple type>";
}
if (Index.isNoneType() || Index.isSimple())
return TypeIndex::simpleTypeName(Index);

if (contains(Index))
return CVUDTNames[Index.toArrayIndex()];
Expand Down
Loading

0 comments on commit 0f6dce0

Please sign in to comment.