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