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 "TypeMerger.h" 14 #include "lld/Common/ErrorHandler.h" 15 #include "lld/Common/Memory.h" 16 #include "llvm/DebugInfo/CodeView/TypeRecord.h" 17 #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" 18 #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" 19 #include "llvm/DebugInfo/PDB/GenericError.h" 20 #include "llvm/DebugInfo/PDB/Native/InfoStream.h" 21 #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 22 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 23 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 24 #include "llvm/Support/Path.h" 25 26 using namespace llvm; 27 using namespace llvm::codeview; 28 using namespace lld; 29 using namespace lld::coff; 30 31 namespace { 32 class TypeServerIpiSource; 33 34 // The TypeServerSource class represents a PDB type server, a file referenced by 35 // OBJ files compiled with MSVC /Zi. A single PDB can be shared by several OBJ 36 // files, therefore there must be only once instance per OBJ lot. The file path 37 // is discovered from the dependent OBJ's debug type stream. The 38 // TypeServerSource object is then queued and loaded by the COFF Driver. The 39 // debug type stream for such PDB files will be merged first in the final PDB, 40 // before any dependent OBJ. 41 class TypeServerSource : public TpiSource { 42 public: 43 explicit TypeServerSource(PDBInputFile *f) 44 : TpiSource(PDB, nullptr), pdbInputFile(f) { 45 if (f->loadErr && *f->loadErr) 46 return; 47 pdb::PDBFile &file = f->session->getPDBFile(); 48 auto expectedInfo = file.getPDBInfoStream(); 49 if (!expectedInfo) 50 return; 51 auto it = mappings.emplace(expectedInfo->getGuid(), this); 52 assert(it.second); 53 (void)it; 54 } 55 56 Error mergeDebugT(TypeMerger *m) override; 57 bool isDependency() const override { return true; } 58 59 PDBInputFile *pdbInputFile = nullptr; 60 61 // TpiSource for IPI stream. 62 TypeServerIpiSource *ipiSrc = nullptr; 63 64 static std::map<codeview::GUID, TypeServerSource *> mappings; 65 }; 66 67 // Companion to TypeServerSource. Stores the index map for the IPI stream in the 68 // PDB. Modeling PDBs with two sources for TPI and IPI helps establish the 69 // invariant of one type index space per source. 70 class TypeServerIpiSource : public TpiSource { 71 public: 72 explicit TypeServerIpiSource() : TpiSource(PDBIpi, nullptr) {} 73 74 friend class TypeServerSource; 75 76 // IPI merging is handled in TypeServerSource::mergeDebugT, since it depends 77 // directly on type merging. 78 Error mergeDebugT(TypeMerger *m) override { return Error::success(); } 79 80 bool isDependency() const override { return true; } 81 }; 82 83 // This class represents the debug type stream of an OBJ file that depends on a 84 // PDB type server (see TypeServerSource). 85 class UseTypeServerSource : public TpiSource { 86 public: 87 UseTypeServerSource(ObjFile *f, TypeServer2Record ts) 88 : TpiSource(UsingPDB, f), typeServerDependency(ts) {} 89 90 Error mergeDebugT(TypeMerger *m) override; 91 92 // Information about the PDB type server dependency, that needs to be loaded 93 // in before merging this OBJ. 94 TypeServer2Record typeServerDependency; 95 }; 96 97 // This class represents the debug type stream of a Microsoft precompiled 98 // headers OBJ (PCH OBJ). This OBJ kind needs to be merged first in the output 99 // PDB, before any other OBJs that depend on this. Note that only MSVC generate 100 // such files, clang does not. 101 class PrecompSource : public TpiSource { 102 public: 103 PrecompSource(ObjFile *f) : TpiSource(PCH, f) { 104 if (!f->pchSignature || !*f->pchSignature) 105 fatal(toString(f) + 106 " claims to be a PCH object, but does not have a valid signature"); 107 auto it = mappings.emplace(*f->pchSignature, this); 108 if (!it.second) 109 fatal("a PCH object with the same signature has already been provided (" + 110 toString(it.first->second->file) + " and " + toString(file) + ")"); 111 } 112 113 bool isDependency() const override { return true; } 114 115 static std::map<uint32_t, PrecompSource *> mappings; 116 }; 117 118 // This class represents the debug type stream of an OBJ file that depends on a 119 // Microsoft precompiled headers OBJ (see PrecompSource). 120 class UsePrecompSource : public TpiSource { 121 public: 122 UsePrecompSource(ObjFile *f, PrecompRecord precomp) 123 : TpiSource(UsingPCH, f), precompDependency(precomp) {} 124 125 Error mergeDebugT(TypeMerger *m) override; 126 127 // Information about the Precomp OBJ dependency, that needs to be loaded in 128 // before merging this OBJ. 129 PrecompRecord precompDependency; 130 }; 131 } // namespace 132 133 static std::vector<TpiSource *> gc; 134 135 TpiSource::TpiSource(TpiKind k, ObjFile *f) : kind(k), file(f) { 136 gc.push_back(this); 137 } 138 139 // Vtable key method. 140 TpiSource::~TpiSource() = default; 141 142 TpiSource *lld::coff::makeTpiSource(ObjFile *file) { 143 return make<TpiSource>(TpiSource::Regular, file); 144 } 145 146 TpiSource *lld::coff::makeTypeServerSource(PDBInputFile *pdbInputFile) { 147 // Type server sources come in pairs: the TPI stream, and the IPI stream. 148 auto *tpiSource = make<TypeServerSource>(pdbInputFile); 149 if (pdbInputFile->session->getPDBFile().hasPDBIpiStream()) 150 tpiSource->ipiSrc = make<TypeServerIpiSource>(); 151 return tpiSource; 152 } 153 154 TpiSource *lld::coff::makeUseTypeServerSource(ObjFile *file, 155 TypeServer2Record ts) { 156 return make<UseTypeServerSource>(file, ts); 157 } 158 159 TpiSource *lld::coff::makePrecompSource(ObjFile *file) { 160 return make<PrecompSource>(file); 161 } 162 163 TpiSource *lld::coff::makeUsePrecompSource(ObjFile *file, 164 PrecompRecord precomp) { 165 return make<UsePrecompSource>(file, precomp); 166 } 167 168 void TpiSource::forEachSource(llvm::function_ref<void(TpiSource *)> fn) { 169 for_each(gc, fn); 170 } 171 172 std::map<codeview::GUID, TypeServerSource *> TypeServerSource::mappings; 173 174 std::map<uint32_t, PrecompSource *> PrecompSource::mappings; 175 176 // A COFF .debug$H section is currently a clang extension. This function checks 177 // if a .debug$H section is in a format that we expect / understand, so that we 178 // can ignore any sections which are coincidentally also named .debug$H but do 179 // not contain a format we recognize. 180 static bool canUseDebugH(ArrayRef<uint8_t> debugH) { 181 if (debugH.size() < sizeof(object::debug_h_header)) 182 return false; 183 auto *header = 184 reinterpret_cast<const object::debug_h_header *>(debugH.data()); 185 debugH = debugH.drop_front(sizeof(object::debug_h_header)); 186 return header->Magic == COFF::DEBUG_HASHES_SECTION_MAGIC && 187 header->Version == 0 && 188 header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::SHA1_8) && 189 (debugH.size() % 8 == 0); 190 } 191 192 static Optional<ArrayRef<uint8_t>> getDebugH(ObjFile *file) { 193 SectionChunk *sec = 194 SectionChunk::findByName(file->getDebugChunks(), ".debug$H"); 195 if (!sec) 196 return llvm::None; 197 ArrayRef<uint8_t> contents = sec->getContents(); 198 if (!canUseDebugH(contents)) 199 return None; 200 return contents; 201 } 202 203 static ArrayRef<GloballyHashedType> 204 getHashesFromDebugH(ArrayRef<uint8_t> debugH) { 205 assert(canUseDebugH(debugH)); 206 207 debugH = debugH.drop_front(sizeof(object::debug_h_header)); 208 uint32_t count = debugH.size() / sizeof(GloballyHashedType); 209 return {reinterpret_cast<const GloballyHashedType *>(debugH.data()), count}; 210 } 211 212 // Merge .debug$T for a generic object file. 213 Error TpiSource::mergeDebugT(TypeMerger *m) { 214 CVTypeArray types; 215 BinaryStreamReader reader(file->debugTypes, support::little); 216 cantFail(reader.readArray(types, reader.getLength())); 217 218 if (config->debugGHashes) { 219 ArrayRef<GloballyHashedType> hashes; 220 std::vector<GloballyHashedType> ownedHashes; 221 if (Optional<ArrayRef<uint8_t>> debugH = getDebugH(file)) 222 hashes = getHashesFromDebugH(*debugH); 223 else { 224 ownedHashes = GloballyHashedType::hashTypes(types); 225 hashes = ownedHashes; 226 } 227 228 if (auto err = mergeTypeAndIdRecords(m->globalIDTable, m->globalTypeTable, 229 indexMapStorage, types, hashes, 230 file->pchSignature)) 231 fatal("codeview::mergeTypeAndIdRecords failed: " + 232 toString(std::move(err))); 233 } else { 234 if (auto err = 235 mergeTypeAndIdRecords(m->idTable, m->typeTable, indexMapStorage, 236 types, file->pchSignature)) 237 fatal("codeview::mergeTypeAndIdRecords failed: " + 238 toString(std::move(err))); 239 } 240 241 // In an object, there is only one mapping for both types and items. 242 tpiMap = indexMapStorage; 243 ipiMap = indexMapStorage; 244 245 if (config->showSummary) { 246 // Count how many times we saw each type record in our input. This 247 // calculation requires a second pass over the type records to classify each 248 // record as a type or index. This is slow, but this code executes when 249 // collecting statistics. 250 m->tpiCounts.resize(m->getTypeTable().size()); 251 m->ipiCounts.resize(m->getIDTable().size()); 252 uint32_t srcIdx = 0; 253 for (CVType &ty : types) { 254 TypeIndex dstIdx = tpiMap[srcIdx++]; 255 // Type merging may fail, so a complex source type may become the simple 256 // NotTranslated type, which cannot be used as an array index. 257 if (dstIdx.isSimple()) 258 continue; 259 SmallVectorImpl<uint32_t> &counts = 260 isIdRecord(ty.kind()) ? m->ipiCounts : m->tpiCounts; 261 ++counts[dstIdx.toArrayIndex()]; 262 } 263 } 264 265 return Error::success(); 266 } 267 268 // Merge types from a type server PDB. 269 Error TypeServerSource::mergeDebugT(TypeMerger *m) { 270 pdb::PDBFile &pdbFile = pdbInputFile->session->getPDBFile(); 271 Expected<pdb::TpiStream &> expectedTpi = pdbFile.getPDBTpiStream(); 272 if (auto e = expectedTpi.takeError()) 273 fatal("Type server does not have TPI stream: " + toString(std::move(e))); 274 pdb::TpiStream *maybeIpi = nullptr; 275 if (pdbFile.hasPDBIpiStream()) { 276 Expected<pdb::TpiStream &> expectedIpi = pdbFile.getPDBIpiStream(); 277 if (auto e = expectedIpi.takeError()) 278 fatal("Error getting type server IPI stream: " + toString(std::move(e))); 279 maybeIpi = &*expectedIpi; 280 } 281 282 if (config->debugGHashes) { 283 // PDBs do not actually store global hashes, so when merging a type server 284 // PDB we have to synthesize global hashes. To do this, we first synthesize 285 // global hashes for the TPI stream, since it is independent, then we 286 // synthesize hashes for the IPI stream, using the hashes for the TPI stream 287 // as inputs. 288 auto tpiHashes = GloballyHashedType::hashTypes(expectedTpi->typeArray()); 289 Optional<uint32_t> endPrecomp; 290 // Merge TPI first, because the IPI stream will reference type indices. 291 if (auto err = 292 mergeTypeRecords(m->globalTypeTable, indexMapStorage, 293 expectedTpi->typeArray(), tpiHashes, endPrecomp)) 294 fatal("codeview::mergeTypeRecords failed: " + toString(std::move(err))); 295 tpiMap = indexMapStorage; 296 297 // Merge IPI. 298 if (maybeIpi) { 299 auto ipiHashes = 300 GloballyHashedType::hashIds(maybeIpi->typeArray(), tpiHashes); 301 if (auto err = 302 mergeIdRecords(m->globalIDTable, tpiMap, ipiSrc->indexMapStorage, 303 maybeIpi->typeArray(), ipiHashes)) 304 fatal("codeview::mergeIdRecords failed: " + toString(std::move(err))); 305 ipiMap = ipiSrc->indexMapStorage; 306 } 307 } else { 308 // Merge TPI first, because the IPI stream will reference type indices. 309 if (auto err = mergeTypeRecords(m->typeTable, indexMapStorage, 310 expectedTpi->typeArray())) 311 fatal("codeview::mergeTypeRecords failed: " + toString(std::move(err))); 312 tpiMap = indexMapStorage; 313 314 // Merge IPI. 315 if (maybeIpi) { 316 if (auto err = mergeIdRecords(m->idTable, tpiMap, ipiSrc->indexMapStorage, 317 maybeIpi->typeArray())) 318 fatal("codeview::mergeIdRecords failed: " + toString(std::move(err))); 319 ipiMap = ipiSrc->indexMapStorage; 320 } 321 } 322 323 if (config->showSummary) { 324 // Count how many times we saw each type record in our input. If a 325 // destination type index is present in the source to destination type index 326 // map, that means we saw it once in the input. Add it to our histogram. 327 m->tpiCounts.resize(m->getTypeTable().size()); 328 m->ipiCounts.resize(m->getIDTable().size()); 329 for (TypeIndex ti : tpiMap) 330 if (!ti.isSimple()) 331 ++m->tpiCounts[ti.toArrayIndex()]; 332 for (TypeIndex ti : ipiMap) 333 if (!ti.isSimple()) 334 ++m->ipiCounts[ti.toArrayIndex()]; 335 } 336 337 return Error::success(); 338 } 339 340 Error UseTypeServerSource::mergeDebugT(TypeMerger *m) { 341 const codeview::GUID &tsId = typeServerDependency.getGuid(); 342 StringRef tsPath = typeServerDependency.getName(); 343 344 TypeServerSource *tsSrc; 345 auto it = TypeServerSource::mappings.find(tsId); 346 if (it != TypeServerSource::mappings.end()) { 347 tsSrc = it->second; 348 } else { 349 // The file failed to load, lookup by name 350 PDBInputFile *pdb = PDBInputFile::findFromRecordPath(tsPath, file); 351 if (!pdb) 352 return createFileError(tsPath, errorCodeToError(std::error_code( 353 ENOENT, std::generic_category()))); 354 // If an error occurred during loading, throw it now 355 if (pdb->loadErr && *pdb->loadErr) 356 return createFileError(tsPath, std::move(*pdb->loadErr)); 357 358 tsSrc = (TypeServerSource *)pdb->debugTypesObj; 359 } 360 361 pdb::PDBFile &pdbSession = tsSrc->pdbInputFile->session->getPDBFile(); 362 auto expectedInfo = pdbSession.getPDBInfoStream(); 363 if (!expectedInfo) 364 return expectedInfo.takeError(); 365 366 // Just because a file with a matching name was found and it was an actual 367 // PDB file doesn't mean it matches. For it to match the InfoStream's GUID 368 // must match the GUID specified in the TypeServer2 record. 369 if (expectedInfo->getGuid() != typeServerDependency.getGuid()) 370 return createFileError( 371 tsPath, 372 make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date)); 373 374 // Reuse the type index map of the type server. 375 tpiMap = tsSrc->tpiMap; 376 ipiMap = tsSrc->ipiMap; 377 return Error::success(); 378 } 379 380 static bool equalsPath(StringRef path1, StringRef path2) { 381 #if defined(_WIN32) 382 return path1.equals_lower(path2); 383 #else 384 return path1.equals(path2); 385 #endif 386 } 387 388 // Find by name an OBJ provided on the command line 389 static PrecompSource *findObjByName(StringRef fileNameOnly) { 390 SmallString<128> currentPath; 391 for (auto kv : PrecompSource::mappings) { 392 StringRef currentFileName = sys::path::filename(kv.second->file->getName(), 393 sys::path::Style::windows); 394 395 // Compare based solely on the file name (link.exe behavior) 396 if (equalsPath(currentFileName, fileNameOnly)) 397 return kv.second; 398 } 399 return nullptr; 400 } 401 402 static Expected<PrecompSource *> findPrecompMap(ObjFile *file, 403 PrecompRecord &pr) { 404 // Cross-compile warning: given that Clang doesn't generate LF_PRECOMP 405 // records, we assume the OBJ comes from a Windows build of cl.exe. Thusly, 406 // the paths embedded in the OBJs are in the Windows format. 407 SmallString<128> prFileName = 408 sys::path::filename(pr.getPrecompFilePath(), sys::path::Style::windows); 409 410 PrecompSource *precomp; 411 auto it = PrecompSource::mappings.find(pr.getSignature()); 412 if (it != PrecompSource::mappings.end()) { 413 precomp = it->second; 414 } else { 415 // Lookup by name 416 precomp = findObjByName(prFileName); 417 } 418 419 if (!precomp) 420 return createFileError( 421 prFileName, 422 make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch)); 423 424 if (pr.getSignature() != file->pchSignature) 425 return createFileError( 426 toString(file), 427 make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch)); 428 429 if (pr.getSignature() != *precomp->file->pchSignature) 430 return createFileError( 431 toString(precomp->file), 432 make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch)); 433 434 return precomp; 435 } 436 437 /// Merges a precompiled headers TPI map into the current TPI map. The 438 /// precompiled headers object will also be loaded and remapped in the 439 /// process. 440 static Error 441 mergeInPrecompHeaderObj(ObjFile *file, 442 SmallVectorImpl<TypeIndex> &indexMapStorage, 443 PrecompRecord &precomp) { 444 auto e = findPrecompMap(file, precomp); 445 if (!e) 446 return e.takeError(); 447 448 PrecompSource *precompSrc = *e; 449 if (precompSrc->tpiMap.empty()) 450 return Error::success(); 451 452 assert(precomp.getStartTypeIndex() == TypeIndex::FirstNonSimpleIndex); 453 assert(precomp.getTypesCount() <= precompSrc->tpiMap.size()); 454 // Use the previously remapped index map from the precompiled headers. 455 indexMapStorage.append(precompSrc->tpiMap.begin(), 456 precompSrc->tpiMap.begin() + precomp.getTypesCount()); 457 return Error::success(); 458 } 459 460 Error UsePrecompSource::mergeDebugT(TypeMerger *m) { 461 // This object was compiled with /Yu, so process the corresponding 462 // precompiled headers object (/Yc) first. Some type indices in the current 463 // object are referencing data in the precompiled headers object, so we need 464 // both to be loaded. 465 if (Error e = 466 mergeInPrecompHeaderObj(file, indexMapStorage, precompDependency)) 467 return e; 468 469 return TpiSource::mergeDebugT(m); 470 } 471 472 uint32_t TpiSource::countTypeServerPDBs() { 473 return TypeServerSource::mappings.size(); 474 } 475 476 uint32_t TpiSource::countPrecompObjs() { 477 return PrecompSource::mappings.size(); 478 } 479 480 void TpiSource::clear() { 481 gc.clear(); 482 TypeServerSource::mappings.clear(); 483 PrecompSource::mappings.clear(); 484 } 485