13#ifndef LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H
14#define LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H
27template <
typename MachOStruct>
33 memcpy(&Buf[
Offset],
reinterpret_cast<const char *
>(&S),
sizeof(MachOStruct));
34 return Offset +
sizeof(MachOStruct);
40 virtual size_t size()
const = 0;
48#define HANDLE_LOAD_COMMAND(Name, Value, LCStruct) \
50 struct MachOBuilderLoadCommandImplBase<MachO::Name> \
51 : public MachO::LCStruct, public MachOBuilderLoadCommandBase { \
52 using CmdStruct = LCStruct; \
53 MachOBuilderLoadCommandImplBase() { \
54 memset(&rawStruct(), 0, sizeof(CmdStruct)); \
56 cmdsize = sizeof(CmdStruct); \
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); \
69#include "llvm/BinaryFormat/MachO.def"
71#undef HANDLE_LOAD_COMMAND
73template <MachO::LoadCommandType LCType>
79 template <
typename... ArgTs>
89 memcpy(uuid,
UUID,
sizeof(uuid));
94 memcpy(uuid,
UUID.data(),
sizeof(uuid));
98template <MachO::LoadCommandType LCType>
106 MachO::dylib{24, Timestamp, CurrentVersion, CompatibilityVersion}),
108 this->cmdsize += (this->Name.size() + 1 + 3) & ~0x3;
112 bool SwapStruct)
override {
115 return Offset + ((
Name.size() + 1 + 3) & ~0x3);
144 cmdsize += (this->Path.size() + 1 + 3) & ~0x3;
148 bool SwapStruct)
override {
151 return Offset + ((
Path.size() + 1 + 3) & ~0x3);
163 cmdsize += (this->TargetTriple.size() + 1 + 3) & ~0x3;
167 bool SwapStruct)
override {
179 struct SymbolContainer {
180 size_t SymbolIndexBase = 0;
181 std::vector<typename MachOTraits::NList> Symbols;
184 struct StringTableEntry {
189 using StringTable = std::vector<StringTableEntry>;
191 static bool swapStruct() {
211 return SC->SymbolIndexBase + Idx;
216 return S->SectionNumber;
219 typename MachOTraits::NList &
nlist() {
221 return SC->Symbols[Idx];
238 assert(
Type < 16 &&
"Relocation type out of range");
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());
276 typename MachOTraits::NList Sym;
282 SC.Symbols.push_back(Sym);
283 return {
SC,
SC.Symbols.size() - 1};
292 return static_cast<typename MachOTraits::Section &
>(*this);
302 assert(SegName.
size() <= 16 &&
"SegName too long");
303 memcpy(this->segname, SegName.
data(), SegName.
size());
306 this->initprot = this->maxprot;
310 Sections.push_back(std::make_unique<Section>(
Builder, SecName, SegName));
315 bool SwapStruct)
override {
326 Header.magic = MachOTraits::Magic;
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)...);
336 LoadCommands.push_back(std::move(LC));
341 if (Strings.empty() && !Str.empty())
343 return Strings.insert(std::make_pair(Str, Strings.size())).first->second;
347 Segments.push_back(
Segment(*
this, SegName));
348 return Segments.back();
354 typename MachOTraits::NList Sym;
360 SC.Symbols.push_back(Sym);
361 return {SC, SC.Symbols.size() - 1};
378 for (
auto &Seg : Segments) {
380 Seg.Sections.size() *
sizeof(
typename MachOTraits::Section);
381 Seg.nsects = Seg.Sections.size();
384 for (
auto &LC : LoadCommands)
390 size_t SegVMAddr = 0;
391 for (
auto &Seg : Segments) {
392 Seg.vmaddr = SegVMAddr;
394 for (
auto &Sec : Seg.Sections) {
396 if (Sec->Content.Size)
398 Sec->size = Sec->Content.Size;
399 Sec->addr = SegVMAddr + Sec->offset - Seg.fileoff;
400 Offset += Sec->Content.Size;
402 size_t SegContentSize =
Offset - Seg.fileoff;
403 Seg.filesize = SegContentSize;
406 :
alignTo(SegContentSize, PageSize);
407 SegVMAddr += Seg.vmsize;
411 for (
auto &Sym : SC.Symbols)
412 Sym.n_strx = StrTab[Sym.n_strx].Offset;
416 size_t NumSymbols = SC.Symbols.size();
417 size_t SectionNumber = 0;
418 for (
auto &Seg : Segments) {
419 for (
auto &Sec : Seg.Sections) {
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;
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;
442 Sec->nreloc = Sec->Relocs.size();
444 for (
auto &R : Sec->Relocs)
445 R.r_symbolnum = R.Target.isSymbol() ? R.Target.getSymbolNum()
446 : R.Target.getSectionId();
452 if (NumSymbols > 0) {
454 SymTabLC->symoff =
Offset;
455 SymTabLC->nsyms = NumSymbols;
458 if (!StrTab.empty()) {
459 Offset += NumSymbols *
sizeof(
typename MachOTraits::NList);
460 size_t StringTableSize =
461 StrTab.back().Offset + StrTab.back().S.size() + 1;
463 SymTabLC->stroff =
Offset;
464 SymTabLC->strsize = StringTableSize;
465 Offset += StringTableSize;
486 void makeStringTable() {
490 StrTab.resize(Strings.size());
491 for (
auto &[Str, Idx] : Strings)
492 StrTab[Idx] = {Str, 0};
494 for (
auto &Elem : StrTab) {
496 Offset += Elem.S.size() + 1;
501 Header.ncmds = Segments.size() + LoadCommands.size();
506 for (
auto &Seg : Segments)
511 size_t writeLoadCommands(MutableArrayRef<char> Buf,
size_t Offset) {
512 for (
auto &LC : LoadCommands)
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");
525 while (
Offset != Sec->offset)
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;
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))
543 for (
auto &R : Sec->Relocs) {
544 assert(
Offset +
sizeof(MachO::relocation_info) <= Buf.size() &&
546 memcpy(&Buf[
Offset],
reinterpret_cast<const char *
>(&
R.rawStruct()),
547 sizeof(MachO::relocation_info));
548 Offset +=
sizeof(MachO::relocation_info);
555 size_t writeSymbols(MutableArrayRef<char> Buf,
size_t Offset) {
558 size_t NumSymbols = SC.Symbols.size();
559 for (
auto &Seg : Segments)
560 for (
auto &Sec : Seg.Sections)
561 NumSymbols += Sec->SC.Symbols.size();
568 while (
Offset %
sizeof(
typename MachOTraits::NList))
572 for (
auto &Sym : SC.Symbols)
576 for (
auto &Seg : Segments) {
577 for (
auto &Sec : Seg.Sections) {
578 for (
auto &Sym : Sec->SC.Symbols) {
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());
597 std::list<Segment> Segments;
598 std::vector<std::unique_ptr<MachOBuilderLoadCommandBase>> LoadCommands;
602 std::map<StringRef, size_t> Strings;
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.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Represent a constant reference to a string, i.e.
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
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.
constexpr 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.
static constexpr uint32_t Magic
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)
MachOBuilderLoadCommand(std::string Path)
size_t write(MutableArrayRef< char > Buf, size_t Offset, bool SwapStruct) override
MachOBuilderLoadCommand(std::string TargetTriple)
size_t write(MutableArrayRef< char > Buf, size_t Offset, bool SwapStruct) override
MachOBuilderLoadCommand(const uint8_t(&UUID)[16])
MachOBuilderLoadCommand(const std::array< uint8_t, 16 > &UUID)
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