[JITLink] Add support of R_X86_64_32S relocation
[llvm-project.git] / llvm / lib / ExecutionEngine / Orc / DebugObjectManagerPlugin.cpp
blob36efc744bf30761b5197fd2b3ae033467ad136ec
1 //===---- DebugObjectManagerPlugin.h - JITLink debug objects ---*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
11 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/ADT/StringMap.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/BinaryFormat/ELF.h"
15 #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
16 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
17 #include "llvm/ExecutionEngine/JITSymbol.h"
18 #include "llvm/Object/ELFObjectFile.h"
19 #include "llvm/Object/ObjectFile.h"
20 #include "llvm/Support/Errc.h"
21 #include "llvm/Support/MSVCErrorWorkarounds.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include "llvm/Support/Process.h"
24 #include "llvm/Support/raw_ostream.h"
26 #include <set>
28 #define DEBUG_TYPE "orc"
30 using namespace llvm::jitlink;
31 using namespace llvm::object;
33 namespace llvm {
34 namespace orc {
36 class DebugObjectSection {
37 public:
38 virtual void setTargetMemoryRange(SectionRange Range) = 0;
39 virtual void dump(raw_ostream &OS, StringRef Name) {}
40 virtual ~DebugObjectSection() {}
43 template <typename ELFT>
44 class ELFDebugObjectSection : public DebugObjectSection {
45 public:
46 // BinaryFormat ELF is not meant as a mutable format. We can only make changes
47 // that don't invalidate the file structure.
48 ELFDebugObjectSection(const typename ELFT::Shdr *Header)
49 : Header(const_cast<typename ELFT::Shdr *>(Header)) {}
51 void setTargetMemoryRange(SectionRange Range) override;
52 void dump(raw_ostream &OS, StringRef Name) override;
54 Error validateInBounds(StringRef Buffer, const char *Name) const;
56 private:
57 typename ELFT::Shdr *Header;
59 bool isTextOrDataSection() const;
62 template <typename ELFT>
63 void ELFDebugObjectSection<ELFT>::setTargetMemoryRange(SectionRange Range) {
64 // Only patch load-addresses for executable and data sections.
65 if (isTextOrDataSection()) {
66 Header->sh_addr = static_cast<typename ELFT::uint>(Range.getStart());
70 template <typename ELFT>
71 bool ELFDebugObjectSection<ELFT>::isTextOrDataSection() const {
72 switch (Header->sh_type) {
73 case ELF::SHT_PROGBITS:
74 case ELF::SHT_X86_64_UNWIND:
75 return Header->sh_flags & (ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
77 return false;
80 template <typename ELFT>
81 Error ELFDebugObjectSection<ELFT>::validateInBounds(StringRef Buffer,
82 const char *Name) const {
83 const uint8_t *Start = Buffer.bytes_begin();
84 const uint8_t *End = Buffer.bytes_end();
85 const uint8_t *HeaderPtr = reinterpret_cast<uint8_t *>(Header);
86 if (HeaderPtr < Start || HeaderPtr + sizeof(typename ELFT::Shdr) > End)
87 return make_error<StringError>(
88 formatv("{0} section header at {1:x16} not within bounds of the "
89 "given debug object buffer [{2:x16} - {3:x16}]",
90 Name, &Header->sh_addr, Start, End),
91 inconvertibleErrorCode());
92 if (Header->sh_offset + Header->sh_size > Buffer.size())
93 return make_error<StringError>(
94 formatv("{0} section data [{1:x16} - {2:x16}] not within bounds of "
95 "the given debug object buffer [{3:x16} - {4:x16}]",
96 Name, Start + Header->sh_offset,
97 Start + Header->sh_offset + Header->sh_size, Start, End),
98 inconvertibleErrorCode());
99 return Error::success();
102 template <typename ELFT>
103 void ELFDebugObjectSection<ELFT>::dump(raw_ostream &OS, StringRef Name) {
104 if (auto Addr = static_cast<JITTargetAddress>(Header->sh_addr)) {
105 OS << formatv(" {0:x16} {1}\n", Addr, Name);
106 } else {
107 OS << formatv(" {0}\n", Name);
111 static constexpr sys::Memory::ProtectionFlags ReadOnly =
112 static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ);
114 enum class Requirement {
115 // Request final target memory load-addresses for all sections.
116 ReportFinalSectionLoadAddresses,
119 /// The plugin creates a debug object from JITLinkContext when JITLink starts
120 /// processing the corresponding LinkGraph. It provides access to the pass
121 /// configuration of the LinkGraph and calls the finalization function, once
122 /// the resulting link artifact was emitted.
124 class DebugObject {
125 public:
126 DebugObject(JITLinkContext &Ctx, ExecutionSession &ES) : Ctx(Ctx), ES(ES) {}
128 void set(Requirement Req) { Reqs.insert(Req); }
129 bool has(Requirement Req) const { return Reqs.count(Req) > 0; }
131 using FinalizeContinuation = std::function<void(Expected<sys::MemoryBlock>)>;
132 void finalizeAsync(FinalizeContinuation OnFinalize);
134 virtual ~DebugObject() {
135 if (Alloc)
136 if (Error Err = Alloc->deallocate())
137 ES.reportError(std::move(Err));
140 virtual void reportSectionTargetMemoryRange(StringRef Name,
141 SectionRange TargetMem) {}
143 protected:
144 using Allocation = JITLinkMemoryManager::Allocation;
146 virtual Expected<std::unique_ptr<Allocation>>
147 finalizeWorkingMemory(JITLinkContext &Ctx) = 0;
149 private:
150 JITLinkContext &Ctx;
151 ExecutionSession &ES;
152 std::set<Requirement> Reqs;
153 std::unique_ptr<Allocation> Alloc{nullptr};
156 // Finalize working memory and take ownership of the resulting allocation. Start
157 // copying memory over to the target and pass on the result once we're done.
158 // Ownership of the allocation remains with us for the rest of our lifetime.
159 void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) {
160 assert(Alloc == nullptr && "Cannot finalize more than once");
162 auto AllocOrErr = finalizeWorkingMemory(Ctx);
163 if (!AllocOrErr)
164 OnFinalize(AllocOrErr.takeError());
165 Alloc = std::move(*AllocOrErr);
167 Alloc->finalizeAsync([this, OnFinalize](Error Err) {
168 if (Err)
169 OnFinalize(std::move(Err));
170 else
171 OnFinalize(sys::MemoryBlock(
172 jitTargetAddressToPointer<void *>(Alloc->getTargetMemory(ReadOnly)),
173 Alloc->getWorkingMemory(ReadOnly).size()));
177 /// The current implementation of ELFDebugObject replicates the approach used in
178 /// RuntimeDyld: It patches executable and data section headers in the given
179 /// object buffer with load-addresses of their corresponding sections in target
180 /// memory.
182 class ELFDebugObject : public DebugObject {
183 public:
184 static Expected<std::unique_ptr<DebugObject>>
185 Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, ExecutionSession &ES);
187 void reportSectionTargetMemoryRange(StringRef Name,
188 SectionRange TargetMem) override;
190 StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); }
192 protected:
193 Expected<std::unique_ptr<Allocation>>
194 finalizeWorkingMemory(JITLinkContext &Ctx) override;
196 template <typename ELFT>
197 Error recordSection(StringRef Name,
198 std::unique_ptr<ELFDebugObjectSection<ELFT>> Section);
199 DebugObjectSection *getSection(StringRef Name);
201 private:
202 template <typename ELFT>
203 static Expected<std::unique_ptr<ELFDebugObject>>
204 CreateArchType(MemoryBufferRef Buffer, JITLinkContext &Ctx,
205 ExecutionSession &ES);
207 static std::unique_ptr<WritableMemoryBuffer>
208 CopyBuffer(MemoryBufferRef Buffer, Error &Err);
210 ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,
211 JITLinkContext &Ctx, ExecutionSession &ES)
212 : DebugObject(Ctx, ES), Buffer(std::move(Buffer)) {
213 set(Requirement::ReportFinalSectionLoadAddresses);
216 std::unique_ptr<WritableMemoryBuffer> Buffer;
217 StringMap<std::unique_ptr<DebugObjectSection>> Sections;
220 static const std::set<StringRef> DwarfSectionNames = {
221 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
222 ELF_NAME,
223 #include "llvm/BinaryFormat/Dwarf.def"
224 #undef HANDLE_DWARF_SECTION
227 static bool isDwarfSection(StringRef SectionName) {
228 return DwarfSectionNames.count(SectionName) == 1;
231 std::unique_ptr<WritableMemoryBuffer>
232 ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) {
233 ErrorAsOutParameter _(&Err);
234 size_t Size = Buffer.getBufferSize();
235 StringRef Name = Buffer.getBufferIdentifier();
236 if (auto Copy = WritableMemoryBuffer::getNewUninitMemBuffer(Size, Name)) {
237 memcpy(Copy->getBufferStart(), Buffer.getBufferStart(), Size);
238 return Copy;
241 Err = errorCodeToError(make_error_code(errc::not_enough_memory));
242 return nullptr;
245 template <typename ELFT>
246 Expected<std::unique_ptr<ELFDebugObject>>
247 ELFDebugObject::CreateArchType(MemoryBufferRef Buffer, JITLinkContext &Ctx,
248 ExecutionSession &ES) {
249 using SectionHeader = typename ELFT::Shdr;
251 Error Err = Error::success();
252 std::unique_ptr<ELFDebugObject> DebugObj(
253 new ELFDebugObject(CopyBuffer(Buffer, Err), Ctx, ES));
254 if (Err)
255 return std::move(Err);
257 Expected<ELFFile<ELFT>> ObjRef = ELFFile<ELFT>::create(DebugObj->getBuffer());
258 if (!ObjRef)
259 return ObjRef.takeError();
261 // TODO: Add support for other architectures.
262 uint16_t TargetMachineArch = ObjRef->getHeader().e_machine;
263 if (TargetMachineArch != ELF::EM_X86_64)
264 return nullptr;
266 Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
267 if (!Sections)
268 return Sections.takeError();
270 bool HasDwarfSection = false;
271 for (const SectionHeader &Header : *Sections) {
272 Expected<StringRef> Name = ObjRef->getSectionName(Header);
273 if (!Name)
274 return Name.takeError();
275 if (Name->empty())
276 continue;
277 HasDwarfSection |= isDwarfSection(*Name);
279 auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
280 if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
281 return std::move(Err);
284 if (!HasDwarfSection) {
285 LLVM_DEBUG(dbgs() << "Aborting debug registration for LinkGraph \""
286 << DebugObj->Buffer->getBufferIdentifier()
287 << "\": input object contains no debug info\n");
288 return nullptr;
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, ES);
303 if (Endian == ELF::ELFDATA2MSB)
304 return CreateArchType<ELF32BE>(Buffer, Ctx, ES);
305 return nullptr;
307 if (Class == ELF::ELFCLASS64) {
308 if (Endian == ELF::ELFDATA2LSB)
309 return CreateArchType<ELF64LE>(Buffer, Ctx, ES);
310 if (Endian == ELF::ELFDATA2MSB)
311 return CreateArchType<ELF64BE>(Buffer, Ctx, ES);
312 return nullptr;
314 return nullptr;
317 Expected<std::unique_ptr<DebugObject::Allocation>>
318 ELFDebugObject::finalizeWorkingMemory(JITLinkContext &Ctx) {
319 LLVM_DEBUG({
320 dbgs() << "Section load-addresses in debug object for \""
321 << Buffer->getBufferIdentifier() << "\":\n";
322 for (const auto &KV : Sections)
323 KV.second->dump(dbgs(), KV.first());
326 // TODO: This works, but what actual alignment requirements do we have?
327 unsigned Alignment = sys::Process::getPageSizeEstimate();
328 JITLinkMemoryManager &MemMgr = Ctx.getMemoryManager();
329 const JITLinkDylib *JD = Ctx.getJITLinkDylib();
330 size_t Size = Buffer->getBufferSize();
332 // Allocate working memory for debug object in read-only segment.
333 JITLinkMemoryManager::SegmentsRequestMap SingleReadOnlySegment;
334 SingleReadOnlySegment[ReadOnly] =
335 JITLinkMemoryManager::SegmentRequest(Alignment, Size, 0);
337 auto AllocOrErr = MemMgr.allocate(JD, SingleReadOnlySegment);
338 if (!AllocOrErr)
339 return AllocOrErr.takeError();
341 // Initialize working memory with a copy of our object buffer.
342 // TODO: Use our buffer as working memory directly.
343 std::unique_ptr<Allocation> Alloc = std::move(*AllocOrErr);
344 MutableArrayRef<char> WorkingMem = Alloc->getWorkingMemory(ReadOnly);
345 memcpy(WorkingMem.data(), Buffer->getBufferStart(), Size);
346 Buffer.reset();
348 return std::move(Alloc);
351 void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name,
352 SectionRange TargetMem) {
353 if (auto *DebugObjSection = getSection(Name))
354 DebugObjSection->setTargetMemoryRange(TargetMem);
357 template <typename ELFT>
358 Error ELFDebugObject::recordSection(
359 StringRef Name, std::unique_ptr<ELFDebugObjectSection<ELFT>> Section) {
360 if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))
361 return Err;
362 auto ItInserted = Sections.try_emplace(Name, std::move(Section));
363 if (!ItInserted.second)
364 return make_error<StringError>("Duplicate section",
365 inconvertibleErrorCode());
366 return Error::success();
369 DebugObjectSection *ELFDebugObject::getSection(StringRef Name) {
370 auto It = Sections.find(Name);
371 return It == Sections.end() ? nullptr : It->second.get();
374 /// Creates a debug object based on the input object file from
375 /// ObjectLinkingLayerJITLinkContext.
377 static Expected<std::unique_ptr<DebugObject>>
378 createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
379 JITLinkContext &Ctx, MemoryBufferRef ObjBuffer) {
380 switch (G.getTargetTriple().getObjectFormat()) {
381 case Triple::ELF:
382 return ELFDebugObject::Create(ObjBuffer, Ctx, ES);
384 default:
385 // TODO: Once we add support for other formats, we might want to split this
386 // into multiple files.
387 return nullptr;
391 DebugObjectManagerPlugin::DebugObjectManagerPlugin(
392 ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
393 : ES(ES), Target(std::move(Target)) {}
395 DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
397 void DebugObjectManagerPlugin::notifyMaterializing(
398 MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
399 MemoryBufferRef ObjBuffer) {
400 std::lock_guard<std::mutex> Lock(PendingObjsLock);
401 assert(PendingObjs.count(&MR) == 0 &&
402 "Cannot have more than one pending debug object per "
403 "MaterializationResponsibility");
405 if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
406 // Not all link artifacts allow debugging.
407 if (*DebugObj != nullptr)
408 PendingObjs[&MR] = std::move(*DebugObj);
409 } else {
410 ES.reportError(DebugObj.takeError());
414 void DebugObjectManagerPlugin::modifyPassConfig(
415 MaterializationResponsibility &MR, LinkGraph &G,
416 PassConfiguration &PassConfig) {
417 // Not all link artifacts have associated debug objects.
418 std::lock_guard<std::mutex> Lock(PendingObjsLock);
419 auto It = PendingObjs.find(&MR);
420 if (It == PendingObjs.end())
421 return;
423 DebugObject &DebugObj = *It->second;
424 if (DebugObj.has(Requirement::ReportFinalSectionLoadAddresses)) {
425 PassConfig.PostAllocationPasses.push_back(
426 [&DebugObj](LinkGraph &Graph) -> Error {
427 for (const Section &GraphSection : Graph.sections())
428 DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
429 SectionRange(GraphSection));
430 return Error::success();
435 Error DebugObjectManagerPlugin::notifyEmitted(
436 MaterializationResponsibility &MR) {
437 std::lock_guard<std::mutex> Lock(PendingObjsLock);
438 auto It = PendingObjs.find(&MR);
439 if (It == PendingObjs.end())
440 return Error::success();
442 // During finalization the debug object is registered with the target.
443 // Materialization must wait for this process to finish. Otherwise we might
444 // start running code before the debugger processed the corresponding debug
445 // info.
446 std::promise<MSVCPError> FinalizePromise;
447 std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future();
449 It->second->finalizeAsync(
450 [this, &FinalizePromise, &MR](Expected<sys::MemoryBlock> TargetMem) {
451 // Any failure here will fail materialization.
452 if (!TargetMem) {
453 FinalizePromise.set_value(TargetMem.takeError());
454 return;
456 if (Error Err = Target->registerDebugObject(*TargetMem)) {
457 FinalizePromise.set_value(std::move(Err));
458 return;
461 // Once our tracking info is updated, notifyEmitted() can return and
462 // finish materialization.
463 FinalizePromise.set_value(MR.withResourceKeyDo([&](ResourceKey K) {
464 assert(PendingObjs.count(&MR) && "We still hold PendingObjsLock");
465 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
466 RegisteredObjs[K].push_back(std::move(PendingObjs[&MR]));
467 PendingObjs.erase(&MR);
468 }));
471 return FinalizeErr.get();
474 Error DebugObjectManagerPlugin::notifyFailed(
475 MaterializationResponsibility &MR) {
476 std::lock_guard<std::mutex> Lock(PendingObjsLock);
477 PendingObjs.erase(&MR);
478 return Error::success();
481 void DebugObjectManagerPlugin::notifyTransferringResources(ResourceKey DstKey,
482 ResourceKey SrcKey) {
483 // Debug objects are stored by ResourceKey only after registration.
484 // Thus, pending objects don't need to be updated here.
485 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
486 auto SrcIt = RegisteredObjs.find(SrcKey);
487 if (SrcIt != RegisteredObjs.end()) {
488 // Resources from distinct MaterializationResponsibilitys can get merged
489 // after emission, so we can have multiple debug objects per resource key.
490 for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
491 RegisteredObjs[DstKey].push_back(std::move(DebugObj));
492 RegisteredObjs.erase(SrcIt);
496 Error DebugObjectManagerPlugin::notifyRemovingResources(ResourceKey Key) {
497 // Removing the resource for a pending object fails materialization, so they
498 // get cleaned up in the notifyFailed() handler.
499 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
500 RegisteredObjs.erase(Key);
502 // TODO: Implement unregister notifications.
503 return Error::success();
506 } // namespace orc
507 } // namespace llvm