DebugObjectManagerPlugin.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. //===------- DebugObjectManagerPlugin.cpp - JITLink debug objects ---------===//
  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. // FIXME: Update Plugin to poke the debug object into a new JITLink section,
  10. // rather than creating a new allocation.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
  14. #include "llvm/ADT/ArrayRef.h"
  15. #include "llvm/ADT/StringMap.h"
  16. #include "llvm/ADT/StringRef.h"
  17. #include "llvm/BinaryFormat/ELF.h"
  18. #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
  19. #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
  20. #include "llvm/ExecutionEngine/JITSymbol.h"
  21. #include "llvm/Object/ELFObjectFile.h"
  22. #include "llvm/Object/ObjectFile.h"
  23. #include "llvm/Support/Errc.h"
  24. #include "llvm/Support/MSVCErrorWorkarounds.h"
  25. #include "llvm/Support/MemoryBuffer.h"
  26. #include "llvm/Support/Process.h"
  27. #include "llvm/Support/raw_ostream.h"
  28. #include <set>
  29. #define DEBUG_TYPE "orc"
  30. using namespace llvm::jitlink;
  31. using namespace llvm::object;
  32. namespace llvm {
  33. namespace orc {
  34. class DebugObjectSection {
  35. public:
  36. virtual void setTargetMemoryRange(SectionRange Range) = 0;
  37. virtual void dump(raw_ostream &OS, StringRef Name) {}
  38. virtual ~DebugObjectSection() = default;
  39. };
  40. template <typename ELFT>
  41. class ELFDebugObjectSection : public DebugObjectSection {
  42. public:
  43. // BinaryFormat ELF is not meant as a mutable format. We can only make changes
  44. // that don't invalidate the file structure.
  45. ELFDebugObjectSection(const typename ELFT::Shdr *Header)
  46. : Header(const_cast<typename ELFT::Shdr *>(Header)) {}
  47. void setTargetMemoryRange(SectionRange Range) override;
  48. void dump(raw_ostream &OS, StringRef Name) override;
  49. Error validateInBounds(StringRef Buffer, const char *Name) const;
  50. private:
  51. typename ELFT::Shdr *Header;
  52. bool isTextOrDataSection() const;
  53. };
  54. template <typename ELFT>
  55. void ELFDebugObjectSection<ELFT>::setTargetMemoryRange(SectionRange Range) {
  56. // Only patch load-addresses for executable and data sections.
  57. if (isTextOrDataSection())
  58. Header->sh_addr =
  59. static_cast<typename ELFT::uint>(Range.getStart().getValue());
  60. }
  61. template <typename ELFT>
  62. bool ELFDebugObjectSection<ELFT>::isTextOrDataSection() const {
  63. switch (Header->sh_type) {
  64. case ELF::SHT_PROGBITS:
  65. case ELF::SHT_X86_64_UNWIND:
  66. return Header->sh_flags & (ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
  67. }
  68. return false;
  69. }
  70. template <typename ELFT>
  71. Error ELFDebugObjectSection<ELFT>::validateInBounds(StringRef Buffer,
  72. const char *Name) const {
  73. const uint8_t *Start = Buffer.bytes_begin();
  74. const uint8_t *End = Buffer.bytes_end();
  75. const uint8_t *HeaderPtr = reinterpret_cast<uint8_t *>(Header);
  76. if (HeaderPtr < Start || HeaderPtr + sizeof(typename ELFT::Shdr) > End)
  77. return make_error<StringError>(
  78. formatv("{0} section header at {1:x16} not within bounds of the "
  79. "given debug object buffer [{2:x16} - {3:x16}]",
  80. Name, &Header->sh_addr, Start, End),
  81. inconvertibleErrorCode());
  82. if (Header->sh_offset + Header->sh_size > Buffer.size())
  83. return make_error<StringError>(
  84. formatv("{0} section data [{1:x16} - {2:x16}] not within bounds of "
  85. "the given debug object buffer [{3:x16} - {4:x16}]",
  86. Name, Start + Header->sh_offset,
  87. Start + Header->sh_offset + Header->sh_size, Start, End),
  88. inconvertibleErrorCode());
  89. return Error::success();
  90. }
  91. template <typename ELFT>
  92. void ELFDebugObjectSection<ELFT>::dump(raw_ostream &OS, StringRef Name) {
  93. if (auto Addr = static_cast<JITTargetAddress>(Header->sh_addr)) {
  94. OS << formatv(" {0:x16} {1}\n", Addr, Name);
  95. } else {
  96. OS << formatv(" {0}\n", Name);
  97. }
  98. }
  99. enum class Requirement {
  100. // Request final target memory load-addresses for all sections.
  101. ReportFinalSectionLoadAddresses,
  102. };
  103. /// The plugin creates a debug object from when JITLink starts processing the
  104. /// corresponding LinkGraph. It provides access to the pass configuration of
  105. /// the LinkGraph and calls the finalization function, once the resulting link
  106. /// artifact was emitted.
  107. ///
  108. class DebugObject {
  109. public:
  110. DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
  111. ExecutionSession &ES)
  112. : MemMgr(MemMgr), JD(JD), ES(ES) {}
  113. void set(Requirement Req) { Reqs.insert(Req); }
  114. bool has(Requirement Req) const { return Reqs.count(Req) > 0; }
  115. using FinalizeContinuation = std::function<void(Expected<ExecutorAddrRange>)>;
  116. void finalizeAsync(FinalizeContinuation OnFinalize);
  117. virtual ~DebugObject() {
  118. if (Alloc) {
  119. std::vector<FinalizedAlloc> Allocs;
  120. Allocs.push_back(std::move(Alloc));
  121. if (Error Err = MemMgr.deallocate(std::move(Allocs)))
  122. ES.reportError(std::move(Err));
  123. }
  124. }
  125. virtual void reportSectionTargetMemoryRange(StringRef Name,
  126. SectionRange TargetMem) {}
  127. protected:
  128. using InFlightAlloc = JITLinkMemoryManager::InFlightAlloc;
  129. using FinalizedAlloc = JITLinkMemoryManager::FinalizedAlloc;
  130. virtual Expected<SimpleSegmentAlloc> finalizeWorkingMemory() = 0;
  131. JITLinkMemoryManager &MemMgr;
  132. const JITLinkDylib *JD = nullptr;
  133. private:
  134. ExecutionSession &ES;
  135. std::set<Requirement> Reqs;
  136. FinalizedAlloc Alloc;
  137. };
  138. // Finalize working memory and take ownership of the resulting allocation. Start
  139. // copying memory over to the target and pass on the result once we're done.
  140. // Ownership of the allocation remains with us for the rest of our lifetime.
  141. void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) {
  142. assert(!Alloc && "Cannot finalize more than once");
  143. if (auto SimpleSegAlloc = finalizeWorkingMemory()) {
  144. auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read);
  145. ExecutorAddrRange DebugObjRange(ExecutorAddr(ROSeg.Addr),
  146. ExecutorAddrDiff(ROSeg.WorkingMem.size()));
  147. SimpleSegAlloc->finalize(
  148. [this, DebugObjRange,
  149. OnFinalize = std::move(OnFinalize)](Expected<FinalizedAlloc> FA) {
  150. if (FA) {
  151. Alloc = std::move(*FA);
  152. OnFinalize(DebugObjRange);
  153. } else
  154. OnFinalize(FA.takeError());
  155. });
  156. } else
  157. OnFinalize(SimpleSegAlloc.takeError());
  158. }
  159. /// The current implementation of ELFDebugObject replicates the approach used in
  160. /// RuntimeDyld: It patches executable and data section headers in the given
  161. /// object buffer with load-addresses of their corresponding sections in target
  162. /// memory.
  163. ///
  164. class ELFDebugObject : public DebugObject {
  165. public:
  166. static Expected<std::unique_ptr<DebugObject>>
  167. Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, ExecutionSession &ES);
  168. void reportSectionTargetMemoryRange(StringRef Name,
  169. SectionRange TargetMem) override;
  170. StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); }
  171. protected:
  172. Expected<SimpleSegmentAlloc> finalizeWorkingMemory() override;
  173. template <typename ELFT>
  174. Error recordSection(StringRef Name,
  175. std::unique_ptr<ELFDebugObjectSection<ELFT>> Section);
  176. DebugObjectSection *getSection(StringRef Name);
  177. private:
  178. template <typename ELFT>
  179. static Expected<std::unique_ptr<ELFDebugObject>>
  180. CreateArchType(MemoryBufferRef Buffer, JITLinkMemoryManager &MemMgr,
  181. const JITLinkDylib *JD, ExecutionSession &ES);
  182. static std::unique_ptr<WritableMemoryBuffer>
  183. CopyBuffer(MemoryBufferRef Buffer, Error &Err);
  184. ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,
  185. JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
  186. ExecutionSession &ES)
  187. : DebugObject(MemMgr, JD, ES), Buffer(std::move(Buffer)) {
  188. set(Requirement::ReportFinalSectionLoadAddresses);
  189. }
  190. std::unique_ptr<WritableMemoryBuffer> Buffer;
  191. StringMap<std::unique_ptr<DebugObjectSection>> Sections;
  192. };
  193. static const std::set<StringRef> DwarfSectionNames = {
  194. #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
  195. ELF_NAME,
  196. #include "llvm/BinaryFormat/Dwarf.def"
  197. #undef HANDLE_DWARF_SECTION
  198. };
  199. static bool isDwarfSection(StringRef SectionName) {
  200. return DwarfSectionNames.count(SectionName) == 1;
  201. }
  202. std::unique_ptr<WritableMemoryBuffer>
  203. ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) {
  204. ErrorAsOutParameter _(&Err);
  205. size_t Size = Buffer.getBufferSize();
  206. StringRef Name = Buffer.getBufferIdentifier();
  207. if (auto Copy = WritableMemoryBuffer::getNewUninitMemBuffer(Size, Name)) {
  208. memcpy(Copy->getBufferStart(), Buffer.getBufferStart(), Size);
  209. return Copy;
  210. }
  211. Err = errorCodeToError(make_error_code(errc::not_enough_memory));
  212. return nullptr;
  213. }
  214. template <typename ELFT>
  215. Expected<std::unique_ptr<ELFDebugObject>>
  216. ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
  217. JITLinkMemoryManager &MemMgr,
  218. const JITLinkDylib *JD, ExecutionSession &ES) {
  219. using SectionHeader = typename ELFT::Shdr;
  220. Error Err = Error::success();
  221. std::unique_ptr<ELFDebugObject> DebugObj(
  222. new ELFDebugObject(CopyBuffer(Buffer, Err), MemMgr, JD, ES));
  223. if (Err)
  224. return std::move(Err);
  225. Expected<ELFFile<ELFT>> ObjRef = ELFFile<ELFT>::create(DebugObj->getBuffer());
  226. if (!ObjRef)
  227. return ObjRef.takeError();
  228. // TODO: Add support for other architectures.
  229. uint16_t TargetMachineArch = ObjRef->getHeader().e_machine;
  230. if (TargetMachineArch != ELF::EM_X86_64)
  231. return nullptr;
  232. Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
  233. if (!Sections)
  234. return Sections.takeError();
  235. bool HasDwarfSection = false;
  236. for (const SectionHeader &Header : *Sections) {
  237. Expected<StringRef> Name = ObjRef->getSectionName(Header);
  238. if (!Name)
  239. return Name.takeError();
  240. if (Name->empty())
  241. continue;
  242. HasDwarfSection |= isDwarfSection(*Name);
  243. if (!(Header.sh_flags & ELF::SHF_ALLOC))
  244. continue;
  245. auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
  246. if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
  247. return std::move(Err);
  248. }
  249. if (!HasDwarfSection) {
  250. LLVM_DEBUG(dbgs() << "Aborting debug registration for LinkGraph \""
  251. << DebugObj->Buffer->getBufferIdentifier()
  252. << "\": input object contains no debug info\n");
  253. return nullptr;
  254. }
  255. return std::move(DebugObj);
  256. }
  257. Expected<std::unique_ptr<DebugObject>>
  258. ELFDebugObject::Create(MemoryBufferRef Buffer, JITLinkContext &Ctx,
  259. ExecutionSession &ES) {
  260. unsigned char Class, Endian;
  261. std::tie(Class, Endian) = getElfArchType(Buffer.getBuffer());
  262. if (Class == ELF::ELFCLASS32) {
  263. if (Endian == ELF::ELFDATA2LSB)
  264. return CreateArchType<ELF32LE>(Buffer, Ctx.getMemoryManager(),
  265. Ctx.getJITLinkDylib(), ES);
  266. if (Endian == ELF::ELFDATA2MSB)
  267. return CreateArchType<ELF32BE>(Buffer, Ctx.getMemoryManager(),
  268. Ctx.getJITLinkDylib(), ES);
  269. return nullptr;
  270. }
  271. if (Class == ELF::ELFCLASS64) {
  272. if (Endian == ELF::ELFDATA2LSB)
  273. return CreateArchType<ELF64LE>(Buffer, Ctx.getMemoryManager(),
  274. Ctx.getJITLinkDylib(), ES);
  275. if (Endian == ELF::ELFDATA2MSB)
  276. return CreateArchType<ELF64BE>(Buffer, Ctx.getMemoryManager(),
  277. Ctx.getJITLinkDylib(), ES);
  278. return nullptr;
  279. }
  280. return nullptr;
  281. }
  282. Expected<SimpleSegmentAlloc> ELFDebugObject::finalizeWorkingMemory() {
  283. LLVM_DEBUG({
  284. dbgs() << "Section load-addresses in debug object for \""
  285. << Buffer->getBufferIdentifier() << "\":\n";
  286. for (const auto &KV : Sections)
  287. KV.second->dump(dbgs(), KV.first());
  288. });
  289. // TODO: This works, but what actual alignment requirements do we have?
  290. unsigned PageSize = sys::Process::getPageSizeEstimate();
  291. size_t Size = Buffer->getBufferSize();
  292. // Allocate working memory for debug object in read-only segment.
  293. auto Alloc = SimpleSegmentAlloc::Create(
  294. MemMgr, JD, {{MemProt::Read, {Size, Align(PageSize)}}});
  295. if (!Alloc)
  296. return Alloc;
  297. // Initialize working memory with a copy of our object buffer.
  298. auto SegInfo = Alloc->getSegInfo(MemProt::Read);
  299. memcpy(SegInfo.WorkingMem.data(), Buffer->getBufferStart(), Size);
  300. Buffer.reset();
  301. return Alloc;
  302. }
  303. void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name,
  304. SectionRange TargetMem) {
  305. if (auto *DebugObjSection = getSection(Name))
  306. DebugObjSection->setTargetMemoryRange(TargetMem);
  307. }
  308. template <typename ELFT>
  309. Error ELFDebugObject::recordSection(
  310. StringRef Name, std::unique_ptr<ELFDebugObjectSection<ELFT>> Section) {
  311. if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))
  312. return Err;
  313. auto ItInserted = Sections.try_emplace(Name, std::move(Section));
  314. if (!ItInserted.second)
  315. return make_error<StringError>("In " + Buffer->getBufferIdentifier() +
  316. ", encountered duplicate section \"" +
  317. Name + "\" while building debug object",
  318. inconvertibleErrorCode());
  319. return Error::success();
  320. }
  321. DebugObjectSection *ELFDebugObject::getSection(StringRef Name) {
  322. auto It = Sections.find(Name);
  323. return It == Sections.end() ? nullptr : It->second.get();
  324. }
  325. /// Creates a debug object based on the input object file from
  326. /// ObjectLinkingLayerJITLinkContext.
  327. ///
  328. static Expected<std::unique_ptr<DebugObject>>
  329. createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
  330. JITLinkContext &Ctx, MemoryBufferRef ObjBuffer) {
  331. switch (G.getTargetTriple().getObjectFormat()) {
  332. case Triple::ELF:
  333. return ELFDebugObject::Create(ObjBuffer, Ctx, ES);
  334. default:
  335. // TODO: Once we add support for other formats, we might want to split this
  336. // into multiple files.
  337. return nullptr;
  338. }
  339. }
  340. DebugObjectManagerPlugin::DebugObjectManagerPlugin(
  341. ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
  342. : ES(ES), Target(std::move(Target)) {}
  343. DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
  344. void DebugObjectManagerPlugin::notifyMaterializing(
  345. MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
  346. MemoryBufferRef ObjBuffer) {
  347. std::lock_guard<std::mutex> Lock(PendingObjsLock);
  348. assert(PendingObjs.count(&MR) == 0 &&
  349. "Cannot have more than one pending debug object per "
  350. "MaterializationResponsibility");
  351. if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
  352. // Not all link artifacts allow debugging.
  353. if (*DebugObj != nullptr)
  354. PendingObjs[&MR] = std::move(*DebugObj);
  355. } else {
  356. ES.reportError(DebugObj.takeError());
  357. }
  358. }
  359. void DebugObjectManagerPlugin::modifyPassConfig(
  360. MaterializationResponsibility &MR, LinkGraph &G,
  361. PassConfiguration &PassConfig) {
  362. // Not all link artifacts have associated debug objects.
  363. std::lock_guard<std::mutex> Lock(PendingObjsLock);
  364. auto It = PendingObjs.find(&MR);
  365. if (It == PendingObjs.end())
  366. return;
  367. DebugObject &DebugObj = *It->second;
  368. if (DebugObj.has(Requirement::ReportFinalSectionLoadAddresses)) {
  369. PassConfig.PostAllocationPasses.push_back(
  370. [&DebugObj](LinkGraph &Graph) -> Error {
  371. for (const Section &GraphSection : Graph.sections())
  372. DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
  373. SectionRange(GraphSection));
  374. return Error::success();
  375. });
  376. }
  377. }
  378. Error DebugObjectManagerPlugin::notifyEmitted(
  379. MaterializationResponsibility &MR) {
  380. std::lock_guard<std::mutex> Lock(PendingObjsLock);
  381. auto It = PendingObjs.find(&MR);
  382. if (It == PendingObjs.end())
  383. return Error::success();
  384. // During finalization the debug object is registered with the target.
  385. // Materialization must wait for this process to finish. Otherwise we might
  386. // start running code before the debugger processed the corresponding debug
  387. // info.
  388. std::promise<MSVCPError> FinalizePromise;
  389. std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future();
  390. It->second->finalizeAsync(
  391. [this, &FinalizePromise, &MR](Expected<ExecutorAddrRange> TargetMem) {
  392. // Any failure here will fail materialization.
  393. if (!TargetMem) {
  394. FinalizePromise.set_value(TargetMem.takeError());
  395. return;
  396. }
  397. if (Error Err = Target->registerDebugObject(*TargetMem)) {
  398. FinalizePromise.set_value(std::move(Err));
  399. return;
  400. }
  401. // Once our tracking info is updated, notifyEmitted() can return and
  402. // finish materialization.
  403. FinalizePromise.set_value(MR.withResourceKeyDo([&](ResourceKey K) {
  404. assert(PendingObjs.count(&MR) && "We still hold PendingObjsLock");
  405. std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
  406. RegisteredObjs[K].push_back(std::move(PendingObjs[&MR]));
  407. PendingObjs.erase(&MR);
  408. }));
  409. });
  410. return FinalizeErr.get();
  411. }
  412. Error DebugObjectManagerPlugin::notifyFailed(
  413. MaterializationResponsibility &MR) {
  414. std::lock_guard<std::mutex> Lock(PendingObjsLock);
  415. PendingObjs.erase(&MR);
  416. return Error::success();
  417. }
  418. void DebugObjectManagerPlugin::notifyTransferringResources(JITDylib &JD,
  419. ResourceKey DstKey,
  420. ResourceKey SrcKey) {
  421. // Debug objects are stored by ResourceKey only after registration.
  422. // Thus, pending objects don't need to be updated here.
  423. std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
  424. auto SrcIt = RegisteredObjs.find(SrcKey);
  425. if (SrcIt != RegisteredObjs.end()) {
  426. // Resources from distinct MaterializationResponsibilitys can get merged
  427. // after emission, so we can have multiple debug objects per resource key.
  428. for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
  429. RegisteredObjs[DstKey].push_back(std::move(DebugObj));
  430. RegisteredObjs.erase(SrcIt);
  431. }
  432. }
  433. Error DebugObjectManagerPlugin::notifyRemovingResources(JITDylib &JD,
  434. ResourceKey Key) {
  435. // Removing the resource for a pending object fails materialization, so they
  436. // get cleaned up in the notifyFailed() handler.
  437. std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
  438. RegisteredObjs.erase(Key);
  439. // TODO: Implement unregister notifications.
  440. return Error::success();
  441. }
  442. } // namespace orc
  443. } // namespace llvm