49 std::vector<MachOYAML::BindOpcode> &BindOpcodes);
74 bool FoundLinkEditSeg =
false;
80 writeLoadCommands(
OS);
81 if (
Error Err = writeSectionData(
OS))
84 if (!FoundLinkEditSeg)
85 writeLinkEditData(
OS);
104 OS.
write((
const char *)&Header, header_size);
107template <
typename SectionType>
110 memcpy(
reinterpret_cast<void *
>(&TempSec.sectname[0]), &Sec.
sectname[0], 16);
111 memcpy(
reinterpret_cast<void *
>(&TempSec.segname[0]), &Sec.
segname[0], 16);
112 TempSec.addr = Sec.
addr;
113 TempSec.size = Sec.
size;
114 TempSec.offset = Sec.
offset;
115 TempSec.align = Sec.
align;
116 TempSec.reloff = Sec.
reloff;
117 TempSec.nreloc = Sec.
nreloc;
118 TempSec.flags = Sec.
flags;
124template <
typename StructType>
126 bool IsLittleEndian) {
133 bool IsLittleEndian) {
134 size_t BytesWritten = 0;
135 for (
const auto &Sec : LC.
Sections) {
136 auto TempSec = constructSection<MachO::section>(Sec);
139 OS.
write(
reinterpret_cast<const char *
>(&(TempSec)),
147size_t writeLoadCommandData<MachO::segment_command_64>(
149 size_t BytesWritten = 0;
150 for (
const auto &Sec : LC.
Sections) {
151 auto TempSec = constructSection<MachO::section_64>(Sec);
155 OS.
write(
reinterpret_cast<const char *
>(&(TempSec)),
163 size_t BytesWritten = 0;
166 BytesWritten = LC.
Content.length();
174 bool IsLittleEndian) {
175 return writePayloadString(LC,
OS);
181 bool IsLittleEndian) {
182 return writePayloadString(LC,
OS);
188 bool IsLittleEndian) {
189 return writePayloadString(LC,
OS);
193size_t writeLoadCommandData<MachO::sub_framework_command>(
195 return writePayloadString(LC,
OS);
199size_t writeLoadCommandData<MachO::sub_umbrella_command>(
201 return writePayloadString(LC,
OS);
205size_t writeLoadCommandData<MachO::sub_client_command>(
207 return writePayloadString(LC,
OS);
211size_t writeLoadCommandData<MachO::sub_library_command>(
213 return writePayloadString(LC,
OS);
217size_t writeLoadCommandData<MachO::build_version_command>(
219 size_t BytesWritten = 0;
220 for (
const auto &
T : LC.
Tools) {
232 std::vector<uint8_t> FillData(
Size, 0);
233 OS.
write(
reinterpret_cast<char *
>(FillData.data()),
Size);
237 std::vector<uint32_t> FillData((
Size / 4) + 1,
Data);
238 OS.
write(
reinterpret_cast<char *
>(FillData.data()),
Size);
242 auto currOffset =
OS.
tell() - fileStart;
249 size_t BytesWritten = 0;
252#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
253 case MachO::LCName: \
254 if (Obj.IsLittleEndian != sys::IsLittleEndianHost) \
255 MachO::swapStruct(Data.LCStruct##_data); \
256 OS.write(reinterpret_cast<const char *>(&(Data.LCStruct##_data)), \
257 sizeof(MachO::LCStruct)); \
258 BytesWritten = sizeof(MachO::LCStruct); \
260 writeLoadCommandData<MachO::LCStruct>(LC, OS, Obj.IsLittleEndian); \
263 switch (LC.
Data.load_command_data.cmd) {
267 OS.
write(
reinterpret_cast<const char *
>(&(
Data.load_command_data)),
273#include "llvm/BinaryFormat/MachO.def"
289 auto BytesRemaining = LC.
Data.load_command_data.cmdsize - BytesWritten;
290 if (BytesRemaining > 0) {
299 switch (LC.
Data.load_command_data.cmd) {
300 case MachO::LC_SEGMENT:
301 case MachO::LC_SEGMENT_64:
303 : LC.
Data.segment_command_data.fileoff;
305 strncmp(&LC.
Data.segment_command_data.segname[0],
"__LINKEDIT", 16)) {
306 FoundLinkEditSeg =
true;
307 LinkEditOff = segOff;
310 writeLinkEditData(
OS);
320 "wrote too much data somewhere, section offsets in "
321 "section {0} for segment {1} don't line up: "
322 "[cursor={2:x}], [fileStart={3:x}], [sectionOffset={4:x}]",
333 "cannot specify section '" + SectName +
334 "' contents in the 'DWARF' entry and "
335 "the 'content' at the same time");
352 Fill(
OS, Sec.
size, 0xDEADBEEFu);
356 : LC.
Data.segment_command_data.filesize;
357 ZeroToOffset(
OS, segOff + segSize);
363 ZeroToOffset(
OS, LinkEditOff);
364 if (
OS.
tell() - fileStart > LinkEditOff || !LinkEditOff)
366 "section offsets don't line up");
378 assert(!
R.is_scattered &&
"non-scattered relocation expected");
394 assert(
R.is_scattered &&
"scattered relocation expected");
405 switch (LC.
Data.load_command_data.cmd) {
406 case MachO::LC_SEGMENT:
407 case MachO::LC_SEGMENT_64:
414 R.is_scattered ? makeScatteredRelocationInfo(R)
415 : makeRelocationInfo(
R, Obj.IsLittleEndian);
418 OS.
write(
reinterpret_cast<const char *
>(&MRE),
426void MachOWriter::writeBindOpcodes(
427 raw_ostream &
OS, std::vector<MachOYAML::BindOpcode> &BindOpcodes) {
429 for (
const auto &
Opcode : BindOpcodes) {
431 OS.
write(
reinterpret_cast<char *
>(&OpByte), 1);
438 if (!
Opcode.Symbol.empty()) {
448 if (Entry.TerminalSize > 0) {
452 OS << Entry.ImportName;
460 OS.
write(
static_cast<uint8_t
>(Entry.Children.size()));
461 for (
const auto &EE : Entry.Children) {
466 for (
auto EE : Entry.Children)
467 dumpExportEntry(
OS, EE);
474template <
typename NListType>
476 bool IsLittleEndian) {
478 ListEntry.n_strx = NLE.
n_strx;
479 ListEntry.n_type = NLE.
n_type;
480 ListEntry.n_sect = NLE.
n_sect;
481 ListEntry.n_desc = NLE.
n_desc;
482 ListEntry.n_value = NLE.
n_value;
490 typedef void (MachOWriter::*writeHandler)(
raw_ostream &);
491 typedef std::pair<uint64_t, writeHandler> writeOperation;
492 std::vector<writeOperation> WriteQueue;
502 switch (LC.
Data.load_command_data.cmd) {
503 case MachO::LC_SYMTAB:
504 SymtabCmd = &LC.
Data.symtab_command_data;
505 WriteQueue.push_back(
506 std::make_pair(SymtabCmd->
symoff, &MachOWriter::writeNameList));
507 WriteQueue.push_back(
508 std::make_pair(SymtabCmd->
stroff, &MachOWriter::writeStringTable));
510 case MachO::LC_DYLD_INFO_ONLY:
511 DyldInfoOnlyCmd = &LC.
Data.dyld_info_command_data;
512 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
rebase_off,
513 &MachOWriter::writeRebaseOpcodes));
514 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
bind_off,
515 &MachOWriter::writeBasicBindOpcodes));
516 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
weak_bind_off,
517 &MachOWriter::writeWeakBindOpcodes));
518 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
lazy_bind_off,
519 &MachOWriter::writeLazyBindOpcodes));
520 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->
export_off,
521 &MachOWriter::writeExportTrie));
523 case MachO::LC_DYSYMTAB:
524 DSymtabCmd = &LC.
Data.dysymtab_command_data;
525 WriteQueue.push_back(std::make_pair(
526 DSymtabCmd->
indirectsymoff, &MachOWriter::writeDynamicSymbolTable));
528 case MachO::LC_FUNCTION_STARTS:
529 FunctionStartsCmd = &LC.
Data.linkedit_data_command_data;
530 WriteQueue.push_back(std::make_pair(FunctionStartsCmd->
dataoff,
531 &MachOWriter::writeFunctionStarts));
533 case MachO::LC_DYLD_CHAINED_FIXUPS:
534 ChainedFixupsCmd = &LC.
Data.linkedit_data_command_data;
535 WriteQueue.push_back(std::make_pair(ChainedFixupsCmd->
dataoff,
536 &MachOWriter::writeChainedFixups));
538 case MachO::LC_DYLD_EXPORTS_TRIE:
539 DyldExportsTrieCmd = &LC.
Data.linkedit_data_command_data;
540 WriteQueue.push_back(std::make_pair(DyldExportsTrieCmd->
dataoff,
541 &MachOWriter::writeDyldExportsTrie));
543 case MachO::LC_DATA_IN_CODE:
544 DataInCodeCmd = &LC.
Data.linkedit_data_command_data;
545 WriteQueue.push_back(std::make_pair(DataInCodeCmd->
dataoff,
546 &MachOWriter::writeDataInCode));
553 for (
auto writeOp : WriteQueue) {
554 ZeroToOffset(
OS, writeOp.first);
555 (this->*writeOp.second)(
OS);
564 OS.
write(
reinterpret_cast<char *
>(&OpByte), 1);
593 OS.
write(Str.data(), Str.size());
601 sizeof(yaml::Hex32::BaseType));
620 OS.
write(
reinterpret_cast<const char *
>(&DICE),
635class UniversalWriter {
656 return Writer.writeMachO(
OS);
663 if (FatFile.FatArchs.size() < FatFile.Slices.size())
665 errc::invalid_argument,
666 "cannot write 'Slices' if not described in 'FatArches'");
668 for (
size_t i = 0; i < FatFile.Slices.size(); i++) {
669 ZeroToOffset(
OS, FatFile.FatArchs[i].offset);
670 MachOWriter Writer(FatFile.Slices[i]);
671 if (
Error Err = Writer.writeMachO(
OS))
674 auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;
675 ZeroToOffset(
OS, SliceEnd);
684 header.
magic = FatFile.Header.magic;
685 header.
nfat_arch = FatFile.Header.nfat_arch;
691template <
typename FatArchType>
694 FatArch.cputype = Arch.
cputype;
696 FatArch.offset = Arch.
offset;
697 FatArch.size = Arch.
size;
698 FatArch.align = Arch.
align;
702template <
typename StructType>
707 auto FatArch = constructFatArch<MachO::fat_arch>(Arch);
716 auto FatArch = constructFatArch<MachO::fat_arch_64>(Arch);
720 OS.
write(
reinterpret_cast<const char *
>(&FatArch),
727 for (
auto Arch : FatFile.FatArchs) {
729 writeFatArch<MachO::fat_arch_64>(Arch,
OS);
731 writeFatArch<MachO::fat_arch>(Arch,
OS);
736 auto currOffset =
OS.
tell() - fileStart;
747 UniversalWriter Writer(Doc);
748 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)
static constexpr uint32_t Opcode
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)
@ EXPORT_SYMBOL_FLAGS_REEXPORT
@ EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
bool isVirtualSection(uint8_t type)
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.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
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.
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.