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