LLVM: include/llvm/ExecutionEngine/Orc/MachOBuilder.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13#ifndef LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H

14#define LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H

15

19

20#include

21#include

22#include

23

24namespace llvm {

25namespace orc {

26

27template

29 bool SwapStruct) {

30 if (SwapStruct)

32 assert(Offset + sizeof(MachOStruct) <= Buf.size() && "Buffer overflow");

33 memcpy(&Buf[Offset], reinterpret_cast<const char *>(&S), sizeof(MachOStruct));

34 return Offset + sizeof(MachOStruct);

35}

36

37

40 virtual size_t size() const = 0;

42 bool SwapStruct) = 0;

43};

44

45

47

48#define HANDLE_LOAD_COMMAND(Name, Value, LCStruct) \

49 template <> \

50 struct MachOBuilderLoadCommandImplBaseMachO::Name \

51 : public MachO::LCStruct, public MachOBuilderLoadCommandBase { \

52 using CmdStruct = LCStruct; \

53 MachOBuilderLoadCommandImplBase() { \

54 memset(&rawStruct(), 0, sizeof(CmdStruct)); \

55 cmd = Value; \

56 cmdsize = sizeof(CmdStruct); \

57 } \

58 template <typename... ArgTs> \

59 MachOBuilderLoadCommandImplBase(ArgTs &&...Args) \

60 : CmdStruct{Value, sizeof(CmdStruct), std::forward(Args)...} {} \

61 CmdStruct &rawStruct() { return static_cast<CmdStruct &>(*this); } \

62 size_t size() const override { return cmdsize; } \

63 size_t write(MutableArrayRef Buf, size_t Offset, \

64 bool SwapStruct) override { \

65 return writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct); \

66 } \

67 };

68

69#include "llvm/BinaryFormat/MachO.def"

70

71#undef HANDLE_LOAD_COMMAND

72

73template <MachO::LoadCommandType LCType>

76public:

78

79 template <typename... ArgTs>

82};

83

84template <>

87

90 uint32_t CompatibilityVersion)

92 MachO::dylib{24, Timestamp, CurrentVersion, CompatibilityVersion}),

94 cmdsize += (this->Name.size() + 1 + 3) & ~0x3;

95 }

96

98 bool SwapStruct) override {

101 return Offset + ((Name.size() + 1 + 3) & ~0x3);

102 }

103

105};

106

107template <>

110

113 uint32_t CompatibilityVersion)

115 MachO::dylib{24, Timestamp, CurrentVersion, CompatibilityVersion}),

117 cmdsize += (this->Name.size() + 1 + 3) & ~0x3;

118 }

119

121 bool SwapStruct) override {

124 return Offset + ((Name.size() + 1 + 3) & ~0x3);

125 }

126

128};

129

130template <>

135 cmdsize += (this->Path.size() + 1 + 3) & ~0x3;

136 }

137

139 bool SwapStruct) override {

141 strcpy(Buf.data() + Offset, Path.data());

142 return Offset + ((Path.size() + 1 + 3) & ~0x3);

143 }

144

146};

147

148

150private:

151 struct SymbolContainer {

152 size_t SymbolIndexBase = 0;

153 std::vector Symbols;

154 };

155

156 struct StringTableEntry {

158 size_t Offset;

159 };

160

161 using StringTable = std::vector;

162

163 static bool swapStruct() {

165 }

166

167public:

169

171

172

173

175 public:

178

180

183 return SC->SymbolIndexBase + Idx;

184 }

185

189 }

190

191 typename MachOTraits::NList &nlist() {

193 return SC->Symbols[Idx];

194 }

195

196 private:

197 union {

199 SymbolContainer *SC;

200 };

201 size_t Idx;

202 };

203

206

208 unsigned Type)

210 assert(Type < 16 && "Relocation type out of range");

211 r_address = Offset;

217 }

218

221 }

222 };

223

225 const char *Data = nullptr;

227 };

228

233 SymbolContainer SC;

235

238 memset(&rawStruct(), 0, sizeof(typename MachOTraits::Section));

239 assert(SecName.size() <= 16 && "SecName too long");

240 assert(SegName.size() <= 16 && "SegName too long");

241 memcpy(this->sectname, SecName.data(), SecName.size());

242 memcpy(this->segname, SegName.data(), SegName.size());

243 }

244

248 typename MachOTraits::NList Sym;

249 Sym.n_strx = SI;

254 SC.Symbols.push_back(Sym);

255 return {SC, SC.Symbols.size() - 1};

256 }

257

261 }

262

264 return static_cast<typename MachOTraits::Section &>(*this);

265 }

266 };

267

270 std::vector<std::unique_ptr

> Sections;

271

274 assert(SegName.size() <= 16 && "SegName too long");

275 memcpy(this->segname, SegName.data(), SegName.size());

276 this->maxprot =

278 this->initprot = this->maxprot;

279 }

280

282 Sections.push_back(std::make_unique

(Builder, SecName, SegName));

284 }

285

287 bool SwapStruct) override {

289 Buf, Offset, SwapStruct);

293 }

294 };

295

298 Header.magic = MachOTraits::Magic;

299 }

300

303 static_assert(LCType != MachOTraits::SegmentCmd,

304 "Use addSegment to add segment load command");

305 auto LC = std::make_unique<MachOBuilderLoadCommand>(

306 std::forward(Args)...);

307 auto &Tmp = *LC;

308 LoadCommands.push_back(std::move(LC));

309 return Tmp;

310 }

311

313 if (Strings.empty() && !Str.empty())

315 return Strings.insert(std::make_pair(Str, Strings.size())).first->second;

316 }

317

319 Segments.push_back(Segment(*this, SegName));

320 return Segments.back();

321 }

322

326 typename MachOTraits::NList Sym;

327 Sym.n_strx = SI;

329 Sym.n_sect = Sect;

332 SC.Symbols.push_back(Sym);

333 return {SC, SC.Symbols.size() - 1};

334 }

335

336

337

338

339

341

342

343 makeStringTable();

345 if (!StrTab.empty())

346 SymTabLC = &addLoadCommandMachOTraits::SymTabCmd();

347

348

350 for (auto &Seg : Segments) {

351 Seg.cmdsize +=

352 Seg.Sections.size() * sizeof(typename MachOTraits::Section);

353 Seg.nsects = Seg.Sections.size();

354 Offset += Seg.cmdsize;

355 }

356 for (auto &LC : LoadCommands)

357 Offset += LC->size();

358

360

361

362 size_t SegVMAddr = 0;

363 for (auto &Seg : Segments) {

364 Seg.vmaddr = SegVMAddr;

365 Seg.fileoff = Offset;

366 for (auto &Sec : Seg.Sections) {

368 if (Sec->Content.Size)

369 Sec->offset = Offset;

370 Sec->size = Sec->Content.Size;

371 Sec->addr = SegVMAddr + Sec->offset - Seg.fileoff;

372 Offset += Sec->Content.Size;

373 }

374 size_t SegContentSize = Offset - Seg.fileoff;

375 Seg.filesize = SegContentSize;

377 ? SegContentSize

378 : alignTo(SegContentSize, PageSize);

379 SegVMAddr += Seg.vmsize;

380 }

381

382

383 for (auto &Sym : SC.Symbols)

384 Sym.n_strx = StrTab[Sym.n_strx].Offset;

385

386

387

388 size_t NumSymbols = SC.Symbols.size();

389 size_t SectionNumber = 0;

390 for (auto &Seg : Segments) {

391 for (auto &Sec : Seg.Sections) {

392 ++SectionNumber;

393 Sec->SectionNumber = SectionNumber;

394 Sec->SC.SymbolIndexBase = NumSymbols;

395 NumSymbols += Sec->SC.Symbols.size();

396 for (auto &Sym : Sec->SC.Symbols) {

397 Sym.n_sect = SectionNumber;

398 Sym.n_strx = StrTab[Sym.n_strx].Offset;

399 Sym.n_value += Sec->addr;

400 }

401 }

402 }

403

404

405 bool OffsetAlignedForRelocs = false;

406 for (auto &Seg : Segments) {

407 for (auto &Sec : Seg.Sections) {

408 if (!Sec->Relocs.empty()) {

409 if (!OffsetAlignedForRelocs) {

411 OffsetAlignedForRelocs = true;

412 }

413 Sec->reloff = Offset;

414 Sec->nreloc = Sec->Relocs.size();

416 for (auto &R : Sec->Relocs)

417 R.r_symbolnum = R.Target.isSymbol() ? R.Target.getSymbolNum()

418 : R.Target.getSectionId();

419 }

420 }

421 }

422

423

424 if (NumSymbols > 0) {

426 SymTabLC->symoff = Offset;

427 SymTabLC->nsyms = NumSymbols;

428

429

430 if (!StrTab.empty()) {

431 Offset += NumSymbols * sizeof(typename MachOTraits::NList);

432 size_t StringTableSize =

433 StrTab.back().Offset + StrTab.back().S.size() + 1;

434

435 SymTabLC->stroff = Offset;

436 SymTabLC->strsize = StringTableSize;

437 Offset += StringTableSize;

438 }

439 }

440

442 }

443

449 Offset = writeSectionContent(Buffer, Offset);

453 }

454

455 typename MachOTraits::Header Header;

456

457private:

458 void makeStringTable() {

459 if (Strings.empty())

460 return;

461

462 StrTab.resize(Strings.size());

463 for (auto &[Str, Idx] : Strings)

464 StrTab[Idx] = {Str, 0};

466 for (auto &Elem : StrTab) {

467 Elem.Offset = Offset;

468 Offset += Elem.S.size() + 1;

469 }

470 }

471

473 Header.ncmds = Segments.size() + LoadCommands.size();

475 }

476

478 for (auto &Seg : Segments)

479 Offset = Seg.write(Buf, Offset, swapStruct());

481 }

482

483 size_t writeLoadCommands(MutableArrayRef Buf, size_t Offset) {

484 for (auto &LC : LoadCommands)

485 Offset = LC->write(Buf, Offset, swapStruct());

487 }

488

489 size_t writeSectionContent(MutableArrayRef Buf, size_t Offset) {

490 for (auto &Seg : Segments) {

491 for (auto &Sec : Seg.Sections) {

492 if (!Sec->Content.Data) {

493 assert(Sec->Relocs.empty() &&

494 "Cant' have relocs for zero-fill segment");

495 continue;

496 }

497 while (Offset != Sec->offset)

498 Buf[Offset++] = '\0';

499

500 assert(Offset + Sec->Content.Size <= Buf.size() && "Buffer overflow");

501 memcpy(&Buf[Offset], Sec->Content.Data, Sec->Content.Size);

502 Offset += Sec->Content.Size;

503 }

504 }

506 }

507

508 size_t writeRelocations(MutableArrayRef Buf, size_t Offset) {

509 for (auto &Seg : Segments) {

510 for (auto &Sec : Seg.Sections) {

511 if (!Sec->Relocs.empty()) {

512 while (Offset % sizeof(MachO::relocation_info))

513 Buf[Offset++] = '\0';

514 }

515 for (auto &R : Sec->Relocs) {

516 assert(Offset + sizeof(MachO::relocation_info) <= Buf.size() &&

517 "Buffer overflow");

518 memcpy(&Buf[Offset], reinterpret_cast<const char *>(&R.rawStruct()),

519 sizeof(MachO::relocation_info));

520 Offset += sizeof(MachO::relocation_info);

521 }

522 }

523 }

525 }

526

527 size_t writeSymbols(MutableArrayRef Buf, size_t Offset) {

528

529

530 size_t NumSymbols = SC.Symbols.size();

531 for (auto &Seg : Segments)

532 for (auto &Sec : Seg.Sections)

533 NumSymbols += Sec->SC.Symbols.size();

534

535

536 if (NumSymbols == 0)

538

539

540 while (Offset % sizeof(typename MachOTraits::NList))

541 Buf[Offset++] = '\0';

542

543

544 for (auto &Sym : SC.Symbols)

546

547

548 for (auto &Seg : Segments) {

549 for (auto &Sec : Seg.Sections) {

550 for (auto &Sym : Sec->SC.Symbols) {

552 }

553 }

554 }

556 }

557

558 size_t writeStrings(MutableArrayRef Buf, size_t Offset) {

559 for (auto &Elem : StrTab) {

560 assert(Offset + Elem.S.size() + 1 <= Buf.size() && "Buffer overflow");

561 memcpy(&Buf[Offset], Elem.S.data(), Elem.S.size());

562 Offset += Elem.S.size();

563 Buf[Offset++] = '\0';

564 }

566 }

567

568 size_t PageSize;

570 std::vector<std::unique_ptr> LoadCommands;

571 SymbolContainer SC;

572

573

574 std::map<StringRef, size_t> Strings;

575 StringTable StrTab;

576};

577

584

589};

590

591}

592}

593

594#endif

Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

size_t size() const

size - Get the array size.

MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...

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

constexpr size_t size() const

size - Get the string size.

constexpr const char * data() const

data - Get a pointer to the start of the string (which may not be null terminated).

Target - Wrapper for Target specific information.

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM Value Representation.

RelocTarget(SymbolContainer &SC, size_t Idx)

MachOTraits::NList & nlist()

RelocTarget(const Section &S)

MachOBuilderLoadCommand< LCType > & addLoadCommand(ArgTs &&...Args)

void write(MutableArrayRef< char > Buffer)

RelocTarget addSymbol(StringRef Name, uint8_t Type, uint8_t Sect, uint16_t Desc, typename MachOTraits::UIntPtr Value)

StringId addString(StringRef Str)

MachOBuilder(size_t PageSize)

Segment & addSegment(StringRef SegName)

MachOTraits::Header Header

void swapStruct(fat_header &mh)

size_t writeMachOStruct(MutableArrayRef< char > Buf, size_t Offset, MachOStruct S, bool SwapStruct)

This is an optimization pass for GlobalISel generic memory operations.

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

OutputIt move(R &&Range, OutputIt Out)

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

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

Description of the encoding of one expression Op.

static constexpr uint32_t Magic

static constexpr llvm::endianness Endianness

static constexpr MachO::LoadCommandType SymTabCmd

static constexpr MachO::LoadCommandType SegmentCmd

Base type for MachOBuilder load command wrappers.

virtual size_t size() const =0

virtual size_t write(MutableArrayRef< char > Buf, size_t Offset, bool SwapStruct)=0

virtual ~MachOBuilderLoadCommandBase()

MachOBuilder load command wrapper type.

size_t write(MutableArrayRef< char > Buf, size_t Offset, bool SwapStruct) override

MachOBuilderLoadCommand(std::string Name, uint32_t Timestamp, uint32_t CurrentVersion, uint32_t CompatibilityVersion)

size_t write(MutableArrayRef< char > Buf, size_t Offset, bool SwapStruct) override

MachOBuilderLoadCommand(std::string Name, uint32_t Timestamp, uint32_t CurrentVersion, uint32_t CompatibilityVersion)

MachOBuilderLoadCommand(std::string Path)

size_t write(MutableArrayRef< char > Buf, size_t Offset, bool SwapStruct) override

MachOBuilderLoadCommand(ArgTs &&...Args)

MachOBuilderLoadCommand()=default

Reloc(int32_t Offset, RelocTarget Target, bool PCRel, unsigned Length, unsigned Type)

MachO::relocation_info & rawStruct()

void addReloc(int32_t Offset, RelocTarget Target, bool PCRel, unsigned Length, unsigned Type)

std::vector< Reloc > Relocs

Section(MachOBuilder &Builder, StringRef SecName, StringRef SegName)

RelocTarget addSymbol(int32_t Offset, StringRef Name, uint8_t Type, uint16_t Desc)

Segment(MachOBuilder &Builder, StringRef SegName)

Section & addSection(StringRef SecName, StringRef SegName)

std::vector< std::unique_ptr< Section > > Sections

size_t write(MutableArrayRef< char > Buf, size_t Offset, bool SwapStruct) override