llvm.org GIT mirror llvm / c779b36
[PDB] One more fix for hasing GSI records. The reference implementation uses a case-insensitive string comparison for strings of equal length. This will cause the string "tEo" to compare less than "VUo". However we were using a case sensitive comparison, which would generate the opposite outcome. Switch to a case insensitive comparison. Also, when one of the strings contains non-ascii characters, fallback to a straight memcmp. The only way to really test this is with a DIA test. Before this patch, the test will fail (but succeed if link.exe is used instead of lld-link). After the patch, it succeeds even with lld-link. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336464 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 1 year, 2 months ago
4 changed file(s) with 118 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
8181 return Error::success();
8282 }
8383
84 static bool isAsciiString(StringRef S) {
85 return llvm::all_of(S, [](char C) { return unsigned(C) < 0x80; });
86 }
87
88 // See `caseInsensitiveComparePchPchCchCch` in gsi.cpp
89 static bool gsiRecordLess(StringRef S1, StringRef S2) {
90 size_t LS = S1.size();
91 size_t RS = S2.size();
92 // Shorter strings always compare less than longer strings.
93 if (LS != RS)
94 return LS < RS;
95
96 // If either string contains non ascii characters, memcmp them.
97 if (LLVM_UNLIKELY(!isAsciiString(S1) || !isAsciiString(S2)))
98 return memcmp(S1.data(), S2.data(), LS) < 0;
99
100 // Both strings are ascii, use memicmp.
101 return memicmp(S1.data(), S2.data(), LS) < 0;
102 }
103
84104 void GSIHashStreamBuilder::finalizeBuckets(uint32_t RecordZeroOffset) {
85105 std::array>, IPHR_HASH + 1>
86106 TmpBuckets;
117137 ulittle32_t(HashRecords.size() * SizeOfHROffsetCalc);
118138 HashBuckets.push_back(ChainStartOff);
119139
120 // Sort each bucket by memcmp of the symbol's name.
140 // Sort each bucket by memcmp of the symbol's name. It's important that
141 // we use the same sorting algorithm as is used by the reference
142 // implementation to ensure that the search for a record within a bucket
143 // can properly early-out when it detects the record won't be found. The
144 // algorithm used here corredsponds to the function
145 // caseInsensitiveComparePchPchCchCch in the reference implementation.
121146 std::sort(Bucket.begin(), Bucket.end(),
122147 [](const std::pair &Left,
123148 const std::pair &Right) {
124 size_t LS = Left.first.size();
125 size_t RS = Right.first.size();
126 if (LS < RS)
127 return true;
128 if (LS > RS)
129 return false;
130 return Left.first < Right.first;
149 return gsiRecordLess(Left.first, Right.first);
131150 });
132151
133152 for (const auto &Entry : Bucket)
3434 Printer.NewLine();
3535 uint64_t Addr = Symbol.getVirtualAddress();
3636
37 Printer << "[";
37 Printer << "public [";
3838 WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Addr, 10);
3939 Printer << "] ";
4040 WithColor(Printer, PDB_ColorItem::Identifier).get() << LinkageName;
1919 #include "InputFile.h"
2020 #include "LinePrinter.h"
2121 #include "OutputStyle.h"
22 #include "PrettyClassDefinitionDumper.h"
2223 #include "PrettyCompilandDumper.h"
24 #include "PrettyEnumDumper.h"
2325 #include "PrettyExternalSymbolDumper.h"
2426 #include "PrettyFunctionDumper.h"
2527 #include "PrettyTypeDumper.h"
28 #include "PrettyTypedefDumper.h"
2629 #include "PrettyVariableDumper.h"
2730 #include "YAMLOutputStyle.h"
2831
6467 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
6568 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
6669 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
70 #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
6771 #include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
72 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
73 #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
74 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
6875 #include "llvm/Support/BinaryByteStream.h"
6976 #include "llvm/Support/COM.h"
7077 #include "llvm/Support/CommandLine.h"
159166 "injected-source-content",
160167 cl::desc("When displaying an injected source, display the file content"),
161168 cl::cat(OtherOptions), cl::sub(PrettySubcommand));
169
170 cl::list WithName(
171 "with-name",
172 cl::desc("Display any symbol or type with the specified exact name"),
173 cl::cat(TypeCategory), cl::ZeroOrMore, cl::sub(PrettySubcommand));
162174
163175 cl::opt Compilands("compilands", cl::desc("Display compilands"),
164176 cl::cat(TypeCategory), cl::sub(PrettySubcommand));
962974 outs() << "HasPrivateSymbols ";
963975 Printer.Unindent();
964976
977 if (!opts::pretty::WithName.empty()) {
978 Printer.NewLine();
979 WithColor(Printer, PDB_ColorItem::SectionHeader).get()
980 << "---SYMBOLS & TYPES BY NAME---";
981
982 for (StringRef Name : opts::pretty::WithName) {
983 auto Symbols = GlobalScope->findChildren(
984 PDB_SymType::None, Name, PDB_NameSearchFlags::NS_CaseSensitive);
985 if (!Symbols || Symbols->getChildCount() == 0) {
986 Printer.formatLine("[not found] - {0}", Name);
987 continue;
988 }
989 Printer.formatLine("[{0} occurrences] - {1}", Symbols->getChildCount(),
990 Name);
991
992 AutoIndent Indent(Printer);
993 Printer.NewLine();
994
995 while (auto Symbol = Symbols->getNext()) {
996 switch (Symbol->getSymTag()) {
997 case PDB_SymType::Typedef: {
998 TypedefDumper TD(Printer);
999 std::unique_ptr T =
1000 llvm::unique_dyn_cast(std::move(Symbol));
1001 TD.start(*T);
1002 break;
1003 }
1004 case PDB_SymType::Enum: {
1005 EnumDumper ED(Printer);
1006 std::unique_ptr E =
1007 llvm::unique_dyn_cast(std::move(Symbol));
1008 ED.start(*E);
1009 break;
1010 }
1011 case PDB_SymType::UDT: {
1012 ClassDefinitionDumper CD(Printer);
1013 std::unique_ptr C =
1014 llvm::unique_dyn_cast(std::move(Symbol));
1015 CD.start(*C);
1016 break;
1017 }
1018 case PDB_SymType::BaseClass:
1019 case PDB_SymType::Friend: {
1020 TypeDumper TD(Printer);
1021 Symbol->dump(TD);
1022 break;
1023 }
1024 case PDB_SymType::Function: {
1025 FunctionDumper FD(Printer);
1026 std::unique_ptr F =
1027 llvm::unique_dyn_cast(std::move(Symbol));
1028 FD.start(*F, FunctionDumper::PointerType::None);
1029 break;
1030 }
1031 case PDB_SymType::Data: {
1032 VariableDumper VD(Printer);
1033 std::unique_ptr D =
1034 llvm::unique_dyn_cast(std::move(Symbol));
1035 VD.start(*D);
1036 break;
1037 }
1038 case PDB_SymType::PublicSymbol: {
1039 ExternalSymbolDumper ED(Printer);
1040 std::unique_ptr PS =
1041 llvm::unique_dyn_cast(std::move(Symbol));
1042 ED.dump(*PS);
1043 break;
1044 }
1045 default:
1046 llvm_unreachable("Unexpected symbol tag!");
1047 }
1048 }
1049 }
1050 llvm::outs().flush();
1051 }
1052
9651053 if (opts::pretty::Compilands) {
9661054 Printer.NewLine();
9671055 WithColor(Printer, PDB_ColorItem::SectionHeader).get()
7373 const std::unique_ptr &F2);
7474 bool compareDataSymbols(const std::unique_ptr &F1,
7575 const std::unique_ptr &F2);
76
77 extern llvm::cl::list WithName;
7678
7779 extern llvm::cl::opt Compilands;
7880 extern llvm::cl::opt Symbols;