LLVM: lib/ExecutionEngine/Orc/Debugging/ELFDebugObjectPlugin.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

15

29

30#include

31

32#define DEBUG_TYPE "orc"

33

36

37namespace llvm {

38namespace orc {

39

46

47template

49public:

50

51

53 : Header(const_cast<typename ELFT::Shdr *>(Header)) {}

54

57

59

60private:

61 typename ELFT::Shdr *Header;

62};

63

64template

66

67 Header->sh_addr =

68 static_cast<typename ELFT::uint>(Range.getStart().getValue());

69}

70

71template

73 const char *Name) const {

76 const uint8_t *HeaderPtr = reinterpret_cast<uint8_t *>(Header);

77 if (HeaderPtr < Start || HeaderPtr + sizeof(typename ELFT::Shdr) > End)

79 formatv("{0} section header at {1:x16} not within bounds of the "

80 "given debug object buffer [{2:x16} - {3:x16}]",

81 Name, &Header->sh_addr, Start, End),

83 if (Header->sh_offset + Header->sh_size > Buffer.size())

85 formatv("{0} section data [{1:x16} - {2:x16}] not within bounds of "

86 "the given debug object buffer [{3:x16} - {4:x16}]",

87 Name, Start + Header->sh_offset,

88 Start + Header->sh_offset + Header->sh_size, Start, End),

91}

92

93template

95 if (uint64_t Addr = Header->sh_addr) {

96 OS << formatv(" {0:x16} {1}\n", Addr, Name);

97 } else {

98 OS << formatv(" {0}\n", Name);

99 }

100}

101

109

110

111

112

113

114

116public:

122

130

133

137

141

143

145 if (Alloc) {

146 std::vector Allocs;

147 Allocs.push_back(std::move(Alloc));

148 if (Error Err = MemMgr.deallocate(std::move(Allocs)))

149 ES.reportError(std::move(Err));

150 }

151 }

152

155

156protected:

159

161

165

168

169private:

172};

173

174

175

176

178 assert(!this->Alloc && "Cannot finalize more than once");

180 auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read);

181 ExecutorAddrRange DebugObjRange(ROSeg.Addr, ROSeg.WorkingMem.size());

182 SimpleSegAlloc->finalize(

183 [this, DebugObjRange,

185 if (FA) {

186

187

188

189 this->Alloc = std::move(*FA);

190 OnFinalize(DebugObjRange);

191 } else

193 });

194 } else {

195

196

197 OnFinalize(SimpleSegAlloc.takeError());

198 }

199}

200

201

202

203

204

205

207public:

210

213

215

216protected:

218

219 template

223

224private:

225 template

229

230 static std::unique_ptr

232

233 ELFDebugObject(std::unique_ptr Buffer,

238 }

239

240 std::unique_ptr Buffer;

242};

243

245#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \

246 ELF_NAME,

247#include "llvm/BinaryFormat/Dwarf.def"

248#undef HANDLE_DWARF_SECTION

249};

250

254

255std::unique_ptr

262 return Copy;

263 }

264

266 return nullptr;

267}

268

269template

270Expected<std::unique_ptr>

271ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,

272 JITLinkMemoryManager &MemMgr,

275

277 std::unique_ptr DebugObj(

278 new ELFDebugObject(CopyBuffer(Buffer, Err), MemMgr, JD, ES));

279 if (Err)

280 return std::move(Err);

281

283 if (!ObjRef)

285

286 Expected<ArrayRef> Sections = ObjRef->sections();

287 if (!Sections)

289

290 for (const SectionHeader &Header : *Sections) {

291 Expected Name = ObjRef->getSectionName(Header);

292 if (!Name)

293 return Name.takeError();

294 if (Name->empty())

295 continue;

298

299

302 continue;

304 continue;

305

306 auto Wrapped = std::make_unique<ELFDebugObjectSection>(&Header);

307 if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))

308 return std::move(Err);

309 }

310

311 return std::move(DebugObj);

312}

313

314Expected<std::unique_ptr>

317 unsigned char Class, Endian;

318 std::tie(Class, Endian) = getElfArchType(Buffer.getBuffer());

319

322 return CreateArchType(Buffer, Ctx.getMemoryManager(),

323 Ctx.getJITLinkDylib(), ES);

325 return CreateArchType(Buffer, Ctx.getMemoryManager(),

326 Ctx.getJITLinkDylib(), ES);

327 return nullptr;

328 }

331 return CreateArchType(Buffer, Ctx.getMemoryManager(),

332 Ctx.getJITLinkDylib(), ES);

334 return CreateArchType(Buffer, Ctx.getMemoryManager(),

335 Ctx.getJITLinkDylib(), ES);

336 return nullptr;

337 }

338 return nullptr;

339}

340

343 dbgs() << "Section load-addresses in debug object for \""

344 << Buffer->getBufferIdentifier() << "\":\n";

345 for (const auto &KV : Sections)

346 KV.second->dump(dbgs(), KV.first());

347 });

348

349

351 size_t Size = Buffer->getBufferSize();

352

353

355 MemMgr, ES.getSymbolStringPool(), ES.getTargetTriple(), JD,

356 {{MemProt::Read, {Size, Align(PageSize)}}});

359

360

363 Buffer.reset();

364

366}

367

370 if (auto *DebugObjSection = getSection(Name))

371 DebugObjSection->setTargetMemoryRange(TargetMem);

372}

373

374template

377 if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))

378 return Err;

379 bool Inserted = Sections.try_emplace(Name, std::move(Section)).second;

380 if (!Inserted)

381 LLVM_DEBUG(dbgs() << "Skipping debug registration for section '" << Name

382 << "' in object " << Buffer->getBufferIdentifier()

383 << " (duplicate name)\n");

385}

386

388 auto It = Sections.find(Name);

389 return It == Sections.end() ? nullptr : It->second.get();

390}

391

392

393

394

398 switch (G.getTargetTriple().getObjectFormat()) {

401

402 default:

403

404

405 return nullptr;

406 }

407}

408

410 bool RequireDebugSections,

411 bool AutoRegisterCode, Error &Err)

412 : ES(ES), RequireDebugSections(RequireDebugSections),

413 AutoRegisterCode(AutoRegisterCode) {

414

416 Err = ES.getExecutorProcessControl().getBootstrapSymbols(

418}

419

421

425 std::lock_guardstd::mutex Lock(PendingObjsLock);

426 assert(PendingObjs.count(&MR) == 0 &&

427 "Cannot have more than one pending debug object per "

428 "MaterializationResponsibility");

429

431

432 if (*DebugObj == nullptr)

433 return;

434 if (RequireDebugSections && !(**DebugObj).hasFlags(HasDebugSections)) {

435 LLVM_DEBUG(dbgs() << "Skipping debug registration for LinkGraph '"

436 << G.getName() << "': no debug info\n");

437 return;

438 }

439 PendingObjs[&MR] = std::move(*DebugObj);

440 } else {

441 ES.reportError(DebugObj.takeError());

442 }

443}

444

448

449 std::lock_guardstd::mutex Lock(PendingObjsLock);

450 auto It = PendingObjs.find(&MR);

451 if (It == PendingObjs.end())

452 return;

453

462 });

463

468 if (!TargetMem) {

470 return;

471 }

472

474 std::lock_guardstd::mutex LockPending(PendingObjsLock);

475 std::lock_guardstd::mutex LockRegistered(RegisteredObjsLock);

476 auto It = PendingObjs.find(&MR);

477 RegisteredObjs[K].push_back(std::move(It->second));

478 PendingObjs.erase(It);

479 });

480

481 if (Err)

483

484

486 });

488 });

489

493 if (!R)

494 return R.takeError();

495 if (R->empty())

497

498 using namespace shared;

499 G.allocActions().push_back(

500 {cantFail(WrapperFunctionCall::Create<

501 SPSArgList<SPSExecutorAddrRange, bool>>(

502 RegistrationAction, *R, AutoRegisterCode)),

503 {}});

505 });

506 }

507}

508

510 std::lock_guardstd::mutex Lock(PendingObjsLock);

511 PendingObjs.erase(&MR);

513}

514

518

519

520 std::lock_guardstd::mutex Lock(RegisteredObjsLock);

521 auto SrcIt = RegisteredObjs.find(SrcKey);

522 if (SrcIt != RegisteredObjs.end()) {

523

524

525 for (std::unique_ptr &DebugObj : SrcIt->second)

526 RegisteredObjs[DstKey].push_back(std::move(DebugObj));

527 RegisteredObjs.erase(SrcIt);

528 }

529}

530

533

534

535 std::lock_guardstd::mutex Lock(RegisteredObjsLock);

536 RegisteredObjs.erase(Key);

537

538

540}

541

542}

543}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

This file defines the StringMap class.

static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)

ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))

Provides a library for accessing information about this process and other processes on the operating ...

Helper for Errors used as out-parameters.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

size_t getBufferSize() const

StringRef getBufferIdentifier() const

const char * getBufferStart() const

StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...

StringRef - Represent a constant reference to a string, i.e.

const unsigned char * bytes_end() const

constexpr size_t size() const

size - Get the string size.

const unsigned char * bytes_begin() const

static LLVM_ABI std::unique_ptr< WritableMemoryBuffer > getNewUninitMemBuffer(size_t Size, const Twine &BufferName="", std::optional< Align > Alignment=std::nullopt)

Allocate a new MemoryBuffer of the specified size that is not initialized.

Holds context for a single jitLink invocation.

Represents a finalized allocation.

Represents an allocation which has not been finalized yet.

Manages allocations of JIT memory.

iterator_range< section_iterator > sections()

Represents a section address range via a pair of Block pointers to the first and last Blocks in the s...

Represents an object file section.

static LLVM_ABI void Create(JITLinkMemoryManager &MemMgr, std::shared_ptr< orc::SymbolStringPool > SSP, Triple TT, const JITLinkDylib *JD, SegmentMap Segments, OnCreatedFunction OnCreated)

static Expected< ELFFile > create(StringRef Object)

virtual void setTargetMemoryRange(SectionRange Range)=0

virtual void dump(raw_ostream &OS, StringRef Name)

Definition ELFDebugObjectPlugin.cpp:43

virtual ~DebugObjectSection()=default

The plugin creates a debug object from when JITLink starts processing the corresponding LinkGraph.

Definition ELFDebugObjectPlugin.cpp:115

virtual ~DebugObject()

Definition ELFDebugObjectPlugin.cpp:144

JITLinkMemoryManager & MemMgr

Definition ELFDebugObjectPlugin.cpp:162

Expected< ExecutorAddrRange > awaitTargetMem()

Definition ELFDebugObjectPlugin.cpp:142

void reportTargetMem(ExecutorAddrRange TargetMem)

Definition ELFDebugObjectPlugin.cpp:138

ExecutionSession & ES

Definition ELFDebugObjectPlugin.cpp:164

void finalizeAsync(FinalizeContinuation OnAsync)

Definition ELFDebugObjectPlugin.cpp:177

bool hasFlags(DebugObjectFlags F) const

Definition ELFDebugObjectPlugin.cpp:123

void failMaterialization(Error Err)

Definition ELFDebugObjectPlugin.cpp:134

virtual Expected< SimpleSegmentAlloc > finalizeWorkingMemory()=0

std::function< void(Expected< ExecutorAddrRange >)> FinalizeContinuation

Definition ELFDebugObjectPlugin.cpp:131

void clearFlags(DebugObjectFlags F)

Definition ELFDebugObjectPlugin.cpp:127

std::future< MSVCPExpected< ExecutorAddrRange > > FinalizeFuture

Definition ELFDebugObjectPlugin.cpp:167

virtual void reportSectionTargetMemoryRange(StringRef Name, SectionRange TargetMem)

Definition ELFDebugObjectPlugin.cpp:153

const JITLinkDylib * JD

Definition ELFDebugObjectPlugin.cpp:163

void setFlags(DebugObjectFlags F)

Definition ELFDebugObjectPlugin.cpp:124

JITLinkMemoryManager::FinalizedAlloc FinalizedAlloc

Definition ELFDebugObjectPlugin.cpp:158

JITLinkMemoryManager::InFlightAlloc InFlightAlloc

Definition ELFDebugObjectPlugin.cpp:157

std::promise< MSVCPExpected< ExecutorAddrRange > > FinalizePromise

Definition ELFDebugObjectPlugin.cpp:166

DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD, ExecutionSession &ES)

Definition ELFDebugObjectPlugin.cpp:117

Error notifyFailed(MaterializationResponsibility &MR) override

Definition ELFDebugObjectPlugin.cpp:509

void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) override

Definition ELFDebugObjectPlugin.cpp:515

~ELFDebugObjectPlugin() override

ELFDebugObjectPlugin(ExecutionSession &ES, bool RequireDebugSections, bool AutoRegisterCode, Error &Err)

Create the plugin to submit DebugObjects for JITLink artifacts.

Definition ELFDebugObjectPlugin.cpp:409

Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override

Definition ELFDebugObjectPlugin.cpp:531

void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &LG, jitlink::PassConfiguration &PassConfig) override

Definition ELFDebugObjectPlugin.cpp:445

void notifyMaterializing(MaterializationResponsibility &MR, jitlink::LinkGraph &G, jitlink::JITLinkContext &Ctx, MemoryBufferRef InputObject) override

Definition ELFDebugObjectPlugin.cpp:422

Error validateInBounds(StringRef Buffer, const char *Name) const

Definition ELFDebugObjectPlugin.cpp:72

void setTargetMemoryRange(SectionRange Range) override

Definition ELFDebugObjectPlugin.cpp:65

void dump(raw_ostream &OS, StringRef Name) override

Definition ELFDebugObjectPlugin.cpp:94

ELFDebugObjectSection(const typename ELFT::Shdr *Header)

Definition ELFDebugObjectPlugin.cpp:52

The current implementation of ELFDebugObject replicates the approach used in RuntimeDyld: It patches ...

Definition ELFDebugObjectPlugin.cpp:206

Error recordSection(StringRef Name, std::unique_ptr< ELFDebugObjectSection< ELFT > > Section)

Definition ELFDebugObjectPlugin.cpp:375

DebugObjectSection * getSection(StringRef Name)

Definition ELFDebugObjectPlugin.cpp:387

Expected< SimpleSegmentAlloc > finalizeWorkingMemory() override

Definition ELFDebugObjectPlugin.cpp:341

void reportSectionTargetMemoryRange(StringRef Name, SectionRange TargetMem) override

Definition ELFDebugObjectPlugin.cpp:368

StringRef getBuffer() const

Definition ELFDebugObjectPlugin.cpp:214

static Expected< std::unique_ptr< DebugObject > > Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, ExecutionSession &ES)

Definition ELFDebugObjectPlugin.cpp:315

An ExecutionSession represents a running JIT program.

Represents a JIT'd dynamic library.

Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...

Error withResourceKeyDo(Func &&F) const

Runs the given callback under the session lock, passing in the associated ResourceKey.

This class implements an extremely fast bulk output stream that can only output to a stream.

static unsigned getPageSizeEstimate()

Get the process's estimated page size.

Expected< const typename ELFT::Shdr * > getSection(typename ELFT::ShdrRange Sections, uint32_t Index)

std::pair< unsigned char, unsigned char > getElfArchType(StringRef Object)

LLVM_ABI const char * RegisterJITLoaderGDBAllocActionName

static const std::set< StringRef > DwarfSectionNames

Definition ELFDebugObjectPlugin.cpp:244

static Expected< std::unique_ptr< DebugObject > > createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G, JITLinkContext &Ctx, MemoryBufferRef ObjBuffer)

Creates a debug object based on the input object file from ObjectLinkingLayerJITLinkContext.

Definition ELFDebugObjectPlugin.cpp:396

static bool isDwarfSection(StringRef SectionName)

Definition ELFDebugObjectPlugin.cpp:251

DebugObjectFlags

Definition ELFDebugObjectPlugin.cpp:102

@ ReportFinalSectionLoadAddresses

Definition ELFDebugObjectPlugin.cpp:104

@ HasDebugSections

Definition ELFDebugObjectPlugin.cpp:107

This is an optimization pass for GlobalISel generic memory operations.

std::error_code make_error_code(BitcodeError E)

LLVM_ABI std::error_code inconvertibleErrorCode()

The value returned by this function can be returned from convertToErrorCode for Error values where no...

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

void cantFail(Error Err, const char *Msg=nullptr)

Report a fatal error if Err is a failure value.

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

LLVM_ABI Error errorCodeToError(std::error_code EC)

Helper for converting an std::error_code to a Error.

Implement std::hash so that hash_code can be used in STL containers.

An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...

LinkGraphPassList PostAllocationPasses

Post-allocation passes.

LinkGraphPassList PreFixupPasses

Pre-fixup passes.

LinkGraphPassList PostFixupPasses

Post-fixup passes.

Represents an address range in the exceutor process.