mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[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. llvm-svn: 336464
This commit is contained in:
parent
587a26d422
commit
9243b281e0
@ -82,6 +82,26 @@ Error GSIHashStreamBuilder::commit(BinaryStreamWriter &Writer) {
|
||||
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::finalizeBuckets(uint32_t RecordZeroOffset) {
|
||||
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)
|
||||
|
@ -35,7 +35,7 @@ void ExternalSymbolDumper::dump(const PDBSymbolPublicSymbol &Symbol) {
|
||||
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;
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user