50 std::vector<MachOYAML::BindOpcode> &BindOpcodes);
75 bool FoundLinkEditSeg =
false;
81 writeLoadCommands(
OS);
82 if (
Error Err = writeSectionData(
OS))
85 if (!FoundLinkEditSeg)
86 writeLinkEditData(
OS);
105 OS.
write((
const char *)&Header, header_size);
108template <
typename SectionType>
111 memcpy(
reinterpret_cast<void *
>(&TempSec.sectname[0]), &Sec.
sectname[0], 16);
112 memcpy(
reinterpret_cast<void *
>(&TempSec.segname[0]), &Sec.
segname[0], 16);
113 TempSec.addr = Sec.
addr;
114 TempSec.size = Sec.
size;
115 TempSec.offset = Sec.
offset;
116 TempSec.align = Sec.
align;
117 TempSec.reloff = Sec.
reloff;
118 TempSec.nreloc = Sec.
nreloc;
119 TempSec.flags = Sec.
flags;
125template <
typename StructType>
127 bool IsLittleEndian) {
134 bool IsLittleEndian) {
135 size_t BytesWritten = 0;
136 for (
const auto &Sec : LC.
Sections) {
137 auto TempSec = constructSection<MachO::section>(Sec);
140 OS.
write(
reinterpret_cast<const char *
>(&(TempSec)),
148size_t writeLoadCommandData<MachO::segment_command_64>(
150 size_t BytesWritten = 0;
151 for (
const auto &Sec : LC.
Sections) {
152 auto TempSec = constructSection<MachO::section_64>(Sec);
156 OS.
write(
reinterpret_cast<const char *
>(&(TempSec)),
164 size_t BytesWritten = 0;
167 BytesWritten = LC.
Content.length();
175 bool IsLittleEndian) {
176 return writePayloadString(LC,
OS);
182 bool IsLittleEndian) {
183 return writePayloadString(LC,
OS);
189 bool IsLittleEndian) {
190 return writePayloadString(LC,
OS);
194size_t writeLoadCommandData<MachO::sub_framework_command>(
196 return writePayloadString(LC,
OS);
200size_t writeLoadCommandData<MachO::sub_umbrella_command>(
202 return writePayloadString(LC,
OS);
206size_t writeLoadCommandData<MachO::sub_client_command>(
208 return writePayloadString(LC,
OS);
212size_t writeLoadCommandData<MachO::sub_library_command>(
214 return writePayloadString(LC,
OS);
218size_t writeLoadCommandData<MachO::build_version_command>(
220 size_t BytesWritten = 0;
221 for (
const auto &
T : LC.
Tools) {
233 std::vector<uint8_t> FillData(
Size, 0);
234 OS.
write(
reinterpret_cast<char *
>(FillData.data()),
Size);
238 std::vector<uint32_t> FillData((
Size / 4) + 1,
Data);
239 OS.
write(
reinterpret_cast<char *
>(FillData.data()),
Size);
243 auto currOffset =
OS.
tell() - fileStart;
250 size_t BytesWritten = 0;
253#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
254 case MachO::LCName: \
255 if (Obj.IsLittleEndian != sys::IsLittleEndianHost) \
256 MachO::swapStruct(Data.LCStruct##_data); \
257 OS.write(reinterpret_cast<const char *>(&(Data.LCStruct##_data)), \
258 sizeof(MachO::LCStruct)); \
259 BytesWritten = sizeof(MachO::LCStruct); \
261 writeLoadCommandData<MachO::LCStruct>(LC, OS, Obj.IsLittleEndian); \
264 switch (LC.
Data.load_command_data.cmd) {
268 OS.
write(
reinterpret_cast<const char *
>(&(
Data.load_command_data)),
274#include "llvm/BinaryFormat/MachO.def"
290 auto BytesRemaining = LC.
Data.load_command_data.cmdsize - BytesWritten;
291 if (BytesRemaining > 0) {
300 switch (LC.
Data.load_command_data.cmd) {
301 case MachO::LC_SEGMENT:
302 case MachO::LC_SEGMENT_64:
304 : LC.
Data.segment_command_data.fileoff;
306 strncmp(&LC.
Data.segment_command_data.segname[0],
"__LINKEDIT", 16)) {
307 FoundLinkEditSeg =
true;
308 LinkEditOff = segOff;
311 writeLinkEditData(
OS);
321 "wrote too much data somewhere, section offsets in "
322 "section {0} for segment {1} don't line up: "
323 "[cursor={2:x}], [fileStart={3:x}], [sectionOffset={4:x}]",
334 "cannot specify section '" + SectName +
335 "' contents in the 'DWARF' entry and "
336 "the 'content' at the same time");
353 Fill(
OS, Sec.
size, 0xDEADBEEFu);
357 : LC.
Data.segment_command_data.filesize;
358 ZeroToOffset(
OS, segOff + segSize);
364 ZeroToOffset(
OS, LinkEditOff);
365 if (
OS.
tell() - fileStart > LinkEditOff || !LinkEditOff)
367 "section offsets don't line up");
379 assert(!
R.is_scattered &&
"non-scattered relocation expected");
395 assert(
R.is_scattered &&
"scattered relocation expected");
406 switch (LC.
Data.load_command_data.cmd) {
407 case MachO::LC_SEGMENT:
408 case MachO::LC_SEGMENT_64:
415 R.is_scattered ? makeScatteredRelocationInfo(R)
416 : makeRelocationInfo(
R, Obj.IsLittleEndian);
419 OS.
write(
reinterpret_cast<const char *
>(&MRE),
427void MachOWriter::writeBindOpcodes(
428 raw_ostream &
OS, std::vector<MachOYAML::BindOpcode> &BindOpcodes) {
430 for (
const auto &Opcode : BindOpcodes) {
431 uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
432 OS.
write(
reinterpret_cast<char *
>(&OpByte), 1);
433 for (
auto Data : Opcode.ULEBExtraData) {
436 for (
auto Data : Opcode.SLEBExtraData) {
439 if (!Opcode.Symbol.empty()) {
440 OS.
write(Opcode.Symbol.data(), Opcode.Symbol.size());
449 if (
Entry.TerminalSize > 0) {
462 for (
const auto &EE :
Entry.Children) {
467 for (
auto EE :
Entry.Children)
468 dumpExportEntry(
OS, EE);
475template <
typename NListType>
477 bool IsLittleEndian) {
479 ListEntry.n_strx = NLE.
n_strx;
480 ListEntry.n_type = NLE.
n_type;
481 ListEntry.n_sect = NLE.
n_sect;
482 ListEntry.n_desc = NLE.
n_desc;
483 ListEntry.n_value = NLE.
n_value;
491 typedef void (MachOWriter::*writeHandler)(
raw_ostream &);
492 typedef std::pair<uint64_t, writeHandler> writeOperation;
493 std::vector<writeOperation> WriteQueue;
503 switch (LC.
Data.load_command_data.cmd) {
504 case MachO::LC_SYMTAB:
505 SymtabCmd = &LC.
Data.symtab_command_data;
506 WriteQueue.push_back(
507 std::make_pair(SymtabCmd->
symoff, &MachOWriter::writeNameList));
508 WriteQueue.push_back(
509 std::make_pair(SymtabCmd->
stroff, &MachOWriter::writeStringTable));
511 case MachO::LC_DYLD_INFO_ONLY:
512 DyldInfoOnlyCmd = &LC.
Data.dyld_info_command_data;
513 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
rebase_off,
514 &MachOWriter::writeRebaseOpcodes));
515 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
bind_off,
516 &MachOWriter::writeBasicBindOpcodes));
517 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
weak_bind_off,
518 &MachOWriter::writeWeakBindOpcodes));
519 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
lazy_bind_off,
520 &MachOWriter::writeLazyBindOpcodes));
521 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
export_off,
522 &MachOWriter::writeExportTrie));
524 case MachO::LC_DYSYMTAB:
525 DSymtabCmd = &LC.
Data.dysymtab_command_data;
526 WriteQueue.push_back(std::make_pair(
527 DSymtabCmd->
indirectsymoff, &MachOWriter::writeDynamicSymbolTable));
529 case MachO::LC_FUNCTION_STARTS:
530 FunctionStartsCmd = &LC.
Data.linkedit_data_command_data;
531 WriteQueue.push_back(std::make_pair(FunctionStartsCmd->
dataoff,
532 &MachOWriter::writeFunctionStarts));
534 case MachO::LC_DYLD_CHAINED_FIXUPS:
535 ChainedFixupsCmd = &LC.
Data.linkedit_data_command_data;
536 WriteQueue.push_back(std::make_pair(ChainedFixupsCmd->
dataoff,
537 &MachOWriter::writeChainedFixups));
539 case MachO::LC_DYLD_EXPORTS_TRIE:
540 DyldExportsTrieCmd = &LC.
Data.linkedit_data_command_data;
541 WriteQueue.push_back(std::make_pair(DyldExportsTrieCmd->
dataoff,
542 &MachOWriter::writeDyldExportsTrie));
544 case MachO::LC_DATA_IN_CODE:
545 DataInCodeCmd = &LC.
Data.linkedit_data_command_data;
546 WriteQueue.push_back(std::make_pair(DataInCodeCmd->
dataoff,
547 &MachOWriter::writeDataInCode));
554 for (
auto writeOp : WriteQueue) {
555 ZeroToOffset(
OS, writeOp.first);
556 (this->*writeOp.second)(
OS);
564 uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
565 OS.
write(
reinterpret_cast<char *
>(&OpByte), 1);
566 for (
auto Data : Opcode.ExtraData)
594 OS.
write(Str.data(), Str.size());
602 sizeof(yaml::Hex32::BaseType));
621 OS.
write(
reinterpret_cast<const char *
>(&DICE),
636class UniversalWriter {
657 return Writer.writeMachO(
OS);
664 if (FatFile.FatArchs.size() < FatFile.Slices.size())
666 errc::invalid_argument,
667 "cannot write 'Slices' if not described in 'FatArches'");
669 for (
size_t i = 0; i < FatFile.Slices.size(); i++) {
670 ZeroToOffset(
OS, FatFile.FatArchs[i].offset);
671 MachOWriter Writer(FatFile.Slices[i]);
672 if (
Error Err = Writer.writeMachO(
OS))
675 auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;
676 ZeroToOffset(
OS, SliceEnd);
685 header.
magic = FatFile.Header.magic;
686 header.
nfat_arch = FatFile.Header.nfat_arch;
692template <
typename FatArchType>
695 FatArch.cputype = Arch.
cputype;
697 FatArch.offset = Arch.
offset;
698 FatArch.size = Arch.
size;
699 FatArch.align = Arch.
align;
703template <
typename StructType>
708 auto FatArch = constructFatArch<MachO::fat_arch>(Arch);
717 auto FatArch = constructFatArch<MachO::fat_arch_64>(Arch);
721 OS.
write(
reinterpret_cast<const char *
>(&FatArch),
728 for (
auto Arch : FatFile.FatArchs) {
730 writeFatArch<MachO::fat_arch_64>(Arch,
OS);
732 writeFatArch<MachO::fat_arch>(Arch,
OS);
737 auto currOffset =
OS.
tell() - fileStart;
748 UniversalWriter Writer(Doc);
749 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)
@ EXPORT_SYMBOL_FLAGS_REEXPORT
@ EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
SectionType
These are the section type and attributes fields.
void swapStruct(fat_header &mh)
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...
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
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.