llvm.org GIT mirror llvm / b5c2dcf
[llvm-pdbutil] Remove the analyze subcommand. Nobody has used this since it was introduced, and it doesn't have test coverage. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@348307 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 8 months ago
4 changed file(s) with 0 addition(s) and 202 deletion(s). Raw diff Collapse all Expand all
+0
-148
tools/llvm-pdbutil/Analyze.cpp less more
None //===- Analyze.cpp - PDB analysis functions ---------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "Analyze.h"
10
11 #include "llvm/ADT/DenseSet.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
14 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
15 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
16 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
17 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
18 #include "llvm/DebugInfo/PDB/Native/RawError.h"
19 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
20
21 #include "llvm/Support/FormatVariadic.h"
22 #include "llvm/Support/raw_ostream.h"
23
24 #include
25
26 using namespace llvm;
27 using namespace llvm::codeview;
28 using namespace llvm::pdb;
29
30 static StringRef getLeafTypeName(TypeLeafKind LT) {
31 switch (LT) {
32 #define TYPE_RECORD(ename, value, name) \
33 case ename: \
34 return #name;
35 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
36 default:
37 break;
38 }
39 return "UnknownLeaf";
40 }
41
42 namespace {
43 struct HashLookupVisitor : public TypeVisitorCallbacks {
44 struct Entry {
45 TypeIndex TI;
46 CVType Record;
47 };
48
49 explicit HashLookupVisitor(TpiStream &Tpi) : Tpi(Tpi) {}
50
51 Error visitTypeBegin(CVType &Record) override {
52 uint32_t H = Tpi.getHashValues()[I];
53 Record.Hash = H;
54 TypeIndex TI(I + TypeIndex::FirstNonSimpleIndex);
55 Lookup[H].push_back(Entry{TI, Record});
56 ++I;
57 return Error::success();
58 }
59
60 uint32_t I = 0;
61 DenseMap> Lookup;
62 TpiStream &Tpi;
63 };
64 }
65
66 AnalysisStyle::AnalysisStyle(PDBFile &File) : File(File) {}
67
68 Error AnalysisStyle::dump() {
69 auto Tpi = File.getPDBTpiStream();
70 if (!Tpi)
71 return Tpi.takeError();
72
73 HashLookupVisitor Hasher(*Tpi);
74
75 uint32_t RecordCount = Tpi->getNumTypeRecords();
76 auto Offsets = Tpi->getTypeIndexOffsets();
77 auto Types = llvm::make_unique(
78 Tpi->typeArray(), RecordCount, Offsets);
79
80 if (auto EC = codeview::visitTypeStream(*Types, Hasher))
81 return EC;
82
83 auto &Adjusters = Tpi->getHashAdjusters();
84 DenseSet AdjusterSet;
85 for (const auto &Adj : Adjusters) {
86 assert(AdjusterSet.find(Adj.second) == AdjusterSet.end());
87 AdjusterSet.insert(Adj.second);
88 }
89
90 uint32_t Count = 0;
91 outs() << "Searching for hash collisions\n";
92 for (const auto &H : Hasher.Lookup) {
93 if (H.second.size() <= 1)
94 continue;
95 ++Count;
96 outs() << formatv("Hash: {0}, Count: {1} records\n", H.first,
97 H.second.size());
98 for (const auto &R : H.second) {
99 auto Iter = AdjusterSet.find(R.TI.getIndex());
100 StringRef Prefix;
101 if (Iter != AdjusterSet.end()) {
102 Prefix = "[HEAD]";
103 AdjusterSet.erase(Iter);
104 }
105 StringRef LeafName = getLeafTypeName(R.Record.Type);
106 uint32_t TI = R.TI.getIndex();
107 StringRef TypeName = Types->getTypeName(R.TI);
108 outs() << formatv("{0,-6} {1} ({2:x}) {3}\n", Prefix, LeafName, TI,
109 TypeName);
110 }
111 }
112
113 outs() << "\n";
114 outs() << "Dumping hash adjustment chains\n";
115 for (const auto &A : Tpi->getHashAdjusters()) {
116 TypeIndex TI(A.second);
117 StringRef TypeName = Types->getTypeName(TI);
118 const CVType &HeadRecord = Types->getType(TI);
119 assert(HeadRecord.Hash.hasValue());
120
121 auto CollisionsIter = Hasher.Lookup.find(*HeadRecord.Hash);
122 if (CollisionsIter == Hasher.Lookup.end())
123 continue;
124
125 const auto &Collisions = CollisionsIter->second;
126 outs() << TypeName << "\n";
127 outs() << formatv(" [HEAD] {0:x} {1} {2}\n", uint32_t(A.second),
128 getLeafTypeName(HeadRecord.Type), TypeName);
129 for (const auto &Chain : Collisions) {
130 if (Chain.TI == TI)
131 continue;
132 const CVType &TailRecord = Types->getType(Chain.TI);
133 outs() << formatv(" {0:x} {1} {2}\n", Chain.TI.getIndex(),
134 getLeafTypeName(TailRecord.Type),
135 Types->getTypeName(Chain.TI));
136 }
137 }
138 outs() << formatv("There are {0} orphaned hash adjusters\n",
139 AdjusterSet.size());
140 for (const auto &Adj : AdjusterSet) {
141 outs() << formatv(" {0}\n", Adj);
142 }
143
144 uint32_t DistinctHashValues = Hasher.Lookup.size();
145 outs() << formatv("{0}/{1} hash collisions", Count, DistinctHashValues);
146 return Error::success();
147 }
+0
-30
tools/llvm-pdbutil/Analyze.h less more
None //===- Analyze.h - PDB analysis functions -----------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVMPDBDUMP_ANALYSIS_H
10 #define LLVM_TOOLS_LLVMPDBDUMP_ANALYSIS_H
11
12 #include "OutputStyle.h"
13
14 namespace llvm {
15 namespace pdb {
16 class PDBFile;
17 class AnalysisStyle : public OutputStyle {
18 public:
19 explicit AnalysisStyle(PDBFile &File);
20
21 Error dump() override;
22
23 private:
24 PDBFile &File;
25 };
26 }
27 }
28
29 #endif
88 )
99
1010 add_llvm_tool(llvm-pdbutil
11 Analyze.cpp
1211 BytesOutputStyle.cpp
1312 DumpOutputStyle.cpp
1413 ExplainOutputStyle.cpp
1212
1313 #include "llvm-pdbutil.h"
1414
15 #include "Analyze.h"
1615 #include "BytesOutputStyle.h"
1716 #include "DumpOutputStyle.h"
1817 #include "ExplainOutputStyle.h"
116115 PdbToYamlSubcommand("pdb2yaml",
117116 "Generate a detailed YAML description of a PDB File");
118117
119 cl::SubCommand
120 AnalyzeSubcommand("analyze",
121 "Analyze various aspects of a PDB's structure");
122
123118 cl::SubCommand MergeSubcommand("merge",
124119 "Merge multiple PDBs into a single PDB");
125120
685680 cl::sub(PdbToYamlSubcommand));
686681 } // namespace pdb2yaml
687682
688 namespace analyze {
689 cl::opt StringTable("hash-collisions", cl::desc("Find hash collisions"),
690 cl::sub(AnalyzeSubcommand), cl::init(false));
691 cl::list InputFilename(cl::Positional,
692 cl::desc(""), cl::Required,
693 cl::sub(AnalyzeSubcommand));
694 }
695
696683 namespace merge {
697684 cl::list InputFilenames(cl::Positional,
698685 cl::desc(""),
886873 auto &File = loadPDB(Path, Session);
887874
888875 auto O = llvm::make_unique(File);
889
890 ExitOnErr(O->dump());
891 }
892
893 static void dumpAnalysis(StringRef Path) {
894 std::unique_ptr Session;
895 auto &File = loadPDB(Path, Session);
896 auto O = llvm::make_unique(File);
897876
898877 ExitOnErr(O->dump());
899878 }
15251504 opts::yaml2pdb::YamlPdbOutputFile = OutputFilename.str();
15261505 }
15271506 yamlToPdb(opts::yaml2pdb::InputFilename);
1528 } else if (opts::AnalyzeSubcommand) {
1529 dumpAnalysis(opts::analyze::InputFilename.front());
15301507 } else if (opts::DiaDumpSubcommand) {
15311508 llvm::for_each(opts::diadump::InputFilenames, dumpDia);
15321509 } else if (opts::PrettySubcommand) {