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 <MachO::LoadCommandType LCType>

87

90 uint32_t CompatibilityVersion)

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

94 this->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 <>

112

113template <>

118

119template <>

124

125template <>

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

131 }

132

134 bool SwapStruct) override {

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

138 }

139

141};

142

143

145private:

146 struct SymbolContainer {

147 size_t SymbolIndexBase = 0;

148 std::vector Symbols;

149 };

150

151 struct StringTableEntry {

154 };

155

156 using StringTable = std::vector;

157

158 static bool swapStruct() {

160 }

161

162public:

164

166

167

168

170 public:

173

175

178 return SC->SymbolIndexBase + Idx;

179 }

180

183 return S->SectionNumber;

184 }

185

186 typename MachOTraits::NList &nlist() {

188 return SC->Symbols[Idx];

189 }

190

191 private:

192 union {

194 SymbolContainer *SC;

195 };

196 size_t Idx;

197 };

198

218

220 const char *Data = nullptr;

222 };

223

228 SymbolContainer SC;

230

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

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

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

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

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

238 }

239

243 typename MachOTraits::NList Sym;

244 Sym.n_strx = SI;

246 Sym.n_sect = MachO::NO_SECT;

247 Sym.n_desc = Desc;

248 Sym.n_value = Offset;

249 SC.Symbols.push_back(Sym);

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

251 }

252

257

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

260 }

261 };

262

265 std::vector<std::unique_ptr

> Sections;

266

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

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

271 this->maxprot =

273 this->initprot = this->maxprot;

274 }

275

277 Sections.push_back(std::make_unique

(Builder, SecName, SegName));

279 }

280

282 bool SwapStruct) override {

284 Buf, Offset, SwapStruct);

288 }

289 };

290

293 Header.magic = MachOTraits::Magic;

294 }

295

298 static_assert(LCType != MachOTraits::SegmentCmd,

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

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

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

302 auto &Tmp = *LC;

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

304 return Tmp;

305 }

306

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

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

311 }

312

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

315 return Segments.back();

316 }

317

321 typename MachOTraits::NList Sym;

322 Sym.n_strx = SI;

323 Sym.n_type = Type;

324 Sym.n_sect = Sect;

325 Sym.n_desc = Desc;

326 Sym.n_value = Value;

327 SC.Symbols.push_back(Sym);

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

329 }

330

331

332

333

334

336

337

338 makeStringTable();

340 if (!StrTab.empty())

342

343

345 for (auto &Seg : Segments) {

346 Seg.cmdsize +=

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

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

349 Offset += Seg.cmdsize;

350 }

351 for (auto &LC : LoadCommands)

352 Offset += LC->size();

353

355

356

357 size_t SegVMAddr = 0;

358 for (auto &Seg : Segments) {

359 Seg.vmaddr = SegVMAddr;

360 Seg.fileoff = Offset;

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

363 if (Sec->Content.Size)

364 Sec->offset = Offset;

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

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

367 Offset += Sec->Content.Size;

368 }

369 size_t SegContentSize = Offset - Seg.fileoff;

370 Seg.filesize = SegContentSize;

372 ? SegContentSize

373 : alignTo(SegContentSize, PageSize);

374 SegVMAddr += Seg.vmsize;

375 }

376

377

378 for (auto &Sym : SC.Symbols)

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

380

381

382

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

384 size_t SectionNumber = 0;

385 for (auto &Seg : Segments) {

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

387 ++SectionNumber;

388 Sec->SectionNumber = SectionNumber;

389 Sec->SC.SymbolIndexBase = NumSymbols;

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

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

392 Sym.n_sect = SectionNumber;

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

394 Sym.n_value += Sec->addr;

395 }

396 }

397 }

398

399

400 bool OffsetAlignedForRelocs = false;

401 for (auto &Seg : Segments) {

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

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

404 if (!OffsetAlignedForRelocs) {

406 OffsetAlignedForRelocs = true;

407 }

408 Sec->reloff = Offset;

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

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

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

413 : R.Target.getSectionId();

414 }

415 }

416 }

417

418

419 if (NumSymbols > 0) {

421 SymTabLC->symoff = Offset;

422 SymTabLC->nsyms = NumSymbols;

423

424

425 if (!StrTab.empty()) {

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

427 size_t StringTableSize =

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

429

430 SymTabLC->stroff = Offset;

431 SymTabLC->strsize = StringTableSize;

432 Offset += StringTableSize;

433 }

434 }

435

437 }

438

449

450 typename MachOTraits::Header Header;

451

452private:

453 void makeStringTable() {

454 if (Strings.empty())

455 return;

456

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

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

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

461 for (auto &Elem : StrTab) {

462 Elem.Offset = Offset;

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

464 }

465 }

466

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

470 }

471

473 for (auto &Seg : Segments)

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

476 }

477

478 size_t writeLoadCommands(MutableArrayRef Buf, size_t Offset) {

479 for (auto &LC : LoadCommands)

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

482 }

483

484 size_t writeSectionContent(MutableArrayRef Buf, size_t Offset) {

485 for (auto &Seg : Segments) {

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

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

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

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

490 continue;

491 }

492 while (Offset != Sec->offset)

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

494

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

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

497 Offset += Sec->Content.Size;

498 }

499 }

501 }

502

503 size_t writeRelocations(MutableArrayRef Buf, size_t Offset) {

504 for (auto &Seg : Segments) {

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

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

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

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

509 }

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

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

512 "Buffer overflow");

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

514 sizeof(MachO::relocation_info));

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

516 }

517 }

518 }

520 }

521

522 size_t writeSymbols(MutableArrayRef Buf, size_t Offset) {

523

524

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

526 for (auto &Seg : Segments)

527 for (auto &Sec : Seg.Sections)

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

529

530

531 if (NumSymbols == 0)

533

534

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

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

537

538

539 for (auto &Sym : SC.Symbols)

541

542

543 for (auto &Seg : Segments) {

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

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

547 }

548 }

549 }

551 }

552

553 size_t writeStrings(MutableArrayRef Buf, size_t Offset) {

554 for (auto &Elem : StrTab) {

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

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

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

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

559 }

561 }

562

563 size_t PageSize;

564 std::list Segments;

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

566 SymbolContainer SC;

567

568

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

570 StringTable StrTab;

571};

572

585

586}

587}

588

589#endif

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

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.

Definition MachOBuilder.h:169

bool isSymbol()

Definition MachOBuilder.h:174

uint32_t getSymbolNum()

Definition MachOBuilder.h:176

RelocTarget(SymbolContainer &SC, size_t Idx)

Definition MachOBuilder.h:172

MachOTraits::NList & nlist()

Definition MachOBuilder.h:186

SymbolContainer * SC

Definition MachOBuilder.h:194

RelocTarget(const Section &S)

Definition MachOBuilder.h:171

const Section * S

Definition MachOBuilder.h:193

uint32_t getSectionId()

Definition MachOBuilder.h:181

size_t layout()

Definition MachOBuilder.h:335

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

Definition MachOBuilder.h:297

void write(MutableArrayRef< char > Buffer)

Definition MachOBuilder.h:439

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

Definition MachOBuilder.h:318

StringId addString(StringRef Str)

Definition MachOBuilder.h:307

MachOBuilder(size_t PageSize)

Definition MachOBuilder.h:291

size_t StringId

Definition MachOBuilder.h:163

Segment & addSegment(StringRef SegName)

Definition MachOBuilder.h:313

MachOTraits::Header Header

Definition MachOBuilder.h:450

void swapStruct(fat_header &mh)

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

Definition MachOBuilder.h:28

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.

Definition MachOBuilder.h:573

static constexpr uint32_t Magic

Definition MachOBuilder.h:581

MachO::nlist_64 NList

Definition MachOBuilder.h:577

MachO::relocation_info Relocation

Definition MachOBuilder.h:578

static constexpr llvm::endianness Endianness

Definition MachOBuilder.h:580

uint64_t UIntPtr

Definition MachOBuilder.h:574

static constexpr MachO::LoadCommandType SymTabCmd

Definition MachOBuilder.h:583

static constexpr MachO::LoadCommandType SegmentCmd

Definition MachOBuilder.h:582

MachO::section_64 Section

Definition MachOBuilder.h:576

MachO::mach_header_64 Header

Definition MachOBuilder.h:575

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

Definition MachOBuilder.h:88

std::string Name

Definition MachOBuilder.h:104

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

Definition MachOBuilder.h:97

Base type for MachOBuilder load command wrappers.

Definition MachOBuilder.h:38

virtual size_t size() const =0

virtual ~MachOBuilderLoadCommandBase()=default

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

MachOBuilder load command wrapper type.

Definition MachOBuilder.h:46

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

Definition MachOBuilder.h:88

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

Definition MachOBuilder.h:88

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

Definition MachOBuilder.h:88

std::string Path

Definition MachOBuilder.h:140

MachOBuilderLoadCommand(std::string Path)

Definition MachOBuilder.h:128

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

Definition MachOBuilder.h:133

Definition MachOBuilder.h:75

MachOBuilderLoadCommand(ArgTs &&...Args)

Definition MachOBuilder.h:80

MachOBuilderLoadCommand()=default

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

Definition MachOBuilder.h:202

RelocTarget Target

Definition MachOBuilder.h:200

MachO::relocation_info & rawStruct()

Definition MachOBuilder.h:214

Definition MachOBuilder.h:219

const char * Data

Definition MachOBuilder.h:220

size_t Size

Definition MachOBuilder.h:221

Definition MachOBuilder.h:224

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

Definition MachOBuilder.h:253

SymbolContainer SC

Definition MachOBuilder.h:228

size_t SectionNumber

Definition MachOBuilder.h:227

std::vector< Reloc > Relocs

Definition MachOBuilder.h:229

auto & rawStruct()

Definition MachOBuilder.h:258

SectionContent Content

Definition MachOBuilder.h:226

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

Definition MachOBuilder.h:231

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

Definition MachOBuilder.h:240

MachOBuilder & Builder

Definition MachOBuilder.h:225

Definition MachOBuilder.h:263

Segment(MachOBuilder &Builder, StringRef SegName)

Definition MachOBuilder.h:267

Section & addSection(StringRef SecName, StringRef SegName)

Definition MachOBuilder.h:276

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

Definition MachOBuilder.h:265

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

Definition MachOBuilder.h:281

MachOBuilder & Builder

Definition MachOBuilder.h:264