LLVM: lib/ObjectYAML/MachOEmitter.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

25

26using namespace llvm;

27

28namespace {

29

30static const char *getLoadCommandName(uint32_t cmd) {

31 switch (cmd) {

32#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \

33 case MachO::LCName: \

34 return #LCName;

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

36 default:

37 return nullptr;

38 }

39}

40

41class MachOWriter {

42public:

43 MachOWriter(MachOYAML::Object &Obj) : Obj(Obj), fileStart(0) {

46 memset(reinterpret_cast<void *>(&Header), 0, sizeof(MachO::mach_header_64));

47 }

48

49 Error writeMachO(raw_ostream &OS);

50

51private:

52 void writeHeader(raw_ostream &OS);

53 void writeLoadCommands(raw_ostream &OS);

54 Error writeSectionData(raw_ostream &OS);

55 void writeRelocations(raw_ostream &OS);

56 void writeLinkEditData(raw_ostream &OS);

57

58 void writeBindOpcodes(raw_ostream &OS,

59 std::vectorMachOYAML::BindOpcode &BindOpcodes);

60

61 void writeRebaseOpcodes(raw_ostream &OS);

62 void writeBasicBindOpcodes(raw_ostream &OS);

63 void writeWeakBindOpcodes(raw_ostream &OS);

64 void writeLazyBindOpcodes(raw_ostream &OS);

65 void writeNameList(raw_ostream &OS);

66 void writeStringTable(raw_ostream &OS);

67 void writeExportTrie(raw_ostream &OS);

68 void writeDynamicSymbolTable(raw_ostream &OS);

69 void writeFunctionStarts(raw_ostream &OS);

70 void writeChainedFixups(raw_ostream &OS);

71 void writeDyldExportsTrie(raw_ostream &OS);

72 void writeDataInCode(raw_ostream &OS);

73

74 void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);

75 void ZeroToOffset(raw_ostream &OS, size_t offset);

76

77 MachOYAML::Object &Obj;

78 bool is64Bit;

79 uint64_t fileStart;

80 MachO::mach_header_64 Header;

81

82

83

84 bool FoundLinkEditSeg = false;

85};

86

88 fileStart = OS.tell();

89 writeHeader(OS);

90 writeLoadCommands(OS);

91 if (Error Err = writeSectionData(OS))

92 return Err;

93 writeRelocations(OS);

94 if (!FoundLinkEditSeg)

95 writeLinkEditData(OS);

97}

98

99void MachOWriter::writeHeader(raw_ostream &OS) {

100 Header.magic = Obj.Header.magic;

104 Header.ncmds = Obj.Header.ncmds;

106 Header.flags = Obj.Header.flags;

108

111

112 auto header_size =

113 is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);

114 OS.write((const char *)&Header, header_size);

115}

116

117template

120 memcpy(reinterpret_cast<void *>(&TempSec.sectname[0]), &Sec.sectname[0], 16);

121 memcpy(reinterpret_cast<void *>(&TempSec.segname[0]), &Sec.segname[0], 16);

122 TempSec.addr = Sec.addr;

123 TempSec.size = Sec.size;

124 TempSec.offset = Sec.offset;

125 TempSec.align = Sec.align;

126 TempSec.reloff = Sec.reloff;

127 TempSec.nreloc = Sec.nreloc;

128 TempSec.flags = Sec.flags;

129 TempSec.reserved1 = Sec.reserved1;

130 TempSec.reserved2 = Sec.reserved2;

131 return TempSec;

132}

133

134template

135size_t writeLoadCommandData(MachOYAML::LoadCommand &LC, raw_ostream &OS,

136 bool IsLittleEndian) {

137 return 0;

138}

139

140template <>

141size_t writeLoadCommandDataMachO::segment\_command(MachOYAML::LoadCommand &LC,

142 raw_ostream &OS,

143 bool IsLittleEndian) {

144 size_t BytesWritten = 0;

145 for (const auto &Sec : LC.Sections) {

149 OS.write(reinterpret_cast<const char *>(&(TempSec)),

150 sizeof(MachO::section));

151 BytesWritten += sizeof(MachO::section);

152 }

153 return BytesWritten;

154}

155

156template <>

157size_t writeLoadCommandDataMachO::segment\_command\_64(

158 MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {

159 size_t BytesWritten = 0;

160 for (const auto &Sec : LC.Sections) {

162 TempSec.reserved3 = Sec.reserved3;

165 OS.write(reinterpret_cast<const char *>(&(TempSec)),

166 sizeof(MachO::section_64));

167 BytesWritten += sizeof(MachO::section_64);

168 }

169 return BytesWritten;

170}

171

172size_t writePayloadString(MachOYAML::LoadCommand &LC, raw_ostream &OS) {

173 size_t BytesWritten = 0;

174 if (!LC.Content.empty()) {

176 BytesWritten = LC.Content.length();

177 }

178 return BytesWritten;

179}

180

181template <>

182size_t writeLoadCommandDataMachO::dylib\_command(MachOYAML::LoadCommand &LC,

183 raw_ostream &OS,

184 bool IsLittleEndian) {

185 return writePayloadString(LC, OS);

186}

187

188template <>

189size_t writeLoadCommandDataMachO::dylinker\_command(MachOYAML::LoadCommand &LC,

190 raw_ostream &OS,

191 bool IsLittleEndian) {

192 return writePayloadString(LC, OS);

193}

194

195template <>

196size_t writeLoadCommandDataMachO::rpath\_command(MachOYAML::LoadCommand &LC,

197 raw_ostream &OS,

198 bool IsLittleEndian) {

199 return writePayloadString(LC, OS);

200}

201

202template <>

203size_t writeLoadCommandDataMachO::sub\_framework\_command(

204 MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {

205 return writePayloadString(LC, OS);

206}

207

208template <>

209size_t writeLoadCommandDataMachO::sub\_umbrella\_command(

210 MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {

211 return writePayloadString(LC, OS);

212}

213

214template <>

215size_t writeLoadCommandDataMachO::sub\_client\_command(

216 MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {

217 return writePayloadString(LC, OS);

218}

219

220template <>

221size_t writeLoadCommandDataMachO::sub\_library\_command(

222 MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {

223 return writePayloadString(LC, OS);

224}

225

226template <>

227size_t writeLoadCommandDataMachO::build\_version\_command(

228 MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {

229 size_t BytesWritten = 0;

230 for (const auto &T : LC.Tools) {

231 struct MachO::build_tool_version tool = T;

234 OS.write(reinterpret_cast<const char *>(&tool),

235 sizeof(MachO::build_tool_version));

236 BytesWritten += sizeof(MachO::build_tool_version);

237 }

238 return BytesWritten;

239}

240

242 std::vector<uint8_t> FillData(Size, 0);

243 OS.write(reinterpret_cast<char *>(FillData.data()), Size);

244}

245

246void Fill(raw_ostream &OS, size_t Size, uint32_t Data) {

247 std::vector<uint32_t> FillData((Size / 4) + 1, Data);

248 OS.write(reinterpret_cast<char *>(FillData.data()), Size);

249}

250

251void MachOWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {

252 auto currOffset = OS.tell() - fileStart;

253 if (currOffset < Offset)

255}

256

257void MachOWriter::writeLoadCommands(raw_ostream &OS) {

258 for (size_t i = 0; i < Obj.LoadCommands.size(); ++i) {

259 auto &LC = Obj.LoadCommands[i];

260 size_t BytesWritten = 0;

261 llvm::MachO::macho_load_command Data = LC.Data;

262

263#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \

264 case MachO::LCName: \

265 if (Obj.IsLittleEndian != sys::IsLittleEndianHost) \

266 MachO::swapStruct(Data.LCStruct##_data); \

267 OS.write(reinterpret_cast<const char *>(&(Data.LCStruct##_data)), \

268 sizeof(MachO::LCStruct)); \

269 BytesWritten = sizeof(MachO::LCStruct); \

270 BytesWritten += \

271 writeLoadCommandDataMachO::LCStruct(LC, OS, Obj.IsLittleEndian); \

272 break;

273

274 switch (LC.Data.load_command_data.cmd) {

275 default:

278 OS.write(reinterpret_cast<const char *>(&(Data.load_command_data)),

279 sizeof(MachO::load_command));

280 BytesWritten = sizeof(MachO::load_command);

281 BytesWritten +=

282 writeLoadCommandDataMachO::load\_command(LC, OS, Obj.IsLittleEndian);

283 break;

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

285 }

286

291 }

292

296 }

297

298

299

300

301 if (BytesWritten > LC.Data.load_command_data.cmdsize) {

302 std::string Name;

303 const char *NameCStr = getLoadCommandName(LC.Data.load_command_data.cmd);

304 if (NameCStr)

305 Name = NameCStr;

306 else

308 .str();

309

311 << " cmdsize too small ("

312 << LC.Data.load_command_data.cmdsize

313 << " bytes) for actual size (" << BytesWritten

314 << " bytes)\n";

315 }

316 auto BytesRemaining = (BytesWritten < LC.Data.load_command_data.cmdsize)

317 ? LC.Data.load_command_data.cmdsize - BytesWritten

318 : 0;

319 if (BytesRemaining > 0) {

321 }

322 }

323}

324

325Error MachOWriter::writeSectionData(raw_ostream &OS) {

326 uint64_t LinkEditOff = 0;

327 for (auto &LC : Obj.LoadCommands) {

328 switch (LC.Data.load_command_data.cmd) {

329 case MachO::LC_SEGMENT:

330 case MachO::LC_SEGMENT_64:

331 uint64_t segOff = is64Bit ? LC.Data.segment_command_64_data.fileoff

332 : LC.Data.segment_command_data.fileoff;

333 if (0 ==

334 strncmp(&LC.Data.segment_command_data.segname[0], "__LINKEDIT", 16)) {

335 FoundLinkEditSeg = true;

336 LinkEditOff = segOff;

337 if (Obj.RawLinkEditSegment)

338 continue;

339 writeLinkEditData(OS);

340 }

341 for (auto &Sec : LC.Sections) {

342 ZeroToOffset(OS, Sec.offset);

343

344

345 if (OS.tell() - fileStart > Sec.offset && Sec.offset != (uint32_t)0)

347 errc::invalid_argument,

349 "wrote too much data somewhere, section offsets in "

350 "section {0} for segment {1} don't line up: "

351 "[cursor={2:x}], [fileStart={3:x}], [sectionOffset={4:x}]",

354

355 StringRef SectName(Sec.sectname,

357

358

359 if (Obj.DWARF.getNonEmptySectionNames().count(SectName.substr(2))) {

362 "cannot specify section '" + SectName +

363 "' contents in the 'DWARF' entry and "

364 "the 'content' at the same time");

366 if (Error Err = EmitFunc(OS, Obj.DWARF))

367 return Err;

368 continue;

369 }

370

371

373 continue;

374

376 yaml::BinaryRef Content = *Sec.content;

379 } else {

380

381 Fill(OS, Sec.size, 0xDEADBEEFu);

382 }

383 }

384 uint64_t segSize = is64Bit ? LC.Data.segment_command_64_data.filesize

385 : LC.Data.segment_command_data.filesize;

386 ZeroToOffset(OS, segOff + segSize);

387 break;

388 }

389 }

390

391 if (Obj.RawLinkEditSegment) {

392 ZeroToOffset(OS, LinkEditOff);

393 if (OS.tell() - fileStart > LinkEditOff || !LinkEditOff)

395 "section offsets don't line up");

396 Obj.RawLinkEditSegment->writeAsBinary(OS);

397 }

399}

400

401

402

403

404

405static MachO::any_relocation_info

406makeRelocationInfo(const MachOYAML::Relocation &R, bool IsLE) {

407 assert(R.is_scattered && "non-scattered relocation expected");

408 MachO::any_relocation_info MRE;

410 if (IsLE)

411 MRE.r_word1 = ((unsigned)R.symbolnum << 0) | ((unsigned)R.is_pcrel << 24) |

412 ((unsigned)R.length << 25) | ((unsigned)R.is_extern << 27) |

413 ((unsigned)R.type << 28);

414 else

415 MRE.r_word1 = ((unsigned)R.symbolnum << 8) | ((unsigned)R.is_pcrel << 7) |

416 ((unsigned)R.length << 5) | ((unsigned)R.is_extern << 4) |

417 ((unsigned)R.type << 0);

418 return MRE;

419}

420

421static MachO::any_relocation_info

422makeScatteredRelocationInfo(const MachOYAML::Relocation &R) {

423 assert(R.is_scattered && "scattered relocation expected");

424 MachO::any_relocation_info MRE;

425 MRE.r_word0 = (((unsigned)R.address << 0) | ((unsigned)R.type << 24) |

426 ((unsigned)R.length << 28) | ((unsigned)R.is_pcrel << 30) |

429 return MRE;

430}

431

432void MachOWriter::writeRelocations(raw_ostream &OS) {

433 for (const MachOYAML::LoadCommand &LC : Obj.LoadCommands) {

434 switch (LC.Data.load_command_data.cmd) {

435 case MachO::LC_SEGMENT:

436 case MachO::LC_SEGMENT_64:

437 for (const MachOYAML::Section &Sec : LC.Sections) {

439 continue;

440 ZeroToOffset(OS, Sec.reloff);

441 for (const MachOYAML::Relocation &R : Sec.relocations) {

442 MachO::any_relocation_info MRE =

443 R.is_scattered ? makeScatteredRelocationInfo(R)

444 : makeRelocationInfo(R, Obj.IsLittleEndian);

447 OS.write(reinterpret_cast<const char *>(&MRE),

448 sizeof(MachO::any_relocation_info));

449 }

450 }

451 }

452 }

453}

454

455void MachOWriter::writeBindOpcodes(

456 raw_ostream &OS, std::vectorMachOYAML::BindOpcode &BindOpcodes) {

457

458 for (const auto &Opcode : BindOpcodes) {

459 uint8_t OpByte = Opcode.Opcode | Opcode.Imm;

460 OS.write(reinterpret_cast<char *>(&OpByte), 1);

461 for (auto Data : Opcode.ULEBExtraData) {

463 }

464 for (auto Data : Opcode.SLEBExtraData) {

466 }

467 if (!Opcode.Symbol.empty()) {

468 OS.write(Opcode.Symbol.data(), Opcode.Symbol.size());

470 }

471 }

472}

473

474void MachOWriter::dumpExportEntry(raw_ostream &OS,

475 MachOYAML::ExportEntry &Entry) {

477 if (Entry.TerminalSize > 0) {

481 OS << Entry.ImportName;

483 } else {

487 }

488 }

489 OS.write(static_cast<uint8_t>(Entry.Children.size()));

490 for (const auto &EE : Entry.Children) {

491 OS << EE.Name;

494 }

495 for (auto EE : Entry.Children)

496 dumpExportEntry(OS, EE);

497}

498

499void MachOWriter::writeExportTrie(raw_ostream &OS) {

500 dumpExportEntry(OS, Obj.LinkEdit.ExportTrie);

501}

502

503template

504void writeNListEntry(MachOYAML::NListEntry &NLE, raw_ostream &OS,

505 bool IsLittleEndian) {

507 ListEntry.n_strx = NLE.n_strx;

508 ListEntry.n_type = NLE.n_type;

509 ListEntry.n_sect = NLE.n_sect;

510 ListEntry.n_desc = NLE.n_desc;

511 ListEntry.n_value = NLE.n_value;

512

515 OS.write(reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));

516}

517

518void MachOWriter::writeLinkEditData(raw_ostream &OS) {

519 typedef void (MachOWriter::*writeHandler)(raw_ostream &);

520 typedef std::pair<uint64_t, writeHandler> writeOperation;

521 std::vector WriteQueue;

522

523 MachO::dyld_info_command *DyldInfoOnlyCmd = nullptr;

524 MachO::symtab_command *SymtabCmd = nullptr;

525 MachO::dysymtab_command *DSymtabCmd = nullptr;

526 MachO::linkedit_data_command *FunctionStartsCmd = nullptr;

527 MachO::linkedit_data_command *ChainedFixupsCmd = nullptr;

528 MachO::linkedit_data_command *DyldExportsTrieCmd = nullptr;

529 MachO::linkedit_data_command *DataInCodeCmd = nullptr;

530 for (auto &LC : Obj.LoadCommands) {

531 switch (LC.Data.load_command_data.cmd) {

532 case MachO::LC_SYMTAB:

533 SymtabCmd = &LC.Data.symtab_command_data;

534 WriteQueue.push_back(

535 std::make_pair(SymtabCmd->symoff, &MachOWriter::writeNameList));

536 WriteQueue.push_back(

537 std::make_pair(SymtabCmd->stroff, &MachOWriter::writeStringTable));

538 break;

539 case MachO::LC_DYLD_INFO_ONLY:

540 DyldInfoOnlyCmd = &LC.Data.dyld_info_command_data;

541 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->rebase_off,

542 &MachOWriter::writeRebaseOpcodes));

543 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->bind_off,

544 &MachOWriter::writeBasicBindOpcodes));

545 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->weak_bind_off,

546 &MachOWriter::writeWeakBindOpcodes));

547 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->lazy_bind_off,

548 &MachOWriter::writeLazyBindOpcodes));

549 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->export_off,

550 &MachOWriter::writeExportTrie));

551 break;

552 case MachO::LC_DYSYMTAB:

553 DSymtabCmd = &LC.Data.dysymtab_command_data;

554 WriteQueue.push_back(std::make_pair(

555 DSymtabCmd->indirectsymoff, &MachOWriter::writeDynamicSymbolTable));

556 break;

557 case MachO::LC_FUNCTION_STARTS:

558 FunctionStartsCmd = &LC.Data.linkedit_data_command_data;

559 WriteQueue.push_back(std::make_pair(FunctionStartsCmd->dataoff,

560 &MachOWriter::writeFunctionStarts));

561 break;

562 case MachO::LC_DYLD_CHAINED_FIXUPS:

563 ChainedFixupsCmd = &LC.Data.linkedit_data_command_data;

564 WriteQueue.push_back(std::make_pair(ChainedFixupsCmd->dataoff,

565 &MachOWriter::writeChainedFixups));

566 break;

567 case MachO::LC_DYLD_EXPORTS_TRIE:

568 DyldExportsTrieCmd = &LC.Data.linkedit_data_command_data;

569 WriteQueue.push_back(std::make_pair(DyldExportsTrieCmd->dataoff,

570 &MachOWriter::writeDyldExportsTrie));

571 break;

572 case MachO::LC_DATA_IN_CODE:

573 DataInCodeCmd = &LC.Data.linkedit_data_command_data;

574 WriteQueue.push_back(std::make_pair(DataInCodeCmd->dataoff,

575 &MachOWriter::writeDataInCode));

576 break;

577 }

578 }

579

580 llvm::sort(WriteQueue, llvm::less_first());

581

582 for (auto writeOp : WriteQueue) {

583 ZeroToOffset(OS, writeOp.first);

584 (this->*writeOp.second)(OS);

585 }

586}

587

588void MachOWriter::writeRebaseOpcodes(raw_ostream &OS) {

589 MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;

590

591 for (const auto &Opcode : LinkEdit.RebaseOpcodes) {

592 uint8_t OpByte = Opcode.Opcode | Opcode.Imm;

593 OS.write(reinterpret_cast<char *>(&OpByte), 1);

594 for (auto Data : Opcode.ExtraData)

596 }

597}

598

599void MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) {

600 writeBindOpcodes(OS, Obj.LinkEdit.BindOpcodes);

601}

602

603void MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) {

604 writeBindOpcodes(OS, Obj.LinkEdit.WeakBindOpcodes);

605}

606

607void MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) {

608 writeBindOpcodes(OS, Obj.LinkEdit.LazyBindOpcodes);

609}

610

611void MachOWriter::writeNameList(raw_ostream &OS) {

612 for (auto NLE : Obj.LinkEdit.NameList) {

615 else

617 }

618}

619

620void MachOWriter::writeStringTable(raw_ostream &OS) {

621 for (auto Str : Obj.LinkEdit.StringTable) {

622 OS.write(Str.data(), Str.size());

624 }

625}

626

627void MachOWriter::writeDynamicSymbolTable(raw_ostream &OS) {

628 for (auto Data : Obj.LinkEdit.IndirectSymbols)

629 OS.write(reinterpret_cast<const char *>(&Data),

630 sizeof(yaml::Hex32::BaseType));

631}

632

633void MachOWriter::writeFunctionStarts(raw_ostream &OS) {

634 uint64_t Addr = 0;

635 for (uint64_t NextAddr : Obj.LinkEdit.FunctionStarts) {

636 uint64_t Delta = NextAddr - Addr;

638 Addr = NextAddr;

639 }

640

642}

643

644void MachOWriter::writeDataInCode(raw_ostream &OS) {

645 for (const auto &Entry : Obj.LinkEdit.DataInCode) {

646 MachO::data_in_code_entry DICE{Entry.Offset, Entry.Length, Entry.Kind};

649 OS.write(reinterpret_cast<const char *>(&DICE),

650 sizeof(MachO::data_in_code_entry));

651 }

652}

653

654void MachOWriter::writeChainedFixups(raw_ostream &OS) {

655 if (Obj.LinkEdit.ChainedFixups.size() > 0)

656 OS.write(reinterpret_cast<const char *>(Obj.LinkEdit.ChainedFixups.data()),

657 Obj.LinkEdit.ChainedFixups.size());

658}

659

660void MachOWriter::writeDyldExportsTrie(raw_ostream &OS) {

661 dumpExportEntry(OS, Obj.LinkEdit.ExportTrie);

662}

663

664class UniversalWriter {

665public:

666 UniversalWriter(yaml::YamlObjectFile &ObjectFile)

668

669 Error writeMachO(raw_ostream &OS);

670

671private:

672 void writeFatHeader(raw_ostream &OS);

673 void writeFatArchs(raw_ostream &OS);

674

675 void ZeroToOffset(raw_ostream &OS, size_t offset);

676

678 uint64_t fileStart;

679};

680

681Error UniversalWriter::writeMachO(raw_ostream &OS) {

682 fileStart = OS.tell();

684 MachOWriter Writer(*ObjectFile.MachO);

685 return Writer.writeMachO(OS);

686 }

687

688 writeFatHeader(OS);

689 writeFatArchs(OS);

690

691 auto &FatFile = *ObjectFile.FatMachO;

692 if (FatFile.FatArchs.size() < FatFile.Slices.size())

694 errc::invalid_argument,

695 "cannot write 'Slices' if not described in 'FatArches'");

696

697 for (size_t i = 0; i < FatFile.Slices.size(); i++) {

698 ZeroToOffset(OS, FatFile.FatArchs[i].offset);

699 MachOWriter Writer(FatFile.Slices[i]);

700 if (Error Err = Writer.writeMachO(OS))

701 return Err;

702

703 auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;

704 ZeroToOffset(OS, SliceEnd);

705 }

706

708}

709

710void UniversalWriter::writeFatHeader(raw_ostream &OS) {

711 auto &FatFile = *ObjectFile.FatMachO;

712 MachO::fat_header header;

713 header.magic = FatFile.Header.magic;

714 header.nfat_arch = FatFile.Header.nfat_arch;

717 OS.write(reinterpret_cast<const char *>(&header), sizeof(MachO::fat_header));

718}

719

720template

721FatArchType constructFatArch(MachOYAML::FatArch &Arch) {

722 FatArchType FatArch;

723 FatArch.cputype = Arch.cputype;

724 FatArch.cpusubtype = Arch.cpusubtype;

725 FatArch.offset = Arch.offset;

726 FatArch.size = Arch.size;

727 FatArch.align = Arch.align;

728 return FatArch;

729}

730

731template

732void writeFatArch(MachOYAML::FatArch &LC, raw_ostream &OS) {}

733

734template <>

735void writeFatArchMachO::fat\_arch(MachOYAML::FatArch &Arch, raw_ostream &OS) {

736 auto FatArch = constructFatArchMachO::fat\_arch(Arch);

739 OS.write(reinterpret_cast<const char *>(&FatArch), sizeof(MachO::fat_arch));

740}

741

742template <>

743void writeFatArchMachO::fat\_arch\_64(MachOYAML::FatArch &Arch,

744 raw_ostream &OS) {

745 auto FatArch = constructFatArchMachO::fat\_arch\_64(Arch);

746 FatArch.reserved = Arch.reserved;

749 OS.write(reinterpret_cast<const char *>(&FatArch),

750 sizeof(MachO::fat_arch_64));

751}

752

753void UniversalWriter::writeFatArchs(raw_ostream &OS) {

754 auto &FatFile = *ObjectFile.FatMachO;

756 for (auto Arch : FatFile.FatArchs) {

758 writeFatArchMachO::fat\_arch\_64(Arch, OS);

759 else

760 writeFatArchMachO::fat\_arch(Arch, OS);

761 }

762}

763

764void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {

765 auto currOffset = OS.tell() - fileStart;

766 if (currOffset < Offset)

768}

769

770}

771

772namespace llvm {

773namespace yaml {

774

776 UniversalWriter Writer(Doc);

777 if (Error Err = Writer.writeMachO(Out)) {

779 [&](const ErrorInfoBase &Err) { EH(Err.message()); });

780 return false;

781 }

782 return true;

783}

784

785}

786}

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

static void ZeroFillBytes(raw_ostream &OS, size_t Size)

Common declarations for yaml2obj.

Section constructSection(const MachO::section &Sec, uint32_t Index)

void writeNListEntry(const SymbolEntry &SE, bool IsLittleEndian, char *&Out, uint32_t Nstrx)

static bool is64Bit(const char *name)

Base class for error info classes.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

static Twine utohexstr(uint64_t Val)

static LLVM_ABI raw_ostream & warning()

Convenience method for printing "warning: " to stderr.

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

uint64_t tell() const

tell - Return the current offset with the file.

raw_ostream & write(unsigned char C)

ArrayRef< uint8_t >::size_type binary_size() const

The number of bytes that are represented by this BinaryRef.

LLVM_ABI void writeAsBinary(raw_ostream &OS, uint64_t N=UINT64_MAX) const

Write the contents (regardless of whether it is binary or a hex string) as binary to the given raw_os...

LLVM_ABI std::function< Error(raw_ostream &, const Data &)> getDWARFEmitterByName(StringRef SecName)

@ EXPORT_SYMBOL_FLAGS_REEXPORT

@ EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER

bool isVirtualSection(uint8_t type)

SectionType

These are the section type and attributes fields.

void swapStruct(fat_header &mh)

constexpr bool IsLittleEndianHost

llvm::function_ref< void(const Twine &Msg)> ErrorHandler

LLVM_ABI bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out, ErrorHandler EH)

Definition MachOEmitter.cpp:775

This is an optimization pass for GlobalISel generic memory operations.

void handleAllErrors(Error E, HandlerTs &&... Handlers)

Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

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

void sort(IteratorTy Start, IteratorTy End)

FunctionAddr VTableAddr uintptr_t uintptr_t Data

unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)

Utility function to encode a SLEB128 value to an output stream.

unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)

Utility function to encode a ULEB128 value to an output stream.

size_t strnlen(const char *S, size_t MaxLen) asm("llvm_zos_strnlen")

llvm::yaml::Hex32 cputype

llvm::yaml::Hex32 cpusubtype

llvm::yaml::Hex32 reserved

std::vector< MachOYAML::RebaseOpcode > RebaseOpcodes

llvm::MachO::macho_load_command Data

std::vector< Section > Sections

std::vector< MachO::build_tool_version > Tools

std::vector< llvm::yaml::Hex8 > PayloadBytes

std::vector< Relocation > relocations

std::optional< llvm::yaml::BinaryRef > content

llvm::yaml::Hex32 reserved2

llvm::yaml::Hex32 reserved1

llvm::yaml::Hex32 reserved3

Common declarations for yaml2obj.