1 //===- yaml2macho - Convert YAML to a Mach object file --------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// The Mach component of yaml2obj.
13 //===----------------------------------------------------------------------===//
16 #include "llvm/BinaryFormat/MachO.h"
17 #include "llvm/ObjectYAML/DWARFEmitter.h"
18 #include "llvm/ObjectYAML/ObjectYAML.h"
19 #include "llvm/Support/Error.h"
20 #include "llvm/Support/LEB128.h"
21 #include "llvm/Support/YAMLTraits.h"
22 #include "llvm/Support/raw_ostream.h"
24 #include "llvm/Support/Format.h"
32 MachOWriter(MachOYAML::Object
&Obj
) : Obj(Obj
), is64Bit(true), fileStart(0) {
33 is64Bit
= Obj
.Header
.magic
== MachO::MH_MAGIC_64
||
34 Obj
.Header
.magic
== MachO::MH_CIGAM_64
;
35 memset(reinterpret_cast<void *>(&Header
), 0, sizeof(MachO::mach_header_64
));
38 Error
writeMachO(raw_ostream
&OS
);
41 Error
writeHeader(raw_ostream
&OS
);
42 Error
writeLoadCommands(raw_ostream
&OS
);
43 Error
writeSectionData(raw_ostream
&OS
);
44 Error
writeLinkEditData(raw_ostream
&OS
);
46 void writeBindOpcodes(raw_ostream
&OS
,
47 std::vector
<MachOYAML::BindOpcode
> &BindOpcodes
);
49 Error
writeRebaseOpcodes(raw_ostream
&OS
);
50 Error
writeBasicBindOpcodes(raw_ostream
&OS
);
51 Error
writeWeakBindOpcodes(raw_ostream
&OS
);
52 Error
writeLazyBindOpcodes(raw_ostream
&OS
);
53 Error
writeNameList(raw_ostream
&OS
);
54 Error
writeStringTable(raw_ostream
&OS
);
55 Error
writeExportTrie(raw_ostream
&OS
);
57 void dumpExportEntry(raw_ostream
&OS
, MachOYAML::ExportEntry
&Entry
);
58 void ZeroToOffset(raw_ostream
&OS
, size_t offset
);
60 MachOYAML::Object
&Obj
;
64 MachO::mach_header_64 Header
;
67 Error
MachOWriter::writeMachO(raw_ostream
&OS
) {
68 fileStart
= OS
.tell();
69 if (auto Err
= writeHeader(OS
))
71 if (auto Err
= writeLoadCommands(OS
))
73 if (auto Err
= writeSectionData(OS
))
75 return Error::success();
78 Error
MachOWriter::writeHeader(raw_ostream
&OS
) {
79 Header
.magic
= Obj
.Header
.magic
;
80 Header
.cputype
= Obj
.Header
.cputype
;
81 Header
.cpusubtype
= Obj
.Header
.cpusubtype
;
82 Header
.filetype
= Obj
.Header
.filetype
;
83 Header
.ncmds
= Obj
.Header
.ncmds
;
84 Header
.sizeofcmds
= Obj
.Header
.sizeofcmds
;
85 Header
.flags
= Obj
.Header
.flags
;
86 Header
.reserved
= Obj
.Header
.reserved
;
88 if (Obj
.IsLittleEndian
!= sys::IsLittleEndianHost
)
89 MachO::swapStruct(Header
);
92 is64Bit
? sizeof(MachO::mach_header_64
) : sizeof(MachO::mach_header
);
93 OS
.write((const char *)&Header
, header_size
);
95 return Error::success();
98 template <typename SectionType
>
99 SectionType
constructSection(MachOYAML::Section Sec
) {
101 memcpy(reinterpret_cast<void *>(&TempSec
.sectname
[0]), &Sec
.sectname
[0], 16);
102 memcpy(reinterpret_cast<void *>(&TempSec
.segname
[0]), &Sec
.segname
[0], 16);
103 TempSec
.addr
= Sec
.addr
;
104 TempSec
.size
= Sec
.size
;
105 TempSec
.offset
= Sec
.offset
;
106 TempSec
.align
= Sec
.align
;
107 TempSec
.reloff
= Sec
.reloff
;
108 TempSec
.nreloc
= Sec
.nreloc
;
109 TempSec
.flags
= Sec
.flags
;
110 TempSec
.reserved1
= Sec
.reserved1
;
111 TempSec
.reserved2
= Sec
.reserved2
;
115 template <typename StructType
>
116 size_t writeLoadCommandData(MachOYAML::LoadCommand
&LC
, raw_ostream
&OS
,
117 bool IsLittleEndian
) {
122 size_t writeLoadCommandData
<MachO::segment_command
>(MachOYAML::LoadCommand
&LC
,
124 bool IsLittleEndian
) {
125 size_t BytesWritten
= 0;
126 for (const auto &Sec
: LC
.Sections
) {
127 auto TempSec
= constructSection
<MachO::section
>(Sec
);
128 if (IsLittleEndian
!= sys::IsLittleEndianHost
)
129 MachO::swapStruct(TempSec
);
130 OS
.write(reinterpret_cast<const char *>(&(TempSec
)),
131 sizeof(MachO::section
));
132 BytesWritten
+= sizeof(MachO::section
);
138 size_t writeLoadCommandData
<MachO::segment_command_64
>(
139 MachOYAML::LoadCommand
&LC
, raw_ostream
&OS
, bool IsLittleEndian
) {
140 size_t BytesWritten
= 0;
141 for (const auto &Sec
: LC
.Sections
) {
142 auto TempSec
= constructSection
<MachO::section_64
>(Sec
);
143 TempSec
.reserved3
= Sec
.reserved3
;
144 if (IsLittleEndian
!= sys::IsLittleEndianHost
)
145 MachO::swapStruct(TempSec
);
146 OS
.write(reinterpret_cast<const char *>(&(TempSec
)),
147 sizeof(MachO::section_64
));
148 BytesWritten
+= sizeof(MachO::section_64
);
153 size_t writePayloadString(MachOYAML::LoadCommand
&LC
, raw_ostream
&OS
) {
154 size_t BytesWritten
= 0;
155 if (!LC
.PayloadString
.empty()) {
156 OS
.write(LC
.PayloadString
.c_str(), LC
.PayloadString
.length());
157 BytesWritten
= LC
.PayloadString
.length();
163 size_t writeLoadCommandData
<MachO::dylib_command
>(MachOYAML::LoadCommand
&LC
,
165 bool IsLittleEndian
) {
166 return writePayloadString(LC
, OS
);
170 size_t writeLoadCommandData
<MachO::dylinker_command
>(MachOYAML::LoadCommand
&LC
,
172 bool IsLittleEndian
) {
173 return writePayloadString(LC
, OS
);
177 size_t writeLoadCommandData
<MachO::rpath_command
>(MachOYAML::LoadCommand
&LC
,
179 bool IsLittleEndian
) {
180 return writePayloadString(LC
, OS
);
184 size_t writeLoadCommandData
<MachO::build_version_command
>(
185 MachOYAML::LoadCommand
&LC
, raw_ostream
&OS
, bool IsLittleEndian
) {
186 size_t BytesWritten
= 0;
187 for (const auto &T
: LC
.Tools
) {
188 struct MachO::build_tool_version tool
= T
;
189 if (IsLittleEndian
!= sys::IsLittleEndianHost
)
190 MachO::swapStruct(tool
);
191 OS
.write(reinterpret_cast<const char *>(&tool
),
192 sizeof(MachO::build_tool_version
));
193 BytesWritten
+= sizeof(MachO::build_tool_version
);
198 void ZeroFillBytes(raw_ostream
&OS
, size_t Size
) {
199 std::vector
<uint8_t> FillData
;
200 FillData
.insert(FillData
.begin(), Size
, 0);
201 OS
.write(reinterpret_cast<char *>(FillData
.data()), Size
);
204 void Fill(raw_ostream
&OS
, size_t Size
, uint32_t Data
) {
205 std::vector
<uint32_t> FillData
;
206 FillData
.insert(FillData
.begin(), (Size
/ 4) + 1, Data
);
207 OS
.write(reinterpret_cast<char *>(FillData
.data()), Size
);
210 void MachOWriter::ZeroToOffset(raw_ostream
&OS
, size_t Offset
) {
211 auto currOffset
= OS
.tell() - fileStart
;
212 if (currOffset
< Offset
)
213 ZeroFillBytes(OS
, Offset
- currOffset
);
216 Error
MachOWriter::writeLoadCommands(raw_ostream
&OS
) {
217 for (auto &LC
: Obj
.LoadCommands
) {
218 size_t BytesWritten
= 0;
219 llvm::MachO::macho_load_command Data
= LC
.Data
;
221 #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
222 case MachO::LCName: \
223 if (Obj.IsLittleEndian != sys::IsLittleEndianHost) \
224 MachO::swapStruct(Data.LCStruct##_data); \
225 OS.write(reinterpret_cast<const char *>(&(Data.LCStruct##_data)), \
226 sizeof(MachO::LCStruct)); \
227 BytesWritten = sizeof(MachO::LCStruct); \
229 writeLoadCommandData<MachO::LCStruct>(LC, OS, Obj.IsLittleEndian); \
232 switch (LC
.Data
.load_command_data
.cmd
) {
234 if (Obj
.IsLittleEndian
!= sys::IsLittleEndianHost
)
235 MachO::swapStruct(Data
.load_command_data
);
236 OS
.write(reinterpret_cast<const char *>(&(Data
.load_command_data
)),
237 sizeof(MachO::load_command
));
238 BytesWritten
= sizeof(MachO::load_command
);
240 writeLoadCommandData
<MachO::load_command
>(LC
, OS
, Obj
.IsLittleEndian
);
242 #include "llvm/BinaryFormat/MachO.def"
245 if (LC
.PayloadBytes
.size() > 0) {
246 OS
.write(reinterpret_cast<const char *>(LC
.PayloadBytes
.data()),
247 LC
.PayloadBytes
.size());
248 BytesWritten
+= LC
.PayloadBytes
.size();
251 if (LC
.ZeroPadBytes
> 0) {
252 ZeroFillBytes(OS
, LC
.ZeroPadBytes
);
253 BytesWritten
+= LC
.ZeroPadBytes
;
256 // Fill remaining bytes with 0. This will only get hit in partially
257 // specified test cases.
258 auto BytesRemaining
= LC
.Data
.load_command_data
.cmdsize
- BytesWritten
;
259 if (BytesRemaining
> 0) {
260 ZeroFillBytes(OS
, BytesRemaining
);
263 return Error::success();
266 Error
MachOWriter::writeSectionData(raw_ostream
&OS
) {
267 bool FoundLinkEditSeg
= false;
268 for (auto &LC
: Obj
.LoadCommands
) {
269 switch (LC
.Data
.load_command_data
.cmd
) {
270 case MachO::LC_SEGMENT
:
271 case MachO::LC_SEGMENT_64
:
272 uint64_t segOff
= is64Bit
? LC
.Data
.segment_command_64_data
.fileoff
273 : LC
.Data
.segment_command_data
.fileoff
;
274 if (0 == strncmp(&LC
.Data
.segment_command_data
.segname
[0], "__LINKEDIT", 16)) {
275 FoundLinkEditSeg
= true;
276 if (auto Err
= writeLinkEditData(OS
))
279 for (auto &Sec
: LC
.Sections
) {
280 ZeroToOffset(OS
, Sec
.offset
);
281 // Zero Fill any data between the end of the last thing we wrote and the
282 // start of this section.
283 assert((OS
.tell() - fileStart
<= Sec
.offset
||
284 Sec
.offset
== (uint32_t)0) &&
285 "Wrote too much data somewhere, section offsets don't line up.");
286 if (0 == strncmp(&Sec
.segname
[0], "__DWARF", 16)) {
287 if (0 == strncmp(&Sec
.sectname
[0], "__debug_str", 16)) {
288 DWARFYAML::EmitDebugStr(OS
, Obj
.DWARF
);
289 } else if (0 == strncmp(&Sec
.sectname
[0], "__debug_abbrev", 16)) {
290 DWARFYAML::EmitDebugAbbrev(OS
, Obj
.DWARF
);
291 } else if (0 == strncmp(&Sec
.sectname
[0], "__debug_aranges", 16)) {
292 DWARFYAML::EmitDebugAranges(OS
, Obj
.DWARF
);
293 } else if (0 == strncmp(&Sec
.sectname
[0], "__debug_pubnames", 16)) {
294 DWARFYAML::EmitPubSection(OS
, Obj
.DWARF
.PubNames
,
296 } else if (0 == strncmp(&Sec
.sectname
[0], "__debug_pubtypes", 16)) {
297 DWARFYAML::EmitPubSection(OS
, Obj
.DWARF
.PubTypes
,
299 } else if (0 == strncmp(&Sec
.sectname
[0], "__debug_info", 16)) {
300 DWARFYAML::EmitDebugInfo(OS
, Obj
.DWARF
);
301 } else if (0 == strncmp(&Sec
.sectname
[0], "__debug_line", 16)) {
302 DWARFYAML::EmitDebugLine(OS
, Obj
.DWARF
);
305 // Fills section data with 0xDEADBEEF
306 Fill(OS
, Sec
.size
, 0xDEADBEEFu
);
309 uint64_t segSize
= is64Bit
? LC
.Data
.segment_command_64_data
.filesize
310 : LC
.Data
.segment_command_data
.filesize
;
311 ZeroToOffset(OS
, segOff
+ segSize
);
315 // Old PPC Object Files didn't have __LINKEDIT segments, the data was just
316 // stuck at the end of the file.
317 if (!FoundLinkEditSeg
) {
318 if (auto Err
= writeLinkEditData(OS
))
321 return Error::success();
324 void MachOWriter::writeBindOpcodes(
325 raw_ostream
&OS
, std::vector
<MachOYAML::BindOpcode
> &BindOpcodes
) {
327 for (auto Opcode
: BindOpcodes
) {
328 uint8_t OpByte
= Opcode
.Opcode
| Opcode
.Imm
;
329 OS
.write(reinterpret_cast<char *>(&OpByte
), 1);
330 for (auto Data
: Opcode
.ULEBExtraData
) {
331 encodeULEB128(Data
, OS
);
333 for (auto Data
: Opcode
.SLEBExtraData
) {
334 encodeSLEB128(Data
, OS
);
336 if (!Opcode
.Symbol
.empty()) {
337 OS
.write(Opcode
.Symbol
.data(), Opcode
.Symbol
.size());
343 void MachOWriter::dumpExportEntry(raw_ostream
&OS
,
344 MachOYAML::ExportEntry
&Entry
) {
345 encodeSLEB128(Entry
.TerminalSize
, OS
);
346 if (Entry
.TerminalSize
> 0) {
347 encodeSLEB128(Entry
.Flags
, OS
);
348 if (Entry
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_REEXPORT
) {
349 encodeSLEB128(Entry
.Other
, OS
);
350 OS
<< Entry
.ImportName
;
353 encodeSLEB128(Entry
.Address
, OS
);
354 if (Entry
.Flags
& MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
)
355 encodeSLEB128(Entry
.Other
, OS
);
358 OS
.write(static_cast<uint8_t>(Entry
.Children
.size()));
359 for (auto EE
: Entry
.Children
) {
362 encodeSLEB128(EE
.NodeOffset
, OS
);
364 for (auto EE
: Entry
.Children
)
365 dumpExportEntry(OS
, EE
);
368 Error
MachOWriter::writeExportTrie(raw_ostream
&OS
) {
369 dumpExportEntry(OS
, Obj
.LinkEdit
.ExportTrie
);
370 return Error::success();
373 template <typename NListType
>
374 void writeNListEntry(MachOYAML::NListEntry
&NLE
, raw_ostream
&OS
,
375 bool IsLittleEndian
) {
377 ListEntry
.n_strx
= NLE
.n_strx
;
378 ListEntry
.n_type
= NLE
.n_type
;
379 ListEntry
.n_sect
= NLE
.n_sect
;
380 ListEntry
.n_desc
= NLE
.n_desc
;
381 ListEntry
.n_value
= NLE
.n_value
;
383 if (IsLittleEndian
!= sys::IsLittleEndianHost
)
384 MachO::swapStruct(ListEntry
);
385 OS
.write(reinterpret_cast<const char *>(&ListEntry
), sizeof(NListType
));
388 Error
MachOWriter::writeLinkEditData(raw_ostream
&OS
) {
389 typedef Error (MachOWriter::*writeHandler
)(raw_ostream
&);
390 typedef std::pair
<uint64_t, writeHandler
> writeOperation
;
391 std::vector
<writeOperation
> WriteQueue
;
393 MachO::dyld_info_command
*DyldInfoOnlyCmd
= 0;
394 MachO::symtab_command
*SymtabCmd
= 0;
395 for (auto &LC
: Obj
.LoadCommands
) {
396 switch (LC
.Data
.load_command_data
.cmd
) {
397 case MachO::LC_SYMTAB
:
398 SymtabCmd
= &LC
.Data
.symtab_command_data
;
399 WriteQueue
.push_back(
400 std::make_pair(SymtabCmd
->symoff
, &MachOWriter::writeNameList
));
401 WriteQueue
.push_back(
402 std::make_pair(SymtabCmd
->stroff
, &MachOWriter::writeStringTable
));
404 case MachO::LC_DYLD_INFO_ONLY
:
405 DyldInfoOnlyCmd
= &LC
.Data
.dyld_info_command_data
;
406 WriteQueue
.push_back(std::make_pair(DyldInfoOnlyCmd
->rebase_off
,
407 &MachOWriter::writeRebaseOpcodes
));
408 WriteQueue
.push_back(std::make_pair(DyldInfoOnlyCmd
->bind_off
,
409 &MachOWriter::writeBasicBindOpcodes
));
410 WriteQueue
.push_back(std::make_pair(DyldInfoOnlyCmd
->weak_bind_off
,
411 &MachOWriter::writeWeakBindOpcodes
));
412 WriteQueue
.push_back(std::make_pair(DyldInfoOnlyCmd
->lazy_bind_off
,
413 &MachOWriter::writeLazyBindOpcodes
));
414 WriteQueue
.push_back(std::make_pair(DyldInfoOnlyCmd
->export_off
,
415 &MachOWriter::writeExportTrie
));
420 llvm::sort(WriteQueue
, [](const writeOperation
&a
, const writeOperation
&b
) {
421 return a
.first
< b
.first
;
424 for (auto writeOp
: WriteQueue
) {
425 ZeroToOffset(OS
, writeOp
.first
);
426 if (auto Err
= (this->*writeOp
.second
)(OS
))
430 return Error::success();
433 Error
MachOWriter::writeRebaseOpcodes(raw_ostream
&OS
) {
434 MachOYAML::LinkEditData
&LinkEdit
= Obj
.LinkEdit
;
436 for (auto Opcode
: LinkEdit
.RebaseOpcodes
) {
437 uint8_t OpByte
= Opcode
.Opcode
| Opcode
.Imm
;
438 OS
.write(reinterpret_cast<char *>(&OpByte
), 1);
439 for (auto Data
: Opcode
.ExtraData
) {
440 encodeULEB128(Data
, OS
);
443 return Error::success();
446 Error
MachOWriter::writeBasicBindOpcodes(raw_ostream
&OS
) {
447 writeBindOpcodes(OS
, Obj
.LinkEdit
.BindOpcodes
);
448 return Error::success();
451 Error
MachOWriter::writeWeakBindOpcodes(raw_ostream
&OS
) {
452 writeBindOpcodes(OS
, Obj
.LinkEdit
.WeakBindOpcodes
);
453 return Error::success();
456 Error
MachOWriter::writeLazyBindOpcodes(raw_ostream
&OS
) {
457 writeBindOpcodes(OS
, Obj
.LinkEdit
.LazyBindOpcodes
);
458 return Error::success();
461 Error
MachOWriter::writeNameList(raw_ostream
&OS
) {
462 for (auto NLE
: Obj
.LinkEdit
.NameList
) {
464 writeNListEntry
<MachO::nlist_64
>(NLE
, OS
, Obj
.IsLittleEndian
);
466 writeNListEntry
<MachO::nlist
>(NLE
, OS
, Obj
.IsLittleEndian
);
468 return Error::success();
471 Error
MachOWriter::writeStringTable(raw_ostream
&OS
) {
472 for (auto Str
: Obj
.LinkEdit
.StringTable
) {
473 OS
.write(Str
.data(), Str
.size());
476 return Error::success();
479 class UniversalWriter
{
481 UniversalWriter(yaml::YamlObjectFile
&ObjectFile
)
482 : ObjectFile(ObjectFile
), fileStart(0) {}
484 Error
writeMachO(raw_ostream
&OS
);
487 Error
writeFatHeader(raw_ostream
&OS
);
488 Error
writeFatArchs(raw_ostream
&OS
);
490 void ZeroToOffset(raw_ostream
&OS
, size_t offset
);
492 yaml::YamlObjectFile
&ObjectFile
;
496 Error
UniversalWriter::writeMachO(raw_ostream
&OS
) {
497 fileStart
= OS
.tell();
498 if (ObjectFile
.MachO
) {
499 MachOWriter
Writer(*ObjectFile
.MachO
);
500 return Writer
.writeMachO(OS
);
502 if (auto Err
= writeFatHeader(OS
))
504 if (auto Err
= writeFatArchs(OS
))
506 auto &FatFile
= *ObjectFile
.FatMachO
;
507 assert(FatFile
.FatArchs
.size() == FatFile
.Slices
.size());
508 for (size_t i
= 0; i
< FatFile
.Slices
.size(); i
++) {
509 ZeroToOffset(OS
, FatFile
.FatArchs
[i
].offset
);
510 MachOWriter
Writer(FatFile
.Slices
[i
]);
511 if (auto Err
= Writer
.writeMachO(OS
))
513 auto SliceEnd
= FatFile
.FatArchs
[i
].offset
+ FatFile
.FatArchs
[i
].size
;
514 ZeroToOffset(OS
, SliceEnd
);
516 return Error::success();
519 Error
UniversalWriter::writeFatHeader(raw_ostream
&OS
) {
520 auto &FatFile
= *ObjectFile
.FatMachO
;
521 MachO::fat_header header
;
522 header
.magic
= FatFile
.Header
.magic
;
523 header
.nfat_arch
= FatFile
.Header
.nfat_arch
;
524 if (sys::IsLittleEndianHost
)
526 OS
.write(reinterpret_cast<const char *>(&header
), sizeof(MachO::fat_header
));
527 return Error::success();
530 template <typename FatArchType
>
531 FatArchType
constructFatArch(MachOYAML::FatArch
&Arch
) {
533 FatArch
.cputype
= Arch
.cputype
;
534 FatArch
.cpusubtype
= Arch
.cpusubtype
;
535 FatArch
.offset
= Arch
.offset
;
536 FatArch
.size
= Arch
.size
;
537 FatArch
.align
= Arch
.align
;
541 template <typename StructType
>
542 void writeFatArch(MachOYAML::FatArch
&LC
, raw_ostream
&OS
) {}
545 void writeFatArch
<MachO::fat_arch
>(MachOYAML::FatArch
&Arch
, raw_ostream
&OS
) {
546 auto FatArch
= constructFatArch
<MachO::fat_arch
>(Arch
);
547 if (sys::IsLittleEndianHost
)
549 OS
.write(reinterpret_cast<const char *>(&FatArch
), sizeof(MachO::fat_arch
));
553 void writeFatArch
<MachO::fat_arch_64
>(MachOYAML::FatArch
&Arch
,
555 auto FatArch
= constructFatArch
<MachO::fat_arch_64
>(Arch
);
556 FatArch
.reserved
= Arch
.reserved
;
557 if (sys::IsLittleEndianHost
)
559 OS
.write(reinterpret_cast<const char *>(&FatArch
),
560 sizeof(MachO::fat_arch_64
));
563 Error
UniversalWriter::writeFatArchs(raw_ostream
&OS
) {
564 auto &FatFile
= *ObjectFile
.FatMachO
;
565 bool is64Bit
= FatFile
.Header
.magic
== MachO::FAT_MAGIC_64
;
566 for (auto Arch
: FatFile
.FatArchs
) {
568 writeFatArch
<MachO::fat_arch_64
>(Arch
, OS
);
570 writeFatArch
<MachO::fat_arch
>(Arch
, OS
);
573 return Error::success();
576 void UniversalWriter::ZeroToOffset(raw_ostream
&OS
, size_t Offset
) {
577 auto currOffset
= OS
.tell() - fileStart
;
578 if (currOffset
< Offset
)
579 ZeroFillBytes(OS
, Offset
- currOffset
);
582 } // end anonymous namespace
584 int yaml2macho(yaml::YamlObjectFile
&Doc
, raw_ostream
&Out
) {
585 UniversalWriter
Writer(Doc
);
586 if (auto Err
= Writer
.writeMachO(Out
)) {
587 errs() << toString(std::move(Err
));