AMDGPU: Mark test as XFAIL in expensive_checks builds
[llvm-project.git] / llvm / lib / ExecutionEngine / Orc / DebugObjectManagerPlugin.cpp
blob180905346d561013377366ba7f62726212229a50
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.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/BinaryFormat/ELF.h"
20 #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
21 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
22 #include "llvm/Object/ELFObjectFile.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"
29 #include <set>
31 #define DEBUG_TYPE "orc"
33 using namespace llvm::jitlink;
34 using namespace llvm::object;
36 namespace llvm {
37 namespace orc {
39 class DebugObjectSection {
40 public:
41 virtual void setTargetMemoryRange(SectionRange Range) = 0;
42 virtual void dump(raw_ostream &OS, StringRef Name) {}
43 virtual ~DebugObjectSection() = default;
46 template <typename ELFT>
47 class ELFDebugObjectSection : public DebugObjectSection {
48 public:
49 // BinaryFormat ELF is not meant as a mutable format. We can only make changes
50 // that don't invalidate the file structure.
51 ELFDebugObjectSection(const typename ELFT::Shdr *Header)
52 : Header(const_cast<typename ELFT::Shdr *>(Header)) {}
54 void setTargetMemoryRange(SectionRange Range) override;
55 void dump(raw_ostream &OS, StringRef Name) override;
57 Error validateInBounds(StringRef Buffer, const char *Name) const;
59 private:
60 typename ELFT::Shdr *Header;
63 template <typename ELFT>
64 void ELFDebugObjectSection<ELFT>::setTargetMemoryRange(SectionRange Range) {
65 // All recorded sections are candidates for load-address patching.
66 Header->sh_addr =
67 static_cast<typename ELFT::uint>(Range.getStart().getValue());
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();
92 template <typename ELFT>
93 void ELFDebugObjectSection<ELFT>::dump(raw_ostream &OS, StringRef Name) {
94 if (uint64_t Addr = Header->sh_addr) {
95 OS << formatv(" {0:x16} {1}\n", Addr, Name);
96 } else {
97 OS << formatv(" {0}\n", Name);
101 enum DebugObjectFlags : int {
102 // Request final target memory load-addresses for all sections.
103 ReportFinalSectionLoadAddresses = 1 << 0,
105 // We found sections with debug information when processing the input object.
106 HasDebugSections = 1 << 1,
109 /// The plugin creates a debug object from when JITLink starts processing the
110 /// corresponding LinkGraph. It provides access to the pass configuration of
111 /// the LinkGraph and calls the finalization function, once the resulting link
112 /// artifact was emitted.
114 class DebugObject {
115 public:
116 DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
117 ExecutionSession &ES)
118 : MemMgr(MemMgr), JD(JD), ES(ES), Flags(DebugObjectFlags{}) {}
120 bool hasFlags(DebugObjectFlags F) const { return Flags & F; }
121 void setFlags(DebugObjectFlags F) {
122 Flags = static_cast<DebugObjectFlags>(Flags | F);
124 void clearFlags(DebugObjectFlags F) {
125 Flags = static_cast<DebugObjectFlags>(Flags & ~F);
128 using FinalizeContinuation = std::function<void(Expected<ExecutorAddrRange>)>;
130 void finalizeAsync(FinalizeContinuation OnFinalize);
132 virtual ~DebugObject() {
133 if (Alloc) {
134 std::vector<FinalizedAlloc> Allocs;
135 Allocs.push_back(std::move(Alloc));
136 if (Error Err = MemMgr.deallocate(std::move(Allocs)))
137 ES.reportError(std::move(Err));
141 virtual void reportSectionTargetMemoryRange(StringRef Name,
142 SectionRange TargetMem) {}
144 protected:
145 using InFlightAlloc = JITLinkMemoryManager::InFlightAlloc;
146 using FinalizedAlloc = JITLinkMemoryManager::FinalizedAlloc;
148 virtual Expected<SimpleSegmentAlloc> finalizeWorkingMemory() = 0;
150 JITLinkMemoryManager &MemMgr;
151 const JITLinkDylib *JD = nullptr;
152 ExecutionSession &ES;
154 private:
155 DebugObjectFlags Flags;
156 FinalizedAlloc Alloc;
159 // Finalize working memory and take ownership of the resulting allocation. Start
160 // copying memory over to the target and pass on the result once we're done.
161 // Ownership of the allocation remains with us for the rest of our lifetime.
162 void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) {
163 assert(!Alloc && "Cannot finalize more than once");
165 if (auto SimpleSegAlloc = finalizeWorkingMemory()) {
166 auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read);
167 ExecutorAddrRange DebugObjRange(ROSeg.Addr, ROSeg.WorkingMem.size());
168 SimpleSegAlloc->finalize(
169 [this, DebugObjRange,
170 OnFinalize = std::move(OnFinalize)](Expected<FinalizedAlloc> FA) {
171 if (FA) {
172 Alloc = std::move(*FA);
173 OnFinalize(DebugObjRange);
174 } else
175 OnFinalize(FA.takeError());
177 } else
178 OnFinalize(SimpleSegAlloc.takeError());
181 /// The current implementation of ELFDebugObject replicates the approach used in
182 /// RuntimeDyld: It patches executable and data section headers in the given
183 /// object buffer with load-addresses of their corresponding sections in target
184 /// memory.
186 class ELFDebugObject : public DebugObject {
187 public:
188 static Expected<std::unique_ptr<DebugObject>>
189 Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, ExecutionSession &ES);
191 void reportSectionTargetMemoryRange(StringRef Name,
192 SectionRange TargetMem) override;
194 StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); }
196 protected:
197 Expected<SimpleSegmentAlloc> finalizeWorkingMemory() override;
199 template <typename ELFT>
200 Error recordSection(StringRef Name,
201 std::unique_ptr<ELFDebugObjectSection<ELFT>> Section);
202 DebugObjectSection *getSection(StringRef Name);
204 private:
205 template <typename ELFT>
206 static Expected<std::unique_ptr<ELFDebugObject>>
207 CreateArchType(MemoryBufferRef Buffer, JITLinkMemoryManager &MemMgr,
208 const JITLinkDylib *JD, ExecutionSession &ES);
210 static std::unique_ptr<WritableMemoryBuffer>
211 CopyBuffer(MemoryBufferRef Buffer, Error &Err);
213 ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,
214 JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
215 ExecutionSession &ES)
216 : DebugObject(MemMgr, JD, ES), Buffer(std::move(Buffer)) {
217 setFlags(ReportFinalSectionLoadAddresses);
220 std::unique_ptr<WritableMemoryBuffer> Buffer;
221 StringMap<std::unique_ptr<DebugObjectSection>> Sections;
224 static const std::set<StringRef> DwarfSectionNames = {
225 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
226 ELF_NAME,
227 #include "llvm/BinaryFormat/Dwarf.def"
228 #undef HANDLE_DWARF_SECTION
231 static bool isDwarfSection(StringRef SectionName) {
232 return DwarfSectionNames.count(SectionName) == 1;
235 std::unique_ptr<WritableMemoryBuffer>
236 ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) {
237 ErrorAsOutParameter _(Err);
238 size_t Size = Buffer.getBufferSize();
239 StringRef Name = Buffer.getBufferIdentifier();
240 if (auto Copy = WritableMemoryBuffer::getNewUninitMemBuffer(Size, Name)) {
241 memcpy(Copy->getBufferStart(), Buffer.getBufferStart(), Size);
242 return Copy;
245 Err = errorCodeToError(make_error_code(errc::not_enough_memory));
246 return nullptr;
249 template <typename ELFT>
250 Expected<std::unique_ptr<ELFDebugObject>>
251 ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
252 JITLinkMemoryManager &MemMgr,
253 const JITLinkDylib *JD, ExecutionSession &ES) {
254 using SectionHeader = typename ELFT::Shdr;
256 Error Err = Error::success();
257 std::unique_ptr<ELFDebugObject> DebugObj(
258 new ELFDebugObject(CopyBuffer(Buffer, Err), MemMgr, JD, ES));
259 if (Err)
260 return std::move(Err);
262 Expected<ELFFile<ELFT>> ObjRef = ELFFile<ELFT>::create(DebugObj->getBuffer());
263 if (!ObjRef)
264 return ObjRef.takeError();
266 Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
267 if (!Sections)
268 return Sections.takeError();
270 for (const SectionHeader &Header : *Sections) {
271 Expected<StringRef> Name = ObjRef->getSectionName(Header);
272 if (!Name)
273 return Name.takeError();
274 if (Name->empty())
275 continue;
276 if (isDwarfSection(*Name))
277 DebugObj->setFlags(HasDebugSections);
279 // Only record text and data sections (i.e. no bss, comments, rel, etc.)
280 if (Header.sh_type != ELF::SHT_PROGBITS &&
281 Header.sh_type != ELF::SHT_X86_64_UNWIND)
282 continue;
283 if (!(Header.sh_flags & ELF::SHF_ALLOC))
284 continue;
286 auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
287 if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
288 return std::move(Err);
291 return std::move(DebugObj);
294 Expected<std::unique_ptr<DebugObject>>
295 ELFDebugObject::Create(MemoryBufferRef Buffer, JITLinkContext &Ctx,
296 ExecutionSession &ES) {
297 unsigned char Class, Endian;
298 std::tie(Class, Endian) = getElfArchType(Buffer.getBuffer());
300 if (Class == ELF::ELFCLASS32) {
301 if (Endian == ELF::ELFDATA2LSB)
302 return CreateArchType<ELF32LE>(Buffer, Ctx.getMemoryManager(),
303 Ctx.getJITLinkDylib(), ES);
304 if (Endian == ELF::ELFDATA2MSB)
305 return CreateArchType<ELF32BE>(Buffer, Ctx.getMemoryManager(),
306 Ctx.getJITLinkDylib(), ES);
307 return nullptr;
309 if (Class == ELF::ELFCLASS64) {
310 if (Endian == ELF::ELFDATA2LSB)
311 return CreateArchType<ELF64LE>(Buffer, Ctx.getMemoryManager(),
312 Ctx.getJITLinkDylib(), ES);
313 if (Endian == ELF::ELFDATA2MSB)
314 return CreateArchType<ELF64BE>(Buffer, Ctx.getMemoryManager(),
315 Ctx.getJITLinkDylib(), ES);
316 return nullptr;
318 return nullptr;
321 Expected<SimpleSegmentAlloc> ELFDebugObject::finalizeWorkingMemory() {
322 LLVM_DEBUG({
323 dbgs() << "Section load-addresses in debug object for \""
324 << Buffer->getBufferIdentifier() << "\":\n";
325 for (const auto &KV : Sections)
326 KV.second->dump(dbgs(), KV.first());
329 // TODO: This works, but what actual alignment requirements do we have?
330 unsigned PageSize = sys::Process::getPageSizeEstimate();
331 size_t Size = Buffer->getBufferSize();
333 // Allocate working memory for debug object in read-only segment.
334 auto Alloc =
335 SimpleSegmentAlloc::Create(MemMgr, ES.getSymbolStringPool(), JD,
336 {{MemProt::Read, {Size, Align(PageSize)}}});
337 if (!Alloc)
338 return Alloc;
340 // Initialize working memory with a copy of our object buffer.
341 auto SegInfo = Alloc->getSegInfo(MemProt::Read);
342 memcpy(SegInfo.WorkingMem.data(), Buffer->getBufferStart(), Size);
343 Buffer.reset();
345 return Alloc;
348 void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name,
349 SectionRange TargetMem) {
350 if (auto *DebugObjSection = getSection(Name))
351 DebugObjSection->setTargetMemoryRange(TargetMem);
354 template <typename ELFT>
355 Error ELFDebugObject::recordSection(
356 StringRef Name, std::unique_ptr<ELFDebugObjectSection<ELFT>> Section) {
357 if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))
358 return Err;
359 bool Inserted = Sections.try_emplace(Name, std::move(Section)).second;
360 if (!Inserted)
361 LLVM_DEBUG(dbgs() << "Skipping debug registration for section '" << Name
362 << "' in object " << Buffer->getBufferIdentifier()
363 << " (duplicate name)\n");
364 return Error::success();
367 DebugObjectSection *ELFDebugObject::getSection(StringRef Name) {
368 auto It = Sections.find(Name);
369 return It == Sections.end() ? nullptr : It->second.get();
372 /// Creates a debug object based on the input object file from
373 /// ObjectLinkingLayerJITLinkContext.
375 static Expected<std::unique_ptr<DebugObject>>
376 createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
377 JITLinkContext &Ctx, MemoryBufferRef ObjBuffer) {
378 switch (G.getTargetTriple().getObjectFormat()) {
379 case Triple::ELF:
380 return ELFDebugObject::Create(ObjBuffer, Ctx, ES);
382 default:
383 // TODO: Once we add support for other formats, we might want to split this
384 // into multiple files.
385 return nullptr;
389 DebugObjectManagerPlugin::DebugObjectManagerPlugin(
390 ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target,
391 bool RequireDebugSections, bool AutoRegisterCode)
392 : ES(ES), Target(std::move(Target)),
393 RequireDebugSections(RequireDebugSections),
394 AutoRegisterCode(AutoRegisterCode) {}
396 DebugObjectManagerPlugin::DebugObjectManagerPlugin(
397 ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
398 : DebugObjectManagerPlugin(ES, std::move(Target), true, true) {}
400 DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
402 void DebugObjectManagerPlugin::notifyMaterializing(
403 MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
404 MemoryBufferRef ObjBuffer) {
405 std::lock_guard<std::mutex> Lock(PendingObjsLock);
406 assert(PendingObjs.count(&MR) == 0 &&
407 "Cannot have more than one pending debug object per "
408 "MaterializationResponsibility");
410 if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
411 // Not all link artifacts allow debugging.
412 if (*DebugObj == nullptr)
413 return;
414 if (RequireDebugSections && !(**DebugObj).hasFlags(HasDebugSections)) {
415 LLVM_DEBUG(dbgs() << "Skipping debug registration for LinkGraph '"
416 << G.getName() << "': no debug info\n");
417 return;
419 PendingObjs[&MR] = std::move(*DebugObj);
420 } else {
421 ES.reportError(DebugObj.takeError());
425 void DebugObjectManagerPlugin::modifyPassConfig(
426 MaterializationResponsibility &MR, LinkGraph &G,
427 PassConfiguration &PassConfig) {
428 // Not all link artifacts have associated debug objects.
429 std::lock_guard<std::mutex> Lock(PendingObjsLock);
430 auto It = PendingObjs.find(&MR);
431 if (It == PendingObjs.end())
432 return;
434 DebugObject &DebugObj = *It->second;
435 if (DebugObj.hasFlags(ReportFinalSectionLoadAddresses)) {
436 PassConfig.PostAllocationPasses.push_back(
437 [&DebugObj](LinkGraph &Graph) -> Error {
438 for (const Section &GraphSection : Graph.sections())
439 DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
440 SectionRange(GraphSection));
441 return Error::success();
446 Error DebugObjectManagerPlugin::notifyEmitted(
447 MaterializationResponsibility &MR) {
448 std::lock_guard<std::mutex> Lock(PendingObjsLock);
449 auto It = PendingObjs.find(&MR);
450 if (It == PendingObjs.end())
451 return Error::success();
453 // During finalization the debug object is registered with the target.
454 // Materialization must wait for this process to finish. Otherwise we might
455 // start running code before the debugger processed the corresponding debug
456 // info.
457 std::promise<MSVCPError> FinalizePromise;
458 std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future();
460 It->second->finalizeAsync(
461 [this, &FinalizePromise, &MR](Expected<ExecutorAddrRange> TargetMem) {
462 // Any failure here will fail materialization.
463 if (!TargetMem) {
464 FinalizePromise.set_value(TargetMem.takeError());
465 return;
467 if (Error Err =
468 Target->registerDebugObject(*TargetMem, AutoRegisterCode)) {
469 FinalizePromise.set_value(std::move(Err));
470 return;
473 // Once our tracking info is updated, notifyEmitted() can return and
474 // finish materialization.
475 FinalizePromise.set_value(MR.withResourceKeyDo([&](ResourceKey K) {
476 assert(PendingObjs.count(&MR) && "We still hold PendingObjsLock");
477 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
478 RegisteredObjs[K].push_back(std::move(PendingObjs[&MR]));
479 PendingObjs.erase(&MR);
480 }));
483 return FinalizeErr.get();
486 Error DebugObjectManagerPlugin::notifyFailed(
487 MaterializationResponsibility &MR) {
488 std::lock_guard<std::mutex> Lock(PendingObjsLock);
489 PendingObjs.erase(&MR);
490 return Error::success();
493 void DebugObjectManagerPlugin::notifyTransferringResources(JITDylib &JD,
494 ResourceKey DstKey,
495 ResourceKey SrcKey) {
496 // Debug objects are stored by ResourceKey only after registration.
497 // Thus, pending objects don't need to be updated here.
498 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
499 auto SrcIt = RegisteredObjs.find(SrcKey);
500 if (SrcIt != RegisteredObjs.end()) {
501 // Resources from distinct MaterializationResponsibilitys can get merged
502 // after emission, so we can have multiple debug objects per resource key.
503 for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
504 RegisteredObjs[DstKey].push_back(std::move(DebugObj));
505 RegisteredObjs.erase(SrcIt);
509 Error DebugObjectManagerPlugin::notifyRemovingResources(JITDylib &JD,
510 ResourceKey Key) {
511 // Removing the resource for a pending object fails materialization, so they
512 // get cleaned up in the notifyFailed() handler.
513 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
514 RegisteredObjs.erase(Key);
516 // TODO: Implement unregister notifications.
517 return Error::success();
520 } // namespace orc
521 } // namespace llvm