LLVM 24.0.0git
MachOBuilder.h
Go to the documentation of this file.
1//===------------ MachOBuilder.h -- Build MachO 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//===----------------------------------------------------------------------===//
8//
9// Build MachO object files for interaction with the ObjC runtime and debugger.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H
14#define LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H
15
17#include "llvm/Support/Endian.h"
19
20#include <list>
21#include <map>
22#include <vector>
23
24namespace llvm {
25namespace orc {
26
27template <typename MachOStruct>
28size_t writeMachOStruct(MutableArrayRef<char> Buf, size_t Offset, MachOStruct S,
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/// Base type for MachOBuilder load command wrappers.
39 virtual ~MachOBuilderLoadCommandBase() = default;
40 virtual size_t size() const = 0;
41 virtual size_t write(MutableArrayRef<char> Buf, size_t Offset,
42 bool SwapStruct) = 0;
43};
44
45/// MachOBuilder load command wrapper type.
46template <MachO::LoadCommandType LCType> struct MachOBuilderLoadCommandImplBase;
47
48#define HANDLE_LOAD_COMMAND(Name, Value, LCStruct) \
49 template <> \
50 struct MachOBuilderLoadCommandImplBase<MachO::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<ArgTs>(Args)...} {} \
61 CmdStruct &rawStruct() { return static_cast<CmdStruct &>(*this); } \
62 size_t size() const override { return cmdsize; } \
63 size_t write(MutableArrayRef<char> 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>
75 : public MachOBuilderLoadCommandImplBase<LCType> {
76public:
78
79 template <typename... ArgTs>
80 MachOBuilderLoadCommand(ArgTs &&...Args)
81 : MachOBuilderLoadCommandImplBase<LCType>(std::forward<ArgTs>(Args)...) {}
82};
83
84template <>
86 : public MachOBuilderLoadCommandImplBase<MachO::LC_UUID> {
89 memcpy(uuid, UUID, sizeof(uuid));
90 }
91
92 MachOBuilderLoadCommand(const std::array<uint8_t, 16> &UUID)
94 memcpy(uuid, UUID.data(), sizeof(uuid));
95 }
96};
97
98template <MachO::LoadCommandType LCType>
100 : public MachOBuilderLoadCommandImplBase<LCType> {
101
103 uint32_t CurrentVersion,
104 uint32_t CompatibilityVersion)
106 MachO::dylib{24, Timestamp, CurrentVersion, CompatibilityVersion}),
107 Name(std::move(Name)) {
108 this->cmdsize += (this->Name.size() + 1 + 3) & ~0x3;
109 }
110
112 bool SwapStruct) override {
113 Offset = writeMachOStruct(Buf, Offset, this->rawStruct(), SwapStruct);
114 strcpy(Buf.data() + Offset, Name.data());
115 return Offset + ((Name.size() + 1 + 3) & ~0x3);
116 }
117
118 std::string Name;
119};
120
121template <>
126
127template <>
128struct MachOBuilderLoadCommand<MachO::LC_LOAD_DYLIB>
129 : public MachOBuilderDylibLoadCommand<MachO::LC_LOAD_DYLIB> {
131};
132
133template <>
134struct MachOBuilderLoadCommand<MachO::LC_LOAD_WEAK_DYLIB>
135 : public MachOBuilderDylibLoadCommand<MachO::LC_LOAD_WEAK_DYLIB> {
137};
138
139template <>
141 : public MachOBuilderLoadCommandImplBase<MachO::LC_RPATH> {
144 cmdsize += (this->Path.size() + 1 + 3) & ~0x3;
145 }
146
148 bool SwapStruct) override {
149 Offset = writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);
150 strcpy(Buf.data() + Offset, Path.data());
151 return Offset + ((Path.size() + 1 + 3) & ~0x3);
152 }
153
154 std::string Path;
155};
156
157template <>
158struct MachOBuilderLoadCommand<MachO::LC_TARGET_TRIPLE>
159 : public MachOBuilderLoadCommandImplBase<MachO::LC_TARGET_TRIPLE> {
163 cmdsize += (this->TargetTriple.size() + 1 + 3) & ~0x3;
164 }
165
167 bool SwapStruct) override {
168 Offset = writeMachOStruct(Buf, Offset, rawStruct(), SwapStruct);
169 strcpy(Buf.data() + Offset, TargetTriple.data());
170 return Offset + ((TargetTriple.size() + 1 + 3) & ~0x3);
171 }
172
173 std::string TargetTriple;
174};
175
176// Builds MachO objects.
177template <typename MachOTraits> class MachOBuilder {
178private:
179 struct SymbolContainer {
180 size_t SymbolIndexBase = 0;
181 std::vector<typename MachOTraits::NList> Symbols;
182 };
183
184 struct StringTableEntry {
185 StringRef S;
186 size_t Offset;
187 };
188
189 using StringTable = std::vector<StringTableEntry>;
190
191 static bool swapStruct() {
192 return MachOTraits::Endianness != llvm::endianness::native;
193 }
194
195public:
197
198 struct Section;
199
200 // Points to either an nlist entry (as a (symbol-container, index) pair), or
201 // a section.
203 public:
204 RelocTarget(const Section &S) : S(&S), Idx(~0U) {}
205 RelocTarget(SymbolContainer &SC, size_t Idx) : SC(&SC), Idx(Idx) {}
206
207 bool isSymbol() { return Idx != ~0U; }
208
210 assert(isSymbol() && "Target is not a symbol");
211 return SC->SymbolIndexBase + Idx;
212 }
213
215 assert(!isSymbol() && "Target is not a section");
216 return S->SectionNumber;
217 }
218
219 typename MachOTraits::NList &nlist() {
220 assert(isSymbol() && "Target is not a symbol");
221 return SC->Symbols[Idx];
222 }
223
224 private:
225 union {
226 const Section *S;
227 SymbolContainer *SC;
228 };
229 size_t Idx;
230 };
231
234
235 Reloc(int32_t Offset, RelocTarget Target, bool PCRel, unsigned Length,
236 unsigned Type)
237 : Target(Target) {
238 assert(Type < 16 && "Relocation type out of range");
239 r_address = Offset; // Will slide to account for sec addr during layout
240 r_symbolnum = 0;
241 r_pcrel = PCRel;
243 r_extern = Target.isSymbol();
244 r_type = Type;
245 }
246
248 return static_cast<MachO::relocation_info &>(*this);
249 }
250 };
251
253 const char *Data = nullptr;
254 size_t Size = 0;
255 };
256
257 struct Section : public MachOTraits::Section, public RelocTarget {
260 size_t SectionNumber = 0;
261 SymbolContainer SC;
262 std::vector<Reloc> Relocs;
263
265 : RelocTarget(*this), Builder(Builder) {
266 memset(&rawStruct(), 0, sizeof(typename MachOTraits::Section));
267 assert(SecName.size() <= 16 && "SecName too long");
268 assert(SegName.size() <= 16 && "SegName too long");
269 memcpy(this->sectname, SecName.data(), SecName.size());
270 memcpy(this->segname, SegName.data(), SegName.size());
271 }
272
274 uint16_t Desc) {
275 StringId SI = Builder.addString(Name);
276 typename MachOTraits::NList Sym;
277 Sym.n_strx = SI;
278 Sym.n_type = Type | MachO::N_SECT;
279 Sym.n_sect = MachO::NO_SECT; // Will be filled in later.
280 Sym.n_desc = Desc;
281 Sym.n_value = Offset;
282 SC.Symbols.push_back(Sym);
283 return {SC, SC.Symbols.size() - 1};
284 }
285
286 void addReloc(int32_t Offset, RelocTarget Target, bool PCRel,
287 unsigned Length, unsigned Type) {
288 Relocs.push_back({Offset, Target, PCRel, Length, Type});
289 }
290
291 auto &rawStruct() {
292 return static_cast<typename MachOTraits::Section &>(*this);
293 }
294 };
295
296 struct Segment : public MachOBuilderLoadCommand<MachOTraits::SegmentCmd> {
298 std::vector<std::unique_ptr<Section>> Sections;
299
301 : MachOBuilderLoadCommand<MachOTraits::SegmentCmd>(), Builder(Builder) {
302 assert(SegName.size() <= 16 && "SegName too long");
303 memcpy(this->segname, SegName.data(), SegName.size());
304 this->maxprot =
306 this->initprot = this->maxprot;
307 }
308
310 Sections.push_back(std::make_unique<Section>(Builder, SecName, SegName));
311 return *Sections.back();
312 }
313
315 bool SwapStruct) override {
317 Buf, Offset, SwapStruct);
318 for (auto &Sec : Sections)
319 Offset = writeMachOStruct(Buf, Offset, Sec->rawStruct(), SwapStruct);
320 return Offset;
321 }
322 };
323
324 MachOBuilder(size_t PageSize) : PageSize(PageSize) {
325 memset((char *)&Header, 0, sizeof(Header));
326 Header.magic = MachOTraits::Magic;
327 }
328
329 template <MachO::LoadCommandType LCType, typename... ArgTs>
331 static_assert(LCType != MachOTraits::SegmentCmd,
332 "Use addSegment to add segment load command");
333 auto LC = std::make_unique<MachOBuilderLoadCommand<LCType>>(
334 std::forward<ArgTs>(Args)...);
335 auto &Tmp = *LC;
336 LoadCommands.push_back(std::move(LC));
337 return Tmp;
338 }
339
341 if (Strings.empty() && !Str.empty())
342 addString("");
343 return Strings.insert(std::make_pair(Str, Strings.size())).first->second;
344 }
345
347 Segments.push_back(Segment(*this, SegName));
348 return Segments.back();
349 }
350
352 uint16_t Desc, typename MachOTraits::UIntPtr Value) {
353 StringId SI = addString(Name);
354 typename MachOTraits::NList Sym;
355 Sym.n_strx = SI;
356 Sym.n_type = Type;
357 Sym.n_sect = Sect;
358 Sym.n_desc = Desc;
359 Sym.n_value = Value;
360 SC.Symbols.push_back(Sym);
361 return {SC, SC.Symbols.size() - 1};
362 }
363
364 // Call to perform layout on the MachO. Returns the total size of the
365 // resulting file.
366 // This method will automatically insert some load commands (e.g.
367 // LC_SYMTAB) and fill in load command fields.
368 size_t layout() {
369
370 // Build symbol table and add LC_SYMTAB command.
371 makeStringTable();
373 if (!StrTab.empty())
375
376 // Lay out header, segment load command, and other load commands.
377 size_t Offset = sizeof(Header);
378 for (auto &Seg : Segments) {
379 Seg.cmdsize +=
380 Seg.Sections.size() * sizeof(typename MachOTraits::Section);
381 Seg.nsects = Seg.Sections.size();
382 Offset += Seg.cmdsize;
383 }
384 for (auto &LC : LoadCommands)
385 Offset += LC->size();
386
387 Header.sizeofcmds = Offset - sizeof(Header);
388
389 // Lay out content, set segment / section addrs and offsets.
390 size_t SegVMAddr = 0;
391 for (auto &Seg : Segments) {
392 Seg.vmaddr = SegVMAddr;
393 Seg.fileoff = Offset;
394 for (auto &Sec : Seg.Sections) {
395 Offset = alignTo(Offset, 1ULL << Sec->align);
396 if (Sec->Content.Size)
397 Sec->offset = Offset;
398 Sec->size = Sec->Content.Size;
399 Sec->addr = SegVMAddr + Sec->offset - Seg.fileoff;
400 Offset += Sec->Content.Size;
401 }
402 size_t SegContentSize = Offset - Seg.fileoff;
403 Seg.filesize = SegContentSize;
404 Seg.vmsize = Header.filetype == MachO::MH_OBJECT
405 ? SegContentSize
406 : alignTo(SegContentSize, PageSize);
407 SegVMAddr += Seg.vmsize;
408 }
409
410 // Set string table offsets for non-section symbols.
411 for (auto &Sym : SC.Symbols)
412 Sym.n_strx = StrTab[Sym.n_strx].Offset;
413
414 // Number sections, set symbol section numbers and string table offsets,
415 // count relocations.
416 size_t NumSymbols = SC.Symbols.size();
417 size_t SectionNumber = 0;
418 for (auto &Seg : Segments) {
419 for (auto &Sec : Seg.Sections) {
420 ++SectionNumber;
421 Sec->SectionNumber = SectionNumber;
422 Sec->SC.SymbolIndexBase = NumSymbols;
423 NumSymbols += Sec->SC.Symbols.size();
424 for (auto &Sym : Sec->SC.Symbols) {
425 Sym.n_sect = SectionNumber;
426 Sym.n_strx = StrTab[Sym.n_strx].Offset;
427 Sym.n_value += Sec->addr;
428 }
429 }
430 }
431
432 // Handle relocations
433 bool OffsetAlignedForRelocs = false;
434 for (auto &Seg : Segments) {
435 for (auto &Sec : Seg.Sections) {
436 if (!Sec->Relocs.empty()) {
437 if (!OffsetAlignedForRelocs) {
439 OffsetAlignedForRelocs = true;
440 }
441 Sec->reloff = Offset;
442 Sec->nreloc = Sec->Relocs.size();
443 Offset += Sec->Relocs.size() * sizeof(MachO::relocation_info);
444 for (auto &R : Sec->Relocs)
445 R.r_symbolnum = R.Target.isSymbol() ? R.Target.getSymbolNum()
446 : R.Target.getSectionId();
447 }
448 }
449 }
450
451 // Calculate offset to start of nlist and update symtab command.
452 if (NumSymbols > 0) {
453 Offset = alignTo(Offset, sizeof(typename MachOTraits::NList));
454 SymTabLC->symoff = Offset;
455 SymTabLC->nsyms = NumSymbols;
456
457 // Calculate string table bounds and update symtab command.
458 if (!StrTab.empty()) {
459 Offset += NumSymbols * sizeof(typename MachOTraits::NList);
460 size_t StringTableSize =
461 StrTab.back().Offset + StrTab.back().S.size() + 1;
462
463 SymTabLC->stroff = Offset;
464 SymTabLC->strsize = StringTableSize;
465 Offset += StringTableSize;
466 }
467 }
468
469 return Offset;
470 }
471
473 size_t Offset = 0;
474 Offset = writeHeader(Buffer, Offset);
475 Offset = writeSegments(Buffer, Offset);
476 Offset = writeLoadCommands(Buffer, Offset);
477 Offset = writeSectionContent(Buffer, Offset);
478 Offset = writeRelocations(Buffer, Offset);
479 Offset = writeSymbols(Buffer, Offset);
480 Offset = writeStrings(Buffer, Offset);
481 }
482
483 typename MachOTraits::Header Header;
484
485private:
486 void makeStringTable() {
487 if (Strings.empty())
488 return;
489
490 StrTab.resize(Strings.size());
491 for (auto &[Str, Idx] : Strings)
492 StrTab[Idx] = {Str, 0};
493 size_t Offset = 0;
494 for (auto &Elem : StrTab) {
495 Elem.Offset = Offset;
496 Offset += Elem.S.size() + 1;
497 }
498 }
499
500 size_t writeHeader(MutableArrayRef<char> Buf, size_t Offset) {
501 Header.ncmds = Segments.size() + LoadCommands.size();
502 return writeMachOStruct(Buf, Offset, Header, swapStruct());
503 }
504
505 size_t writeSegments(MutableArrayRef<char> Buf, size_t Offset) {
506 for (auto &Seg : Segments)
507 Offset = Seg.write(Buf, Offset, swapStruct());
508 return Offset;
509 }
510
511 size_t writeLoadCommands(MutableArrayRef<char> Buf, size_t Offset) {
512 for (auto &LC : LoadCommands)
513 Offset = LC->write(Buf, Offset, swapStruct());
514 return Offset;
515 }
516
517 size_t writeSectionContent(MutableArrayRef<char> Buf, size_t Offset) {
518 for (auto &Seg : Segments) {
519 for (auto &Sec : Seg.Sections) {
520 if (!Sec->Content.Data) {
521 assert(Sec->Relocs.empty() &&
522 "Cant' have relocs for zero-fill segment");
523 continue;
524 }
525 while (Offset != Sec->offset)
526 Buf[Offset++] = '\0';
527
528 assert(Offset + Sec->Content.Size <= Buf.size() && "Buffer overflow");
529 memcpy(&Buf[Offset], Sec->Content.Data, Sec->Content.Size);
530 Offset += Sec->Content.Size;
531 }
532 }
533 return Offset;
534 }
535
536 size_t writeRelocations(MutableArrayRef<char> Buf, size_t Offset) {
537 for (auto &Seg : Segments) {
538 for (auto &Sec : Seg.Sections) {
539 if (!Sec->Relocs.empty()) {
540 while (Offset % sizeof(MachO::relocation_info))
541 Buf[Offset++] = '\0';
542 }
543 for (auto &R : Sec->Relocs) {
544 assert(Offset + sizeof(MachO::relocation_info) <= Buf.size() &&
545 "Buffer overflow");
546 memcpy(&Buf[Offset], reinterpret_cast<const char *>(&R.rawStruct()),
547 sizeof(MachO::relocation_info));
548 Offset += sizeof(MachO::relocation_info);
549 }
550 }
551 }
552 return Offset;
553 }
554
555 size_t writeSymbols(MutableArrayRef<char> Buf, size_t Offset) {
556
557 // Count symbols.
558 size_t NumSymbols = SC.Symbols.size();
559 for (auto &Seg : Segments)
560 for (auto &Sec : Seg.Sections)
561 NumSymbols += Sec->SC.Symbols.size();
562
563 // If none then return.
564 if (NumSymbols == 0)
565 return Offset;
566
567 // Align to nlist entry size.
568 while (Offset % sizeof(typename MachOTraits::NList))
569 Buf[Offset++] = '\0';
570
571 // Write non-section symbols.
572 for (auto &Sym : SC.Symbols)
573 Offset = writeMachOStruct(Buf, Offset, Sym, swapStruct());
574
575 // Write section symbols.
576 for (auto &Seg : Segments) {
577 for (auto &Sec : Seg.Sections) {
578 for (auto &Sym : Sec->SC.Symbols) {
579 Offset = writeMachOStruct(Buf, Offset, Sym, swapStruct());
580 }
581 }
582 }
583 return Offset;
584 }
585
586 size_t writeStrings(MutableArrayRef<char> Buf, size_t Offset) {
587 for (auto &Elem : StrTab) {
588 assert(Offset + Elem.S.size() + 1 <= Buf.size() && "Buffer overflow");
589 memcpy(&Buf[Offset], Elem.S.data(), Elem.S.size());
590 Offset += Elem.S.size();
591 Buf[Offset++] = '\0';
592 }
593 return Offset;
594 }
595
596 size_t PageSize;
597 std::list<Segment> Segments;
598 std::vector<std::unique_ptr<MachOBuilderLoadCommandBase>> LoadCommands;
599 SymbolContainer SC;
600
601 // Maps strings to their "id" (addition order).
602 std::map<StringRef, size_t> Strings;
603 StringTable StrTab;
604};
605
618
619} // namespace orc
620} // namespace llvm
621
622#endif // LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
std::pair< llvm::MachO::Target, std::string > UUID
size_t size() const
Get the array size.
Definition ArrayRef.h:141
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM Value Representation.
Definition Value.h:75
RelocTarget(SymbolContainer &SC, size_t Idx)
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
@ VM_PROT_EXECUTE
Definition MachO.h:554
@ VM_PROT_READ
Definition MachO.h:554
@ VM_PROT_WRITE
Definition MachO.h:554
@ MH_OBJECT
Definition MachO.h:43
void swapStruct(fat_header &mh)
Definition MachO.h:1203
@ MH_MAGIC_64
Definition MachO.h:32
LoadCommandType
Definition MachO.h:98
size_t writeMachOStruct(MutableArrayRef< char > Buf, size_t Offset, MachOStruct S, bool SwapStruct)
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
@ Length
Definition DWP.cpp:578
Op::Description Desc
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
endianness
Definition bit.h:71
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
static constexpr uint32_t Magic
MachO::nlist_64 NList
MachO::relocation_info Relocation
static constexpr llvm::endianness Endianness
static constexpr MachO::LoadCommandType SymTabCmd
static constexpr MachO::LoadCommandType SegmentCmd
MachO::section_64 Section
MachO::mach_header_64 Header
MachOBuilderDylibLoadCommand(std::string Name, uint32_t Timestamp, uint32_t CurrentVersion, uint32_t CompatibilityVersion)
size_t write(MutableArrayRef< char > Buf, size_t Offset, bool SwapStruct) override
Base type for MachOBuilder load command wrappers.
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.
MachOBuilderDylibLoadCommand(std::string Name, uint32_t Timestamp, uint32_t CurrentVersion, uint32_t CompatibilityVersion)
MachOBuilderDylibLoadCommand(std::string Name, uint32_t Timestamp, uint32_t CurrentVersion, uint32_t CompatibilityVersion)
MachOBuilderDylibLoadCommand(std::string Name, uint32_t Timestamp, uint32_t CurrentVersion, uint32_t CompatibilityVersion)
size_t write(MutableArrayRef< char > Buf, size_t Offset, bool SwapStruct) override
size_t write(MutableArrayRef< char > Buf, size_t Offset, bool SwapStruct) override
MachOBuilderLoadCommand(const std::array< uint8_t, 16 > &UUID)
MachOBuilderLoadCommand(ArgTs &&...Args)
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)
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