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 26using namespace llvm; 27using namespace llvm::codeview; 28using namespace lld; 29using namespace lld::coff; 30 31namespace { 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. 39class TypeServerSource : public TpiSource { 40public: 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). 68class UseTypeServerSource : public TpiSource { 69public: 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. 85class PrecompSource : public TpiSource { 86public: 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). 109class UsePrecompSource : public TpiSource { 110public: 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 123static std::vector<TpiSource *> gc; 124 125TpiSource::TpiSource(TpiKind k, ObjFile *f) : kind(k), file(f) { 126 gc.push_back(this); 127} 128 129// Vtable key method. 130TpiSource::~TpiSource() = default; 131 132TpiSource *lld::coff::makeTpiSource(ObjFile *file) { 133 return make<TpiSource>(TpiSource::Regular, file); 134} 135 136TpiSource *lld::coff::makeTypeServerSource(PDBInputFile *pdbInputFile) { 137 return make<TypeServerSource>(pdbInputFile); 138} 139 140TpiSource *lld::coff::makeUseTypeServerSource(ObjFile *file, 141 TypeServer2Record ts) { 142 return make<UseTypeServerSource>(file, ts); 143} 144 145TpiSource *lld::coff::makePrecompSource(ObjFile *file) { 146 return make<PrecompSource>(file); 147} 148 149TpiSource *lld::coff::makeUsePrecompSource(ObjFile *file, 150 PrecompRecord precomp) { 151 return make<UsePrecompSource>(file, precomp); 152} 153 154void TpiSource::forEachSource(llvm::function_ref<void(TpiSource *)> fn) { 155 for_each(gc, fn); 156} 157 158std::map<codeview::GUID, TypeServerSource *> TypeServerSource::mappings; 159 160std::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. 166static 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 178static 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 189static ArrayRef<GloballyHashedType> 190getHashesFromDebugH(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. 199Expected<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 // When dealing with PCH.OBJ, some indices were already merged. 206 unsigned nbHeadIndices = indexMap->tpiMap.size(); 207 208 if (config->debugGHashes) { 209 ArrayRef<GloballyHashedType> hashes; 210 std::vector<GloballyHashedType> ownedHashes; 211 if (Optional<ArrayRef<uint8_t>> debugH = getDebugH(file)) 212 hashes = getHashesFromDebugH(*debugH); 213 else { 214 ownedHashes = GloballyHashedType::hashTypes(types); 215 hashes = ownedHashes; 216 } 217 218 if (auto err = mergeTypeAndIdRecords(m->globalIDTable, m->globalTypeTable, 219 indexMap->tpiMap, types, hashes, 220 file->pchSignature)) 221 fatal("codeview::mergeTypeAndIdRecords failed: " + 222 toString(std::move(err))); 223 } else { 224 if (auto err = 225 mergeTypeAndIdRecords(m->idTable, m->typeTable, indexMap->tpiMap, 226 types, file->pchSignature)) 227 fatal("codeview::mergeTypeAndIdRecords failed: " + 228 toString(std::move(err))); 229 } 230 231 if (config->showSummary) { 232 // Count how many times we saw each type record in our input. This 233 // calculation requires a second pass over the type records to classify each 234 // record as a type or index. This is slow, but this code executes when 235 // collecting statistics. 236 m->tpiCounts.resize(m->getTypeTable().size()); 237 m->ipiCounts.resize(m->getIDTable().size()); 238 uint32_t srcIdx = nbHeadIndices; 239 for (CVType &ty : types) { 240 TypeIndex dstIdx = indexMap->tpiMap[srcIdx++]; 241 // Type merging may fail, so a complex source type may become the simple 242 // NotTranslated type, which cannot be used as an array index. 243 if (dstIdx.isSimple()) 244 continue; 245 SmallVectorImpl<uint32_t> &counts = 246 isIdRecord(ty.kind()) ? m->ipiCounts : m->tpiCounts; 247 ++counts[dstIdx.toArrayIndex()]; 248 } 249 } 250 251 return indexMap; 252} 253 254// Merge types from a type server PDB. 255Expected<const CVIndexMap *> TypeServerSource::mergeDebugT(TypeMerger *m, 256 CVIndexMap *) { 257 pdb::PDBFile &pdbFile = pdbInputFile->session->getPDBFile(); 258 Expected<pdb::TpiStream &> expectedTpi = pdbFile.getPDBTpiStream(); 259 if (auto e = expectedTpi.takeError()) 260 fatal("Type server does not have TPI stream: " + toString(std::move(e))); 261 pdb::TpiStream *maybeIpi = nullptr; 262 if (pdbFile.hasPDBIpiStream()) { 263 Expected<pdb::TpiStream &> expectedIpi = pdbFile.getPDBIpiStream(); 264 if (auto e = expectedIpi.takeError()) 265 fatal("Error getting type server IPI stream: " + toString(std::move(e))); 266 maybeIpi = &*expectedIpi; 267 } 268 269 if (config->debugGHashes) { 270 // PDBs do not actually store global hashes, so when merging a type server 271 // PDB we have to synthesize global hashes. To do this, we first synthesize 272 // global hashes for the TPI stream, since it is independent, then we 273 // synthesize hashes for the IPI stream, using the hashes for the TPI stream 274 // as inputs. 275 auto tpiHashes = GloballyHashedType::hashTypes(expectedTpi->typeArray()); 276 Optional<uint32_t> endPrecomp; 277 // Merge TPI first, because the IPI stream will reference type indices. 278 if (auto err = 279 mergeTypeRecords(m->globalTypeTable, tsIndexMap.tpiMap, 280 expectedTpi->typeArray(), tpiHashes, endPrecomp)) 281 fatal("codeview::mergeTypeRecords failed: " + toString(std::move(err))); 282 283 // Merge IPI. 284 if (maybeIpi) { 285 auto ipiHashes = 286 GloballyHashedType::hashIds(maybeIpi->typeArray(), tpiHashes); 287 if (auto err = mergeIdRecords(m->globalIDTable, tsIndexMap.tpiMap, 288 tsIndexMap.ipiMap, maybeIpi->typeArray(), 289 ipiHashes)) 290 fatal("codeview::mergeIdRecords failed: " + toString(std::move(err))); 291 } 292 } else { 293 // Merge TPI first, because the IPI stream will reference type indices. 294 if (auto err = mergeTypeRecords(m->typeTable, tsIndexMap.tpiMap, 295 expectedTpi->typeArray())) 296 fatal("codeview::mergeTypeRecords failed: " + toString(std::move(err))); 297 298 // Merge IPI. 299 if (maybeIpi) { 300 if (auto err = mergeIdRecords(m->idTable, tsIndexMap.tpiMap, 301 tsIndexMap.ipiMap, maybeIpi->typeArray())) 302 fatal("codeview::mergeIdRecords failed: " + toString(std::move(err))); 303 } 304 } 305 306 if (config->showSummary) { 307 // Count how many times we saw each type record in our input. If a 308 // destination type index is present in the source to destination type index 309 // map, that means we saw it once in the input. Add it to our histogram. 310 m->tpiCounts.resize(m->getTypeTable().size()); 311 m->ipiCounts.resize(m->getIDTable().size()); 312 for (TypeIndex ti : tsIndexMap.tpiMap) 313 if (!ti.isSimple()) 314 ++m->tpiCounts[ti.toArrayIndex()]; 315 for (TypeIndex ti : tsIndexMap.ipiMap) 316 if (!ti.isSimple()) 317 ++m->ipiCounts[ti.toArrayIndex()]; 318 } 319 320 return &tsIndexMap; 321} 322 323Expected<const CVIndexMap *> 324UseTypeServerSource::mergeDebugT(TypeMerger *m, CVIndexMap *indexMap) { 325 const codeview::GUID &tsId = typeServerDependency.getGuid(); 326 StringRef tsPath = typeServerDependency.getName(); 327 328 TypeServerSource *tsSrc; 329 auto it = TypeServerSource::mappings.find(tsId); 330 if (it != TypeServerSource::mappings.end()) { 331 tsSrc = it->second; 332 } else { 333 // The file failed to load, lookup by name 334 PDBInputFile *pdb = PDBInputFile::findFromRecordPath(tsPath, file); 335 if (!pdb) 336 return createFileError(tsPath, errorCodeToError(std::error_code( 337 ENOENT, std::generic_category()))); 338 // If an error occurred during loading, throw it now 339 if (pdb->loadErr && *pdb->loadErr) 340 return createFileError(tsPath, std::move(*pdb->loadErr)); 341 342 tsSrc = (TypeServerSource *)pdb->debugTypesObj; 343 } 344 345 pdb::PDBFile &pdbSession = tsSrc->pdbInputFile->session->getPDBFile(); 346 auto expectedInfo = pdbSession.getPDBInfoStream(); 347 if (!expectedInfo) 348 return &tsSrc->tsIndexMap; 349 350 // Just because a file with a matching name was found and it was an actual 351 // PDB file doesn't mean it matches. For it to match the InfoStream's GUID 352 // must match the GUID specified in the TypeServer2 record. 353 if (expectedInfo->getGuid() != typeServerDependency.getGuid()) 354 return createFileError( 355 tsPath, 356 make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date)); 357 358 return &tsSrc->tsIndexMap; 359} 360 361static bool equalsPath(StringRef path1, StringRef path2) { 362#if defined(_WIN32) 363 return path1.equals_lower(path2); 364#else 365 return path1.equals(path2); 366#endif 367} 368 369// Find by name an OBJ provided on the command line 370static PrecompSource *findObjByName(StringRef fileNameOnly) { 371 SmallString<128> currentPath; 372 for (auto kv : PrecompSource::mappings) { 373 StringRef currentFileName = sys::path::filename(kv.second->file->getName(), 374 sys::path::Style::windows); 375 376 // Compare based solely on the file name (link.exe behavior) 377 if (equalsPath(currentFileName, fileNameOnly)) 378 return kv.second; 379 } 380 return nullptr; 381} 382 383Expected<const CVIndexMap *> findPrecompMap(ObjFile *file, PrecompRecord &pr) { 384 // Cross-compile warning: given that Clang doesn't generate LF_PRECOMP 385 // records, we assume the OBJ comes from a Windows build of cl.exe. Thusly, 386 // the paths embedded in the OBJs are in the Windows format. 387 SmallString<128> prFileName = 388 sys::path::filename(pr.getPrecompFilePath(), sys::path::Style::windows); 389 390 PrecompSource *precomp; 391 auto it = PrecompSource::mappings.find(pr.getSignature()); 392 if (it != PrecompSource::mappings.end()) { 393 precomp = it->second; 394 } else { 395 // Lookup by name 396 precomp = findObjByName(prFileName); 397 } 398 399 if (!precomp) 400 return createFileError( 401 prFileName, 402 make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch)); 403 404 if (pr.getSignature() != file->pchSignature) 405 return createFileError( 406 toString(file), 407 make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch)); 408 409 if (pr.getSignature() != *precomp->file->pchSignature) 410 return createFileError( 411 toString(precomp->file), 412 make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch)); 413 414 return &precomp->precompIndexMap; 415} 416 417/// Merges a precompiled headers TPI map into the current TPI map. The 418/// precompiled headers object will also be loaded and remapped in the 419/// process. 420static Expected<const CVIndexMap *> 421mergeInPrecompHeaderObj(ObjFile *file, CVIndexMap *indexMap, 422 PrecompRecord &precomp) { 423 auto e = findPrecompMap(file, precomp); 424 if (!e) 425 return e.takeError(); 426 427 const CVIndexMap *precompIndexMap = *e; 428 assert(precompIndexMap->isPrecompiledTypeMap); 429 430 if (precompIndexMap->tpiMap.empty()) 431 return precompIndexMap; 432 433 assert(precomp.getStartTypeIndex() == TypeIndex::FirstNonSimpleIndex); 434 assert(precomp.getTypesCount() <= precompIndexMap->tpiMap.size()); 435 // Use the previously remapped index map from the precompiled headers. 436 indexMap->tpiMap.append(precompIndexMap->tpiMap.begin(), 437 precompIndexMap->tpiMap.begin() + 438 precomp.getTypesCount()); 439 return indexMap; 440} 441 442Expected<const CVIndexMap *> 443UsePrecompSource::mergeDebugT(TypeMerger *m, CVIndexMap *indexMap) { 444 // This object was compiled with /Yu, so process the corresponding 445 // precompiled headers object (/Yc) first. Some type indices in the current 446 // object are referencing data in the precompiled headers object, so we need 447 // both to be loaded. 448 auto e = mergeInPrecompHeaderObj(file, indexMap, precompDependency); 449 if (!e) 450 return e.takeError(); 451 452 // Drop LF_PRECOMP record from the input stream, as it has been replaced 453 // with the precompiled headers Type stream in the mergeInPrecompHeaderObj() 454 // call above. Note that we can't just call Types.drop_front(), as we 455 // explicitly want to rebase the stream. 456 CVTypeArray types; 457 BinaryStreamReader reader(file->debugTypes, support::little); 458 cantFail(reader.readArray(types, reader.getLength())); 459 auto firstType = types.begin(); 460 file->debugTypes = file->debugTypes.drop_front(firstType->RecordData.size()); 461 462 return TpiSource::mergeDebugT(m, indexMap); 463} 464 465Expected<const CVIndexMap *> PrecompSource::mergeDebugT(TypeMerger *m, 466 CVIndexMap *) { 467 // Note that we're not using the provided CVIndexMap. Instead, we use our 468 // local one. Precompiled headers objects need to save the index map for 469 // further reference by other objects which use the precompiled headers. 470 return TpiSource::mergeDebugT(m, &precompIndexMap); 471} 472 473uint32_t TpiSource::countTypeServerPDBs() { 474 return TypeServerSource::mappings.size(); 475} 476 477uint32_t TpiSource::countPrecompObjs() { 478 return PrecompSource::mappings.size(); 479} 480 481void TpiSource::clear() { 482 gc.clear(); 483 TypeServerSource::mappings.clear(); 484 PrecompSource::mappings.clear(); 485} 486