[llvm] r336464 - [PDB] One more fix for hasing GSI records.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 6 14:01:43 PDT 2018


Author: zturner
Date: Fri Jul  6 14:01:42 2018
New Revision: 336464

URL: http://llvm.org/viewvc/llvm-project?rev=336464&view=rev
Log:
[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.

Modified:
    llvm/trunk/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
    llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp
    llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
    llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp?rev=336464&r1=336463&r2=336464&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp Fri Jul  6 14:01:42 2018
@@ -82,6 +82,26 @@ Error GSIHashStreamBuilder::commit(Binar
   return Error::success();
 }
 
+static bool isAsciiString(StringRef S) {
+  return llvm::all_of(S, [](char C) { return unsigned(C) < 0x80; });
+}
+
+// See `caseInsensitiveComparePchPchCchCch` in gsi.cpp
+static bool gsiRecordLess(StringRef S1, StringRef S2) {
+  size_t LS = S1.size();
+  size_t RS = S2.size();
+  // Shorter strings always compare less than longer strings.
+  if (LS != RS)
+    return LS < RS;
+
+  // If either string contains non ascii characters, memcmp them.
+  if (LLVM_UNLIKELY(!isAsciiString(S1) || !isAsciiString(S2)))
+    return memcmp(S1.data(), S2.data(), LS) < 0;
+
+  // Both strings are ascii, use memicmp.
+  return memicmp(S1.data(), S2.data(), LS) < 0;
+}
+
 void GSIHashStreamBuilder::finalizeBuckets(uint32_t RecordZeroOffset) {
   std::array<std::vector<std::pair<StringRef, PSHashRecord>>, IPHR_HASH + 1>
       TmpBuckets;
@@ -118,17 +138,16 @@ void GSIHashStreamBuilder::finalizeBucke
         ulittle32_t(HashRecords.size() * SizeOfHROffsetCalc);
     HashBuckets.push_back(ChainStartOff);
 
-    // Sort each bucket by memcmp of the symbol's name.
+    // Sort each bucket by memcmp of the symbol's name.  It's important that
+    // we use the same sorting algorithm as is used by the reference
+    // implementation to ensure that the search for a record within a bucket
+    // can properly early-out when it detects the record won't be found.  The
+    // algorithm used here corredsponds to the function
+    // caseInsensitiveComparePchPchCchCch in the reference implementation.
     std::sort(Bucket.begin(), Bucket.end(),
               [](const std::pair<StringRef, PSHashRecord> &Left,
                  const std::pair<StringRef, PSHashRecord> &Right) {
-                size_t LS = Left.first.size();
-                size_t RS = Right.first.size();
-                if (LS < RS)
-                  return true;
-                if (LS > RS)
-                  return false;
-                return Left.first < Right.first;
+                return gsiRecordLess(Left.first, Right.first);
               });
 
     for (const auto &Entry : Bucket)

Modified: llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp?rev=336464&r1=336463&r2=336464&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp (original)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp Fri Jul  6 14:01:42 2018
@@ -35,7 +35,7 @@ void ExternalSymbolDumper::dump(const PD
   Printer.NewLine();
   uint64_t Addr = Symbol.getVirtualAddress();
 
-  Printer << "[";
+  Printer << "public [";
   WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Addr, 10);
   Printer << "] ";
   WithColor(Printer, PDB_ColorItem::Identifier).get() << LinkageName;

Modified: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp?rev=336464&r1=336463&r2=336464&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp (original)
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp Fri Jul  6 14:01:42 2018
@@ -20,10 +20,13 @@
 #include "InputFile.h"
 #include "LinePrinter.h"
 #include "OutputStyle.h"
+#include "PrettyClassDefinitionDumper.h"
 #include "PrettyCompilandDumper.h"
+#include "PrettyEnumDumper.h"
 #include "PrettyExternalSymbolDumper.h"
 #include "PrettyFunctionDumper.h"
 #include "PrettyTypeDumper.h"
+#include "PrettyTypedefDumper.h"
 #include "PrettyVariableDumper.h"
 #include "YAMLOutputStyle.h"
 
@@ -65,7 +68,11 @@
 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
 #include "llvm/Support/BinaryByteStream.h"
 #include "llvm/Support/COM.h"
 #include "llvm/Support/CommandLine.h"
@@ -161,6 +168,11 @@ cl::opt<bool> ShowInjectedSourceContent(
     cl::desc("When displaying an injected source, display the file content"),
     cl::cat(OtherOptions), cl::sub(PrettySubcommand));
 
+cl::list<std::string> WithName(
+    "with-name",
+    cl::desc("Display any symbol or type with the specified exact name"),
+    cl::cat(TypeCategory), cl::ZeroOrMore, cl::sub(PrettySubcommand));
+
 cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
                          cl::cat(TypeCategory), cl::sub(PrettySubcommand));
 cl::opt<bool> Symbols("module-syms",
@@ -963,6 +975,82 @@ static void dumpPretty(StringRef Path) {
     outs() << "HasPrivateSymbols ";
   Printer.Unindent();
 
+  if (!opts::pretty::WithName.empty()) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
+        << "---SYMBOLS & TYPES BY NAME---";
+
+    for (StringRef Name : opts::pretty::WithName) {
+      auto Symbols = GlobalScope->findChildren(
+          PDB_SymType::None, Name, PDB_NameSearchFlags::NS_CaseSensitive);
+      if (!Symbols || Symbols->getChildCount() == 0) {
+        Printer.formatLine("[not found] - {0}", Name);
+        continue;
+      }
+      Printer.formatLine("[{0} occurrences] - {1}", Symbols->getChildCount(),
+                         Name);
+
+      AutoIndent Indent(Printer);
+      Printer.NewLine();
+
+      while (auto Symbol = Symbols->getNext()) {
+        switch (Symbol->getSymTag()) {
+        case PDB_SymType::Typedef: {
+          TypedefDumper TD(Printer);
+          std::unique_ptr<PDBSymbolTypeTypedef> T =
+              llvm::unique_dyn_cast<PDBSymbolTypeTypedef>(std::move(Symbol));
+          TD.start(*T);
+          break;
+        }
+        case PDB_SymType::Enum: {
+          EnumDumper ED(Printer);
+          std::unique_ptr<PDBSymbolTypeEnum> E =
+              llvm::unique_dyn_cast<PDBSymbolTypeEnum>(std::move(Symbol));
+          ED.start(*E);
+          break;
+        }
+        case PDB_SymType::UDT: {
+          ClassDefinitionDumper CD(Printer);
+          std::unique_ptr<PDBSymbolTypeUDT> C =
+              llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Symbol));
+          CD.start(*C);
+          break;
+        }
+        case PDB_SymType::BaseClass:
+        case PDB_SymType::Friend: {
+          TypeDumper TD(Printer);
+          Symbol->dump(TD);
+          break;
+        }
+        case PDB_SymType::Function: {
+          FunctionDumper FD(Printer);
+          std::unique_ptr<PDBSymbolFunc> F =
+              llvm::unique_dyn_cast<PDBSymbolFunc>(std::move(Symbol));
+          FD.start(*F, FunctionDumper::PointerType::None);
+          break;
+        }
+        case PDB_SymType::Data: {
+          VariableDumper VD(Printer);
+          std::unique_ptr<PDBSymbolData> D =
+              llvm::unique_dyn_cast<PDBSymbolData>(std::move(Symbol));
+          VD.start(*D);
+          break;
+        }
+        case PDB_SymType::PublicSymbol: {
+          ExternalSymbolDumper ED(Printer);
+          std::unique_ptr<PDBSymbolPublicSymbol> PS =
+              llvm::unique_dyn_cast<PDBSymbolPublicSymbol>(std::move(Symbol));
+          ED.dump(*PS);
+          break;
+        }
+        default:
+          llvm_unreachable("Unexpected symbol tag!");
+        }
+      }
+    }
+    llvm::outs().flush();
+  }
+
   if (opts::pretty::Compilands) {
     Printer.NewLine();
     WithColor(Printer, PDB_ColorItem::SectionHeader).get()

Modified: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h?rev=336464&r1=336463&r2=336464&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h (original)
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h Fri Jul  6 14:01:42 2018
@@ -75,6 +75,8 @@ bool compareFunctionSymbols(
 bool compareDataSymbols(const std::unique_ptr<llvm::pdb::PDBSymbolData> &F1,
                         const std::unique_ptr<llvm::pdb::PDBSymbolData> &F2);
 
+extern llvm::cl::list<std::string> WithName;
+
 extern llvm::cl::opt<bool> Compilands;
 extern llvm::cl::opt<bool> Symbols;
 extern llvm::cl::opt<bool> Globals;




More information about the llvm-commits mailing list