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 {
195 };
196 size_t Idx;
197 };
198
218
220 const char *Data = nullptr;
222 };
223
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
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
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