1 //===- DebugTypes.cpp -----------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "DebugTypes.h" 10 #include "Chunks.h" 11 #include "Driver.h" 12 #include "InputFiles.h" 13 #include "PDB.h" 14 #include "TypeMerger.h" 15 #include "lld/Common/ErrorHandler.h" 16 #include "lld/Common/Memory.h" 17 #include "lld/Common/Timer.h" 18 #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" 19 #include "llvm/DebugInfo/CodeView/TypeRecord.h" 20 #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" 21 #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" 22 #include "llvm/DebugInfo/PDB/GenericError.h" 23 #include "llvm/DebugInfo/PDB/Native/InfoStream.h" 24 #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 25 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 26 #include "llvm/DebugInfo/PDB/Native/TpiHashing.h" 27 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 28 #include "llvm/Support/FormatVariadic.h" 29 #include "llvm/Support/Parallel.h" 30 #include "llvm/Support/Path.h" 31 32 using namespace llvm; 33 using namespace llvm::codeview; 34 using namespace lld; 35 using namespace lld::coff; 36 37 namespace { 38 class TypeServerIpiSource; 39 40 // The TypeServerSource class represents a PDB type server, a file referenced by 41 // OBJ files compiled with MSVC /Zi. A single PDB can be shared by several OBJ 42 // files, therefore there must be only once instance per OBJ lot. The file path 43 // is discovered from the dependent OBJ's debug type stream. The 44 // TypeServerSource object is then queued and loaded by the COFF Driver. The 45 // debug type stream for such PDB files will be merged first in the final PDB, 46 // before any dependent OBJ. 47 class TypeServerSource : public TpiSource { 48 public: 49 explicit TypeServerSource(PDBInputFile *f) 50 : TpiSource(PDB, nullptr), pdbInputFile(f) { 51 if (f->loadErr && *f->loadErr) 52 return; 53 pdb::PDBFile &file = f->session->getPDBFile(); 54 auto expectedInfo = file.getPDBInfoStream(); 55 if (!expectedInfo) 56 return; 57 auto it = mappings.emplace(expectedInfo->getGuid(), this); 58 assert(it.second); 59 (void)it; 60 } 61 62 Error mergeDebugT(TypeMerger *m) override; 63 64 void loadGHashes() override; 65 void remapTpiWithGHashes(GHashState *g) override; 66 67 bool isDependency() const override { return true; } 68 69 PDBInputFile *pdbInputFile = nullptr; 70 71 // TpiSource for IPI stream. 72 TypeServerIpiSource *ipiSrc = nullptr; 73 74 static std::map<codeview::GUID, TypeServerSource *> mappings; 75 }; 76 77 // Companion to TypeServerSource. Stores the index map for the IPI stream in the 78 // PDB. Modeling PDBs with two sources for TPI and IPI helps establish the 79 // invariant of one type index space per source. 80 class TypeServerIpiSource : public TpiSource { 81 public: 82 explicit TypeServerIpiSource() : TpiSource(PDBIpi, nullptr) {} 83 84 friend class TypeServerSource; 85 86 // All of the TpiSource methods are no-ops. The parent TypeServerSource 87 // handles both TPI and IPI. 88 Error mergeDebugT(TypeMerger *m) override { return Error::success(); } 89 void loadGHashes() override {} 90 void remapTpiWithGHashes(GHashState *g) override {} 91 bool isDependency() const override { return true; } 92 }; 93 94 // This class represents the debug type stream of an OBJ file that depends on a 95 // PDB type server (see TypeServerSource). 96 class UseTypeServerSource : public TpiSource { 97 Expected<TypeServerSource *> getTypeServerSource(); 98 99 public: 100 UseTypeServerSource(ObjFile *f, TypeServer2Record ts) 101 : TpiSource(UsingPDB, f), typeServerDependency(ts) {} 102 103 Error mergeDebugT(TypeMerger *m) override; 104 105 // No need to load ghashes from /Zi objects. 106 void loadGHashes() override {} 107 void remapTpiWithGHashes(GHashState *g) override; 108 109 // Information about the PDB type server dependency, that needs to be loaded 110 // in before merging this OBJ. 111 TypeServer2Record typeServerDependency; 112 }; 113 114 // This class represents the debug type stream of a Microsoft precompiled 115 // headers OBJ (PCH OBJ). This OBJ kind needs to be merged first in the output 116 // PDB, before any other OBJs that depend on this. Note that only MSVC generate 117 // such files, clang does not. 118 class PrecompSource : public TpiSource { 119 public: 120 PrecompSource(ObjFile *f) : TpiSource(PCH, f) { 121 if (!f->pchSignature || !*f->pchSignature) 122 fatal(toString(f) + 123 " claims to be a PCH object, but does not have a valid signature"); 124 auto it = mappings.emplace(*f->pchSignature, this); 125 if (!it.second) 126 fatal("a PCH object with the same signature has already been provided (" + 127 toString(it.first->second->file) + " and " + toString(file) + ")"); 128 } 129 130 void loadGHashes() override; 131 132 bool isDependency() const override { return true; } 133 134 static std::map<uint32_t, PrecompSource *> mappings; 135 }; 136 137 // This class represents the debug type stream of an OBJ file that depends on a 138 // Microsoft precompiled headers OBJ (see PrecompSource). 139 class UsePrecompSource : public TpiSource { 140 public: 141 UsePrecompSource(ObjFile *f, PrecompRecord precomp) 142 : TpiSource(UsingPCH, f), precompDependency(precomp) {} 143 144 Error mergeDebugT(TypeMerger *m) override; 145 146 void loadGHashes() override; 147 void remapTpiWithGHashes(GHashState *g) override; 148 149 private: 150 Error mergeInPrecompHeaderObj(); 151 152 public: 153 // Information about the Precomp OBJ dependency, that needs to be loaded in 154 // before merging this OBJ. 155 PrecompRecord precompDependency; 156 }; 157 } // namespace 158 159 std::vector<TpiSource *> TpiSource::instances; 160 ArrayRef<TpiSource *> TpiSource::dependencySources; 161 ArrayRef<TpiSource *> TpiSource::objectSources; 162 163 TpiSource::TpiSource(TpiKind k, ObjFile *f) 164 : kind(k), tpiSrcIdx(instances.size()), file(f) { 165 instances.push_back(this); 166 } 167 168 // Vtable key method. 169 TpiSource::~TpiSource() { 170 // Silence any assertions about unchecked errors. 171 consumeError(std::move(typeMergingError)); 172 } 173 174 void TpiSource::sortDependencies() { 175 // Order dependencies first, but preserve the existing order. 176 std::vector<TpiSource *> deps; 177 std::vector<TpiSource *> objs; 178 for (TpiSource *s : instances) 179 (s->isDependency() ? deps : objs).push_back(s); 180 uint32_t numDeps = deps.size(); 181 uint32_t numObjs = objs.size(); 182 instances = std::move(deps); 183 instances.insert(instances.end(), objs.begin(), objs.end()); 184 for (uint32_t i = 0, e = instances.size(); i < e; ++i) 185 instances[i]->tpiSrcIdx = i; 186 dependencySources = makeArrayRef(instances.data(), numDeps); 187 objectSources = makeArrayRef(instances.data() + numDeps, numObjs); 188 } 189 190 TpiSource *lld::coff::makeTpiSource(ObjFile *file) { 191 return make<TpiSource>(TpiSource::Regular, file); 192 } 193 194 TpiSource *lld::coff::makeTypeServerSource(PDBInputFile *pdbInputFile) { 195 // Type server sources come in pairs: the TPI stream, and the IPI stream. 196 auto *tpiSource = make<TypeServerSource>(pdbInputFile); 197 if (pdbInputFile->session->getPDBFile().hasPDBIpiStream()) 198 tpiSource->ipiSrc = make<TypeServerIpiSource>(); 199 return tpiSource; 200 } 201 202 TpiSource *lld::coff::makeUseTypeServerSource(ObjFile *file, 203 TypeServer2Record ts) { 204 return make<UseTypeServerSource>(file, ts); 205 } 206 207 TpiSource *lld::coff::makePrecompSource(ObjFile *file) { 208 return make<PrecompSource>(file); 209 } 210 211 TpiSource *lld::coff::makeUsePrecompSource(ObjFile *file, 212 PrecompRecord precomp) { 213 return make<UsePrecompSource>(file, precomp); 214 } 215 216 std::map<codeview::GUID, TypeServerSource *> TypeServerSource::mappings; 217 218 std::map<uint32_t, PrecompSource *> PrecompSource::mappings; 219 220 bool TpiSource::remapTypeIndex(TypeIndex &ti, TiRefKind refKind) const { 221 if (ti.isSimple()) 222 return true; 223 224 // This can be an item index or a type index. Choose the appropriate map. 225 ArrayRef<TypeIndex> tpiOrIpiMap = 226 (refKind == TiRefKind::IndexRef) ? ipiMap : tpiMap; 227 if (ti.toArrayIndex() >= tpiOrIpiMap.size()) 228 return false; 229 ti = tpiOrIpiMap[ti.toArrayIndex()]; 230 return true; 231 } 232 233 void TpiSource::remapRecord(MutableArrayRef<uint8_t> rec, 234 ArrayRef<TiReference> typeRefs) { 235 MutableArrayRef<uint8_t> contents = rec.drop_front(sizeof(RecordPrefix)); 236 for (const TiReference &ref : typeRefs) { 237 unsigned byteSize = ref.Count * sizeof(TypeIndex); 238 if (contents.size() < ref.Offset + byteSize) 239 fatal("symbol record too short"); 240 241 MutableArrayRef<TypeIndex> indices( 242 reinterpret_cast<TypeIndex *>(contents.data() + ref.Offset), ref.Count); 243 for (TypeIndex &ti : indices) { 244 if (!remapTypeIndex(ti, ref.Kind)) { 245 if (config->verbose) { 246 uint16_t kind = 247 reinterpret_cast<const RecordPrefix *>(rec.data())->RecordKind; 248 StringRef fname = file ? file->getName() : "<unknown PDB>"; 249 log("failed to remap type index in record of kind 0x" + 250 utohexstr(kind) + " in " + fname + " with bad " + 251 (ref.Kind == TiRefKind::IndexRef ? "item" : "type") + 252 " index 0x" + utohexstr(ti.getIndex())); 253 } 254 ti = TypeIndex(SimpleTypeKind::NotTranslated); 255 continue; 256 } 257 } 258 } 259 } 260 261 void TpiSource::remapTypesInTypeRecord(MutableArrayRef<uint8_t> rec) { 262 // TODO: Handle errors similar to symbols. 263 SmallVector<TiReference, 32> typeRefs; 264 discoverTypeIndices(CVType(rec), typeRefs); 265 remapRecord(rec, typeRefs); 266 } 267 268 bool TpiSource::remapTypesInSymbolRecord(MutableArrayRef<uint8_t> rec) { 269 // Discover type index references in the record. Skip it if we don't 270 // know where they are. 271 SmallVector<TiReference, 32> typeRefs; 272 if (!discoverTypeIndicesInSymbol(rec, typeRefs)) 273 return false; 274 remapRecord(rec, typeRefs); 275 return true; 276 } 277 278 // A COFF .debug$H section is currently a clang extension. This function checks 279 // if a .debug$H section is in a format that we expect / understand, so that we 280 // can ignore any sections which are coincidentally also named .debug$H but do 281 // not contain a format we recognize. 282 static bool canUseDebugH(ArrayRef<uint8_t> debugH) { 283 if (debugH.size() < sizeof(object::debug_h_header)) 284 return false; 285 auto *header = 286 reinterpret_cast<const object::debug_h_header *>(debugH.data()); 287 debugH = debugH.drop_front(sizeof(object::debug_h_header)); 288 return header->Magic == COFF::DEBUG_HASHES_SECTION_MAGIC && 289 header->Version == 0 && 290 header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::SHA1_8) && 291 (debugH.size() % 8 == 0); 292 } 293 294 static Optional<ArrayRef<uint8_t>> getDebugH(ObjFile *file) { 295 SectionChunk *sec = 296 SectionChunk::findByName(file->getDebugChunks(), ".debug$H"); 297 if (!sec) 298 return llvm::None; 299 ArrayRef<uint8_t> contents = sec->getContents(); 300 if (!canUseDebugH(contents)) 301 return None; 302 return contents; 303 } 304 305 static ArrayRef<GloballyHashedType> 306 getHashesFromDebugH(ArrayRef<uint8_t> debugH) { 307 assert(canUseDebugH(debugH)); 308 debugH = debugH.drop_front(sizeof(object::debug_h_header)); 309 uint32_t count = debugH.size() / sizeof(GloballyHashedType); 310 return {reinterpret_cast<const GloballyHashedType *>(debugH.data()), count}; 311 } 312 313 // Merge .debug$T for a generic object file. 314 Error TpiSource::mergeDebugT(TypeMerger *m) { 315 assert(!config->debugGHashes && 316 "use remapTpiWithGHashes when ghash is enabled"); 317 318 CVTypeArray types; 319 BinaryStreamReader reader(file->debugTypes, support::little); 320 cantFail(reader.readArray(types, reader.getLength())); 321 322 // When dealing with PCH.OBJ, some indices were already merged. 323 unsigned nbHeadIndices = indexMapStorage.size(); 324 325 if (auto err = mergeTypeAndIdRecords( 326 m->idTable, m->typeTable, indexMapStorage, types, file->pchSignature)) 327 fatal("codeview::mergeTypeAndIdRecords failed: " + 328 toString(std::move(err))); 329 330 // In an object, there is only one mapping for both types and items. 331 tpiMap = indexMapStorage; 332 ipiMap = indexMapStorage; 333 334 if (config->showSummary) { 335 nbTypeRecords = indexMapStorage.size() - nbHeadIndices; 336 nbTypeRecordsBytes = reader.getLength(); 337 // Count how many times we saw each type record in our input. This 338 // calculation requires a second pass over the type records to classify each 339 // record as a type or index. This is slow, but this code executes when 340 // collecting statistics. 341 m->tpiCounts.resize(m->getTypeTable().size()); 342 m->ipiCounts.resize(m->getIDTable().size()); 343 uint32_t srcIdx = nbHeadIndices; 344 for (CVType &ty : types) { 345 TypeIndex dstIdx = tpiMap[srcIdx++]; 346 // Type merging may fail, so a complex source type may become the simple 347 // NotTranslated type, which cannot be used as an array index. 348 if (dstIdx.isSimple()) 349 continue; 350 SmallVectorImpl<uint32_t> &counts = 351 isIdRecord(ty.kind()) ? m->ipiCounts : m->tpiCounts; 352 ++counts[dstIdx.toArrayIndex()]; 353 } 354 } 355 356 return Error::success(); 357 } 358 359 // Merge types from a type server PDB. 360 Error TypeServerSource::mergeDebugT(TypeMerger *m) { 361 assert(!config->debugGHashes && 362 "use remapTpiWithGHashes when ghash is enabled"); 363 364 pdb::PDBFile &pdbFile = pdbInputFile->session->getPDBFile(); 365 Expected<pdb::TpiStream &> expectedTpi = pdbFile.getPDBTpiStream(); 366 if (auto e = expectedTpi.takeError()) 367 fatal("Type server does not have TPI stream: " + toString(std::move(e))); 368 pdb::TpiStream *maybeIpi = nullptr; 369 if (pdbFile.hasPDBIpiStream()) { 370 Expected<pdb::TpiStream &> expectedIpi = pdbFile.getPDBIpiStream(); 371 if (auto e = expectedIpi.takeError()) 372 fatal("Error getting type server IPI stream: " + toString(std::move(e))); 373 maybeIpi = &*expectedIpi; 374 } 375 376 // Merge TPI first, because the IPI stream will reference type indices. 377 if (auto err = mergeTypeRecords(m->typeTable, indexMapStorage, 378 expectedTpi->typeArray())) 379 fatal("codeview::mergeTypeRecords failed: " + toString(std::move(err))); 380 tpiMap = indexMapStorage; 381 382 // Merge IPI. 383 if (maybeIpi) { 384 if (auto err = mergeIdRecords(m->idTable, tpiMap, ipiSrc->indexMapStorage, 385 maybeIpi->typeArray())) 386 fatal("codeview::mergeIdRecords failed: " + toString(std::move(err))); 387 ipiMap = ipiSrc->indexMapStorage; 388 } 389 390 if (config->showSummary) { 391 nbTypeRecords = tpiMap.size() + ipiMap.size(); 392 nbTypeRecordsBytes = 393 expectedTpi->typeArray().getUnderlyingStream().getLength() + 394 (maybeIpi ? maybeIpi->typeArray().getUnderlyingStream().getLength() 395 : 0); 396 397 // Count how many times we saw each type record in our input. If a 398 // destination type index is present in the source to destination type index 399 // map, that means we saw it once in the input. Add it to our histogram. 400 m->tpiCounts.resize(m->getTypeTable().size()); 401 m->ipiCounts.resize(m->getIDTable().size()); 402 for (TypeIndex ti : tpiMap) 403 if (!ti.isSimple()) 404 ++m->tpiCounts[ti.toArrayIndex()]; 405 for (TypeIndex ti : ipiMap) 406 if (!ti.isSimple()) 407 ++m->ipiCounts[ti.toArrayIndex()]; 408 } 409 410 return Error::success(); 411 } 412 413 Expected<TypeServerSource *> UseTypeServerSource::getTypeServerSource() { 414 const codeview::GUID &tsId = typeServerDependency.getGuid(); 415 StringRef tsPath = typeServerDependency.getName(); 416 417 TypeServerSource *tsSrc; 418 auto it = TypeServerSource::mappings.find(tsId); 419 if (it != TypeServerSource::mappings.end()) { 420 tsSrc = it->second; 421 } else { 422 // The file failed to load, lookup by name 423 PDBInputFile *pdb = PDBInputFile::findFromRecordPath(tsPath, file); 424 if (!pdb) 425 return createFileError(tsPath, errorCodeToError(std::error_code( 426 ENOENT, std::generic_category()))); 427 // If an error occurred during loading, throw it now 428 if (pdb->loadErr && *pdb->loadErr) 429 return createFileError(tsPath, std::move(*pdb->loadErr)); 430 431 tsSrc = (TypeServerSource *)pdb->debugTypesObj; 432 } 433 return tsSrc; 434 } 435 436 Error UseTypeServerSource::mergeDebugT(TypeMerger *m) { 437 Expected<TypeServerSource *> tsSrc = getTypeServerSource(); 438 if (!tsSrc) 439 return tsSrc.takeError(); 440 441 pdb::PDBFile &pdbSession = (*tsSrc)->pdbInputFile->session->getPDBFile(); 442 auto expectedInfo = pdbSession.getPDBInfoStream(); 443 if (!expectedInfo) 444 return expectedInfo.takeError(); 445 446 // Just because a file with a matching name was found and it was an actual 447 // PDB file doesn't mean it matches. For it to match the InfoStream's GUID 448 // must match the GUID specified in the TypeServer2 record. 449 if (expectedInfo->getGuid() != typeServerDependency.getGuid()) 450 return createFileError( 451 typeServerDependency.getName(), 452 make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date)); 453 454 // Reuse the type index map of the type server. 455 tpiMap = (*tsSrc)->tpiMap; 456 ipiMap = (*tsSrc)->ipiMap; 457 return Error::success(); 458 } 459 460 static bool equalsPath(StringRef path1, StringRef path2) { 461 #if defined(_WIN32) 462 return path1.equals_lower(path2); 463 #else 464 return path1.equals(path2); 465 #endif 466 } 467 468 // Find by name an OBJ provided on the command line 469 static PrecompSource *findObjByName(StringRef fileNameOnly) { 470 SmallString<128> currentPath; 471 for (auto kv : PrecompSource::mappings) { 472 StringRef currentFileName = sys::path::filename(kv.second->file->getName(), 473 sys::path::Style::windows); 474 475 // Compare based solely on the file name (link.exe behavior) 476 if (equalsPath(currentFileName, fileNameOnly)) 477 return kv.second; 478 } 479 return nullptr; 480 } 481 482 static PrecompSource *findPrecompSource(ObjFile *file, PrecompRecord &pr) { 483 // Cross-compile warning: given that Clang doesn't generate LF_PRECOMP 484 // records, we assume the OBJ comes from a Windows build of cl.exe. Thusly, 485 // the paths embedded in the OBJs are in the Windows format. 486 SmallString<128> prFileName = 487 sys::path::filename(pr.getPrecompFilePath(), sys::path::Style::windows); 488 489 auto it = PrecompSource::mappings.find(pr.getSignature()); 490 if (it != PrecompSource::mappings.end()) { 491 return it->second; 492 } 493 // Lookup by name 494 return findObjByName(prFileName); 495 } 496 497 static Expected<PrecompSource *> findPrecompMap(ObjFile *file, 498 PrecompRecord &pr) { 499 PrecompSource *precomp = findPrecompSource(file, pr); 500 501 if (!precomp) 502 return createFileError( 503 pr.getPrecompFilePath(), 504 make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch)); 505 506 if (pr.getSignature() != file->pchSignature) 507 return createFileError( 508 toString(file), 509 make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch)); 510 511 if (pr.getSignature() != *precomp->file->pchSignature) 512 return createFileError( 513 toString(precomp->file), 514 make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch)); 515 516 return precomp; 517 } 518 519 /// Merges a precompiled headers TPI map into the current TPI map. The 520 /// precompiled headers object will also be loaded and remapped in the 521 /// process. 522 Error UsePrecompSource::mergeInPrecompHeaderObj() { 523 auto e = findPrecompMap(file, precompDependency); 524 if (!e) 525 return e.takeError(); 526 527 PrecompSource *precompSrc = *e; 528 if (precompSrc->tpiMap.empty()) 529 return Error::success(); 530 531 assert(precompDependency.getStartTypeIndex() == 532 TypeIndex::FirstNonSimpleIndex); 533 assert(precompDependency.getTypesCount() <= precompSrc->tpiMap.size()); 534 // Use the previously remapped index map from the precompiled headers. 535 indexMapStorage.insert(indexMapStorage.begin(), precompSrc->tpiMap.begin(), 536 precompSrc->tpiMap.begin() + 537 precompDependency.getTypesCount()); 538 539 return Error::success(); 540 } 541 542 Error UsePrecompSource::mergeDebugT(TypeMerger *m) { 543 // This object was compiled with /Yu, so process the corresponding 544 // precompiled headers object (/Yc) first. Some type indices in the current 545 // object are referencing data in the precompiled headers object, so we need 546 // both to be loaded. 547 if (Error e = mergeInPrecompHeaderObj()) 548 return e; 549 550 return TpiSource::mergeDebugT(m); 551 } 552 553 uint32_t TpiSource::countTypeServerPDBs() { 554 return TypeServerSource::mappings.size(); 555 } 556 557 uint32_t TpiSource::countPrecompObjs() { 558 return PrecompSource::mappings.size(); 559 } 560 561 void TpiSource::clear() { 562 // Clean up any owned ghash allocations. 563 clearGHashes(); 564 TpiSource::instances.clear(); 565 TypeServerSource::mappings.clear(); 566 PrecompSource::mappings.clear(); 567 } 568 569 //===----------------------------------------------------------------------===// 570 // Parellel GHash type merging implementation. 571 //===----------------------------------------------------------------------===// 572 573 void TpiSource::loadGHashes() { 574 if (Optional<ArrayRef<uint8_t>> debugH = getDebugH(file)) { 575 ghashes = getHashesFromDebugH(*debugH); 576 ownedGHashes = false; 577 } else { 578 CVTypeArray types; 579 BinaryStreamReader reader(file->debugTypes, support::little); 580 cantFail(reader.readArray(types, reader.getLength())); 581 assignGHashesFromVector(GloballyHashedType::hashTypes(types)); 582 } 583 584 fillIsItemIndexFromDebugT(); 585 } 586 587 // Copies ghashes from a vector into an array. These are long lived, so it's 588 // worth the time to copy these into an appropriately sized vector to reduce 589 // memory usage. 590 void TpiSource::assignGHashesFromVector( 591 std::vector<GloballyHashedType> &&hashVec) { 592 GloballyHashedType *hashes = new GloballyHashedType[hashVec.size()]; 593 memcpy(hashes, hashVec.data(), hashVec.size() * sizeof(GloballyHashedType)); 594 ghashes = makeArrayRef(hashes, hashVec.size()); 595 ownedGHashes = true; 596 } 597 598 // Faster way to iterate type records. forEachTypeChecked is faster than 599 // iterating CVTypeArray. It avoids virtual readBytes calls in inner loops. 600 static void forEachTypeChecked(ArrayRef<uint8_t> types, 601 function_ref<void(const CVType &)> fn) { 602 checkError( 603 forEachCodeViewRecord<CVType>(types, [fn](const CVType &ty) -> Error { 604 fn(ty); 605 return Error::success(); 606 })); 607 } 608 609 // Walk over file->debugTypes and fill in the isItemIndex bit vector. 610 // TODO: Store this information in .debug$H so that we don't have to recompute 611 // it. This is the main bottleneck slowing down parallel ghashing with one 612 // thread over single-threaded ghashing. 613 void TpiSource::fillIsItemIndexFromDebugT() { 614 uint32_t index = 0; 615 isItemIndex.resize(ghashes.size()); 616 forEachTypeChecked(file->debugTypes, [&](const CVType &ty) { 617 if (isIdRecord(ty.kind())) 618 isItemIndex.set(index); 619 ++index; 620 }); 621 } 622 623 void TpiSource::mergeTypeRecord(TypeIndex curIndex, CVType ty) { 624 // Decide if the merged type goes into TPI or IPI. 625 bool isItem = isIdRecord(ty.kind()); 626 MergedInfo &merged = isItem ? mergedIpi : mergedTpi; 627 628 // Copy the type into our mutable buffer. 629 assert(ty.length() <= codeview::MaxRecordLength); 630 size_t offset = merged.recs.size(); 631 size_t newSize = alignTo(ty.length(), 4); 632 merged.recs.resize(offset + newSize); 633 auto newRec = makeMutableArrayRef(&merged.recs[offset], newSize); 634 memcpy(newRec.data(), ty.data().data(), newSize); 635 636 // Fix up the record prefix and padding bytes if it required resizing. 637 if (newSize != ty.length()) { 638 reinterpret_cast<RecordPrefix *>(newRec.data())->RecordLen = newSize - 2; 639 for (size_t i = ty.length(); i < newSize; ++i) 640 newRec[i] = LF_PAD0 + (newSize - i); 641 } 642 643 // Remap the type indices in the new record. 644 remapTypesInTypeRecord(newRec); 645 uint32_t pdbHash = check(pdb::hashTypeRecord(CVType(newRec))); 646 merged.recSizes.push_back(static_cast<uint16_t>(newSize)); 647 merged.recHashes.push_back(pdbHash); 648 649 // Retain a mapping from PDB function id to PDB function type. This mapping is 650 // used during symbol processing to rewrite S_GPROC32_ID symbols to S_GPROC32 651 // symbols. 652 if (ty.kind() == LF_FUNC_ID || ty.kind() == LF_MFUNC_ID) { 653 bool success = ty.length() >= 12; 654 TypeIndex funcId = curIndex; 655 if (success) 656 success &= remapTypeIndex(funcId, TiRefKind::IndexRef); 657 TypeIndex funcType = 658 *reinterpret_cast<const TypeIndex *>(&newRec.data()[8]); 659 if (success) { 660 funcIdToType.push_back({funcId, funcType}); 661 } else { 662 StringRef fname = file ? file->getName() : "<unknown PDB>"; 663 warn("corrupt LF_[M]FUNC_ID record 0x" + utohexstr(curIndex.getIndex()) + 664 " in " + fname); 665 } 666 } 667 } 668 669 void TpiSource::mergeUniqueTypeRecords(ArrayRef<uint8_t> typeRecords, 670 TypeIndex beginIndex) { 671 // Re-sort the list of unique types by index. 672 if (kind == PDB) 673 assert(std::is_sorted(uniqueTypes.begin(), uniqueTypes.end())); 674 else 675 llvm::sort(uniqueTypes); 676 677 // Accumulate all the unique types into one buffer in mergedTypes. 678 uint32_t ghashIndex = 0; 679 auto nextUniqueIndex = uniqueTypes.begin(); 680 assert(mergedTpi.recs.empty()); 681 assert(mergedIpi.recs.empty()); 682 683 // Pre-compute the number of elements in advance to avoid std::vector resizes. 684 unsigned nbTpiRecs = 0; 685 unsigned nbIpiRecs = 0; 686 forEachTypeChecked(typeRecords, [&](const CVType &ty) { 687 if (nextUniqueIndex != uniqueTypes.end() && 688 *nextUniqueIndex == ghashIndex) { 689 assert(ty.length() <= codeview::MaxRecordLength); 690 size_t newSize = alignTo(ty.length(), 4); 691 (isIdRecord(ty.kind()) ? nbIpiRecs : nbTpiRecs) += newSize; 692 ++nextUniqueIndex; 693 } 694 ++ghashIndex; 695 }); 696 mergedTpi.recs.reserve(nbTpiRecs); 697 mergedIpi.recs.reserve(nbIpiRecs); 698 699 // Do the actual type merge. 700 ghashIndex = 0; 701 nextUniqueIndex = uniqueTypes.begin(); 702 forEachTypeChecked(typeRecords, [&](const CVType &ty) { 703 if (nextUniqueIndex != uniqueTypes.end() && 704 *nextUniqueIndex == ghashIndex) { 705 mergeTypeRecord(beginIndex + ghashIndex, ty); 706 ++nextUniqueIndex; 707 } 708 ++ghashIndex; 709 }); 710 assert(nextUniqueIndex == uniqueTypes.end() && 711 "failed to merge all desired records"); 712 assert(uniqueTypes.size() == 713 mergedTpi.recSizes.size() + mergedIpi.recSizes.size() && 714 "missing desired record"); 715 } 716 717 void TpiSource::remapTpiWithGHashes(GHashState *g) { 718 assert(config->debugGHashes && "ghashes must be enabled"); 719 fillMapFromGHashes(g); 720 tpiMap = indexMapStorage; 721 ipiMap = indexMapStorage; 722 mergeUniqueTypeRecords(file->debugTypes); 723 // TODO: Free all unneeded ghash resources now that we have a full index map. 724 725 if (config->showSummary) { 726 nbTypeRecords = ghashes.size(); 727 nbTypeRecordsBytes = file->debugTypes.size(); 728 } 729 } 730 731 // PDBs do not actually store global hashes, so when merging a type server 732 // PDB we have to synthesize global hashes. To do this, we first synthesize 733 // global hashes for the TPI stream, since it is independent, then we 734 // synthesize hashes for the IPI stream, using the hashes for the TPI stream 735 // as inputs. 736 void TypeServerSource::loadGHashes() { 737 // Don't hash twice. 738 if (!ghashes.empty()) 739 return; 740 pdb::PDBFile &pdbFile = pdbInputFile->session->getPDBFile(); 741 742 // Hash TPI stream. 743 Expected<pdb::TpiStream &> expectedTpi = pdbFile.getPDBTpiStream(); 744 if (auto e = expectedTpi.takeError()) 745 fatal("Type server does not have TPI stream: " + toString(std::move(e))); 746 assignGHashesFromVector( 747 GloballyHashedType::hashTypes(expectedTpi->typeArray())); 748 isItemIndex.resize(ghashes.size()); 749 750 // Hash IPI stream, which depends on TPI ghashes. 751 if (!pdbFile.hasPDBIpiStream()) 752 return; 753 Expected<pdb::TpiStream &> expectedIpi = pdbFile.getPDBIpiStream(); 754 if (auto e = expectedIpi.takeError()) 755 fatal("error retrieving IPI stream: " + toString(std::move(e))); 756 ipiSrc->assignGHashesFromVector( 757 GloballyHashedType::hashIds(expectedIpi->typeArray(), ghashes)); 758 759 // The IPI stream isItemIndex bitvector should be all ones. 760 ipiSrc->isItemIndex.resize(ipiSrc->ghashes.size()); 761 ipiSrc->isItemIndex.set(0, ipiSrc->ghashes.size()); 762 } 763 764 // Flatten discontiguous PDB type arrays to bytes so that we can use 765 // forEachTypeChecked instead of CVTypeArray iteration. Copying all types from 766 // type servers is faster than iterating all object files compiled with /Z7 with 767 // CVTypeArray, which has high overheads due to the virtual interface of 768 // BinaryStream::readBytes. 769 static ArrayRef<uint8_t> typeArrayToBytes(const CVTypeArray &types) { 770 BinaryStreamRef stream = types.getUnderlyingStream(); 771 ArrayRef<uint8_t> debugTypes; 772 checkError(stream.readBytes(0, stream.getLength(), debugTypes)); 773 return debugTypes; 774 } 775 776 // Merge types from a type server PDB. 777 void TypeServerSource::remapTpiWithGHashes(GHashState *g) { 778 assert(config->debugGHashes && "ghashes must be enabled"); 779 780 // IPI merging depends on TPI, so do TPI first, then do IPI. No need to 781 // propagate errors, those should've been handled during ghash loading. 782 pdb::PDBFile &pdbFile = pdbInputFile->session->getPDBFile(); 783 pdb::TpiStream &tpi = check(pdbFile.getPDBTpiStream()); 784 fillMapFromGHashes(g); 785 tpiMap = indexMapStorage; 786 mergeUniqueTypeRecords(typeArrayToBytes(tpi.typeArray())); 787 if (pdbFile.hasPDBIpiStream()) { 788 pdb::TpiStream &ipi = check(pdbFile.getPDBIpiStream()); 789 ipiSrc->indexMapStorage.resize(ipiSrc->ghashes.size()); 790 ipiSrc->fillMapFromGHashes(g); 791 ipiMap = ipiSrc->indexMapStorage; 792 ipiSrc->tpiMap = tpiMap; 793 ipiSrc->ipiMap = ipiMap; 794 ipiSrc->mergeUniqueTypeRecords(typeArrayToBytes(ipi.typeArray())); 795 796 if (config->showSummary) { 797 nbTypeRecords = ipiSrc->ghashes.size(); 798 nbTypeRecordsBytes = ipi.typeArray().getUnderlyingStream().getLength(); 799 } 800 } 801 802 if (config->showSummary) { 803 nbTypeRecords += ghashes.size(); 804 nbTypeRecordsBytes += tpi.typeArray().getUnderlyingStream().getLength(); 805 } 806 } 807 808 void UseTypeServerSource::remapTpiWithGHashes(GHashState *g) { 809 // No remapping to do with /Zi objects. Simply use the index map from the type 810 // server. Errors should have been reported earlier. Symbols from this object 811 // will be ignored. 812 Expected<TypeServerSource *> maybeTsSrc = getTypeServerSource(); 813 if (!maybeTsSrc) { 814 typeMergingError = 815 joinErrors(std::move(typeMergingError), maybeTsSrc.takeError()); 816 return; 817 } 818 TypeServerSource *tsSrc = *maybeTsSrc; 819 tpiMap = tsSrc->tpiMap; 820 ipiMap = tsSrc->ipiMap; 821 } 822 823 void PrecompSource::loadGHashes() { 824 if (getDebugH(file)) { 825 warn("ignoring .debug$H section; pch with ghash is not implemented"); 826 } 827 828 uint32_t ghashIdx = 0; 829 std::vector<GloballyHashedType> hashVec; 830 forEachTypeChecked(file->debugTypes, [&](const CVType &ty) { 831 // Remember the index of the LF_ENDPRECOMP record so it can be excluded from 832 // the PDB. There must be an entry in the list of ghashes so that the type 833 // indexes of the following records in the /Yc PCH object line up. 834 if (ty.kind() == LF_ENDPRECOMP) 835 endPrecompGHashIdx = ghashIdx; 836 837 hashVec.push_back(GloballyHashedType::hashType(ty, hashVec, hashVec)); 838 isItemIndex.push_back(isIdRecord(ty.kind())); 839 ++ghashIdx; 840 }); 841 assignGHashesFromVector(std::move(hashVec)); 842 } 843 844 void UsePrecompSource::loadGHashes() { 845 PrecompSource *pchSrc = findPrecompSource(file, precompDependency); 846 if (!pchSrc) 847 return; 848 849 // To compute ghashes of a /Yu object file, we need to build on the the 850 // ghashes of the /Yc PCH object. After we are done hashing, discard the 851 // ghashes from the PCH source so we don't unnecessarily try to deduplicate 852 // them. 853 std::vector<GloballyHashedType> hashVec = 854 pchSrc->ghashes.take_front(precompDependency.getTypesCount()); 855 forEachTypeChecked(file->debugTypes, [&](const CVType &ty) { 856 hashVec.push_back(GloballyHashedType::hashType(ty, hashVec, hashVec)); 857 isItemIndex.push_back(isIdRecord(ty.kind())); 858 }); 859 hashVec.erase(hashVec.begin(), 860 hashVec.begin() + precompDependency.getTypesCount()); 861 assignGHashesFromVector(std::move(hashVec)); 862 } 863 864 void UsePrecompSource::remapTpiWithGHashes(GHashState *g) { 865 fillMapFromGHashes(g); 866 // This object was compiled with /Yu, so process the corresponding 867 // precompiled headers object (/Yc) first. Some type indices in the current 868 // object are referencing data in the precompiled headers object, so we need 869 // both to be loaded. 870 if (Error e = mergeInPrecompHeaderObj()) { 871 typeMergingError = joinErrors(std::move(typeMergingError), std::move(e)); 872 return; 873 } 874 875 tpiMap = indexMapStorage; 876 ipiMap = indexMapStorage; 877 mergeUniqueTypeRecords(file->debugTypes, 878 TypeIndex(precompDependency.getStartTypeIndex() + 879 precompDependency.getTypesCount())); 880 if (config->showSummary) { 881 nbTypeRecords = ghashes.size(); 882 nbTypeRecordsBytes = file->debugTypes.size(); 883 } 884 } 885 886 namespace { 887 /// A concurrent hash table for global type hashing. It is based on this paper: 888 /// Concurrent Hash Tables: Fast and General(?)! 889 /// https://dl.acm.org/doi/10.1145/3309206 890 /// 891 /// This hash table is meant to be used in two phases: 892 /// 1. concurrent insertions 893 /// 2. concurrent reads 894 /// It does not support lookup, deletion, or rehashing. It uses linear probing. 895 /// 896 /// The paper describes storing a key-value pair in two machine words. 897 /// Generally, the values stored in this map are type indices, and we can use 898 /// those values to recover the ghash key from a side table. This allows us to 899 /// shrink the table entries further at the cost of some loads, and sidesteps 900 /// the need for a 128 bit atomic compare-and-swap operation. 901 /// 902 /// During insertion, a priority function is used to decide which insertion 903 /// should be preferred. This ensures that the output is deterministic. For 904 /// ghashing, lower tpiSrcIdx values (earlier inputs) are preferred. 905 /// 906 class GHashCell; 907 struct GHashTable { 908 GHashCell *table = nullptr; 909 uint32_t tableSize = 0; 910 911 GHashTable() = default; 912 ~GHashTable(); 913 914 /// Initialize the table with the given size. Because the table cannot be 915 /// resized, the initial size of the table must be large enough to contain all 916 /// inputs, or insertion may not be able to find an empty cell. 917 void init(uint32_t newTableSize); 918 919 /// Insert the cell with the given ghash into the table. Return the insertion 920 /// position in the table. It is safe for the caller to store the insertion 921 /// position because the table cannot be resized. 922 uint32_t insert(GloballyHashedType ghash, GHashCell newCell); 923 }; 924 925 /// A ghash table cell for deduplicating types from TpiSources. 926 class GHashCell { 927 uint64_t data = 0; 928 929 public: 930 GHashCell() = default; 931 932 // Construct data most to least significant so that sorting works well: 933 // - isItem 934 // - tpiSrcIdx 935 // - ghashIdx 936 // Add one to the tpiSrcIdx so that the 0th record from the 0th source has a 937 // non-zero representation. 938 GHashCell(bool isItem, uint32_t tpiSrcIdx, uint32_t ghashIdx) 939 : data((uint64_t(isItem) << 63U) | (uint64_t(tpiSrcIdx + 1) << 32ULL) | 940 ghashIdx) { 941 assert(tpiSrcIdx == getTpiSrcIdx() && "round trip failure"); 942 assert(ghashIdx == getGHashIdx() && "round trip failure"); 943 } 944 945 explicit GHashCell(uint64_t data) : data(data) {} 946 947 // The empty cell is all zeros. 948 bool isEmpty() const { return data == 0ULL; } 949 950 /// Extract the tpiSrcIdx. 951 uint32_t getTpiSrcIdx() const { 952 return ((uint32_t)(data >> 32U) & 0x7FFFFFFF) - 1; 953 } 954 955 /// Extract the index into the ghash array of the TpiSource. 956 uint32_t getGHashIdx() const { return (uint32_t)data; } 957 958 bool isItem() const { return data & (1ULL << 63U); } 959 960 /// Get the ghash key for this cell. 961 GloballyHashedType getGHash() const { 962 return TpiSource::instances[getTpiSrcIdx()]->ghashes[getGHashIdx()]; 963 } 964 965 /// The priority function for the cell. The data is stored such that lower 966 /// tpiSrcIdx and ghashIdx values are preferred, which means that type record 967 /// from earlier sources are more likely to prevail. 968 friend inline bool operator<(const GHashCell &l, const GHashCell &r) { 969 return l.data < r.data; 970 } 971 }; 972 } // namespace 973 974 namespace lld { 975 namespace coff { 976 /// This type is just a wrapper around GHashTable with external linkage so it 977 /// can be used from a header. 978 struct GHashState { 979 GHashTable table; 980 }; 981 } // namespace coff 982 } // namespace lld 983 984 GHashTable::~GHashTable() { delete[] table; } 985 986 void GHashTable::init(uint32_t newTableSize) { 987 table = new GHashCell[newTableSize]; 988 memset(table, 0, newTableSize * sizeof(GHashCell)); 989 tableSize = newTableSize; 990 } 991 992 uint32_t GHashTable::insert(GloballyHashedType ghash, GHashCell newCell) { 993 assert(!newCell.isEmpty() && "cannot insert empty cell value"); 994 995 // FIXME: The low bytes of SHA1 have low entropy for short records, which 996 // type records are. Swap the byte order for better entropy. A better ghash 997 // won't need this. 998 uint32_t startIdx = 999 ByteSwap_64(*reinterpret_cast<uint64_t *>(&ghash)) % tableSize; 1000 1001 // Do a linear probe starting at startIdx. 1002 uint32_t idx = startIdx; 1003 while (true) { 1004 // Run a compare and swap loop. There are four cases: 1005 // - cell is empty: CAS into place and return 1006 // - cell has matching key, earlier priority: do nothing, return 1007 // - cell has matching key, later priority: CAS into place and return 1008 // - cell has non-matching key: hash collision, probe next cell 1009 auto *cellPtr = reinterpret_cast<std::atomic<GHashCell> *>(&table[idx]); 1010 GHashCell oldCell(cellPtr->load()); 1011 while (oldCell.isEmpty() || oldCell.getGHash() == ghash) { 1012 // Check if there is an existing ghash entry with a higher priority 1013 // (earlier ordering). If so, this is a duplicate, we are done. 1014 if (!oldCell.isEmpty() && oldCell < newCell) 1015 return idx; 1016 // Either the cell is empty, or our value is higher priority. Try to 1017 // compare and swap. If it succeeds, we are done. 1018 if (cellPtr->compare_exchange_weak(oldCell, newCell)) 1019 return idx; 1020 // If the CAS failed, check this cell again. 1021 } 1022 1023 // Advance the probe. Wrap around to the beginning if we run off the end. 1024 ++idx; 1025 idx = idx == tableSize ? 0 : idx; 1026 if (idx == startIdx) { 1027 // If this becomes an issue, we could mark failure and rehash from the 1028 // beginning with a bigger table. There is no difference between rehashing 1029 // internally and starting over. 1030 report_fatal_error("ghash table is full"); 1031 } 1032 } 1033 llvm_unreachable("left infloop"); 1034 } 1035 1036 TypeMerger::TypeMerger(llvm::BumpPtrAllocator &alloc) 1037 : typeTable(alloc), idTable(alloc) {} 1038 1039 TypeMerger::~TypeMerger() = default; 1040 1041 void TypeMerger::mergeTypesWithGHash() { 1042 // Load ghashes. Do type servers and PCH objects first. 1043 { 1044 ScopedTimer t1(loadGHashTimer); 1045 parallelForEach(TpiSource::dependencySources, 1046 [&](TpiSource *source) { source->loadGHashes(); }); 1047 parallelForEach(TpiSource::objectSources, 1048 [&](TpiSource *source) { source->loadGHashes(); }); 1049 } 1050 1051 ScopedTimer t2(mergeGHashTimer); 1052 GHashState ghashState; 1053 1054 // Estimate the size of hash table needed to deduplicate ghashes. This *must* 1055 // be larger than the number of unique types, or hash table insertion may not 1056 // be able to find a vacant slot. Summing the input types guarantees this, but 1057 // it is a gross overestimate. The table size could be reduced to save memory, 1058 // but it would require implementing rehashing, and this table is generally 1059 // small compared to total memory usage, at eight bytes per input type record, 1060 // and most input type records are larger than eight bytes. 1061 size_t tableSize = 0; 1062 for (TpiSource *source : TpiSource::instances) 1063 tableSize += source->ghashes.size(); 1064 1065 // Cap the table size so that we can use 32-bit cell indices. Type indices are 1066 // also 32-bit, so this is an inherent PDB file format limit anyway. 1067 tableSize = std::min(size_t(INT32_MAX), tableSize); 1068 ghashState.table.init(static_cast<uint32_t>(tableSize)); 1069 1070 // Insert ghashes in parallel. During concurrent insertion, we cannot observe 1071 // the contents of the hash table cell, but we can remember the insertion 1072 // position. Because the table does not rehash, the position will not change 1073 // under insertion. After insertion is done, the value of the cell can be read 1074 // to retrieve the final PDB type index. 1075 parallelForEachN(0, TpiSource::instances.size(), [&](size_t tpiSrcIdx) { 1076 TpiSource *source = TpiSource::instances[tpiSrcIdx]; 1077 source->indexMapStorage.resize(source->ghashes.size()); 1078 for (uint32_t i = 0, e = source->ghashes.size(); i < e; i++) { 1079 if (source->shouldOmitFromPdb(i)) { 1080 source->indexMapStorage[i] = TypeIndex(SimpleTypeKind::NotTranslated); 1081 continue; 1082 } 1083 GloballyHashedType ghash = source->ghashes[i]; 1084 bool isItem = source->isItemIndex.test(i); 1085 uint32_t cellIdx = 1086 ghashState.table.insert(ghash, GHashCell(isItem, tpiSrcIdx, i)); 1087 1088 // Store the ghash cell index as a type index in indexMapStorage. Later 1089 // we will replace it with the PDB type index. 1090 source->indexMapStorage[i] = TypeIndex::fromArrayIndex(cellIdx); 1091 } 1092 }); 1093 1094 // Collect all non-empty cells and sort them. This will implicitly assign 1095 // destination type indices, and partition the entries into type records and 1096 // item records. It arranges types in this order: 1097 // - type records 1098 // - source 0, type 0... 1099 // - source 1, type 1... 1100 // - item records 1101 // - source 0, type 1... 1102 // - source 1, type 0... 1103 std::vector<GHashCell> entries; 1104 for (const GHashCell &cell : 1105 makeArrayRef(ghashState.table.table, tableSize)) { 1106 if (!cell.isEmpty()) 1107 entries.push_back(cell); 1108 } 1109 parallelSort(entries, std::less<GHashCell>()); 1110 log(formatv("ghash table load factor: {0:p} (size {1} / capacity {2})\n", 1111 tableSize ? double(entries.size()) / tableSize : 0, 1112 entries.size(), tableSize)); 1113 1114 // Find out how many type and item indices there are. 1115 auto mid = 1116 std::lower_bound(entries.begin(), entries.end(), GHashCell(true, 0, 0)); 1117 assert((mid == entries.end() || mid->isItem()) && 1118 (mid == entries.begin() || !std::prev(mid)->isItem()) && 1119 "midpoint is not midpoint"); 1120 uint32_t numTypes = std::distance(entries.begin(), mid); 1121 uint32_t numItems = std::distance(mid, entries.end()); 1122 log("Tpi record count: " + Twine(numTypes)); 1123 log("Ipi record count: " + Twine(numItems)); 1124 1125 // Make a list of the "unique" type records to merge for each tpi source. Type 1126 // merging will skip indices not on this list. Store the destination PDB type 1127 // index for these unique types in the tpiMap for each source. The entries for 1128 // non-unique types will be filled in prior to type merging. 1129 for (uint32_t i = 0, e = entries.size(); i < e; ++i) { 1130 auto &cell = entries[i]; 1131 uint32_t tpiSrcIdx = cell.getTpiSrcIdx(); 1132 TpiSource *source = TpiSource::instances[tpiSrcIdx]; 1133 source->uniqueTypes.push_back(cell.getGHashIdx()); 1134 1135 // Update the ghash table to store the destination PDB type index in the 1136 // table. 1137 uint32_t pdbTypeIndex = i < numTypes ? i : i - numTypes; 1138 uint32_t ghashCellIndex = 1139 source->indexMapStorage[cell.getGHashIdx()].toArrayIndex(); 1140 ghashState.table.table[ghashCellIndex] = 1141 GHashCell(cell.isItem(), cell.getTpiSrcIdx(), pdbTypeIndex); 1142 } 1143 1144 // In parallel, remap all types. 1145 for_each(TpiSource::dependencySources, [&](TpiSource *source) { 1146 source->remapTpiWithGHashes(&ghashState); 1147 }); 1148 parallelForEach(TpiSource::objectSources, [&](TpiSource *source) { 1149 source->remapTpiWithGHashes(&ghashState); 1150 }); 1151 1152 // Build a global map of from function ID to function type. 1153 for (TpiSource *source : TpiSource::instances) { 1154 for (auto idToType : source->funcIdToType) 1155 funcIdToType.insert(idToType); 1156 source->funcIdToType.clear(); 1157 } 1158 1159 TpiSource::clearGHashes(); 1160 } 1161 1162 /// Given the index into the ghash table for a particular type, return the type 1163 /// index for that type in the output PDB. 1164 static TypeIndex loadPdbTypeIndexFromCell(GHashState *g, 1165 uint32_t ghashCellIdx) { 1166 GHashCell cell = g->table.table[ghashCellIdx]; 1167 return TypeIndex::fromArrayIndex(cell.getGHashIdx()); 1168 } 1169 1170 // Fill in a TPI or IPI index map using ghashes. For each source type, use its 1171 // ghash to lookup its final type index in the PDB, and store that in the map. 1172 void TpiSource::fillMapFromGHashes(GHashState *g) { 1173 for (size_t i = 0, e = ghashes.size(); i < e; ++i) { 1174 TypeIndex fakeCellIndex = indexMapStorage[i]; 1175 if (fakeCellIndex.isSimple()) 1176 indexMapStorage[i] = fakeCellIndex; 1177 else 1178 indexMapStorage[i] = 1179 loadPdbTypeIndexFromCell(g, fakeCellIndex.toArrayIndex()); 1180 } 1181 } 1182 1183 void TpiSource::clearGHashes() { 1184 for (TpiSource *src : TpiSource::instances) { 1185 if (src->ownedGHashes) 1186 delete[] src->ghashes.data(); 1187 src->ghashes = {}; 1188 src->isItemIndex.clear(); 1189 src->uniqueTypes.clear(); 1190 } 1191 } 1192