48 std::vector<MachOYAML::BindOpcode> &BindOpcodes);
73 bool FoundLinkEditSeg =
false;
79 writeLoadCommands(
OS);
80 if (
Error Err = writeSectionData(
OS))
83 if (!FoundLinkEditSeg)
84 writeLinkEditData(
OS);
103 OS.
write((
const char *)&Header, header_size);
106template <
typename SectionType>
109 memcpy(
reinterpret_cast<void *
>(&TempSec.sectname[0]), &Sec.
sectname[0], 16);
110 memcpy(
reinterpret_cast<void *
>(&TempSec.segname[0]), &Sec.
segname[0], 16);
111 TempSec.addr = Sec.
addr;
112 TempSec.size = Sec.
size;
113 TempSec.offset = Sec.
offset;
114 TempSec.align = Sec.
align;
115 TempSec.reloff = Sec.
reloff;
116 TempSec.nreloc = Sec.
nreloc;
117 TempSec.flags = Sec.
flags;
123template <
typename StructType>
125 bool IsLittleEndian) {
132 bool IsLittleEndian) {
133 size_t BytesWritten = 0;
134 for (
const auto &Sec : LC.
Sections) {
135 auto TempSec = constructSection<MachO::section>(Sec);
138 OS.
write(
reinterpret_cast<const char *
>(&(TempSec)),
146size_t writeLoadCommandData<MachO::segment_command_64>(
148 size_t BytesWritten = 0;
149 for (
const auto &Sec : LC.
Sections) {
150 auto TempSec = constructSection<MachO::section_64>(Sec);
154 OS.
write(
reinterpret_cast<const char *
>(&(TempSec)),
162 size_t BytesWritten = 0;
165 BytesWritten = LC.
Content.length();
173 bool IsLittleEndian) {
174 return writePayloadString(LC,
OS);
180 bool IsLittleEndian) {
181 return writePayloadString(LC,
OS);
187 bool IsLittleEndian) {
188 return writePayloadString(LC,
OS);
192size_t writeLoadCommandData<MachO::sub_framework_command>(
194 return writePayloadString(LC,
OS);
198size_t writeLoadCommandData<MachO::sub_umbrella_command>(
200 return writePayloadString(LC,
OS);
204size_t writeLoadCommandData<MachO::sub_client_command>(
206 return writePayloadString(LC,
OS);
210size_t writeLoadCommandData<MachO::sub_library_command>(
212 return writePayloadString(LC,
OS);
216size_t writeLoadCommandData<MachO::build_version_command>(
218 size_t BytesWritten = 0;
219 for (
const auto &
T : LC.
Tools) {
231 std::vector<uint8_t> FillData(
Size, 0);
232 OS.
write(
reinterpret_cast<char *
>(FillData.data()),
Size);
236 std::vector<uint32_t> FillData((
Size / 4) + 1,
Data);
237 OS.
write(
reinterpret_cast<char *
>(FillData.data()),
Size);
241 auto currOffset =
OS.
tell() - fileStart;
248 size_t BytesWritten = 0;
251#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
252 case MachO::LCName: \
253 if (Obj.IsLittleEndian != sys::IsLittleEndianHost) \
254 MachO::swapStruct(Data.LCStruct##_data); \
255 OS.write(reinterpret_cast<const char *>(&(Data.LCStruct##_data)), \
256 sizeof(MachO::LCStruct)); \
257 BytesWritten = sizeof(MachO::LCStruct); \
259 writeLoadCommandData<MachO::LCStruct>(LC, OS, Obj.IsLittleEndian); \
262 switch (LC.
Data.load_command_data.cmd) {
266 OS.
write(
reinterpret_cast<const char *
>(&(
Data.load_command_data)),
272#include "llvm/BinaryFormat/MachO.def"
288 auto BytesRemaining = LC.
Data.load_command_data.cmdsize - BytesWritten;
289 if (BytesRemaining > 0) {
298 switch (LC.
Data.load_command_data.cmd) {
299 case MachO::LC_SEGMENT:
300 case MachO::LC_SEGMENT_64:
302 : LC.
Data.segment_command_data.fileoff;
304 strncmp(&LC.
Data.segment_command_data.segname[0],
"__LINKEDIT", 16)) {
305 FoundLinkEditSeg =
true;
306 LinkEditOff = segOff;
309 writeLinkEditData(
OS);
319 "wrote too much data somewhere, section offsets in "
320 "section {0} for segment {1} don't line up: "
321 "[cursor={2:x}], [fileStart={3:x}], [sectionOffset={4:x}]",
332 "cannot specify section '" + SectName +
333 "' contents in the 'DWARF' entry and "
334 "the 'content' at the same time");
351 Fill(
OS, Sec.
size, 0xDEADBEEFu);
355 : LC.
Data.segment_command_data.filesize;
356 ZeroToOffset(
OS, segOff + segSize);
362 ZeroToOffset(
OS, LinkEditOff);
363 if (
OS.
tell() - fileStart > LinkEditOff || !LinkEditOff)
365 "section offsets don't line up");
377 assert(!
R.is_scattered &&
"non-scattered relocation expected");
393 assert(
R.is_scattered &&
"scattered relocation expected");
404 switch (LC.
Data.load_command_data.cmd) {
405 case MachO::LC_SEGMENT:
406 case MachO::LC_SEGMENT_64:
413 R.is_scattered ? makeScatteredRelocationInfo(R)
414 : makeRelocationInfo(
R, Obj.IsLittleEndian);
417 OS.
write(
reinterpret_cast<const char *
>(&MRE),
425void MachOWriter::writeBindOpcodes(
426 raw_ostream &
OS, std::vector<MachOYAML::BindOpcode> &BindOpcodes) {
428 for (
const auto &Opcode : BindOpcodes) {
429 uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
430 OS.
write(
reinterpret_cast<char *
>(&OpByte), 1);
431 for (
auto Data : Opcode.ULEBExtraData) {
434 for (
auto Data : Opcode.SLEBExtraData) {
437 if (!Opcode.Symbol.empty()) {
438 OS.
write(Opcode.Symbol.data(), Opcode.Symbol.size());
447 if (
Entry.TerminalSize > 0) {
460 for (
const auto &EE :
Entry.Children) {
465 for (
auto EE :
Entry.Children)
466 dumpExportEntry(
OS, EE);
473template <
typename NListType>
475 bool IsLittleEndian) {
477 ListEntry.n_strx = NLE.
n_strx;
478 ListEntry.n_type = NLE.
n_type;
479 ListEntry.n_sect = NLE.
n_sect;
480 ListEntry.n_desc = NLE.
n_desc;
481 ListEntry.n_value = NLE.
n_value;
489 typedef void (MachOWriter::*writeHandler)(
raw_ostream &);
490 typedef std::pair<uint64_t, writeHandler> writeOperation;
491 std::vector<writeOperation> WriteQueue;
501 switch (LC.
Data.load_command_data.cmd) {
502 case MachO::LC_SYMTAB:
503 SymtabCmd = &LC.
Data.symtab_command_data;
504 WriteQueue.push_back(
505 std::make_pair(SymtabCmd->
symoff, &MachOWriter::writeNameList));
506 WriteQueue.push_back(
507 std::make_pair(SymtabCmd->
stroff, &MachOWriter::writeStringTable));
509 case MachO::LC_DYLD_INFO_ONLY:
510 DyldInfoOnlyCmd = &LC.
Data.dyld_info_command_data;
511 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
rebase_off,
512 &MachOWriter::writeRebaseOpcodes));
513 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
bind_off,
514 &MachOWriter::writeBasicBindOpcodes));
515 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
weak_bind_off,
516 &MachOWriter::writeWeakBindOpcodes));
517 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
lazy_bind_off,
518 &MachOWriter::writeLazyBindOpcodes));
519 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
export_off,
520 &MachOWriter::writeExportTrie));
522 case MachO::LC_DYSYMTAB:
523 DSymtabCmd = &LC.
Data.dysymtab_command_data;
524 WriteQueue.push_back(std::make_pair(
525 DSymtabCmd->
indirectsymoff, &MachOWriter::writeDynamicSymbolTable));
527 case MachO::LC_FUNCTION_STARTS:
528 FunctionStartsCmd = &LC.
Data.linkedit_data_command_data;
529 WriteQueue.push_back(std::make_pair(FunctionStartsCmd->
dataoff,
530 &MachOWriter::writeFunctionStarts));
532 case MachO::LC_DYLD_CHAINED_FIXUPS:
533 ChainedFixupsCmd = &LC.
Data.linkedit_data_command_data;
534 WriteQueue.push_back(std::make_pair(ChainedFixupsCmd->
dataoff,
535 &MachOWriter::writeChainedFixups));
537 case MachO::LC_DYLD_EXPORTS_TRIE:
538 DyldExportsTrieCmd = &LC.
Data.linkedit_data_command_data;
539 WriteQueue.push_back(std::make_pair(DyldExportsTrieCmd->
dataoff,
540 &MachOWriter::writeDyldExportsTrie));
542 case MachO::LC_DATA_IN_CODE:
543 DataInCodeCmd = &LC.
Data.linkedit_data_command_data;
544 WriteQueue.push_back(std::make_pair(DataInCodeCmd->
dataoff,
545 &MachOWriter::writeDataInCode));
552 for (
auto writeOp : WriteQueue) {
553 ZeroToOffset(
OS, writeOp.first);
554 (this->*writeOp.second)(
OS);
562 uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
563 OS.
write(
reinterpret_cast<char *
>(&OpByte), 1);
564 for (
auto Data : Opcode.ExtraData)
592 OS.
write(Str.data(), Str.size());
600 sizeof(yaml::Hex32::BaseType));
619 OS.
write(
reinterpret_cast<const char *
>(&DICE),
634class UniversalWriter {
655 return Writer.writeMachO(
OS);
662 if (FatFile.FatArchs.size() < FatFile.Slices.size())
664 errc::invalid_argument,
665 "cannot write 'Slices' if not described in 'FatArches'");
667 for (
size_t i = 0; i < FatFile.Slices.size(); i++) {
668 ZeroToOffset(
OS, FatFile.FatArchs[i].offset);
669 MachOWriter Writer(FatFile.Slices[i]);
670 if (
Error Err = Writer.writeMachO(
OS))
673 auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;
674 ZeroToOffset(
OS, SliceEnd);
683 header.
magic = FatFile.Header.magic;
684 header.
nfat_arch = FatFile.Header.nfat_arch;
690template <
typename FatArchType>
693 FatArch.cputype = Arch.
cputype;
695 FatArch.offset = Arch.
offset;
696 FatArch.size = Arch.
size;
697 FatArch.align = Arch.
align;
701template <
typename StructType>
706 auto FatArch = constructFatArch<MachO::fat_arch>(Arch);
715 auto FatArch = constructFatArch<MachO::fat_arch_64>(Arch);
719 OS.
write(
reinterpret_cast<const char *
>(&FatArch),
726 for (
auto Arch : FatFile.FatArchs) {
728 writeFatArch<MachO::fat_arch_64>(Arch,
OS);
730 writeFatArch<MachO::fat_arch>(Arch,
OS);
735 auto currOffset =
OS.
tell() - fileStart;
746 UniversalWriter Writer(Doc);
747 if (
Error Err = Writer.writeMachO(Out)) {
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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
StringRef - Represent a constant reference to a string, i.e.
An efficient, type-erasing, non-owning reference to a callable.
This class is the base class for all object file types.
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)
Specialized YAMLIO scalar type for representing a binary blob.
std::function< Error(raw_ostream &, const Data &)> getDWARFEmitterByName(StringRef SecName)
bool isVirtualSection(uint8_t type)
SectionType
These are the section type and attributes fields.
void swapStruct(fat_header &mh)
@ EXPORT_SYMBOL_FLAGS_REEXPORT
@ EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
static const bool IsLittleEndianHost
bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out, ErrorHandler EH)
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)
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.
SetVector< StringRef > getNonEmptySectionNames() const
llvm::yaml::Hex32 cputype
llvm::yaml::Hex32 cpusubtype
llvm::yaml::Hex32 reserved
std::vector< MachOYAML::BindOpcode > WeakBindOpcodes
std::vector< DataInCodeEntry > DataInCode
std::vector< yaml::Hex8 > ChainedFixups
std::vector< MachOYAML::BindOpcode > LazyBindOpcodes
std::vector< MachOYAML::BindOpcode > BindOpcodes
std::vector< MachOYAML::RebaseOpcode > RebaseOpcodes
std::vector< StringRef > StringTable
std::vector< yaml::Hex32 > IndirectSymbols
std::vector< yaml::Hex64 > FunctionStarts
MachOYAML::ExportEntry ExportTrie
std::vector< NListEntry > NameList
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< LoadCommand > LoadCommands
std::optional< llvm::yaml::BinaryRef > RawLinkEditSegment
std::vector< Relocation > relocations
std::optional< llvm::yaml::BinaryRef > content
llvm::yaml::Hex32 reserved2
llvm::yaml::Hex32 reserved1
llvm::yaml::Hex32 reserved3
Function object to check whether the first component of a container supported by std::get (like std::...
Common declarations for yaml2obj.