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