DebugTypes.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. #include "DebugTypes.h"
  9. #include "Driver.h"
  10. #include "InputFiles.h"
  11. #include "lld/Common/ErrorHandler.h"
  12. #include "llvm/DebugInfo/CodeView/TypeRecord.h"
  13. #include "llvm/DebugInfo/PDB/GenericError.h"
  14. #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
  15. #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
  16. #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
  17. #include "llvm/Support/Path.h"
  18. using namespace llvm;
  19. using namespace llvm::codeview;
  20. namespace lld {
  21. namespace coff {
  22. namespace {
  23. // The TypeServerSource class represents a PDB type server, a file referenced by
  24. // OBJ files compiled with MSVC /Zi. A single PDB can be shared by several OBJ
  25. // files, therefore there must be only once instance per OBJ lot. The file path
  26. // is discovered from the dependent OBJ's debug type stream. The
  27. // TypeServerSource object is then queued and loaded by the COFF Driver. The
  28. // debug type stream for such PDB files will be merged first in the final PDB,
  29. // before any dependent OBJ.
  30. class TypeServerSource : public TpiSource {
  31. public:
  32. explicit TypeServerSource(MemoryBufferRef m, llvm::pdb::NativeSession *s)
  33. : TpiSource(PDB, nullptr), session(s), mb(m) {}
  34. // Queue a PDB type server for loading in the COFF Driver
  35. static void enqueue(const ObjFile *dependentFile,
  36. const TypeServer2Record &ts);
  37. // Create an instance
  38. static Expected<TypeServerSource *> getInstance(MemoryBufferRef m);
  39. // Fetch the PDB instance loaded for a corresponding dependent OBJ.
  40. static Expected<TypeServerSource *>
  41. findFromFile(const ObjFile *dependentFile);
  42. static std::map<std::string, std::pair<std::string, TypeServerSource *>>
  43. instances;
  44. // The interface to the PDB (if it was opened successfully)
  45. std::unique_ptr<llvm::pdb::NativeSession> session;
  46. private:
  47. MemoryBufferRef mb;
  48. };
  49. // This class represents the debug type stream of an OBJ file that depends on a
  50. // PDB type server (see TypeServerSource).
  51. class UseTypeServerSource : public TpiSource {
  52. public:
  53. UseTypeServerSource(const ObjFile *f, const TypeServer2Record *ts)
  54. : TpiSource(UsingPDB, f), typeServerDependency(*ts) {}
  55. // Information about the PDB type server dependency, that needs to be loaded
  56. // in before merging this OBJ.
  57. TypeServer2Record typeServerDependency;
  58. };
  59. // This class represents the debug type stream of a Microsoft precompiled
  60. // headers OBJ (PCH OBJ). This OBJ kind needs to be merged first in the output
  61. // PDB, before any other OBJs that depend on this. Note that only MSVC generate
  62. // such files, clang does not.
  63. class PrecompSource : public TpiSource {
  64. public:
  65. PrecompSource(const ObjFile *f) : TpiSource(PCH, f) {}
  66. };
  67. // This class represents the debug type stream of an OBJ file that depends on a
  68. // Microsoft precompiled headers OBJ (see PrecompSource).
  69. class UsePrecompSource : public TpiSource {
  70. public:
  71. UsePrecompSource(const ObjFile *f, const PrecompRecord *precomp)
  72. : TpiSource(UsingPCH, f), precompDependency(*precomp) {}
  73. // Information about the Precomp OBJ dependency, that needs to be loaded in
  74. // before merging this OBJ.
  75. PrecompRecord precompDependency;
  76. };
  77. } // namespace
  78. static std::vector<std::unique_ptr<TpiSource>> GC;
  79. TpiSource::TpiSource(TpiKind k, const ObjFile *f) : kind(k), file(f) {
  80. GC.push_back(std::unique_ptr<TpiSource>(this));
  81. }
  82. TpiSource *makeTpiSource(const ObjFile *f) {
  83. return new TpiSource(TpiSource::Regular, f);
  84. }
  85. TpiSource *makeUseTypeServerSource(const ObjFile *f,
  86. const TypeServer2Record *ts) {
  87. TypeServerSource::enqueue(f, *ts);
  88. return new UseTypeServerSource(f, ts);
  89. }
  90. TpiSource *makePrecompSource(const ObjFile *f) {
  91. return new PrecompSource(f);
  92. }
  93. TpiSource *makeUsePrecompSource(const ObjFile *f,
  94. const PrecompRecord *precomp) {
  95. return new UsePrecompSource(f, precomp);
  96. }
  97. template <>
  98. const PrecompRecord &retrieveDependencyInfo(const TpiSource *source) {
  99. assert(source->kind == TpiSource::UsingPCH);
  100. return ((const UsePrecompSource *)source)->precompDependency;
  101. }
  102. template <>
  103. const TypeServer2Record &retrieveDependencyInfo(const TpiSource *source) {
  104. assert(source->kind == TpiSource::UsingPDB);
  105. return ((const UseTypeServerSource *)source)->typeServerDependency;
  106. }
  107. std::map<std::string, std::pair<std::string, TypeServerSource *>>
  108. TypeServerSource::instances;
  109. // Make a PDB path assuming the PDB is in the same folder as the OBJ
  110. static std::string getPdbBaseName(const ObjFile *file, StringRef tSPath) {
  111. StringRef localPath =
  112. !file->parentName.empty() ? file->parentName : file->getName();
  113. SmallString<128> path = sys::path::parent_path(localPath);
  114. // Currently, type server PDBs are only created by MSVC cl, which only runs
  115. // on Windows, so we can assume type server paths are Windows style.
  116. sys::path::append(path, sys::path::filename(tSPath, sys::path::Style::windows));
  117. return path.str();
  118. }
  119. // The casing of the PDB path stamped in the OBJ can differ from the actual path
  120. // on disk. With this, we ensure to always use lowercase as a key for the
  121. // PDBInputFile::Instances map, at least on Windows.
  122. static std::string normalizePdbPath(StringRef path) {
  123. #if defined(_WIN32)
  124. return path.lower();
  125. #else // LINUX
  126. return path;
  127. #endif
  128. }
  129. // If existing, return the actual PDB path on disk.
  130. static Optional<std::string> findPdbPath(StringRef pdbPath,
  131. const ObjFile *dependentFile) {
  132. // Ensure the file exists before anything else. In some cases, if the path
  133. // points to a removable device, Driver::enqueuePath() would fail with an
  134. // error (EAGAIN, "resource unavailable try again") which we want to skip
  135. // silently.
  136. if (llvm::sys::fs::exists(pdbPath))
  137. return normalizePdbPath(pdbPath);
  138. std::string ret = getPdbBaseName(dependentFile, pdbPath);
  139. if (llvm::sys::fs::exists(ret))
  140. return normalizePdbPath(ret);
  141. return None;
  142. }
  143. // Fetch the PDB instance that was already loaded by the COFF Driver.
  144. Expected<TypeServerSource *>
  145. TypeServerSource::findFromFile(const ObjFile *dependentFile) {
  146. const TypeServer2Record &ts =
  147. retrieveDependencyInfo<TypeServer2Record>(dependentFile->debugTypesObj);
  148. Optional<std::string> p = findPdbPath(ts.Name, dependentFile);
  149. if (!p)
  150. return createFileError(ts.Name, errorCodeToError(std::error_code(
  151. ENOENT, std::generic_category())));
  152. auto it = TypeServerSource::instances.find(*p);
  153. // The PDB file exists on disk, at this point we expect it to have been
  154. // inserted in the map by TypeServerSource::loadPDB()
  155. assert(it != TypeServerSource::instances.end());
  156. std::pair<std::string, TypeServerSource *> &pdb = it->second;
  157. if (!pdb.second)
  158. return createFileError(
  159. *p, createStringError(inconvertibleErrorCode(), pdb.first.c_str()));
  160. pdb::PDBFile &pdbFile = (pdb.second)->session->getPDBFile();
  161. pdb::InfoStream &info = cantFail(pdbFile.getPDBInfoStream());
  162. // Just because a file with a matching name was found doesn't mean it can be
  163. // used. The GUID must match between the PDB header and the OBJ
  164. // TypeServer2 record. The 'Age' is used by MSVC incremental compilation.
  165. if (info.getGuid() != ts.getGuid())
  166. return createFileError(
  167. ts.Name,
  168. make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date));
  169. return pdb.second;
  170. }
  171. // FIXME: Temporary interface until PDBLinker::maybeMergeTypeServerPDB() is
  172. // moved here.
  173. Expected<llvm::pdb::NativeSession *> findTypeServerSource(const ObjFile *f) {
  174. Expected<TypeServerSource *> ts = TypeServerSource::findFromFile(f);
  175. if (!ts)
  176. return ts.takeError();
  177. return ts.get()->session.get();
  178. }
  179. // Queue a PDB type server for loading in the COFF Driver
  180. void TypeServerSource::enqueue(const ObjFile *dependentFile,
  181. const TypeServer2Record &ts) {
  182. // Start by finding where the PDB is located (either the record path or next
  183. // to the OBJ file)
  184. Optional<std::string> p = findPdbPath(ts.Name, dependentFile);
  185. if (!p)
  186. return;
  187. auto it = TypeServerSource::instances.emplace(
  188. *p, std::pair<std::string, TypeServerSource *>{});
  189. if (!it.second)
  190. return; // another OBJ already scheduled this PDB for load
  191. driver->enqueuePath(*p, false, false);
  192. }
  193. // Create an instance of TypeServerSource or an error string if the PDB couldn't
  194. // be loaded. The error message will be displayed later, when the referring OBJ
  195. // will be merged in. NOTE - a PDB load failure is not a link error: some
  196. // debug info will simply be missing from the final PDB - that is the default
  197. // accepted behavior.
  198. void loadTypeServerSource(llvm::MemoryBufferRef m) {
  199. std::string path = normalizePdbPath(m.getBufferIdentifier());
  200. Expected<TypeServerSource *> ts = TypeServerSource::getInstance(m);
  201. if (!ts)
  202. TypeServerSource::instances[path] = {toString(ts.takeError()), nullptr};
  203. else
  204. TypeServerSource::instances[path] = {{}, *ts};
  205. }
  206. Expected<TypeServerSource *> TypeServerSource::getInstance(MemoryBufferRef m) {
  207. std::unique_ptr<llvm::pdb::IPDBSession> iSession;
  208. Error err = pdb::NativeSession::createFromPdb(
  209. MemoryBuffer::getMemBuffer(m, false), iSession);
  210. if (err)
  211. return std::move(err);
  212. std::unique_ptr<llvm::pdb::NativeSession> session(
  213. static_cast<pdb::NativeSession *>(iSession.release()));
  214. pdb::PDBFile &pdbFile = session->getPDBFile();
  215. Expected<pdb::InfoStream &> info = pdbFile.getPDBInfoStream();
  216. // All PDB Files should have an Info stream.
  217. if (!info)
  218. return info.takeError();
  219. return new TypeServerSource(m, session.release());
  220. }
  221. } // namespace coff
  222. } // namespace lld