DebugObjectManagerPlugin.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  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() {}
  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. auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
  244. if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
  245. return std::move(Err);
  246. }
  247. if (!HasDwarfSection) {
  248. LLVM_DEBUG(dbgs() << "Aborting debug registration for LinkGraph \""
  249. << DebugObj->Buffer->getBufferIdentifier()
  250. << "\": input object contains no debug info\n");
  251. return nullptr;
  252. }
  253. return std::move(DebugObj);
  254. }
  255. Expected<std::unique_ptr<DebugObject>>
  256. ELFDebugObject::Create(MemoryBufferRef Buffer, JITLinkContext &Ctx,
  257. ExecutionSession &ES) {
  258. unsigned char Class, Endian;
  259. std::tie(Class, Endian) = getElfArchType(Buffer.getBuffer());
  260. if (Class == ELF::ELFCLASS32) {
  261. if (Endian == ELF::ELFDATA2LSB)
  262. return CreateArchType<ELF32LE>(Buffer, Ctx.getMemoryManager(),
  263. Ctx.getJITLinkDylib(), ES);
  264. if (Endian == ELF::ELFDATA2MSB)
  265. return CreateArchType<ELF32BE>(Buffer, Ctx.getMemoryManager(),
  266. Ctx.getJITLinkDylib(), ES);
  267. return nullptr;
  268. }
  269. if (Class == ELF::ELFCLASS64) {
  270. if (Endian == ELF::ELFDATA2LSB)
  271. return CreateArchType<ELF64LE>(Buffer, Ctx.getMemoryManager(),
  272. Ctx.getJITLinkDylib(), ES);
  273. if (Endian == ELF::ELFDATA2MSB)
  274. return CreateArchType<ELF64BE>(Buffer, Ctx.getMemoryManager(),
  275. Ctx.getJITLinkDylib(), ES);
  276. return nullptr;
  277. }
  278. return nullptr;
  279. }
  280. Expected<SimpleSegmentAlloc> ELFDebugObject::finalizeWorkingMemory() {
  281. LLVM_DEBUG({
  282. dbgs() << "Section load-addresses in debug object for \""
  283. << Buffer->getBufferIdentifier() << "\":\n";
  284. for (const auto &KV : Sections)
  285. KV.second->dump(dbgs(), KV.first());
  286. });
  287. // TODO: This works, but what actual alignment requirements do we have?
  288. unsigned PageSize = sys::Process::getPageSizeEstimate();
  289. size_t Size = Buffer->getBufferSize();
  290. // Allocate working memory for debug object in read-only segment.
  291. auto Alloc = SimpleSegmentAlloc::Create(
  292. MemMgr, JD, {{MemProt::Read, {Size, Align(PageSize)}}});
  293. if (!Alloc)
  294. return Alloc;
  295. // Initialize working memory with a copy of our object buffer.
  296. auto SegInfo = Alloc->getSegInfo(MemProt::Read);
  297. memcpy(SegInfo.WorkingMem.data(), Buffer->getBufferStart(), Size);
  298. Buffer.reset();
  299. return Alloc;
  300. }
  301. void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name,
  302. SectionRange TargetMem) {
  303. if (auto *DebugObjSection = getSection(Name))
  304. DebugObjSection->setTargetMemoryRange(TargetMem);
  305. }
  306. template <typename ELFT>
  307. Error ELFDebugObject::recordSection(
  308. StringRef Name, std::unique_ptr<ELFDebugObjectSection<ELFT>> Section) {
  309. if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))
  310. return Err;
  311. auto ItInserted = Sections.try_emplace(Name, std::move(Section));
  312. if (!ItInserted.second)
  313. return make_error<StringError>("Duplicate section",
  314. inconvertibleErrorCode());
  315. return Error::success();
  316. }
  317. DebugObjectSection *ELFDebugObject::getSection(StringRef Name) {
  318. auto It = Sections.find(Name);
  319. return It == Sections.end() ? nullptr : It->second.get();
  320. }
  321. /// Creates a debug object based on the input object file from
  322. /// ObjectLinkingLayerJITLinkContext.
  323. ///
  324. static Expected<std::unique_ptr<DebugObject>>
  325. createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
  326. JITLinkContext &Ctx, MemoryBufferRef ObjBuffer) {
  327. switch (G.getTargetTriple().getObjectFormat()) {
  328. case Triple::ELF:
  329. return ELFDebugObject::Create(ObjBuffer, Ctx, ES);
  330. default:
  331. // TODO: Once we add support for other formats, we might want to split this
  332. // into multiple files.
  333. return nullptr;
  334. }
  335. }
  336. DebugObjectManagerPlugin::DebugObjectManagerPlugin(
  337. ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
  338. : ES(ES), Target(std::move(Target)) {}
  339. DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
  340. void DebugObjectManagerPlugin::notifyMaterializing(
  341. MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
  342. MemoryBufferRef ObjBuffer) {
  343. std::lock_guard<std::mutex> Lock(PendingObjsLock);
  344. assert(PendingObjs.count(&MR) == 0 &&
  345. "Cannot have more than one pending debug object per "
  346. "MaterializationResponsibility");
  347. if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
  348. // Not all link artifacts allow debugging.
  349. if (*DebugObj != nullptr)
  350. PendingObjs[&MR] = std::move(*DebugObj);
  351. } else {
  352. ES.reportError(DebugObj.takeError());
  353. }
  354. }
  355. void DebugObjectManagerPlugin::modifyPassConfig(
  356. MaterializationResponsibility &MR, LinkGraph &G,
  357. PassConfiguration &PassConfig) {
  358. // Not all link artifacts have associated debug objects.
  359. std::lock_guard<std::mutex> Lock(PendingObjsLock);
  360. auto It = PendingObjs.find(&MR);
  361. if (It == PendingObjs.end())
  362. return;
  363. DebugObject &DebugObj = *It->second;
  364. if (DebugObj.has(Requirement::ReportFinalSectionLoadAddresses)) {
  365. PassConfig.PostAllocationPasses.push_back(
  366. [&DebugObj](LinkGraph &Graph) -> Error {
  367. for (const Section &GraphSection : Graph.sections())
  368. DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
  369. SectionRange(GraphSection));
  370. return Error::success();
  371. });
  372. }
  373. }
  374. Error DebugObjectManagerPlugin::notifyEmitted(
  375. MaterializationResponsibility &MR) {
  376. std::lock_guard<std::mutex> Lock(PendingObjsLock);
  377. auto It = PendingObjs.find(&MR);
  378. if (It == PendingObjs.end())
  379. return Error::success();
  380. // During finalization the debug object is registered with the target.
  381. // Materialization must wait for this process to finish. Otherwise we might
  382. // start running code before the debugger processed the corresponding debug
  383. // info.
  384. std::promise<MSVCPError> FinalizePromise;
  385. std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future();
  386. It->second->finalizeAsync(
  387. [this, &FinalizePromise, &MR](Expected<ExecutorAddrRange> TargetMem) {
  388. // Any failure here will fail materialization.
  389. if (!TargetMem) {
  390. FinalizePromise.set_value(TargetMem.takeError());
  391. return;
  392. }
  393. if (Error Err = Target->registerDebugObject(*TargetMem)) {
  394. FinalizePromise.set_value(std::move(Err));
  395. return;
  396. }
  397. // Once our tracking info is updated, notifyEmitted() can return and
  398. // finish materialization.
  399. FinalizePromise.set_value(MR.withResourceKeyDo([&](ResourceKey K) {
  400. assert(PendingObjs.count(&MR) && "We still hold PendingObjsLock");
  401. std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
  402. RegisteredObjs[K].push_back(std::move(PendingObjs[&MR]));
  403. PendingObjs.erase(&MR);
  404. }));
  405. });
  406. return FinalizeErr.get();
  407. }
  408. Error DebugObjectManagerPlugin::notifyFailed(
  409. MaterializationResponsibility &MR) {
  410. std::lock_guard<std::mutex> Lock(PendingObjsLock);
  411. PendingObjs.erase(&MR);
  412. return Error::success();
  413. }
  414. void DebugObjectManagerPlugin::notifyTransferringResources(ResourceKey DstKey,
  415. ResourceKey SrcKey) {
  416. // Debug objects are stored by ResourceKey only after registration.
  417. // Thus, pending objects don't need to be updated here.
  418. std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
  419. auto SrcIt = RegisteredObjs.find(SrcKey);
  420. if (SrcIt != RegisteredObjs.end()) {
  421. // Resources from distinct MaterializationResponsibilitys can get merged
  422. // after emission, so we can have multiple debug objects per resource key.
  423. for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
  424. RegisteredObjs[DstKey].push_back(std::move(DebugObj));
  425. RegisteredObjs.erase(SrcIt);
  426. }
  427. }
  428. Error DebugObjectManagerPlugin::notifyRemovingResources(ResourceKey Key) {
  429. // Removing the resource for a pending object fails materialization, so they
  430. // get cleaned up in the notifyFailed() handler.
  431. std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
  432. RegisteredObjs.erase(Key);
  433. // TODO: Implement unregister notifications.
  434. return Error::success();
  435. }
  436. } // namespace orc
  437. } // namespace llvm