1 //===------- DebugObjectManagerPlugin.cpp - JITLink debug objects ---------===//
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
7 //===----------------------------------------------------------------------===//
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/ExecutionEngine/JITSymbol.h"
23 #include "llvm/Object/ELFObjectFile.h"
24 #include "llvm/Object/ObjectFile.h"
25 #include "llvm/Support/Errc.h"
26 #include "llvm/Support/MSVCErrorWorkarounds.h"
27 #include "llvm/Support/MemoryBuffer.h"
28 #include "llvm/Support/Process.h"
29 #include "llvm/Support/raw_ostream.h"
33 #define DEBUG_TYPE "orc"
35 using namespace llvm::jitlink
;
36 using namespace llvm::object
;
41 class DebugObjectSection
{
43 virtual void setTargetMemoryRange(SectionRange Range
) = 0;
44 virtual void dump(raw_ostream
&OS
, StringRef Name
) {}
45 virtual ~DebugObjectSection() = default;
48 template <typename ELFT
>
49 class ELFDebugObjectSection
: public DebugObjectSection
{
51 // BinaryFormat ELF is not meant as a mutable format. We can only make changes
52 // that don't invalidate the file structure.
53 ELFDebugObjectSection(const typename
ELFT::Shdr
*Header
)
54 : Header(const_cast<typename
ELFT::Shdr
*>(Header
)) {}
56 void setTargetMemoryRange(SectionRange Range
) override
;
57 void dump(raw_ostream
&OS
, StringRef Name
) override
;
59 Error
validateInBounds(StringRef Buffer
, const char *Name
) const;
62 typename
ELFT::Shdr
*Header
;
65 template <typename ELFT
>
66 void ELFDebugObjectSection
<ELFT
>::setTargetMemoryRange(SectionRange Range
) {
67 // All recorded sections are candidates for load-address patching.
69 static_cast<typename
ELFT::uint
>(Range
.getStart().getValue());
72 template <typename ELFT
>
73 Error ELFDebugObjectSection
<ELFT
>::validateInBounds(StringRef Buffer
,
74 const char *Name
) const {
75 const uint8_t *Start
= Buffer
.bytes_begin();
76 const uint8_t *End
= Buffer
.bytes_end();
77 const uint8_t *HeaderPtr
= reinterpret_cast<uint8_t *>(Header
);
78 if (HeaderPtr
< Start
|| HeaderPtr
+ sizeof(typename
ELFT::Shdr
) > End
)
79 return make_error
<StringError
>(
80 formatv("{0} section header at {1:x16} not within bounds of the "
81 "given debug object buffer [{2:x16} - {3:x16}]",
82 Name
, &Header
->sh_addr
, Start
, End
),
83 inconvertibleErrorCode());
84 if (Header
->sh_offset
+ Header
->sh_size
> Buffer
.size())
85 return make_error
<StringError
>(
86 formatv("{0} section data [{1:x16} - {2:x16}] not within bounds of "
87 "the given debug object buffer [{3:x16} - {4:x16}]",
88 Name
, Start
+ Header
->sh_offset
,
89 Start
+ Header
->sh_offset
+ Header
->sh_size
, Start
, End
),
90 inconvertibleErrorCode());
91 return Error::success();
94 template <typename ELFT
>
95 void ELFDebugObjectSection
<ELFT
>::dump(raw_ostream
&OS
, StringRef Name
) {
96 if (uint64_t Addr
= Header
->sh_addr
) {
97 OS
<< formatv(" {0:x16} {1}\n", Addr
, Name
);
99 OS
<< formatv(" {0}\n", Name
);
103 enum DebugObjectFlags
: int {
104 // Request final target memory load-addresses for all sections.
105 ReportFinalSectionLoadAddresses
= 1 << 0,
107 // We found sections with debug information when processing the input object.
108 HasDebugSections
= 1 << 1,
111 /// The plugin creates a debug object from when JITLink starts processing the
112 /// corresponding LinkGraph. It provides access to the pass configuration of
113 /// the LinkGraph and calls the finalization function, once the resulting link
114 /// artifact was emitted.
118 DebugObject(JITLinkMemoryManager
&MemMgr
, const JITLinkDylib
*JD
,
119 ExecutionSession
&ES
)
120 : MemMgr(MemMgr
), JD(JD
), ES(ES
), Flags(DebugObjectFlags
{}) {}
122 bool hasFlags(DebugObjectFlags F
) const { return Flags
& F
; }
123 void setFlags(DebugObjectFlags F
) {
124 Flags
= static_cast<DebugObjectFlags
>(Flags
| F
);
126 void clearFlags(DebugObjectFlags F
) {
127 Flags
= static_cast<DebugObjectFlags
>(Flags
& ~F
);
130 using FinalizeContinuation
= std::function
<void(Expected
<ExecutorAddrRange
>)>;
132 void finalizeAsync(FinalizeContinuation OnFinalize
);
134 virtual ~DebugObject() {
136 std::vector
<FinalizedAlloc
> Allocs
;
137 Allocs
.push_back(std::move(Alloc
));
138 if (Error Err
= MemMgr
.deallocate(std::move(Allocs
)))
139 ES
.reportError(std::move(Err
));
143 virtual void reportSectionTargetMemoryRange(StringRef Name
,
144 SectionRange TargetMem
) {}
147 using InFlightAlloc
= JITLinkMemoryManager::InFlightAlloc
;
148 using FinalizedAlloc
= JITLinkMemoryManager::FinalizedAlloc
;
150 virtual Expected
<SimpleSegmentAlloc
> finalizeWorkingMemory() = 0;
152 JITLinkMemoryManager
&MemMgr
;
153 const JITLinkDylib
*JD
= nullptr;
156 ExecutionSession
&ES
;
157 DebugObjectFlags Flags
;
158 FinalizedAlloc Alloc
;
161 // Finalize working memory and take ownership of the resulting allocation. Start
162 // copying memory over to the target and pass on the result once we're done.
163 // Ownership of the allocation remains with us for the rest of our lifetime.
164 void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize
) {
165 assert(!Alloc
&& "Cannot finalize more than once");
167 if (auto SimpleSegAlloc
= finalizeWorkingMemory()) {
168 auto ROSeg
= SimpleSegAlloc
->getSegInfo(MemProt::Read
);
169 ExecutorAddrRange
DebugObjRange(ROSeg
.Addr
, ROSeg
.WorkingMem
.size());
170 SimpleSegAlloc
->finalize(
171 [this, DebugObjRange
,
172 OnFinalize
= std::move(OnFinalize
)](Expected
<FinalizedAlloc
> FA
) {
174 Alloc
= std::move(*FA
);
175 OnFinalize(DebugObjRange
);
177 OnFinalize(FA
.takeError());
180 OnFinalize(SimpleSegAlloc
.takeError());
183 /// The current implementation of ELFDebugObject replicates the approach used in
184 /// RuntimeDyld: It patches executable and data section headers in the given
185 /// object buffer with load-addresses of their corresponding sections in target
188 class ELFDebugObject
: public DebugObject
{
190 static Expected
<std::unique_ptr
<DebugObject
>>
191 Create(MemoryBufferRef Buffer
, JITLinkContext
&Ctx
, ExecutionSession
&ES
);
193 void reportSectionTargetMemoryRange(StringRef Name
,
194 SectionRange TargetMem
) override
;
196 StringRef
getBuffer() const { return Buffer
->getMemBufferRef().getBuffer(); }
199 Expected
<SimpleSegmentAlloc
> finalizeWorkingMemory() override
;
201 template <typename ELFT
>
202 Error
recordSection(StringRef Name
,
203 std::unique_ptr
<ELFDebugObjectSection
<ELFT
>> Section
);
204 DebugObjectSection
*getSection(StringRef Name
);
207 template <typename ELFT
>
208 static Expected
<std::unique_ptr
<ELFDebugObject
>>
209 CreateArchType(MemoryBufferRef Buffer
, JITLinkMemoryManager
&MemMgr
,
210 const JITLinkDylib
*JD
, ExecutionSession
&ES
);
212 static std::unique_ptr
<WritableMemoryBuffer
>
213 CopyBuffer(MemoryBufferRef Buffer
, Error
&Err
);
215 ELFDebugObject(std::unique_ptr
<WritableMemoryBuffer
> Buffer
,
216 JITLinkMemoryManager
&MemMgr
, const JITLinkDylib
*JD
,
217 ExecutionSession
&ES
)
218 : DebugObject(MemMgr
, JD
, ES
), Buffer(std::move(Buffer
)) {
219 setFlags(ReportFinalSectionLoadAddresses
);
222 std::unique_ptr
<WritableMemoryBuffer
> Buffer
;
223 StringMap
<std::unique_ptr
<DebugObjectSection
>> Sections
;
226 static const std::set
<StringRef
> DwarfSectionNames
= {
227 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
229 #include "llvm/BinaryFormat/Dwarf.def"
230 #undef HANDLE_DWARF_SECTION
233 static bool isDwarfSection(StringRef SectionName
) {
234 return DwarfSectionNames
.count(SectionName
) == 1;
237 std::unique_ptr
<WritableMemoryBuffer
>
238 ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer
, Error
&Err
) {
239 ErrorAsOutParameter
_(&Err
);
240 size_t Size
= Buffer
.getBufferSize();
241 StringRef Name
= Buffer
.getBufferIdentifier();
242 if (auto Copy
= WritableMemoryBuffer::getNewUninitMemBuffer(Size
, Name
)) {
243 memcpy(Copy
->getBufferStart(), Buffer
.getBufferStart(), Size
);
247 Err
= errorCodeToError(make_error_code(errc::not_enough_memory
));
251 template <typename ELFT
>
252 Expected
<std::unique_ptr
<ELFDebugObject
>>
253 ELFDebugObject::CreateArchType(MemoryBufferRef Buffer
,
254 JITLinkMemoryManager
&MemMgr
,
255 const JITLinkDylib
*JD
, ExecutionSession
&ES
) {
256 using SectionHeader
= typename
ELFT::Shdr
;
258 Error Err
= Error::success();
259 std::unique_ptr
<ELFDebugObject
> DebugObj(
260 new ELFDebugObject(CopyBuffer(Buffer
, Err
), MemMgr
, JD
, ES
));
262 return std::move(Err
);
264 Expected
<ELFFile
<ELFT
>> ObjRef
= ELFFile
<ELFT
>::create(DebugObj
->getBuffer());
266 return ObjRef
.takeError();
268 Expected
<ArrayRef
<SectionHeader
>> Sections
= ObjRef
->sections();
270 return Sections
.takeError();
272 for (const SectionHeader
&Header
: *Sections
) {
273 Expected
<StringRef
> Name
= ObjRef
->getSectionName(Header
);
275 return Name
.takeError();
278 if (isDwarfSection(*Name
))
279 DebugObj
->setFlags(HasDebugSections
);
281 // Only record text and data sections (i.e. no bss, comments, rel, etc.)
282 if (Header
.sh_type
!= ELF::SHT_PROGBITS
&&
283 Header
.sh_type
!= ELF::SHT_X86_64_UNWIND
)
285 if (!(Header
.sh_flags
& ELF::SHF_ALLOC
))
288 auto Wrapped
= std::make_unique
<ELFDebugObjectSection
<ELFT
>>(&Header
);
289 if (Error Err
= DebugObj
->recordSection(*Name
, std::move(Wrapped
)))
290 return std::move(Err
);
293 return std::move(DebugObj
);
296 Expected
<std::unique_ptr
<DebugObject
>>
297 ELFDebugObject::Create(MemoryBufferRef Buffer
, JITLinkContext
&Ctx
,
298 ExecutionSession
&ES
) {
299 unsigned char Class
, Endian
;
300 std::tie(Class
, Endian
) = getElfArchType(Buffer
.getBuffer());
302 if (Class
== ELF::ELFCLASS32
) {
303 if (Endian
== ELF::ELFDATA2LSB
)
304 return CreateArchType
<ELF32LE
>(Buffer
, Ctx
.getMemoryManager(),
305 Ctx
.getJITLinkDylib(), ES
);
306 if (Endian
== ELF::ELFDATA2MSB
)
307 return CreateArchType
<ELF32BE
>(Buffer
, Ctx
.getMemoryManager(),
308 Ctx
.getJITLinkDylib(), ES
);
311 if (Class
== ELF::ELFCLASS64
) {
312 if (Endian
== ELF::ELFDATA2LSB
)
313 return CreateArchType
<ELF64LE
>(Buffer
, Ctx
.getMemoryManager(),
314 Ctx
.getJITLinkDylib(), ES
);
315 if (Endian
== ELF::ELFDATA2MSB
)
316 return CreateArchType
<ELF64BE
>(Buffer
, Ctx
.getMemoryManager(),
317 Ctx
.getJITLinkDylib(), ES
);
323 Expected
<SimpleSegmentAlloc
> ELFDebugObject::finalizeWorkingMemory() {
325 dbgs() << "Section load-addresses in debug object for \""
326 << Buffer
->getBufferIdentifier() << "\":\n";
327 for (const auto &KV
: Sections
)
328 KV
.second
->dump(dbgs(), KV
.first());
331 // TODO: This works, but what actual alignment requirements do we have?
332 unsigned PageSize
= sys::Process::getPageSizeEstimate();
333 size_t Size
= Buffer
->getBufferSize();
335 // Allocate working memory for debug object in read-only segment.
336 auto Alloc
= SimpleSegmentAlloc::Create(
337 MemMgr
, JD
, {{MemProt::Read
, {Size
, Align(PageSize
)}}});
341 // Initialize working memory with a copy of our object buffer.
342 auto SegInfo
= Alloc
->getSegInfo(MemProt::Read
);
343 memcpy(SegInfo
.WorkingMem
.data(), Buffer
->getBufferStart(), Size
);
349 void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name
,
350 SectionRange TargetMem
) {
351 if (auto *DebugObjSection
= getSection(Name
))
352 DebugObjSection
->setTargetMemoryRange(TargetMem
);
355 template <typename ELFT
>
356 Error
ELFDebugObject::recordSection(
357 StringRef Name
, std::unique_ptr
<ELFDebugObjectSection
<ELFT
>> Section
) {
358 if (Error Err
= Section
->validateInBounds(this->getBuffer(), Name
.data()))
360 bool Inserted
= Sections
.try_emplace(Name
, std::move(Section
)).second
;
362 LLVM_DEBUG(dbgs() << "Skipping debug registration for section '" << Name
363 << "' in object " << Buffer
->getBufferIdentifier()
364 << " (duplicate name)\n");
365 return Error::success();
368 DebugObjectSection
*ELFDebugObject::getSection(StringRef Name
) {
369 auto It
= Sections
.find(Name
);
370 return It
== Sections
.end() ? nullptr : It
->second
.get();
373 /// Creates a debug object based on the input object file from
374 /// ObjectLinkingLayerJITLinkContext.
376 static Expected
<std::unique_ptr
<DebugObject
>>
377 createDebugObjectFromBuffer(ExecutionSession
&ES
, LinkGraph
&G
,
378 JITLinkContext
&Ctx
, MemoryBufferRef ObjBuffer
) {
379 switch (G
.getTargetTriple().getObjectFormat()) {
381 return ELFDebugObject::Create(ObjBuffer
, Ctx
, ES
);
384 // TODO: Once we add support for other formats, we might want to split this
385 // into multiple files.
390 DebugObjectManagerPlugin::DebugObjectManagerPlugin(
391 ExecutionSession
&ES
, std::unique_ptr
<DebugObjectRegistrar
> Target
,
392 bool RequireDebugSections
, bool AutoRegisterCode
)
393 : ES(ES
), Target(std::move(Target
)),
394 RequireDebugSections(RequireDebugSections
),
395 AutoRegisterCode(AutoRegisterCode
) {}
397 DebugObjectManagerPlugin::DebugObjectManagerPlugin(
398 ExecutionSession
&ES
, std::unique_ptr
<DebugObjectRegistrar
> Target
)
399 : DebugObjectManagerPlugin(ES
, std::move(Target
), true, true) {}
401 DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
403 void DebugObjectManagerPlugin::notifyMaterializing(
404 MaterializationResponsibility
&MR
, LinkGraph
&G
, JITLinkContext
&Ctx
,
405 MemoryBufferRef ObjBuffer
) {
406 std::lock_guard
<std::mutex
> Lock(PendingObjsLock
);
407 assert(PendingObjs
.count(&MR
) == 0 &&
408 "Cannot have more than one pending debug object per "
409 "MaterializationResponsibility");
411 if (auto DebugObj
= createDebugObjectFromBuffer(ES
, G
, Ctx
, ObjBuffer
)) {
412 // Not all link artifacts allow debugging.
413 if (*DebugObj
== nullptr)
415 if (RequireDebugSections
&& !(**DebugObj
).hasFlags(HasDebugSections
)) {
416 LLVM_DEBUG(dbgs() << "Skipping debug registration for LinkGraph '"
417 << G
.getName() << "': no debug info\n");
420 PendingObjs
[&MR
] = std::move(*DebugObj
);
422 ES
.reportError(DebugObj
.takeError());
426 void DebugObjectManagerPlugin::modifyPassConfig(
427 MaterializationResponsibility
&MR
, LinkGraph
&G
,
428 PassConfiguration
&PassConfig
) {
429 // Not all link artifacts have associated debug objects.
430 std::lock_guard
<std::mutex
> Lock(PendingObjsLock
);
431 auto It
= PendingObjs
.find(&MR
);
432 if (It
== PendingObjs
.end())
435 DebugObject
&DebugObj
= *It
->second
;
436 if (DebugObj
.hasFlags(ReportFinalSectionLoadAddresses
)) {
437 PassConfig
.PostAllocationPasses
.push_back(
438 [&DebugObj
](LinkGraph
&Graph
) -> Error
{
439 for (const Section
&GraphSection
: Graph
.sections())
440 DebugObj
.reportSectionTargetMemoryRange(GraphSection
.getName(),
441 SectionRange(GraphSection
));
442 return Error::success();
447 Error
DebugObjectManagerPlugin::notifyEmitted(
448 MaterializationResponsibility
&MR
) {
449 std::lock_guard
<std::mutex
> Lock(PendingObjsLock
);
450 auto It
= PendingObjs
.find(&MR
);
451 if (It
== PendingObjs
.end())
452 return Error::success();
454 // During finalization the debug object is registered with the target.
455 // Materialization must wait for this process to finish. Otherwise we might
456 // start running code before the debugger processed the corresponding debug
458 std::promise
<MSVCPError
> FinalizePromise
;
459 std::future
<MSVCPError
> FinalizeErr
= FinalizePromise
.get_future();
461 It
->second
->finalizeAsync(
462 [this, &FinalizePromise
, &MR
](Expected
<ExecutorAddrRange
> TargetMem
) {
463 // Any failure here will fail materialization.
465 FinalizePromise
.set_value(TargetMem
.takeError());
469 Target
->registerDebugObject(*TargetMem
, AutoRegisterCode
)) {
470 FinalizePromise
.set_value(std::move(Err
));
474 // Once our tracking info is updated, notifyEmitted() can return and
475 // finish materialization.
476 FinalizePromise
.set_value(MR
.withResourceKeyDo([&](ResourceKey K
) {
477 assert(PendingObjs
.count(&MR
) && "We still hold PendingObjsLock");
478 std::lock_guard
<std::mutex
> Lock(RegisteredObjsLock
);
479 RegisteredObjs
[K
].push_back(std::move(PendingObjs
[&MR
]));
480 PendingObjs
.erase(&MR
);
484 return FinalizeErr
.get();
487 Error
DebugObjectManagerPlugin::notifyFailed(
488 MaterializationResponsibility
&MR
) {
489 std::lock_guard
<std::mutex
> Lock(PendingObjsLock
);
490 PendingObjs
.erase(&MR
);
491 return Error::success();
494 void DebugObjectManagerPlugin::notifyTransferringResources(JITDylib
&JD
,
496 ResourceKey SrcKey
) {
497 // Debug objects are stored by ResourceKey only after registration.
498 // Thus, pending objects don't need to be updated here.
499 std::lock_guard
<std::mutex
> Lock(RegisteredObjsLock
);
500 auto SrcIt
= RegisteredObjs
.find(SrcKey
);
501 if (SrcIt
!= RegisteredObjs
.end()) {
502 // Resources from distinct MaterializationResponsibilitys can get merged
503 // after emission, so we can have multiple debug objects per resource key.
504 for (std::unique_ptr
<DebugObject
> &DebugObj
: SrcIt
->second
)
505 RegisteredObjs
[DstKey
].push_back(std::move(DebugObj
));
506 RegisteredObjs
.erase(SrcIt
);
510 Error
DebugObjectManagerPlugin::notifyRemovingResources(JITDylib
&JD
,
512 // Removing the resource for a pending object fails materialization, so they
513 // get cleaned up in the notifyFailed() handler.
514 std::lock_guard
<std::mutex
> Lock(RegisteredObjsLock
);
515 RegisteredObjs
.erase(Key
);
517 // TODO: Implement unregister notifications.
518 return Error::success();