2016-05-24 01:41:13 +02:00
|
|
|
//===-- SymbolDumper.cpp - CodeView symbol info dumper ----------*- 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/CodeView/SymbolDumper.h"
|
|
|
|
#include "llvm/ADT/SmallString.h"
|
|
|
|
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
|
2017-05-30 19:13:33 +02:00
|
|
|
#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
|
2016-06-02 07:07:49 +02:00
|
|
|
#include "llvm/DebugInfo/CodeView/EnumTables.h"
|
2016-10-07 23:34:46 +02:00
|
|
|
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
|
2016-05-24 01:41:13 +02:00
|
|
|
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
|
|
|
|
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
2016-10-07 23:34:46 +02:00
|
|
|
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
|
|
|
|
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
|
2016-05-24 01:41:13 +02:00
|
|
|
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
2016-10-07 23:34:46 +02:00
|
|
|
#include "llvm/Support/Error.h"
|
2016-05-24 01:41:13 +02:00
|
|
|
#include "llvm/Support/ScopedPrinter.h"
|
|
|
|
|
|
|
|
#include <system_error>
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::codeview;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
/// Use this private dumper implementation to keep implementation details about
|
|
|
|
/// the visitor out of SymbolDumper.h.
|
2016-10-07 23:34:46 +02:00
|
|
|
class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
|
2016-05-24 01:41:13 +02:00
|
|
|
public:
|
2017-05-19 21:26:58 +02:00
|
|
|
CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate,
|
2016-05-24 02:06:04 +02:00
|
|
|
ScopedPrinter &W, bool PrintRecordBytes)
|
2017-05-19 21:26:58 +02:00
|
|
|
: Types(Types), ObjDelegate(ObjDelegate), W(W),
|
2016-10-07 23:34:46 +02:00
|
|
|
PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
|
2016-05-24 01:41:13 +02:00
|
|
|
|
|
|
|
/// CVSymbolVisitor overrides.
|
|
|
|
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
|
2016-10-07 23:34:46 +02:00
|
|
|
Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
|
2016-05-24 01:41:13 +02:00
|
|
|
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
2017-05-30 23:53:05 +02:00
|
|
|
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
|
2016-05-24 01:41:13 +02:00
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error visitSymbolBegin(CVSymbol &Record) override;
|
|
|
|
Error visitSymbolEnd(CVSymbol &Record) override;
|
|
|
|
Error visitUnknownSymbol(CVSymbol &Record) override;
|
2016-05-24 01:41:13 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
|
|
|
|
uint32_t RelocationOffset);
|
|
|
|
void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
void printTypeIndex(StringRef FieldName, TypeIndex TI);
|
2016-05-24 01:41:13 +02:00
|
|
|
|
2017-05-19 21:26:58 +02:00
|
|
|
TypeCollection &Types;
|
2016-05-24 01:41:13 +02:00
|
|
|
SymbolDumpDelegate *ObjDelegate;
|
|
|
|
ScopedPrinter &W;
|
|
|
|
|
|
|
|
bool PrintRecordBytes;
|
|
|
|
bool InFunctionScope;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-07-12 01:41:41 +02:00
|
|
|
static StringRef getSymbolKindName(SymbolKind Kind) {
|
|
|
|
switch (Kind) {
|
|
|
|
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
|
|
|
|
case EnumName: \
|
|
|
|
return #Name;
|
|
|
|
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return "UnknownSym";
|
|
|
|
}
|
|
|
|
|
2016-05-24 01:41:13 +02:00
|
|
|
void CVSymbolDumperImpl::printLocalVariableAddrRange(
|
|
|
|
const LocalVariableAddrRange &Range, uint32_t RelocationOffset) {
|
|
|
|
DictScope S(W, "LocalVariableAddrRange");
|
|
|
|
if (ObjDelegate)
|
|
|
|
ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset,
|
|
|
|
Range.OffsetStart);
|
|
|
|
W.printHex("ISectStart", Range.ISectStart);
|
|
|
|
W.printHex("Range", Range.Range);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVSymbolDumperImpl::printLocalVariableAddrGap(
|
|
|
|
ArrayRef<LocalVariableAddrGap> Gaps) {
|
|
|
|
for (auto &Gap : Gaps) {
|
|
|
|
ListScope S(W, "LocalVariableAddrGap");
|
|
|
|
W.printHex("GapStartOffset", Gap.GapStartOffset);
|
|
|
|
W.printHex("Range", Gap.Range);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) {
|
2017-05-19 21:26:58 +02:00
|
|
|
codeview::printTypeIndex(W, FieldName, TI, Types);
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
|
2017-07-12 01:41:41 +02:00
|
|
|
W.startLine() << getSymbolKindName(CVR.Type);
|
|
|
|
W.getOStream() << " {\n";
|
|
|
|
W.indent();
|
|
|
|
W.printEnum("Kind", unsigned(CVR.Type), getSymbolTypeNames());
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
|
|
|
}
|
2016-05-24 01:41:13 +02:00
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitSymbolEnd(CVSymbol &CVR) {
|
2016-05-24 01:41:13 +02:00
|
|
|
if (PrintRecordBytes && ObjDelegate)
|
2016-10-07 23:34:46 +02:00
|
|
|
ObjDelegate->printBinaryBlockWithRelocs("SymData", CVR.content());
|
2017-07-12 01:41:41 +02:00
|
|
|
|
|
|
|
W.unindent();
|
|
|
|
W.startLine() << "}\n";
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
|
2016-05-24 01:41:13 +02:00
|
|
|
StringRef LinkageName;
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printHex("PtrParent", Block.Parent);
|
|
|
|
W.printHex("PtrEnd", Block.End);
|
|
|
|
W.printHex("CodeSize", Block.CodeSize);
|
2016-05-24 01:41:13 +02:00
|
|
|
if (ObjDelegate) {
|
|
|
|
ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(),
|
2016-12-16 23:48:14 +01:00
|
|
|
Block.CodeOffset, &LinkageName);
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printHex("Segment", Block.Segment);
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printString("BlockName", Block.Name);
|
|
|
|
W.printString("LinkageName", LinkageName);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
|
2018-04-16 18:53:57 +02:00
|
|
|
W.printString("Name", Thunk.Name);
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("Parent", Thunk.Parent);
|
|
|
|
W.printNumber("End", Thunk.End);
|
|
|
|
W.printNumber("Next", Thunk.Next);
|
|
|
|
W.printNumber("Off", Thunk.Offset);
|
|
|
|
W.printNumber("Seg", Thunk.Segment);
|
|
|
|
W.printNumber("Len", Thunk.Length);
|
|
|
|
W.printEnum("Ordinal", uint8_t(Thunk.Thunk), getThunkOrdinalNames());
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-25 00:58:46 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
TrampolineSym &Tramp) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printEnum("Type", uint16_t(Tramp.Type), getTrampolineNames());
|
|
|
|
W.printNumber("Size", Tramp.Size);
|
|
|
|
W.printNumber("ThunkOff", Tramp.ThunkOffset);
|
|
|
|
W.printNumber("TargetOff", Tramp.TargetOffset);
|
|
|
|
W.printNumber("ThunkSection", Tramp.ThunkSection);
|
|
|
|
W.printNumber("TargetSection", Tramp.TargetSection);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-25 00:58:46 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, SectionSym &Section) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("SectionNumber", Section.SectionNumber);
|
|
|
|
W.printNumber("Alignment", Section.Alignment);
|
|
|
|
W.printNumber("Rva", Section.Rva);
|
|
|
|
W.printNumber("Length", Section.Length);
|
|
|
|
W.printFlags("Characteristics", Section.Characteristics,
|
2016-06-02 07:07:49 +02:00
|
|
|
getImageSectionCharacteristicNames(),
|
|
|
|
COFF::SectionCharacteristics(0x00F00000));
|
|
|
|
|
2016-05-25 00:58:46 +02:00
|
|
|
W.printString("Name", Section.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-25 00:58:46 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
2016-05-25 00:58:46 +02:00
|
|
|
CoffGroupSym &CoffGroup) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("Size", CoffGroup.Size);
|
|
|
|
W.printFlags("Characteristics", CoffGroup.Characteristics,
|
2016-06-02 07:07:49 +02:00
|
|
|
getImageSectionCharacteristicNames(),
|
|
|
|
COFF::SectionCharacteristics(0x00F00000));
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("Offset", CoffGroup.Offset);
|
|
|
|
W.printNumber("Segment", CoffGroup.Segment);
|
2016-05-25 00:58:46 +02:00
|
|
|
W.printString("Name", CoffGroup.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-25 00:58:46 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
BPRelativeSym &BPRel) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("Offset", BPRel.Offset);
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
printTypeIndex("Type", BPRel.Type);
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printString("VarName", BPRel.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
2016-05-24 01:41:13 +02:00
|
|
|
BuildInfoSym &BuildInfo) {
|
2017-07-15 20:10:39 +02:00
|
|
|
printTypeIndex("BuildId", BuildInfo.BuildId);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
CallSiteInfoSym &CallSiteInfo) {
|
2016-05-24 01:41:13 +02:00
|
|
|
StringRef LinkageName;
|
|
|
|
if (ObjDelegate) {
|
2016-12-16 23:48:14 +01:00
|
|
|
ObjDelegate->printRelocatedField("CodeOffset",
|
|
|
|
CallSiteInfo.getRelocationOffset(),
|
|
|
|
CallSiteInfo.CodeOffset, &LinkageName);
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printHex("Segment", CallSiteInfo.Segment);
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
printTypeIndex("Type", CallSiteInfo.Type);
|
2016-05-24 01:41:13 +02:00
|
|
|
if (!LinkageName.empty())
|
|
|
|
W.printString("LinkageName", LinkageName);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
EnvBlockSym &EnvBlock) {
|
2016-05-25 00:58:46 +02:00
|
|
|
ListScope L(W, "Entries");
|
|
|
|
for (auto Entry : EnvBlock.Fields) {
|
|
|
|
W.printString(Entry);
|
|
|
|
}
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-25 00:58:46 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
FileStaticSym &FileStatic) {
|
2017-06-16 00:24:24 +02:00
|
|
|
printTypeIndex("Index", FileStatic.Index);
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("ModFilenameOffset", FileStatic.ModFilenameOffset);
|
|
|
|
W.printFlags("Flags", uint16_t(FileStatic.Flags), getLocalFlagNames());
|
2016-05-25 00:58:46 +02:00
|
|
|
W.printString("Name", FileStatic.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-25 00:58:46 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("Ordinal", Export.Ordinal);
|
|
|
|
W.printFlags("Flags", uint16_t(Export.Flags), getExportSymFlagNames());
|
2016-05-25 02:12:40 +02:00
|
|
|
W.printString("Name", Export.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-25 02:12:40 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
Compile2Sym &Compile2) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printEnum("Language", Compile2.getLanguage(), getSourceLanguageNames());
|
|
|
|
W.printFlags("Flags", Compile2.getFlags(), getCompileSym2FlagNames());
|
|
|
|
W.printEnum("Machine", unsigned(Compile2.Machine), getCPUTypeNames());
|
2016-05-25 00:58:46 +02:00
|
|
|
std::string FrontendVersion;
|
|
|
|
{
|
|
|
|
raw_string_ostream Out(FrontendVersion);
|
2016-12-16 23:48:14 +01:00
|
|
|
Out << Compile2.VersionFrontendMajor << '.' << Compile2.VersionFrontendMinor
|
|
|
|
<< '.' << Compile2.VersionFrontendBuild;
|
2016-05-25 00:58:46 +02:00
|
|
|
}
|
|
|
|
std::string BackendVersion;
|
|
|
|
{
|
|
|
|
raw_string_ostream Out(BackendVersion);
|
2016-12-16 23:48:14 +01:00
|
|
|
Out << Compile2.VersionBackendMajor << '.' << Compile2.VersionBackendMinor
|
|
|
|
<< '.' << Compile2.VersionBackendBuild;
|
2016-05-25 00:58:46 +02:00
|
|
|
}
|
|
|
|
W.printString("FrontendVersion", FrontendVersion);
|
|
|
|
W.printString("BackendVersion", BackendVersion);
|
|
|
|
W.printString("VersionName", Compile2.Version);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-25 00:58:46 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
Compile3Sym &Compile3) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printEnum("Language", Compile3.getLanguage(), getSourceLanguageNames());
|
|
|
|
W.printFlags("Flags", Compile3.getFlags(), getCompileSym3FlagNames());
|
|
|
|
W.printEnum("Machine", unsigned(Compile3.Machine), getCPUTypeNames());
|
2016-05-24 01:41:13 +02:00
|
|
|
std::string FrontendVersion;
|
|
|
|
{
|
|
|
|
raw_string_ostream Out(FrontendVersion);
|
2016-12-16 23:48:14 +01:00
|
|
|
Out << Compile3.VersionFrontendMajor << '.' << Compile3.VersionFrontendMinor
|
|
|
|
<< '.' << Compile3.VersionFrontendBuild << '.'
|
|
|
|
<< Compile3.VersionFrontendQFE;
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
std::string BackendVersion;
|
|
|
|
{
|
|
|
|
raw_string_ostream Out(BackendVersion);
|
2016-12-16 23:48:14 +01:00
|
|
|
Out << Compile3.VersionBackendMajor << '.' << Compile3.VersionBackendMinor
|
|
|
|
<< '.' << Compile3.VersionBackendBuild << '.'
|
|
|
|
<< Compile3.VersionBackendQFE;
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
W.printString("FrontendVersion", FrontendVersion);
|
|
|
|
W.printString("BackendVersion", BackendVersion);
|
|
|
|
W.printString("VersionName", Compile3.Version);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
ConstantSym &Constant) {
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
printTypeIndex("Type", Constant.Type);
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printNumber("Value", Constant.Value);
|
|
|
|
W.printString("Name", Constant.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
|
2016-05-24 01:41:13 +02:00
|
|
|
StringRef LinkageName;
|
|
|
|
if (ObjDelegate) {
|
|
|
|
ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
|
2016-12-16 23:48:14 +01:00
|
|
|
Data.DataOffset, &LinkageName);
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
printTypeIndex("Type", Data.Type);
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printString("DisplayName", Data.Name);
|
|
|
|
if (!LinkageName.empty())
|
|
|
|
W.printString("LinkageName", LinkageName);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(
|
|
|
|
CVSymbol &CVR,
|
2016-05-24 01:41:13 +02:00
|
|
|
DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("Offset", DefRangeFramePointerRelFullScope.Offset);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(
|
|
|
|
CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("Offset", DefRangeFramePointerRel.Offset);
|
|
|
|
printLocalVariableAddrRange(DefRangeFramePointerRel.Range,
|
2016-05-24 01:41:13 +02:00
|
|
|
DefRangeFramePointerRel.getRelocationOffset());
|
|
|
|
printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(
|
|
|
|
CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
|
2017-10-02 19:44:47 +02:00
|
|
|
W.printEnum("BaseRegister", uint16_t(DefRangeRegisterRel.Hdr.Register),
|
|
|
|
getRegisterNames());
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printBoolean("HasSpilledUDTMember",
|
|
|
|
DefRangeRegisterRel.hasSpilledUDTMember());
|
|
|
|
W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("BasePointerOffset", DefRangeRegisterRel.Hdr.BasePointerOffset);
|
|
|
|
printLocalVariableAddrRange(DefRangeRegisterRel.Range,
|
2016-05-24 01:41:13 +02:00
|
|
|
DefRangeRegisterRel.getRelocationOffset());
|
|
|
|
printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(
|
|
|
|
CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
|
2017-10-02 19:44:47 +02:00
|
|
|
W.printEnum("Register", uint16_t(DefRangeRegister.Hdr.Register),
|
|
|
|
getRegisterNames());
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("MayHaveNoName", DefRangeRegister.Hdr.MayHaveNoName);
|
|
|
|
printLocalVariableAddrRange(DefRangeRegister.Range,
|
2016-05-24 01:41:13 +02:00
|
|
|
DefRangeRegister.getRelocationOffset());
|
|
|
|
printLocalVariableAddrGap(DefRangeRegister.Gaps);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(
|
|
|
|
CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
|
2017-10-02 19:44:47 +02:00
|
|
|
W.printEnum("Register", uint16_t(DefRangeSubfieldRegister.Hdr.Register),
|
|
|
|
getRegisterNames());
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Hdr.MayHaveNoName);
|
|
|
|
W.printNumber("OffsetInParent", DefRangeSubfieldRegister.Hdr.OffsetInParent);
|
|
|
|
printLocalVariableAddrRange(DefRangeSubfieldRegister.Range,
|
2016-05-24 01:41:13 +02:00
|
|
|
DefRangeSubfieldRegister.getRelocationOffset());
|
|
|
|
printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(
|
|
|
|
CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
|
2016-05-24 01:41:13 +02:00
|
|
|
if (ObjDelegate) {
|
2017-05-30 19:13:33 +02:00
|
|
|
DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable();
|
2017-05-03 19:11:11 +02:00
|
|
|
auto ExpectedProgram = Strings.getString(DefRangeSubfield.Program);
|
|
|
|
if (!ExpectedProgram) {
|
|
|
|
consumeError(ExpectedProgram.takeError());
|
2016-10-07 23:34:46 +02:00
|
|
|
return llvm::make_error<CodeViewError>(
|
|
|
|
"String table offset outside of bounds of String Table!");
|
2017-05-03 19:11:11 +02:00
|
|
|
}
|
|
|
|
W.printString("Program", *ExpectedProgram);
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("OffsetInParent", DefRangeSubfield.OffsetInParent);
|
|
|
|
printLocalVariableAddrRange(DefRangeSubfield.Range,
|
2016-05-24 01:41:13 +02:00
|
|
|
DefRangeSubfield.getRelocationOffset());
|
|
|
|
printLocalVariableAddrGap(DefRangeSubfield.Gaps);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
DefRangeSym &DefRange) {
|
2016-05-24 01:41:13 +02:00
|
|
|
if (ObjDelegate) {
|
2017-05-30 19:13:33 +02:00
|
|
|
DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable();
|
2017-05-03 19:11:11 +02:00
|
|
|
auto ExpectedProgram = Strings.getString(DefRange.Program);
|
|
|
|
if (!ExpectedProgram) {
|
|
|
|
consumeError(ExpectedProgram.takeError());
|
2016-10-07 23:34:46 +02:00
|
|
|
return llvm::make_error<CodeViewError>(
|
|
|
|
"String table offset outside of bounds of String Table!");
|
2017-05-03 19:11:11 +02:00
|
|
|
}
|
|
|
|
W.printString("Program", *ExpectedProgram);
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
2016-12-16 23:48:14 +01:00
|
|
|
printLocalVariableAddrRange(DefRange.Range, DefRange.getRelocationOffset());
|
2016-05-24 01:41:13 +02:00
|
|
|
printLocalVariableAddrGap(DefRange.Gaps);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
FrameCookieSym &FrameCookie) {
|
2016-05-24 01:41:13 +02:00
|
|
|
StringRef LinkageName;
|
|
|
|
if (ObjDelegate) {
|
2016-12-16 23:48:14 +01:00
|
|
|
ObjDelegate->printRelocatedField("CodeOffset",
|
|
|
|
FrameCookie.getRelocationOffset(),
|
|
|
|
FrameCookie.CodeOffset, &LinkageName);
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
2017-10-02 19:44:47 +02:00
|
|
|
W.printEnum("Register", uint16_t(FrameCookie.Register), getRegisterNames());
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printEnum("CookieKind", uint16_t(FrameCookie.CookieKind),
|
2016-06-02 07:07:49 +02:00
|
|
|
getFrameCookieKindNames());
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printHex("Flags", FrameCookie.Flags);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
2016-05-24 01:41:13 +02:00
|
|
|
FrameProcSym &FrameProc) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printHex("TotalFrameBytes", FrameProc.TotalFrameBytes);
|
|
|
|
W.printHex("PaddingFrameBytes", FrameProc.PaddingFrameBytes);
|
|
|
|
W.printHex("OffsetToPadding", FrameProc.OffsetToPadding);
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printHex("BytesOfCalleeSavedRegisters",
|
2016-12-16 23:48:14 +01:00
|
|
|
FrameProc.BytesOfCalleeSavedRegisters);
|
|
|
|
W.printHex("OffsetOfExceptionHandler", FrameProc.OffsetOfExceptionHandler);
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printHex("SectionIdOfExceptionHandler",
|
2016-12-16 23:48:14 +01:00
|
|
|
FrameProc.SectionIdOfExceptionHandler);
|
|
|
|
W.printFlags("Flags", static_cast<uint32_t>(FrameProc.Flags),
|
|
|
|
getFrameProcSymFlagNames());
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(
|
|
|
|
CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
|
2016-05-24 01:41:13 +02:00
|
|
|
StringRef LinkageName;
|
|
|
|
if (ObjDelegate) {
|
2016-12-16 23:48:14 +01:00
|
|
|
ObjDelegate->printRelocatedField("CodeOffset",
|
|
|
|
HeapAllocSite.getRelocationOffset(),
|
|
|
|
HeapAllocSite.CodeOffset, &LinkageName);
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printHex("Segment", HeapAllocSite.Segment);
|
|
|
|
W.printHex("CallInstructionSize", HeapAllocSite.CallInstructionSize);
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
printTypeIndex("Type", HeapAllocSite.Type);
|
2016-05-24 01:41:13 +02:00
|
|
|
if (!LinkageName.empty())
|
|
|
|
W.printString("LinkageName", LinkageName);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
InlineSiteSym &InlineSite) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printHex("PtrParent", InlineSite.Parent);
|
|
|
|
W.printHex("PtrEnd", InlineSite.End);
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
printTypeIndex("Inlinee", InlineSite.Inlinee);
|
2016-05-24 01:41:13 +02:00
|
|
|
|
|
|
|
ListScope BinaryAnnotations(W, "BinaryAnnotations");
|
|
|
|
for (auto &Annotation : InlineSite.annotations()) {
|
|
|
|
switch (Annotation.OpCode) {
|
|
|
|
case BinaryAnnotationsOpCode::Invalid:
|
2017-03-17 01:15:27 +01:00
|
|
|
W.printString("(Annotation Padding)");
|
|
|
|
break;
|
2016-05-24 01:41:13 +02:00
|
|
|
case BinaryAnnotationsOpCode::CodeOffset:
|
|
|
|
case BinaryAnnotationsOpCode::ChangeCodeOffset:
|
|
|
|
case BinaryAnnotationsOpCode::ChangeCodeLength:
|
|
|
|
W.printHex(Annotation.Name, Annotation.U1);
|
|
|
|
break;
|
|
|
|
case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
|
|
|
|
case BinaryAnnotationsOpCode::ChangeLineEndDelta:
|
|
|
|
case BinaryAnnotationsOpCode::ChangeRangeKind:
|
|
|
|
case BinaryAnnotationsOpCode::ChangeColumnStart:
|
|
|
|
case BinaryAnnotationsOpCode::ChangeColumnEnd:
|
|
|
|
W.printNumber(Annotation.Name, Annotation.U1);
|
|
|
|
break;
|
|
|
|
case BinaryAnnotationsOpCode::ChangeLineOffset:
|
|
|
|
case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
|
|
|
|
W.printNumber(Annotation.Name, Annotation.S1);
|
|
|
|
break;
|
|
|
|
case BinaryAnnotationsOpCode::ChangeFile:
|
|
|
|
if (ObjDelegate) {
|
|
|
|
W.printHex("ChangeFile",
|
|
|
|
ObjDelegate->getFileNameForFileOffset(Annotation.U1),
|
|
|
|
Annotation.U1);
|
|
|
|
} else {
|
|
|
|
W.printHex("ChangeFile", Annotation.U1);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
|
|
|
|
W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
|
|
|
|
<< W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1
|
|
|
|
<< "}\n";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
|
|
|
|
W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
|
|
|
|
<< W.hex(Annotation.U2)
|
|
|
|
<< ", Length: " << W.hex(Annotation.U1) << "}\n";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
RegisterSym &Register) {
|
2017-06-16 00:24:24 +02:00
|
|
|
printTypeIndex("Type", Register.Index);
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printEnum("Seg", uint16_t(Register.Register), getRegisterNames());
|
2016-05-25 00:58:46 +02:00
|
|
|
W.printString("Name", Register.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-25 00:58:46 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) {
|
2017-06-19 18:54:51 +02:00
|
|
|
W.printFlags("Flags", uint32_t(Public.Flags), getPublicSymFlagNames());
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("Seg", Public.Segment);
|
|
|
|
W.printNumber("Off", Public.Offset);
|
2016-05-24 20:55:14 +02:00
|
|
|
W.printString("Name", Public.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 20:55:14 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcRefSym &ProcRef) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printNumber("SumName", ProcRef.SumName);
|
|
|
|
W.printNumber("SymOffset", ProcRef.SymOffset);
|
|
|
|
W.printNumber("Mod", ProcRef.Module);
|
2016-05-24 20:55:14 +02:00
|
|
|
W.printString("Name", ProcRef.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 20:55:14 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
|
2016-05-24 01:41:13 +02:00
|
|
|
StringRef LinkageName;
|
|
|
|
if (ObjDelegate) {
|
|
|
|
ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(),
|
2016-12-16 23:48:14 +01:00
|
|
|
Label.CodeOffset, &LinkageName);
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printHex("Segment", Label.Segment);
|
|
|
|
W.printHex("Flags", uint8_t(Label.Flags));
|
|
|
|
W.printFlags("Flags", uint8_t(Label.Flags), getProcSymFlagNames());
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printString("DisplayName", Label.Name);
|
|
|
|
if (!LinkageName.empty())
|
|
|
|
W.printString("LinkageName", LinkageName);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
printTypeIndex("Type", Local.Type);
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printFlags("Flags", uint16_t(Local.Flags), getLocalFlagNames());
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printString("VarName", Local.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ObjNameSym &ObjName) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printHex("Signature", ObjName.Signature);
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printString("ObjectName", ObjName.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
|
2016-05-24 01:41:13 +02:00
|
|
|
if (InFunctionScope)
|
2016-10-07 23:34:46 +02:00
|
|
|
return llvm::make_error<CodeViewError>(
|
|
|
|
"Visiting a ProcSym while inside function scope!");
|
2016-05-24 01:41:13 +02:00
|
|
|
|
|
|
|
InFunctionScope = true;
|
|
|
|
|
|
|
|
StringRef LinkageName;
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printHex("PtrParent", Proc.Parent);
|
|
|
|
W.printHex("PtrEnd", Proc.End);
|
|
|
|
W.printHex("PtrNext", Proc.Next);
|
|
|
|
W.printHex("CodeSize", Proc.CodeSize);
|
|
|
|
W.printHex("DbgStart", Proc.DbgStart);
|
|
|
|
W.printHex("DbgEnd", Proc.DbgEnd);
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
printTypeIndex("FunctionType", Proc.FunctionType);
|
2016-05-24 01:41:13 +02:00
|
|
|
if (ObjDelegate) {
|
|
|
|
ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(),
|
2016-12-16 23:48:14 +01:00
|
|
|
Proc.CodeOffset, &LinkageName);
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printHex("Segment", Proc.Segment);
|
|
|
|
W.printFlags("Flags", static_cast<uint8_t>(Proc.Flags),
|
2016-06-02 07:07:49 +02:00
|
|
|
getProcSymFlagNames());
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printString("DisplayName", Proc.Name);
|
|
|
|
if (!LinkageName.empty())
|
|
|
|
W.printString("LinkageName", LinkageName);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
ScopeEndSym &ScopeEnd) {
|
2016-05-24 01:41:13 +02:00
|
|
|
InFunctionScope = false;
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
|
|
|
|
ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers");
|
2016-05-24 01:41:13 +02:00
|
|
|
for (auto FuncID : Caller.Indices)
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
printTypeIndex("FuncID", FuncID);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
RegRelativeSym &RegRel) {
|
2016-12-16 23:48:14 +01:00
|
|
|
W.printHex("Offset", RegRel.Offset);
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
printTypeIndex("Type", RegRel.Type);
|
2017-06-16 00:24:24 +02:00
|
|
|
W.printEnum("Register", uint16_t(RegRel.Register), getRegisterNames());
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printString("VarName", RegRel.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
ThreadLocalDataSym &Data) {
|
2016-05-24 01:41:13 +02:00
|
|
|
StringRef LinkageName;
|
|
|
|
if (ObjDelegate) {
|
|
|
|
ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
|
2016-12-16 23:48:14 +01:00
|
|
|
Data.DataOffset, &LinkageName);
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
printTypeIndex("Type", Data.Type);
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printString("DisplayName", Data.Name);
|
|
|
|
if (!LinkageName.empty())
|
|
|
|
W.printString("LinkageName", LinkageName);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
|
[CodeView] Finish decoupling TypeDatabase from TypeDumper.
Previously the type dumper itself was passed around to a lot of different
places and manipulated in ways that were more appropriate on the type
database. For example, the entire TypeDumper was passed into the symbol
dumper, when all the symbol dumper wanted to do was lookup the name of a
TypeIndex so it could print it. That's what the TypeDatabase is for --
mapping type indices to names.
Another example is how if the user runs llvm-pdbdump with the option to
dump symbols but not types, we still have to visit all types so that we
can print minimal information about the type of a symbol, but just without
dumping full symbol records. The way we did this before is by hacking it
up so that we run everything through the type dumper with a null printer,
so that the output goes to /dev/null. But really, we don't need to dump
anything, all we want to do is build the type database. Since
TypeDatabaseVisitor now exists independently of TypeDumper, we can do
this. We just build a custom visitor callback pipeline that includes a
database visitor but not a dumper.
All the hackery around printers etc goes away. After this patch, we could
probably even delete the entire CVTypeDumper class since really all it is
at this point is a thin wrapper that hides the details of how to build a
useful visitation pipeline. It's not a priority though, so CVTypeDumper
remains for now.
After this patch we will be able to easily plug in a different style of
type dumper by only implementing the proper visitation methods to dump
one-line output and then sticking it on the pipeline.
Differential Revision: https://reviews.llvm.org/D28524
llvm-svn: 291724
2017-01-12 00:24:22 +01:00
|
|
|
printTypeIndex("Type", UDT.Type);
|
2016-05-24 01:41:13 +02:00
|
|
|
W.printString("UDTName", UDT.Name);
|
2016-10-07 23:34:46 +02:00
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2018-07-31 21:15:50 +02:00
|
|
|
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
|
|
|
|
UsingNamespaceSym &UN) {
|
|
|
|
W.printString("Namespace", UN.Name);
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) {
|
|
|
|
W.printNumber("Length", CVR.length());
|
|
|
|
return Error::success();
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
|
|
|
|
SymbolVisitorCallbackPipeline Pipeline;
|
2017-06-01 23:52:41 +02:00
|
|
|
SymbolDeserializer Deserializer(ObjDelegate.get(), Container);
|
2017-05-19 21:26:58 +02:00
|
|
|
CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes);
|
2016-10-07 23:34:46 +02:00
|
|
|
|
|
|
|
Pipeline.addCallbackToPipeline(Deserializer);
|
|
|
|
Pipeline.addCallbackToPipeline(Dumper);
|
|
|
|
CVSymbolVisitor Visitor(Pipeline);
|
|
|
|
return Visitor.visitSymbolRecord(Record);
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|
|
|
|
|
2016-10-07 23:34:46 +02:00
|
|
|
Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
|
|
|
|
SymbolVisitorCallbackPipeline Pipeline;
|
2017-06-01 23:52:41 +02:00
|
|
|
SymbolDeserializer Deserializer(ObjDelegate.get(), Container);
|
2017-05-19 21:26:58 +02:00
|
|
|
CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes);
|
2016-10-07 23:34:46 +02:00
|
|
|
|
|
|
|
Pipeline.addCallbackToPipeline(Deserializer);
|
|
|
|
Pipeline.addCallbackToPipeline(Dumper);
|
|
|
|
CVSymbolVisitor Visitor(Pipeline);
|
|
|
|
return Visitor.visitSymbolStream(Symbols);
|
2016-05-24 01:41:13 +02:00
|
|
|
}
|