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 {
200 };
201 size_t Idx;
202 };
203
206
208 unsigned Type)
210 assert(Type < 16 && "Relocation type out of range");
217 }
218
221 }
222 };
223
225 const char *Data = nullptr;
227 };
228
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
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
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