xref: /aosp_15_r20/external/llvm/tools/yaml2obj/yaml2macho.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- yaml2macho - Convert YAML to a Mach object file --------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker ///
10*9880d681SAndroid Build Coastguard Worker /// \file
11*9880d681SAndroid Build Coastguard Worker /// \brief The Mach component of yaml2obj.
12*9880d681SAndroid Build Coastguard Worker ///
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #include "yaml2obj.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ObjectYAML/ObjectYAML.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Error.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/LEB128.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MachO.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/YAMLTraits.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
22*9880d681SAndroid Build Coastguard Worker 
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker using namespace llvm;
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker namespace {
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker class MachOWriter {
30*9880d681SAndroid Build Coastguard Worker public:
MachOWriter(MachOYAML::Object & Obj)31*9880d681SAndroid Build Coastguard Worker   MachOWriter(MachOYAML::Object &Obj) : Obj(Obj), is64Bit(true), fileStart(0) {
32*9880d681SAndroid Build Coastguard Worker     is64Bit = Obj.Header.magic == MachO::MH_MAGIC_64 ||
33*9880d681SAndroid Build Coastguard Worker               Obj.Header.magic == MachO::MH_CIGAM_64;
34*9880d681SAndroid Build Coastguard Worker     memset(reinterpret_cast<void *>(&Header), 0, sizeof(MachO::mach_header_64));
35*9880d681SAndroid Build Coastguard Worker   }
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker   Error writeMachO(raw_ostream &OS);
38*9880d681SAndroid Build Coastguard Worker 
39*9880d681SAndroid Build Coastguard Worker private:
40*9880d681SAndroid Build Coastguard Worker   Error writeHeader(raw_ostream &OS);
41*9880d681SAndroid Build Coastguard Worker   Error writeLoadCommands(raw_ostream &OS);
42*9880d681SAndroid Build Coastguard Worker   Error writeSectionData(raw_ostream &OS);
43*9880d681SAndroid Build Coastguard Worker   Error writeLinkEditData(raw_ostream &OS);
44*9880d681SAndroid Build Coastguard Worker   void writeBindOpcodes(raw_ostream &OS,
45*9880d681SAndroid Build Coastguard Worker                         std::vector<MachOYAML::BindOpcode> &BindOpcodes);
46*9880d681SAndroid Build Coastguard Worker   // LinkEdit writers
47*9880d681SAndroid Build Coastguard Worker   Error writeRebaseOpcodes(raw_ostream &OS);
48*9880d681SAndroid Build Coastguard Worker   Error writeBasicBindOpcodes(raw_ostream &OS);
49*9880d681SAndroid Build Coastguard Worker   Error writeWeakBindOpcodes(raw_ostream &OS);
50*9880d681SAndroid Build Coastguard Worker   Error writeLazyBindOpcodes(raw_ostream &OS);
51*9880d681SAndroid Build Coastguard Worker   Error writeNameList(raw_ostream &OS);
52*9880d681SAndroid Build Coastguard Worker   Error writeStringTable(raw_ostream &OS);
53*9880d681SAndroid Build Coastguard Worker   Error writeExportTrie(raw_ostream &OS);
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker   void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);
56*9880d681SAndroid Build Coastguard Worker   void ZeroToOffset(raw_ostream &OS, size_t offset);
57*9880d681SAndroid Build Coastguard Worker 
58*9880d681SAndroid Build Coastguard Worker   MachOYAML::Object &Obj;
59*9880d681SAndroid Build Coastguard Worker   bool is64Bit;
60*9880d681SAndroid Build Coastguard Worker   uint64_t fileStart;
61*9880d681SAndroid Build Coastguard Worker 
62*9880d681SAndroid Build Coastguard Worker   MachO::mach_header_64 Header;
63*9880d681SAndroid Build Coastguard Worker };
64*9880d681SAndroid Build Coastguard Worker 
writeMachO(raw_ostream & OS)65*9880d681SAndroid Build Coastguard Worker Error MachOWriter::writeMachO(raw_ostream &OS) {
66*9880d681SAndroid Build Coastguard Worker   fileStart = OS.tell();
67*9880d681SAndroid Build Coastguard Worker   if (auto Err = writeHeader(OS))
68*9880d681SAndroid Build Coastguard Worker     return Err;
69*9880d681SAndroid Build Coastguard Worker   if (auto Err = writeLoadCommands(OS))
70*9880d681SAndroid Build Coastguard Worker     return Err;
71*9880d681SAndroid Build Coastguard Worker   if (auto Err = writeSectionData(OS))
72*9880d681SAndroid Build Coastguard Worker     return Err;
73*9880d681SAndroid Build Coastguard Worker   return Error::success();
74*9880d681SAndroid Build Coastguard Worker }
75*9880d681SAndroid Build Coastguard Worker 
writeHeader(raw_ostream & OS)76*9880d681SAndroid Build Coastguard Worker Error MachOWriter::writeHeader(raw_ostream &OS) {
77*9880d681SAndroid Build Coastguard Worker   Header.magic = Obj.Header.magic;
78*9880d681SAndroid Build Coastguard Worker   Header.cputype = Obj.Header.cputype;
79*9880d681SAndroid Build Coastguard Worker   Header.cpusubtype = Obj.Header.cpusubtype;
80*9880d681SAndroid Build Coastguard Worker   Header.filetype = Obj.Header.filetype;
81*9880d681SAndroid Build Coastguard Worker   Header.ncmds = Obj.Header.ncmds;
82*9880d681SAndroid Build Coastguard Worker   Header.sizeofcmds = Obj.Header.sizeofcmds;
83*9880d681SAndroid Build Coastguard Worker   Header.flags = Obj.Header.flags;
84*9880d681SAndroid Build Coastguard Worker   Header.reserved = Obj.Header.reserved;
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker   auto header_size =
87*9880d681SAndroid Build Coastguard Worker       is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
88*9880d681SAndroid Build Coastguard Worker   OS.write((const char *)&Header, header_size);
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker   return Error::success();
91*9880d681SAndroid Build Coastguard Worker }
92*9880d681SAndroid Build Coastguard Worker 
93*9880d681SAndroid Build Coastguard Worker template <typename SectionType>
constructSection(MachOYAML::Section Sec)94*9880d681SAndroid Build Coastguard Worker SectionType constructSection(MachOYAML::Section Sec) {
95*9880d681SAndroid Build Coastguard Worker   SectionType TempSec;
96*9880d681SAndroid Build Coastguard Worker   memcpy(reinterpret_cast<void *>(&TempSec.sectname[0]), &Sec.sectname[0], 16);
97*9880d681SAndroid Build Coastguard Worker   memcpy(reinterpret_cast<void *>(&TempSec.segname[0]), &Sec.segname[0], 16);
98*9880d681SAndroid Build Coastguard Worker   TempSec.addr = Sec.addr;
99*9880d681SAndroid Build Coastguard Worker   TempSec.size = Sec.size;
100*9880d681SAndroid Build Coastguard Worker   TempSec.offset = Sec.offset;
101*9880d681SAndroid Build Coastguard Worker   TempSec.align = Sec.align;
102*9880d681SAndroid Build Coastguard Worker   TempSec.reloff = Sec.reloff;
103*9880d681SAndroid Build Coastguard Worker   TempSec.nreloc = Sec.nreloc;
104*9880d681SAndroid Build Coastguard Worker   TempSec.flags = Sec.flags;
105*9880d681SAndroid Build Coastguard Worker   TempSec.reserved1 = Sec.reserved1;
106*9880d681SAndroid Build Coastguard Worker   TempSec.reserved2 = Sec.reserved2;
107*9880d681SAndroid Build Coastguard Worker   return TempSec;
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker 
110*9880d681SAndroid Build Coastguard Worker template <typename StructType>
writeLoadCommandData(MachOYAML::LoadCommand & LC,raw_ostream & OS)111*9880d681SAndroid Build Coastguard Worker size_t writeLoadCommandData(MachOYAML::LoadCommand &LC, raw_ostream &OS) {
112*9880d681SAndroid Build Coastguard Worker   return 0;
113*9880d681SAndroid Build Coastguard Worker }
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker template <>
writeLoadCommandData(MachOYAML::LoadCommand & LC,raw_ostream & OS)116*9880d681SAndroid Build Coastguard Worker size_t writeLoadCommandData<MachO::segment_command>(MachOYAML::LoadCommand &LC,
117*9880d681SAndroid Build Coastguard Worker                                                     raw_ostream &OS) {
118*9880d681SAndroid Build Coastguard Worker   size_t BytesWritten = 0;
119*9880d681SAndroid Build Coastguard Worker   for (const auto &Sec : LC.Sections) {
120*9880d681SAndroid Build Coastguard Worker     auto TempSec = constructSection<MachO::section>(Sec);
121*9880d681SAndroid Build Coastguard Worker     OS.write(reinterpret_cast<const char *>(&(TempSec)),
122*9880d681SAndroid Build Coastguard Worker              sizeof(MachO::section));
123*9880d681SAndroid Build Coastguard Worker     BytesWritten += sizeof(MachO::section);
124*9880d681SAndroid Build Coastguard Worker   }
125*9880d681SAndroid Build Coastguard Worker   return BytesWritten;
126*9880d681SAndroid Build Coastguard Worker }
127*9880d681SAndroid Build Coastguard Worker 
128*9880d681SAndroid Build Coastguard Worker template <>
129*9880d681SAndroid Build Coastguard Worker size_t
writeLoadCommandData(MachOYAML::LoadCommand & LC,raw_ostream & OS)130*9880d681SAndroid Build Coastguard Worker writeLoadCommandData<MachO::segment_command_64>(MachOYAML::LoadCommand &LC,
131*9880d681SAndroid Build Coastguard Worker                                                 raw_ostream &OS) {
132*9880d681SAndroid Build Coastguard Worker   size_t BytesWritten = 0;
133*9880d681SAndroid Build Coastguard Worker   for (const auto &Sec : LC.Sections) {
134*9880d681SAndroid Build Coastguard Worker     auto TempSec = constructSection<MachO::section_64>(Sec);
135*9880d681SAndroid Build Coastguard Worker     TempSec.reserved3 = Sec.reserved3;
136*9880d681SAndroid Build Coastguard Worker     OS.write(reinterpret_cast<const char *>(&(TempSec)),
137*9880d681SAndroid Build Coastguard Worker              sizeof(MachO::section_64));
138*9880d681SAndroid Build Coastguard Worker     BytesWritten += sizeof(MachO::section_64);
139*9880d681SAndroid Build Coastguard Worker   }
140*9880d681SAndroid Build Coastguard Worker   return BytesWritten;
141*9880d681SAndroid Build Coastguard Worker }
142*9880d681SAndroid Build Coastguard Worker 
writePayloadString(MachOYAML::LoadCommand & LC,raw_ostream & OS)143*9880d681SAndroid Build Coastguard Worker size_t writePayloadString(MachOYAML::LoadCommand &LC, raw_ostream &OS) {
144*9880d681SAndroid Build Coastguard Worker   size_t BytesWritten = 0;
145*9880d681SAndroid Build Coastguard Worker   if (!LC.PayloadString.empty()) {
146*9880d681SAndroid Build Coastguard Worker     OS.write(LC.PayloadString.c_str(), LC.PayloadString.length());
147*9880d681SAndroid Build Coastguard Worker     BytesWritten = LC.PayloadString.length();
148*9880d681SAndroid Build Coastguard Worker   }
149*9880d681SAndroid Build Coastguard Worker   return BytesWritten;
150*9880d681SAndroid Build Coastguard Worker }
151*9880d681SAndroid Build Coastguard Worker 
152*9880d681SAndroid Build Coastguard Worker template <>
writeLoadCommandData(MachOYAML::LoadCommand & LC,raw_ostream & OS)153*9880d681SAndroid Build Coastguard Worker size_t writeLoadCommandData<MachO::dylib_command>(MachOYAML::LoadCommand &LC,
154*9880d681SAndroid Build Coastguard Worker                                                   raw_ostream &OS) {
155*9880d681SAndroid Build Coastguard Worker   return writePayloadString(LC, OS);
156*9880d681SAndroid Build Coastguard Worker }
157*9880d681SAndroid Build Coastguard Worker 
158*9880d681SAndroid Build Coastguard Worker template <>
writeLoadCommandData(MachOYAML::LoadCommand & LC,raw_ostream & OS)159*9880d681SAndroid Build Coastguard Worker size_t writeLoadCommandData<MachO::dylinker_command>(MachOYAML::LoadCommand &LC,
160*9880d681SAndroid Build Coastguard Worker                                                      raw_ostream &OS) {
161*9880d681SAndroid Build Coastguard Worker   return writePayloadString(LC, OS);
162*9880d681SAndroid Build Coastguard Worker }
163*9880d681SAndroid Build Coastguard Worker 
164*9880d681SAndroid Build Coastguard Worker template <>
writeLoadCommandData(MachOYAML::LoadCommand & LC,raw_ostream & OS)165*9880d681SAndroid Build Coastguard Worker size_t writeLoadCommandData<MachO::rpath_command>(MachOYAML::LoadCommand &LC,
166*9880d681SAndroid Build Coastguard Worker                                                   raw_ostream &OS) {
167*9880d681SAndroid Build Coastguard Worker   return writePayloadString(LC, OS);
168*9880d681SAndroid Build Coastguard Worker }
169*9880d681SAndroid Build Coastguard Worker 
ZeroFillBytes(raw_ostream & OS,size_t Size)170*9880d681SAndroid Build Coastguard Worker void ZeroFillBytes(raw_ostream &OS, size_t Size) {
171*9880d681SAndroid Build Coastguard Worker   std::vector<uint8_t> FillData;
172*9880d681SAndroid Build Coastguard Worker   FillData.insert(FillData.begin(), Size, 0);
173*9880d681SAndroid Build Coastguard Worker   OS.write(reinterpret_cast<char *>(FillData.data()), Size);
174*9880d681SAndroid Build Coastguard Worker }
175*9880d681SAndroid Build Coastguard Worker 
Fill(raw_ostream & OS,size_t Size,uint32_t Data)176*9880d681SAndroid Build Coastguard Worker void Fill(raw_ostream &OS, size_t Size, uint32_t Data) {
177*9880d681SAndroid Build Coastguard Worker   std::vector<uint32_t> FillData;
178*9880d681SAndroid Build Coastguard Worker   FillData.insert(FillData.begin(), (Size / 4) + 1, Data);
179*9880d681SAndroid Build Coastguard Worker   OS.write(reinterpret_cast<char *>(FillData.data()), Size);
180*9880d681SAndroid Build Coastguard Worker }
181*9880d681SAndroid Build Coastguard Worker 
ZeroToOffset(raw_ostream & OS,size_t Offset)182*9880d681SAndroid Build Coastguard Worker void MachOWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
183*9880d681SAndroid Build Coastguard Worker   auto currOffset = OS.tell() - fileStart;
184*9880d681SAndroid Build Coastguard Worker   if (currOffset < Offset)
185*9880d681SAndroid Build Coastguard Worker     ZeroFillBytes(OS, Offset - currOffset);
186*9880d681SAndroid Build Coastguard Worker }
187*9880d681SAndroid Build Coastguard Worker 
writeLoadCommands(raw_ostream & OS)188*9880d681SAndroid Build Coastguard Worker Error MachOWriter::writeLoadCommands(raw_ostream &OS) {
189*9880d681SAndroid Build Coastguard Worker   for (auto &LC : Obj.LoadCommands) {
190*9880d681SAndroid Build Coastguard Worker     size_t BytesWritten = 0;
191*9880d681SAndroid Build Coastguard Worker #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct)                         \
192*9880d681SAndroid Build Coastguard Worker   case MachO::LCName:                                                          \
193*9880d681SAndroid Build Coastguard Worker     OS.write(reinterpret_cast<const char *>(&(LC.Data.LCStruct##_data)),       \
194*9880d681SAndroid Build Coastguard Worker              sizeof(MachO::LCStruct));                                         \
195*9880d681SAndroid Build Coastguard Worker     BytesWritten = sizeof(MachO::LCStruct);                                    \
196*9880d681SAndroid Build Coastguard Worker     BytesWritten += writeLoadCommandData<MachO::LCStruct>(LC, OS);             \
197*9880d681SAndroid Build Coastguard Worker     break;
198*9880d681SAndroid Build Coastguard Worker 
199*9880d681SAndroid Build Coastguard Worker     switch (LC.Data.load_command_data.cmd) {
200*9880d681SAndroid Build Coastguard Worker     default:
201*9880d681SAndroid Build Coastguard Worker       OS.write(reinterpret_cast<const char *>(&(LC.Data.load_command_data)),
202*9880d681SAndroid Build Coastguard Worker                sizeof(MachO::load_command));
203*9880d681SAndroid Build Coastguard Worker       BytesWritten = sizeof(MachO::load_command);
204*9880d681SAndroid Build Coastguard Worker       BytesWritten += writeLoadCommandData<MachO::load_command>(LC, OS);
205*9880d681SAndroid Build Coastguard Worker       break;
206*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MachO.def"
207*9880d681SAndroid Build Coastguard Worker     }
208*9880d681SAndroid Build Coastguard Worker 
209*9880d681SAndroid Build Coastguard Worker     if (LC.PayloadBytes.size() > 0) {
210*9880d681SAndroid Build Coastguard Worker       OS.write(reinterpret_cast<const char *>(LC.PayloadBytes.data()),
211*9880d681SAndroid Build Coastguard Worker                LC.PayloadBytes.size());
212*9880d681SAndroid Build Coastguard Worker       BytesWritten += LC.PayloadBytes.size();
213*9880d681SAndroid Build Coastguard Worker     }
214*9880d681SAndroid Build Coastguard Worker 
215*9880d681SAndroid Build Coastguard Worker     if (LC.ZeroPadBytes > 0) {
216*9880d681SAndroid Build Coastguard Worker       ZeroFillBytes(OS, LC.ZeroPadBytes);
217*9880d681SAndroid Build Coastguard Worker       BytesWritten += LC.ZeroPadBytes;
218*9880d681SAndroid Build Coastguard Worker     }
219*9880d681SAndroid Build Coastguard Worker 
220*9880d681SAndroid Build Coastguard Worker     // Fill remaining bytes with 0. This will only get hit in partially
221*9880d681SAndroid Build Coastguard Worker     // specified test cases.
222*9880d681SAndroid Build Coastguard Worker     auto BytesRemaining = LC.Data.load_command_data.cmdsize - BytesWritten;
223*9880d681SAndroid Build Coastguard Worker     if (BytesRemaining > 0) {
224*9880d681SAndroid Build Coastguard Worker       ZeroFillBytes(OS, BytesRemaining);
225*9880d681SAndroid Build Coastguard Worker     }
226*9880d681SAndroid Build Coastguard Worker   }
227*9880d681SAndroid Build Coastguard Worker   return Error::success();
228*9880d681SAndroid Build Coastguard Worker }
229*9880d681SAndroid Build Coastguard Worker 
writeSectionData(raw_ostream & OS)230*9880d681SAndroid Build Coastguard Worker Error MachOWriter::writeSectionData(raw_ostream &OS) {
231*9880d681SAndroid Build Coastguard Worker   for (auto &LC : Obj.LoadCommands) {
232*9880d681SAndroid Build Coastguard Worker     switch (LC.Data.load_command_data.cmd) {
233*9880d681SAndroid Build Coastguard Worker     case MachO::LC_SEGMENT:
234*9880d681SAndroid Build Coastguard Worker     case MachO::LC_SEGMENT_64:
235*9880d681SAndroid Build Coastguard Worker       auto currOffset = OS.tell() - fileStart;
236*9880d681SAndroid Build Coastguard Worker       auto segname = LC.Data.segment_command_data.segname;
237*9880d681SAndroid Build Coastguard Worker       uint64_t segOff = is64Bit ? LC.Data.segment_command_64_data.fileoff
238*9880d681SAndroid Build Coastguard Worker                                 : LC.Data.segment_command_data.fileoff;
239*9880d681SAndroid Build Coastguard Worker 
240*9880d681SAndroid Build Coastguard Worker       if (0 == strncmp(&segname[0], "__LINKEDIT", 16)) {
241*9880d681SAndroid Build Coastguard Worker         if (auto Err = writeLinkEditData(OS))
242*9880d681SAndroid Build Coastguard Worker           return Err;
243*9880d681SAndroid Build Coastguard Worker       } else {
244*9880d681SAndroid Build Coastguard Worker         // Zero Fill any data between the end of the last thing we wrote and the
245*9880d681SAndroid Build Coastguard Worker         // start of this section.
246*9880d681SAndroid Build Coastguard Worker         if (currOffset < segOff) {
247*9880d681SAndroid Build Coastguard Worker           ZeroFillBytes(OS, segOff - currOffset);
248*9880d681SAndroid Build Coastguard Worker         }
249*9880d681SAndroid Build Coastguard Worker 
250*9880d681SAndroid Build Coastguard Worker         for (auto &Sec : LC.Sections) {
251*9880d681SAndroid Build Coastguard Worker           // Zero Fill any data between the end of the last thing we wrote and
252*9880d681SAndroid Build Coastguard Worker           // the
253*9880d681SAndroid Build Coastguard Worker           // start of this section.
254*9880d681SAndroid Build Coastguard Worker           assert(
255*9880d681SAndroid Build Coastguard Worker               OS.tell() - fileStart <= Sec.offset &&
256*9880d681SAndroid Build Coastguard Worker               "Wrote too much data somewhere, section offsets don't line up.");
257*9880d681SAndroid Build Coastguard Worker           currOffset = OS.tell() - fileStart;
258*9880d681SAndroid Build Coastguard Worker           if (currOffset < Sec.offset) {
259*9880d681SAndroid Build Coastguard Worker             ZeroFillBytes(OS, Sec.offset - currOffset);
260*9880d681SAndroid Build Coastguard Worker           }
261*9880d681SAndroid Build Coastguard Worker 
262*9880d681SAndroid Build Coastguard Worker           // Fills section data with 0xDEADBEEF
263*9880d681SAndroid Build Coastguard Worker           Fill(OS, Sec.size, 0xDEADBEEFu);
264*9880d681SAndroid Build Coastguard Worker         }
265*9880d681SAndroid Build Coastguard Worker       }
266*9880d681SAndroid Build Coastguard Worker       uint64_t segSize = is64Bit ? LC.Data.segment_command_64_data.filesize
267*9880d681SAndroid Build Coastguard Worker                                  : LC.Data.segment_command_data.filesize;
268*9880d681SAndroid Build Coastguard Worker       ZeroToOffset(OS, segOff + segSize);
269*9880d681SAndroid Build Coastguard Worker       break;
270*9880d681SAndroid Build Coastguard Worker     }
271*9880d681SAndroid Build Coastguard Worker   }
272*9880d681SAndroid Build Coastguard Worker   return Error::success();
273*9880d681SAndroid Build Coastguard Worker }
274*9880d681SAndroid Build Coastguard Worker 
writeBindOpcodes(raw_ostream & OS,std::vector<MachOYAML::BindOpcode> & BindOpcodes)275*9880d681SAndroid Build Coastguard Worker void MachOWriter::writeBindOpcodes(
276*9880d681SAndroid Build Coastguard Worker     raw_ostream &OS, std::vector<MachOYAML::BindOpcode> &BindOpcodes) {
277*9880d681SAndroid Build Coastguard Worker 
278*9880d681SAndroid Build Coastguard Worker   for (auto Opcode : BindOpcodes) {
279*9880d681SAndroid Build Coastguard Worker     uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
280*9880d681SAndroid Build Coastguard Worker     OS.write(reinterpret_cast<char *>(&OpByte), 1);
281*9880d681SAndroid Build Coastguard Worker     for (auto Data : Opcode.ULEBExtraData) {
282*9880d681SAndroid Build Coastguard Worker       encodeULEB128(Data, OS);
283*9880d681SAndroid Build Coastguard Worker     }
284*9880d681SAndroid Build Coastguard Worker     for (auto Data : Opcode.SLEBExtraData) {
285*9880d681SAndroid Build Coastguard Worker       encodeSLEB128(Data, OS);
286*9880d681SAndroid Build Coastguard Worker     }
287*9880d681SAndroid Build Coastguard Worker     if (!Opcode.Symbol.empty()) {
288*9880d681SAndroid Build Coastguard Worker       OS.write(Opcode.Symbol.data(), Opcode.Symbol.size());
289*9880d681SAndroid Build Coastguard Worker       OS.write('\0');
290*9880d681SAndroid Build Coastguard Worker     }
291*9880d681SAndroid Build Coastguard Worker   }
292*9880d681SAndroid Build Coastguard Worker }
293*9880d681SAndroid Build Coastguard Worker 
dumpExportEntry(raw_ostream & OS,MachOYAML::ExportEntry & Entry)294*9880d681SAndroid Build Coastguard Worker void MachOWriter::dumpExportEntry(raw_ostream &OS,
295*9880d681SAndroid Build Coastguard Worker                                   MachOYAML::ExportEntry &Entry) {
296*9880d681SAndroid Build Coastguard Worker   encodeSLEB128(Entry.TerminalSize, OS);
297*9880d681SAndroid Build Coastguard Worker   if (Entry.TerminalSize > 0) {
298*9880d681SAndroid Build Coastguard Worker     encodeSLEB128(Entry.Flags, OS);
299*9880d681SAndroid Build Coastguard Worker     if (Entry.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
300*9880d681SAndroid Build Coastguard Worker       encodeSLEB128(Entry.Other, OS);
301*9880d681SAndroid Build Coastguard Worker       OS << Entry.ImportName;
302*9880d681SAndroid Build Coastguard Worker       OS.write('\0');
303*9880d681SAndroid Build Coastguard Worker     } else {
304*9880d681SAndroid Build Coastguard Worker       encodeSLEB128(Entry.Address, OS);
305*9880d681SAndroid Build Coastguard Worker       if (Entry.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
306*9880d681SAndroid Build Coastguard Worker         encodeSLEB128(Entry.Other, OS);
307*9880d681SAndroid Build Coastguard Worker     }
308*9880d681SAndroid Build Coastguard Worker   }
309*9880d681SAndroid Build Coastguard Worker   OS.write(static_cast<uint8_t>(Entry.Children.size()));
310*9880d681SAndroid Build Coastguard Worker   for (auto EE : Entry.Children) {
311*9880d681SAndroid Build Coastguard Worker     OS << EE.Name;
312*9880d681SAndroid Build Coastguard Worker     OS.write('\0');
313*9880d681SAndroid Build Coastguard Worker     encodeSLEB128(EE.NodeOffset, OS);
314*9880d681SAndroid Build Coastguard Worker   }
315*9880d681SAndroid Build Coastguard Worker   for (auto EE : Entry.Children)
316*9880d681SAndroid Build Coastguard Worker     dumpExportEntry(OS, EE);
317*9880d681SAndroid Build Coastguard Worker }
318*9880d681SAndroid Build Coastguard Worker 
writeExportTrie(raw_ostream & OS)319*9880d681SAndroid Build Coastguard Worker Error MachOWriter::writeExportTrie(raw_ostream &OS) {
320*9880d681SAndroid Build Coastguard Worker   dumpExportEntry(OS, Obj.LinkEdit.ExportTrie);
321*9880d681SAndroid Build Coastguard Worker   return Error::success();
322*9880d681SAndroid Build Coastguard Worker }
323*9880d681SAndroid Build Coastguard Worker 
324*9880d681SAndroid Build Coastguard Worker template <typename NListType>
writeNListEntry(MachOYAML::NListEntry & NLE,raw_ostream & OS)325*9880d681SAndroid Build Coastguard Worker void writeNListEntry(MachOYAML::NListEntry &NLE, raw_ostream &OS) {
326*9880d681SAndroid Build Coastguard Worker   NListType ListEntry;
327*9880d681SAndroid Build Coastguard Worker   ListEntry.n_strx = NLE.n_strx;
328*9880d681SAndroid Build Coastguard Worker   ListEntry.n_type = NLE.n_type;
329*9880d681SAndroid Build Coastguard Worker   ListEntry.n_sect = NLE.n_sect;
330*9880d681SAndroid Build Coastguard Worker   ListEntry.n_desc = NLE.n_desc;
331*9880d681SAndroid Build Coastguard Worker   ListEntry.n_value = NLE.n_value;
332*9880d681SAndroid Build Coastguard Worker   OS.write(reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
333*9880d681SAndroid Build Coastguard Worker }
334*9880d681SAndroid Build Coastguard Worker 
writeLinkEditData(raw_ostream & OS)335*9880d681SAndroid Build Coastguard Worker Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
336*9880d681SAndroid Build Coastguard Worker   typedef Error (MachOWriter::*writeHandler)(raw_ostream &);
337*9880d681SAndroid Build Coastguard Worker   typedef std::pair<uint64_t, writeHandler> writeOperation;
338*9880d681SAndroid Build Coastguard Worker   std::vector<writeOperation> WriteQueue;
339*9880d681SAndroid Build Coastguard Worker 
340*9880d681SAndroid Build Coastguard Worker   MachO::dyld_info_command *DyldInfoOnlyCmd = 0;
341*9880d681SAndroid Build Coastguard Worker   MachO::symtab_command *SymtabCmd = 0;
342*9880d681SAndroid Build Coastguard Worker   for (auto &LC : Obj.LoadCommands) {
343*9880d681SAndroid Build Coastguard Worker     switch (LC.Data.load_command_data.cmd) {
344*9880d681SAndroid Build Coastguard Worker     case MachO::LC_SYMTAB:
345*9880d681SAndroid Build Coastguard Worker       SymtabCmd = &LC.Data.symtab_command_data;
346*9880d681SAndroid Build Coastguard Worker       WriteQueue.push_back(
347*9880d681SAndroid Build Coastguard Worker           std::make_pair(SymtabCmd->symoff, &MachOWriter::writeNameList));
348*9880d681SAndroid Build Coastguard Worker       WriteQueue.push_back(
349*9880d681SAndroid Build Coastguard Worker           std::make_pair(SymtabCmd->stroff, &MachOWriter::writeStringTable));
350*9880d681SAndroid Build Coastguard Worker       break;
351*9880d681SAndroid Build Coastguard Worker     case MachO::LC_DYLD_INFO_ONLY:
352*9880d681SAndroid Build Coastguard Worker       DyldInfoOnlyCmd = &LC.Data.dyld_info_command_data;
353*9880d681SAndroid Build Coastguard Worker       WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->rebase_off,
354*9880d681SAndroid Build Coastguard Worker                                           &MachOWriter::writeRebaseOpcodes));
355*9880d681SAndroid Build Coastguard Worker       WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->bind_off,
356*9880d681SAndroid Build Coastguard Worker                                           &MachOWriter::writeBasicBindOpcodes));
357*9880d681SAndroid Build Coastguard Worker       WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->weak_bind_off,
358*9880d681SAndroid Build Coastguard Worker                                           &MachOWriter::writeWeakBindOpcodes));
359*9880d681SAndroid Build Coastguard Worker       WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->lazy_bind_off,
360*9880d681SAndroid Build Coastguard Worker                                           &MachOWriter::writeLazyBindOpcodes));
361*9880d681SAndroid Build Coastguard Worker       WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->export_off,
362*9880d681SAndroid Build Coastguard Worker                                           &MachOWriter::writeExportTrie));
363*9880d681SAndroid Build Coastguard Worker       break;
364*9880d681SAndroid Build Coastguard Worker     }
365*9880d681SAndroid Build Coastguard Worker   }
366*9880d681SAndroid Build Coastguard Worker 
367*9880d681SAndroid Build Coastguard Worker   std::sort(WriteQueue.begin(), WriteQueue.end(),
368*9880d681SAndroid Build Coastguard Worker             [](const writeOperation &a, const writeOperation &b) {
369*9880d681SAndroid Build Coastguard Worker               return a.first < b.first;
370*9880d681SAndroid Build Coastguard Worker             });
371*9880d681SAndroid Build Coastguard Worker 
372*9880d681SAndroid Build Coastguard Worker   for (auto writeOp : WriteQueue) {
373*9880d681SAndroid Build Coastguard Worker     ZeroToOffset(OS, writeOp.first);
374*9880d681SAndroid Build Coastguard Worker     if (auto Err = (this->*writeOp.second)(OS))
375*9880d681SAndroid Build Coastguard Worker       return Err;
376*9880d681SAndroid Build Coastguard Worker   }
377*9880d681SAndroid Build Coastguard Worker 
378*9880d681SAndroid Build Coastguard Worker   return Error::success();
379*9880d681SAndroid Build Coastguard Worker }
380*9880d681SAndroid Build Coastguard Worker 
writeRebaseOpcodes(raw_ostream & OS)381*9880d681SAndroid Build Coastguard Worker Error MachOWriter::writeRebaseOpcodes(raw_ostream &OS) {
382*9880d681SAndroid Build Coastguard Worker   MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
383*9880d681SAndroid Build Coastguard Worker 
384*9880d681SAndroid Build Coastguard Worker   for (auto Opcode : LinkEdit.RebaseOpcodes) {
385*9880d681SAndroid Build Coastguard Worker     uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
386*9880d681SAndroid Build Coastguard Worker     OS.write(reinterpret_cast<char *>(&OpByte), 1);
387*9880d681SAndroid Build Coastguard Worker     for (auto Data : Opcode.ExtraData) {
388*9880d681SAndroid Build Coastguard Worker       encodeULEB128(Data, OS);
389*9880d681SAndroid Build Coastguard Worker     }
390*9880d681SAndroid Build Coastguard Worker   }
391*9880d681SAndroid Build Coastguard Worker   return Error::success();
392*9880d681SAndroid Build Coastguard Worker }
393*9880d681SAndroid Build Coastguard Worker 
writeBasicBindOpcodes(raw_ostream & OS)394*9880d681SAndroid Build Coastguard Worker Error MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) {
395*9880d681SAndroid Build Coastguard Worker   writeBindOpcodes(OS, Obj.LinkEdit.BindOpcodes);
396*9880d681SAndroid Build Coastguard Worker   return Error::success();
397*9880d681SAndroid Build Coastguard Worker }
398*9880d681SAndroid Build Coastguard Worker 
writeWeakBindOpcodes(raw_ostream & OS)399*9880d681SAndroid Build Coastguard Worker Error MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) {
400*9880d681SAndroid Build Coastguard Worker   writeBindOpcodes(OS, Obj.LinkEdit.WeakBindOpcodes);
401*9880d681SAndroid Build Coastguard Worker   return Error::success();
402*9880d681SAndroid Build Coastguard Worker }
403*9880d681SAndroid Build Coastguard Worker 
writeLazyBindOpcodes(raw_ostream & OS)404*9880d681SAndroid Build Coastguard Worker Error MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) {
405*9880d681SAndroid Build Coastguard Worker   writeBindOpcodes(OS, Obj.LinkEdit.LazyBindOpcodes);
406*9880d681SAndroid Build Coastguard Worker   return Error::success();
407*9880d681SAndroid Build Coastguard Worker }
408*9880d681SAndroid Build Coastguard Worker 
writeNameList(raw_ostream & OS)409*9880d681SAndroid Build Coastguard Worker Error MachOWriter::writeNameList(raw_ostream &OS) {
410*9880d681SAndroid Build Coastguard Worker   for (auto NLE : Obj.LinkEdit.NameList) {
411*9880d681SAndroid Build Coastguard Worker     if (is64Bit)
412*9880d681SAndroid Build Coastguard Worker       writeNListEntry<MachO::nlist_64>(NLE, OS);
413*9880d681SAndroid Build Coastguard Worker     else
414*9880d681SAndroid Build Coastguard Worker       writeNListEntry<MachO::nlist>(NLE, OS);
415*9880d681SAndroid Build Coastguard Worker   }
416*9880d681SAndroid Build Coastguard Worker   return Error::success();
417*9880d681SAndroid Build Coastguard Worker }
418*9880d681SAndroid Build Coastguard Worker 
writeStringTable(raw_ostream & OS)419*9880d681SAndroid Build Coastguard Worker Error MachOWriter::writeStringTable(raw_ostream &OS) {
420*9880d681SAndroid Build Coastguard Worker   for (auto Str : Obj.LinkEdit.StringTable) {
421*9880d681SAndroid Build Coastguard Worker     OS.write(Str.data(), Str.size());
422*9880d681SAndroid Build Coastguard Worker     OS.write('\0');
423*9880d681SAndroid Build Coastguard Worker   }
424*9880d681SAndroid Build Coastguard Worker   return Error::success();
425*9880d681SAndroid Build Coastguard Worker }
426*9880d681SAndroid Build Coastguard Worker 
427*9880d681SAndroid Build Coastguard Worker class UniversalWriter {
428*9880d681SAndroid Build Coastguard Worker public:
UniversalWriter(yaml::YamlObjectFile & ObjectFile)429*9880d681SAndroid Build Coastguard Worker   UniversalWriter(yaml::YamlObjectFile &ObjectFile)
430*9880d681SAndroid Build Coastguard Worker       : ObjectFile(ObjectFile), fileStart(0) {}
431*9880d681SAndroid Build Coastguard Worker 
432*9880d681SAndroid Build Coastguard Worker   Error writeMachO(raw_ostream &OS);
433*9880d681SAndroid Build Coastguard Worker 
434*9880d681SAndroid Build Coastguard Worker private:
435*9880d681SAndroid Build Coastguard Worker   Error writeFatHeader(raw_ostream &OS);
436*9880d681SAndroid Build Coastguard Worker   Error writeFatArchs(raw_ostream &OS);
437*9880d681SAndroid Build Coastguard Worker 
438*9880d681SAndroid Build Coastguard Worker   void ZeroToOffset(raw_ostream &OS, size_t offset);
439*9880d681SAndroid Build Coastguard Worker 
440*9880d681SAndroid Build Coastguard Worker   yaml::YamlObjectFile &ObjectFile;
441*9880d681SAndroid Build Coastguard Worker   uint64_t fileStart;
442*9880d681SAndroid Build Coastguard Worker };
443*9880d681SAndroid Build Coastguard Worker 
writeMachO(raw_ostream & OS)444*9880d681SAndroid Build Coastguard Worker Error UniversalWriter::writeMachO(raw_ostream &OS) {
445*9880d681SAndroid Build Coastguard Worker   fileStart = OS.tell();
446*9880d681SAndroid Build Coastguard Worker   if (ObjectFile.MachO) {
447*9880d681SAndroid Build Coastguard Worker     MachOWriter Writer(*ObjectFile.MachO);
448*9880d681SAndroid Build Coastguard Worker     return Writer.writeMachO(OS);
449*9880d681SAndroid Build Coastguard Worker   }
450*9880d681SAndroid Build Coastguard Worker   if (auto Err = writeFatHeader(OS))
451*9880d681SAndroid Build Coastguard Worker     return Err;
452*9880d681SAndroid Build Coastguard Worker   if (auto Err = writeFatArchs(OS))
453*9880d681SAndroid Build Coastguard Worker     return Err;
454*9880d681SAndroid Build Coastguard Worker   auto &FatFile = *ObjectFile.FatMachO;
455*9880d681SAndroid Build Coastguard Worker   assert(FatFile.FatArchs.size() == FatFile.Slices.size());
456*9880d681SAndroid Build Coastguard Worker   for (size_t i = 0; i < FatFile.Slices.size(); i++) {
457*9880d681SAndroid Build Coastguard Worker     ZeroToOffset(OS, FatFile.FatArchs[i].offset);
458*9880d681SAndroid Build Coastguard Worker     MachOWriter Writer(FatFile.Slices[i]);
459*9880d681SAndroid Build Coastguard Worker     if (auto Err = Writer.writeMachO(OS))
460*9880d681SAndroid Build Coastguard Worker       return Err;
461*9880d681SAndroid Build Coastguard Worker     auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;
462*9880d681SAndroid Build Coastguard Worker     ZeroToOffset(OS, SliceEnd);
463*9880d681SAndroid Build Coastguard Worker   }
464*9880d681SAndroid Build Coastguard Worker   return Error::success();
465*9880d681SAndroid Build Coastguard Worker }
466*9880d681SAndroid Build Coastguard Worker 
writeFatHeader(raw_ostream & OS)467*9880d681SAndroid Build Coastguard Worker Error UniversalWriter::writeFatHeader(raw_ostream &OS) {
468*9880d681SAndroid Build Coastguard Worker   auto &FatFile = *ObjectFile.FatMachO;
469*9880d681SAndroid Build Coastguard Worker   MachO::fat_header header;
470*9880d681SAndroid Build Coastguard Worker   header.magic = FatFile.Header.magic;
471*9880d681SAndroid Build Coastguard Worker   header.nfat_arch = FatFile.Header.nfat_arch;
472*9880d681SAndroid Build Coastguard Worker   if (sys::IsLittleEndianHost)
473*9880d681SAndroid Build Coastguard Worker     swapStruct(header);
474*9880d681SAndroid Build Coastguard Worker   OS.write(reinterpret_cast<const char *>(&header), sizeof(MachO::fat_header));
475*9880d681SAndroid Build Coastguard Worker   return Error::success();
476*9880d681SAndroid Build Coastguard Worker }
477*9880d681SAndroid Build Coastguard Worker 
478*9880d681SAndroid Build Coastguard Worker template <typename FatArchType>
constructFatArch(MachOYAML::FatArch & Arch)479*9880d681SAndroid Build Coastguard Worker FatArchType constructFatArch(MachOYAML::FatArch &Arch) {
480*9880d681SAndroid Build Coastguard Worker   FatArchType FatArch;
481*9880d681SAndroid Build Coastguard Worker   FatArch.cputype = Arch.cputype;
482*9880d681SAndroid Build Coastguard Worker   FatArch.cpusubtype = Arch.cpusubtype;
483*9880d681SAndroid Build Coastguard Worker   FatArch.offset = Arch.offset;
484*9880d681SAndroid Build Coastguard Worker   FatArch.size = Arch.size;
485*9880d681SAndroid Build Coastguard Worker   FatArch.align = Arch.align;
486*9880d681SAndroid Build Coastguard Worker   return FatArch;
487*9880d681SAndroid Build Coastguard Worker }
488*9880d681SAndroid Build Coastguard Worker 
489*9880d681SAndroid Build Coastguard Worker template <typename StructType>
writeFatArch(MachOYAML::FatArch & LC,raw_ostream & OS)490*9880d681SAndroid Build Coastguard Worker void writeFatArch(MachOYAML::FatArch &LC, raw_ostream &OS) {}
491*9880d681SAndroid Build Coastguard Worker 
492*9880d681SAndroid Build Coastguard Worker template <>
writeFatArch(MachOYAML::FatArch & Arch,raw_ostream & OS)493*9880d681SAndroid Build Coastguard Worker void writeFatArch<MachO::fat_arch>(MachOYAML::FatArch &Arch, raw_ostream &OS) {
494*9880d681SAndroid Build Coastguard Worker   auto FatArch = constructFatArch<MachO::fat_arch>(Arch);
495*9880d681SAndroid Build Coastguard Worker   if (sys::IsLittleEndianHost)
496*9880d681SAndroid Build Coastguard Worker     swapStruct(FatArch);
497*9880d681SAndroid Build Coastguard Worker   OS.write(reinterpret_cast<const char *>(&FatArch), sizeof(MachO::fat_arch));
498*9880d681SAndroid Build Coastguard Worker }
499*9880d681SAndroid Build Coastguard Worker 
500*9880d681SAndroid Build Coastguard Worker template <>
writeFatArch(MachOYAML::FatArch & Arch,raw_ostream & OS)501*9880d681SAndroid Build Coastguard Worker void writeFatArch<MachO::fat_arch_64>(MachOYAML::FatArch &Arch,
502*9880d681SAndroid Build Coastguard Worker                                       raw_ostream &OS) {
503*9880d681SAndroid Build Coastguard Worker   auto FatArch = constructFatArch<MachO::fat_arch_64>(Arch);
504*9880d681SAndroid Build Coastguard Worker   FatArch.reserved = Arch.reserved;
505*9880d681SAndroid Build Coastguard Worker   if (sys::IsLittleEndianHost)
506*9880d681SAndroid Build Coastguard Worker     swapStruct(FatArch);
507*9880d681SAndroid Build Coastguard Worker   OS.write(reinterpret_cast<const char *>(&FatArch),
508*9880d681SAndroid Build Coastguard Worker            sizeof(MachO::fat_arch_64));
509*9880d681SAndroid Build Coastguard Worker }
510*9880d681SAndroid Build Coastguard Worker 
writeFatArchs(raw_ostream & OS)511*9880d681SAndroid Build Coastguard Worker Error UniversalWriter::writeFatArchs(raw_ostream &OS) {
512*9880d681SAndroid Build Coastguard Worker   auto &FatFile = *ObjectFile.FatMachO;
513*9880d681SAndroid Build Coastguard Worker   bool is64Bit = FatFile.Header.magic == MachO::FAT_MAGIC_64;
514*9880d681SAndroid Build Coastguard Worker   for (auto Arch : FatFile.FatArchs) {
515*9880d681SAndroid Build Coastguard Worker     if (is64Bit)
516*9880d681SAndroid Build Coastguard Worker       writeFatArch<MachO::fat_arch_64>(Arch, OS);
517*9880d681SAndroid Build Coastguard Worker     else
518*9880d681SAndroid Build Coastguard Worker       writeFatArch<MachO::fat_arch>(Arch, OS);
519*9880d681SAndroid Build Coastguard Worker   }
520*9880d681SAndroid Build Coastguard Worker 
521*9880d681SAndroid Build Coastguard Worker   return Error::success();
522*9880d681SAndroid Build Coastguard Worker }
523*9880d681SAndroid Build Coastguard Worker 
ZeroToOffset(raw_ostream & OS,size_t Offset)524*9880d681SAndroid Build Coastguard Worker void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
525*9880d681SAndroid Build Coastguard Worker   auto currOffset = OS.tell() - fileStart;
526*9880d681SAndroid Build Coastguard Worker   if (currOffset < Offset)
527*9880d681SAndroid Build Coastguard Worker     ZeroFillBytes(OS, Offset - currOffset);
528*9880d681SAndroid Build Coastguard Worker }
529*9880d681SAndroid Build Coastguard Worker 
530*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
531*9880d681SAndroid Build Coastguard Worker 
yaml2macho(yaml::YamlObjectFile & Doc,raw_ostream & Out)532*9880d681SAndroid Build Coastguard Worker int yaml2macho(yaml::YamlObjectFile &Doc, raw_ostream &Out) {
533*9880d681SAndroid Build Coastguard Worker   UniversalWriter Writer(Doc);
534*9880d681SAndroid Build Coastguard Worker   if (auto Err = Writer.writeMachO(Out)) {
535*9880d681SAndroid Build Coastguard Worker     errs() << toString(std::move(Err));
536*9880d681SAndroid Build Coastguard Worker     return 1;
537*9880d681SAndroid Build Coastguard Worker   }
538*9880d681SAndroid Build Coastguard Worker   return 0;
539*9880d681SAndroid Build Coastguard Worker }
540