LLVM  15.0.0git
MachOEmitter.cpp
Go to the documentation of this file.
1 //===- yaml2macho - Convert YAML to a Mach object file --------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// The Mach component of yaml2obj.
11 ///
12 //===----------------------------------------------------------------------===//
13 
18 #include "llvm/Support/Errc.h"
19 #include "llvm/Support/Error.h"
20 #include "llvm/Support/LEB128.h"
23 
24 #include "llvm/Support/Format.h"
25 
26 using namespace llvm;
27 
28 namespace {
29 
30 class MachOWriter {
31 public:
32  MachOWriter(MachOYAML::Object &Obj) : Obj(Obj), fileStart(0) {
35  memset(reinterpret_cast<void *>(&Header), 0, sizeof(MachO::mach_header_64));
36  }
37 
38  Error writeMachO(raw_ostream &OS);
39 
40 private:
41  void writeHeader(raw_ostream &OS);
42  void writeLoadCommands(raw_ostream &OS);
43  Error writeSectionData(raw_ostream &OS);
44  void writeRelocations(raw_ostream &OS);
45  void writeLinkEditData(raw_ostream &OS);
46 
47  void writeBindOpcodes(raw_ostream &OS,
48  std::vector<MachOYAML::BindOpcode> &BindOpcodes);
49  // LinkEdit writers
50  void writeRebaseOpcodes(raw_ostream &OS);
51  void writeBasicBindOpcodes(raw_ostream &OS);
52  void writeWeakBindOpcodes(raw_ostream &OS);
53  void writeLazyBindOpcodes(raw_ostream &OS);
54  void writeNameList(raw_ostream &OS);
55  void writeStringTable(raw_ostream &OS);
56  void writeExportTrie(raw_ostream &OS);
57  void writeDynamicSymbolTable(raw_ostream &OS);
58  void writeFunctionStarts(raw_ostream &OS);
59 
60  void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);
61  void ZeroToOffset(raw_ostream &OS, size_t offset);
62 
63  MachOYAML::Object &Obj;
64  bool is64Bit;
65  uint64_t fileStart;
66  MachO::mach_header_64 Header;
67 
68  // Old PPC Object Files didn't have __LINKEDIT segments, the data was just
69  // stuck at the end of the file.
70  bool FoundLinkEditSeg = false;
71 };
72 
73 Error MachOWriter::writeMachO(raw_ostream &OS) {
74  fileStart = OS.tell();
75  writeHeader(OS);
76  writeLoadCommands(OS);
77  if (Error Err = writeSectionData(OS))
78  return Err;
79  writeRelocations(OS);
80  if (!FoundLinkEditSeg)
81  writeLinkEditData(OS);
82  return Error::success();
83 }
84 
85 void MachOWriter::writeHeader(raw_ostream &OS) {
86  Header.magic = Obj.Header.magic;
87  Header.cputype = Obj.Header.cputype;
88  Header.cpusubtype = Obj.Header.cpusubtype;
89  Header.filetype = Obj.Header.filetype;
90  Header.ncmds = Obj.Header.ncmds;
91  Header.sizeofcmds = Obj.Header.sizeofcmds;
92  Header.flags = Obj.Header.flags;
93  Header.reserved = Obj.Header.reserved;
94 
96  MachO::swapStruct(Header);
97 
98  auto header_size =
100  OS.write((const char *)&Header, header_size);
101 }
102 
103 template <typename SectionType>
105  SectionType TempSec;
106  memcpy(reinterpret_cast<void *>(&TempSec.sectname[0]), &Sec.sectname[0], 16);
107  memcpy(reinterpret_cast<void *>(&TempSec.segname[0]), &Sec.segname[0], 16);
108  TempSec.addr = Sec.addr;
109  TempSec.size = Sec.size;
110  TempSec.offset = Sec.offset;
111  TempSec.align = Sec.align;
112  TempSec.reloff = Sec.reloff;
113  TempSec.nreloc = Sec.nreloc;
114  TempSec.flags = Sec.flags;
115  TempSec.reserved1 = Sec.reserved1;
116  TempSec.reserved2 = Sec.reserved2;
117  return TempSec;
118 }
119 
120 template <typename StructType>
121 size_t writeLoadCommandData(MachOYAML::LoadCommand &LC, raw_ostream &OS,
122  bool IsLittleEndian) {
123  return 0;
124 }
125 
126 template <>
127 size_t writeLoadCommandData<MachO::segment_command>(MachOYAML::LoadCommand &LC,
128  raw_ostream &OS,
129  bool IsLittleEndian) {
130  size_t BytesWritten = 0;
131  for (const auto &Sec : LC.Sections) {
132  auto TempSec = constructSection<MachO::section>(Sec);
133  if (IsLittleEndian != sys::IsLittleEndianHost)
134  MachO::swapStruct(TempSec);
135  OS.write(reinterpret_cast<const char *>(&(TempSec)),
136  sizeof(MachO::section));
137  BytesWritten += sizeof(MachO::section);
138  }
139  return BytesWritten;
140 }
141 
142 template <>
143 size_t writeLoadCommandData<MachO::segment_command_64>(
144  MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
145  size_t BytesWritten = 0;
146  for (const auto &Sec : LC.Sections) {
147  auto TempSec = constructSection<MachO::section_64>(Sec);
148  TempSec.reserved3 = Sec.reserved3;
149  if (IsLittleEndian != sys::IsLittleEndianHost)
150  MachO::swapStruct(TempSec);
151  OS.write(reinterpret_cast<const char *>(&(TempSec)),
152  sizeof(MachO::section_64));
153  BytesWritten += sizeof(MachO::section_64);
154  }
155  return BytesWritten;
156 }
157 
158 size_t writePayloadString(MachOYAML::LoadCommand &LC, raw_ostream &OS) {
159  size_t BytesWritten = 0;
160  if (!LC.Content.empty()) {
161  OS.write(LC.Content.c_str(), LC.Content.length());
162  BytesWritten = LC.Content.length();
163  }
164  return BytesWritten;
165 }
166 
167 template <>
168 size_t writeLoadCommandData<MachO::dylib_command>(MachOYAML::LoadCommand &LC,
169  raw_ostream &OS,
170  bool IsLittleEndian) {
171  return writePayloadString(LC, OS);
172 }
173 
174 template <>
175 size_t writeLoadCommandData<MachO::dylinker_command>(MachOYAML::LoadCommand &LC,
176  raw_ostream &OS,
177  bool IsLittleEndian) {
178  return writePayloadString(LC, OS);
179 }
180 
181 template <>
182 size_t writeLoadCommandData<MachO::rpath_command>(MachOYAML::LoadCommand &LC,
183  raw_ostream &OS,
184  bool IsLittleEndian) {
185  return writePayloadString(LC, OS);
186 }
187 
188 template <>
189 size_t writeLoadCommandData<MachO::sub_framework_command>(
190  MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
191  return writePayloadString(LC, OS);
192 }
193 
194 template <>
195 size_t writeLoadCommandData<MachO::sub_umbrella_command>(
196  MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
197  return writePayloadString(LC, OS);
198 }
199 
200 template <>
201 size_t writeLoadCommandData<MachO::sub_client_command>(
202  MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
203  return writePayloadString(LC, OS);
204 }
205 
206 template <>
207 size_t writeLoadCommandData<MachO::sub_library_command>(
208  MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
209  return writePayloadString(LC, OS);
210 }
211 
212 template <>
213 size_t writeLoadCommandData<MachO::build_version_command>(
214  MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
215  size_t BytesWritten = 0;
216  for (const auto &T : LC.Tools) {
217  struct MachO::build_tool_version tool = T;
218  if (IsLittleEndian != sys::IsLittleEndianHost)
219  MachO::swapStruct(tool);
220  OS.write(reinterpret_cast<const char *>(&tool),
221  sizeof(MachO::build_tool_version));
222  BytesWritten += sizeof(MachO::build_tool_version);
223  }
224  return BytesWritten;
225 }
226 
227 void ZeroFillBytes(raw_ostream &OS, size_t Size) {
228  std::vector<uint8_t> FillData(Size, 0);
229  OS.write(reinterpret_cast<char *>(FillData.data()), Size);
230 }
231 
232 void Fill(raw_ostream &OS, size_t Size, uint32_t Data) {
233  std::vector<uint32_t> FillData((Size / 4) + 1, Data);
234  OS.write(reinterpret_cast<char *>(FillData.data()), Size);
235 }
236 
237 void MachOWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
238  auto currOffset = OS.tell() - fileStart;
239  if (currOffset < Offset)
240  ZeroFillBytes(OS, Offset - currOffset);
241 }
242 
243 void MachOWriter::writeLoadCommands(raw_ostream &OS) {
244  for (auto &LC : Obj.LoadCommands) {
245  size_t BytesWritten = 0;
247 
248 #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
249  case MachO::LCName: \
250  if (Obj.IsLittleEndian != sys::IsLittleEndianHost) \
251  MachO::swapStruct(Data.LCStruct##_data); \
252  OS.write(reinterpret_cast<const char *>(&(Data.LCStruct##_data)), \
253  sizeof(MachO::LCStruct)); \
254  BytesWritten = sizeof(MachO::LCStruct); \
255  BytesWritten += \
256  writeLoadCommandData<MachO::LCStruct>(LC, OS, Obj.IsLittleEndian); \
257  break;
258 
259  switch (LC.Data.load_command_data.cmd) {
260  default:
262  MachO::swapStruct(Data.load_command_data);
263  OS.write(reinterpret_cast<const char *>(&(Data.load_command_data)),
264  sizeof(MachO::load_command));
265  BytesWritten = sizeof(MachO::load_command);
266  BytesWritten +=
267  writeLoadCommandData<MachO::load_command>(LC, OS, Obj.IsLittleEndian);
268  break;
269 #include "llvm/BinaryFormat/MachO.def"
270  }
271 
272  if (LC.PayloadBytes.size() > 0) {
273  OS.write(reinterpret_cast<const char *>(LC.PayloadBytes.data()),
274  LC.PayloadBytes.size());
275  BytesWritten += LC.PayloadBytes.size();
276  }
277 
278  if (LC.ZeroPadBytes > 0) {
279  ZeroFillBytes(OS, LC.ZeroPadBytes);
280  BytesWritten += LC.ZeroPadBytes;
281  }
282 
283  // Fill remaining bytes with 0. This will only get hit in partially
284  // specified test cases.
285  auto BytesRemaining = LC.Data.load_command_data.cmdsize - BytesWritten;
286  if (BytesRemaining > 0) {
287  ZeroFillBytes(OS, BytesRemaining);
288  }
289  }
290 }
291 
292 Error MachOWriter::writeSectionData(raw_ostream &OS) {
293  uint64_t LinkEditOff = 0;
294  for (auto &LC : Obj.LoadCommands) {
295  switch (LC.Data.load_command_data.cmd) {
296  case MachO::LC_SEGMENT:
297  case MachO::LC_SEGMENT_64:
298  uint64_t segOff = is64Bit ? LC.Data.segment_command_64_data.fileoff
299  : LC.Data.segment_command_data.fileoff;
300  if (0 ==
301  strncmp(&LC.Data.segment_command_data.segname[0], "__LINKEDIT", 16)) {
302  FoundLinkEditSeg = true;
303  LinkEditOff = segOff;
304  if (Obj.RawLinkEditSegment)
305  continue;
306  writeLinkEditData(OS);
307  }
308  for (auto &Sec : LC.Sections) {
309  ZeroToOffset(OS, Sec.offset);
310  // Zero Fill any data between the end of the last thing we wrote and the
311  // start of this section.
312  if (OS.tell() - fileStart > Sec.offset && Sec.offset != (uint32_t)0)
313  return createStringError(
315  "wrote too much data somewhere, section offsets don't line up");
316 
317  StringRef SectName(Sec.sectname,
318  strnlen(Sec.sectname, sizeof(Sec.sectname)));
319  // If the section's content is specified in the 'DWARF' entry, we will
320  // emit it regardless of the section's segname.
321  if (Obj.DWARF.getNonEmptySectionNames().count(SectName.substr(2))) {
322  if (Sec.content)
324  "cannot specify section '" + SectName +
325  "' contents in the 'DWARF' entry and "
326  "the 'content' at the same time");
327  auto EmitFunc = DWARFYAML::getDWARFEmitterByName(SectName.substr(2));
328  if (Error Err = EmitFunc(OS, Obj.DWARF))
329  return Err;
330  continue;
331  }
332 
333  // Skip if it's a virtual section.
335  continue;
336 
337  if (Sec.content) {
339  Content.writeAsBinary(OS);
340  ZeroFillBytes(OS, Sec.size - Content.binary_size());
341  } else {
342  // Fill section data with 0xDEADBEEF.
343  Fill(OS, Sec.size, 0xDEADBEEFu);
344  }
345  }
346  uint64_t segSize = is64Bit ? LC.Data.segment_command_64_data.filesize
347  : LC.Data.segment_command_data.filesize;
348  ZeroToOffset(OS, segOff + segSize);
349  break;
350  }
351  }
352 
353  if (Obj.RawLinkEditSegment) {
354  ZeroToOffset(OS, LinkEditOff);
355  if (OS.tell() - fileStart > LinkEditOff || !LinkEditOff)
357  "section offsets don't line up");
359  }
360  return Error::success();
361 }
362 
363 // The implementation of makeRelocationInfo and makeScatteredRelocationInfo is
364 // consistent with how libObject parses MachO binary files. For the reference
365 // see getStruct, getRelocation, getPlainRelocationPCRel,
366 // getPlainRelocationLength and related methods in MachOObjectFile.cpp
368 makeRelocationInfo(const MachOYAML::Relocation &R, bool IsLE) {
369  assert(!R.is_scattered && "non-scattered relocation expected");
371  MRE.r_word0 = R.address;
372  if (IsLE)
373  MRE.r_word1 = ((unsigned)R.symbolnum << 0) | ((unsigned)R.is_pcrel << 24) |
374  ((unsigned)R.length << 25) | ((unsigned)R.is_extern << 27) |
375  ((unsigned)R.type << 28);
376  else
377  MRE.r_word1 = ((unsigned)R.symbolnum << 8) | ((unsigned)R.is_pcrel << 7) |
378  ((unsigned)R.length << 5) | ((unsigned)R.is_extern << 4) |
379  ((unsigned)R.type << 0);
380  return MRE;
381 }
382 
384 makeScatteredRelocationInfo(const MachOYAML::Relocation &R) {
385  assert(R.is_scattered && "scattered relocation expected");
387  MRE.r_word0 = (((unsigned)R.address << 0) | ((unsigned)R.type << 24) |
388  ((unsigned)R.length << 28) | ((unsigned)R.is_pcrel << 30) |
390  MRE.r_word1 = R.value;
391  return MRE;
392 }
393 
394 void MachOWriter::writeRelocations(raw_ostream &OS) {
395  for (const MachOYAML::LoadCommand &LC : Obj.LoadCommands) {
396  switch (LC.Data.load_command_data.cmd) {
397  case MachO::LC_SEGMENT:
398  case MachO::LC_SEGMENT_64:
399  for (const MachOYAML::Section &Sec : LC.Sections) {
400  if (Sec.relocations.empty())
401  continue;
402  ZeroToOffset(OS, Sec.reloff);
403  for (const MachOYAML::Relocation &R : Sec.relocations) {
405  R.is_scattered ? makeScatteredRelocationInfo(R)
406  : makeRelocationInfo(R, Obj.IsLittleEndian);
408  MachO::swapStruct(MRE);
409  OS.write(reinterpret_cast<const char *>(&MRE),
411  }
412  }
413  }
414  }
415 }
416 
417 void MachOWriter::writeBindOpcodes(
418  raw_ostream &OS, std::vector<MachOYAML::BindOpcode> &BindOpcodes) {
419 
420  for (auto Opcode : BindOpcodes) {
421  uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
422  OS.write(reinterpret_cast<char *>(&OpByte), 1);
423  for (auto Data : Opcode.ULEBExtraData) {
424  encodeULEB128(Data, OS);
425  }
426  for (auto Data : Opcode.SLEBExtraData) {
427  encodeSLEB128(Data, OS);
428  }
429  if (!Opcode.Symbol.empty()) {
430  OS.write(Opcode.Symbol.data(), Opcode.Symbol.size());
431  OS.write('\0');
432  }
433  }
434 }
435 
436 void MachOWriter::dumpExportEntry(raw_ostream &OS,
437  MachOYAML::ExportEntry &Entry) {
438  encodeSLEB128(Entry.TerminalSize, OS);
439  if (Entry.TerminalSize > 0) {
440  encodeSLEB128(Entry.Flags, OS);
441  if (Entry.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
442  encodeSLEB128(Entry.Other, OS);
443  OS << Entry.ImportName;
444  OS.write('\0');
445  } else {
446  encodeSLEB128(Entry.Address, OS);
448  encodeSLEB128(Entry.Other, OS);
449  }
450  }
451  OS.write(static_cast<uint8_t>(Entry.Children.size()));
452  for (auto EE : Entry.Children) {
453  OS << EE.Name;
454  OS.write('\0');
455  encodeSLEB128(EE.NodeOffset, OS);
456  }
457  for (auto EE : Entry.Children)
458  dumpExportEntry(OS, EE);
459 }
460 
461 void MachOWriter::writeExportTrie(raw_ostream &OS) {
462  dumpExportEntry(OS, Obj.LinkEdit.ExportTrie);
463 }
464 
465 template <typename NListType>
467  bool IsLittleEndian) {
468  NListType ListEntry;
469  ListEntry.n_strx = NLE.n_strx;
470  ListEntry.n_type = NLE.n_type;
471  ListEntry.n_sect = NLE.n_sect;
472  ListEntry.n_desc = NLE.n_desc;
473  ListEntry.n_value = NLE.n_value;
474 
475  if (IsLittleEndian != sys::IsLittleEndianHost)
476  MachO::swapStruct(ListEntry);
477  OS.write(reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
478 }
479 
480 void MachOWriter::writeLinkEditData(raw_ostream &OS) {
481  typedef void (MachOWriter::*writeHandler)(raw_ostream &);
482  typedef std::pair<uint64_t, writeHandler> writeOperation;
483  std::vector<writeOperation> WriteQueue;
484 
485  MachO::dyld_info_command *DyldInfoOnlyCmd = nullptr;
486  MachO::symtab_command *SymtabCmd = nullptr;
487  MachO::dysymtab_command *DSymtabCmd = nullptr;
488  MachO::linkedit_data_command *FunctionStartsCmd = nullptr;
489  for (auto &LC : Obj.LoadCommands) {
490  switch (LC.Data.load_command_data.cmd) {
491  case MachO::LC_SYMTAB:
492  SymtabCmd = &LC.Data.symtab_command_data;
493  WriteQueue.push_back(
494  std::make_pair(SymtabCmd->symoff, &MachOWriter::writeNameList));
495  WriteQueue.push_back(
496  std::make_pair(SymtabCmd->stroff, &MachOWriter::writeStringTable));
497  break;
498  case MachO::LC_DYLD_INFO_ONLY:
499  DyldInfoOnlyCmd = &LC.Data.dyld_info_command_data;
500  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->rebase_off,
501  &MachOWriter::writeRebaseOpcodes));
502  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->bind_off,
503  &MachOWriter::writeBasicBindOpcodes));
504  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->weak_bind_off,
505  &MachOWriter::writeWeakBindOpcodes));
506  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->lazy_bind_off,
507  &MachOWriter::writeLazyBindOpcodes));
508  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->export_off,
509  &MachOWriter::writeExportTrie));
510  break;
511  case MachO::LC_DYSYMTAB:
512  DSymtabCmd = &LC.Data.dysymtab_command_data;
513  WriteQueue.push_back(std::make_pair(
514  DSymtabCmd->indirectsymoff, &MachOWriter::writeDynamicSymbolTable));
515  break;
516  case MachO::LC_FUNCTION_STARTS:
517  FunctionStartsCmd = &LC.Data.linkedit_data_command_data;
518  WriteQueue.push_back(std::make_pair(FunctionStartsCmd->dataoff,
519  &MachOWriter::writeFunctionStarts));
520  break;
521  }
522  }
523 
524  llvm::sort(WriteQueue, llvm::less_first());
525 
526  for (auto writeOp : WriteQueue) {
527  ZeroToOffset(OS, writeOp.first);
528  (this->*writeOp.second)(OS);
529  }
530 }
531 
532 void MachOWriter::writeRebaseOpcodes(raw_ostream &OS) {
533  MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
534 
535  for (auto Opcode : LinkEdit.RebaseOpcodes) {
536  uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
537  OS.write(reinterpret_cast<char *>(&OpByte), 1);
538  for (auto Data : Opcode.ExtraData)
539  encodeULEB128(Data, OS);
540  }
541 }
542 
543 void MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) {
544  writeBindOpcodes(OS, Obj.LinkEdit.BindOpcodes);
545 }
546 
547 void MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) {
548  writeBindOpcodes(OS, Obj.LinkEdit.WeakBindOpcodes);
549 }
550 
551 void MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) {
552  writeBindOpcodes(OS, Obj.LinkEdit.LazyBindOpcodes);
553 }
554 
555 void MachOWriter::writeNameList(raw_ostream &OS) {
556  for (auto NLE : Obj.LinkEdit.NameList) {
557  if (is64Bit)
558  writeNListEntry<MachO::nlist_64>(NLE, OS, Obj.IsLittleEndian);
559  else
560  writeNListEntry<MachO::nlist>(NLE, OS, Obj.IsLittleEndian);
561  }
562 }
563 
565  for (auto Str : Obj.LinkEdit.StringTable) {
566  OS.write(Str.data(), Str.size());
567  OS.write('\0');
568  }
569 }
570 
571 void MachOWriter::writeDynamicSymbolTable(raw_ostream &OS) {
572  for (auto Data : Obj.LinkEdit.IndirectSymbols)
573  OS.write(reinterpret_cast<const char *>(&Data),
574  sizeof(yaml::Hex32::BaseType));
575 }
576 
577 void MachOWriter::writeFunctionStarts(raw_ostream &OS) {
578  uint64_t Addr = 0;
579  for (uint64_t NextAddr : Obj.LinkEdit.FunctionStarts) {
580  uint64_t Delta = NextAddr - Addr;
581  encodeULEB128(Delta, OS);
582  Addr = NextAddr;
583  }
584 
585  OS.write('\0');
586 }
587 
588 class UniversalWriter {
589 public:
590  UniversalWriter(yaml::YamlObjectFile &ObjectFile)
591  : ObjectFile(ObjectFile), fileStart(0) {}
592 
593  Error writeMachO(raw_ostream &OS);
594 
595 private:
596  void writeFatHeader(raw_ostream &OS);
597  void writeFatArchs(raw_ostream &OS);
598 
599  void ZeroToOffset(raw_ostream &OS, size_t offset);
600 
602  uint64_t fileStart;
603 };
604 
605 Error UniversalWriter::writeMachO(raw_ostream &OS) {
606  fileStart = OS.tell();
607  if (ObjectFile.MachO) {
608  MachOWriter Writer(*ObjectFile.MachO);
609  return Writer.writeMachO(OS);
610  }
611 
612  writeFatHeader(OS);
613  writeFatArchs(OS);
614 
615  auto &FatFile = *ObjectFile.FatMachO;
616  if (FatFile.FatArchs.size() < FatFile.Slices.size())
617  return createStringError(
619  "cannot write 'Slices' if not described in 'FatArches'");
620 
621  for (size_t i = 0; i < FatFile.Slices.size(); i++) {
622  ZeroToOffset(OS, FatFile.FatArchs[i].offset);
623  MachOWriter Writer(FatFile.Slices[i]);
624  if (Error Err = Writer.writeMachO(OS))
625  return Err;
626 
627  auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;
628  ZeroToOffset(OS, SliceEnd);
629  }
630 
631  return Error::success();
632 }
633 
634 void UniversalWriter::writeFatHeader(raw_ostream &OS) {
635  auto &FatFile = *ObjectFile.FatMachO;
636  MachO::fat_header header;
637  header.magic = FatFile.Header.magic;
638  header.nfat_arch = FatFile.Header.nfat_arch;
640  swapStruct(header);
641  OS.write(reinterpret_cast<const char *>(&header), sizeof(MachO::fat_header));
642 }
643 
644 template <typename FatArchType>
645 FatArchType constructFatArch(MachOYAML::FatArch &Arch) {
646  FatArchType FatArch;
647  FatArch.cputype = Arch.cputype;
648  FatArch.cpusubtype = Arch.cpusubtype;
649  FatArch.offset = Arch.offset;
650  FatArch.size = Arch.size;
651  FatArch.align = Arch.align;
652  return FatArch;
653 }
654 
655 template <typename StructType>
656 void writeFatArch(MachOYAML::FatArch &LC, raw_ostream &OS) {}
657 
658 template <>
659 void writeFatArch<MachO::fat_arch>(MachOYAML::FatArch &Arch, raw_ostream &OS) {
660  auto FatArch = constructFatArch<MachO::fat_arch>(Arch);
662  swapStruct(FatArch);
663  OS.write(reinterpret_cast<const char *>(&FatArch), sizeof(MachO::fat_arch));
664 }
665 
666 template <>
667 void writeFatArch<MachO::fat_arch_64>(MachOYAML::FatArch &Arch,
668  raw_ostream &OS) {
669  auto FatArch = constructFatArch<MachO::fat_arch_64>(Arch);
670  FatArch.reserved = Arch.reserved;
672  swapStruct(FatArch);
673  OS.write(reinterpret_cast<const char *>(&FatArch),
674  sizeof(MachO::fat_arch_64));
675 }
676 
677 void UniversalWriter::writeFatArchs(raw_ostream &OS) {
678  auto &FatFile = *ObjectFile.FatMachO;
679  bool is64Bit = FatFile.Header.magic == MachO::FAT_MAGIC_64;
680  for (auto Arch : FatFile.FatArchs) {
681  if (is64Bit)
682  writeFatArch<MachO::fat_arch_64>(Arch, OS);
683  else
684  writeFatArch<MachO::fat_arch>(Arch, OS);
685  }
686 }
687 
688 void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
689  auto currOffset = OS.tell() - fileStart;
690  if (currOffset < Offset)
691  ZeroFillBytes(OS, Offset - currOffset);
692 }
693 
694 } // end anonymous namespace
695 
696 namespace llvm {
697 namespace yaml {
698 
700  UniversalWriter Writer(Doc);
701  if (Error Err = Writer.writeMachO(Out)) {
703  [&](const ErrorInfoBase &Err) { EH(Err.message()); });
704  return false;
705  }
706  return true;
707 }
708 
709 } // namespace yaml
710 } // namespace llvm
llvm::Check::Size
@ Size
Definition: FileCheck.h:77
llvm::MachOYAML::ExportEntry
Definition: MachOYAML.h:105
llvm::MachOYAML::FatArch::offset
llvm::yaml::Hex64 offset
Definition: MachOYAML.h:148
i
i
Definition: README.txt:29
llvm::raw_ostream::tell
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:136
llvm::MachOYAML::LoadCommand::Sections
std::vector< Section > Sections
Definition: MachOYAML.h:76
llvm::errc::invalid_argument
@ invalid_argument
llvm::MachO::section
Definition: MachO.h:565
llvm::MachOYAML::NListEntry::n_desc
uint16_t n_desc
Definition: MachOYAML.h:87
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
ObjectYAML.h
llvm::MachO::any_relocation_info
Definition: MachO.h:977
llvm::MachO::MH_CIGAM_64
@ MH_CIGAM_64
Definition: MachO.h:33
llvm::MachOYAML::Object
Definition: MachOYAML.h:130
llvm::MachOYAML::Section
Definition: MachOYAML.h:44
llvm::MachOYAML::Section::segname
char segname[16]
Definition: MachOYAML.h:46
llvm::MachO::fat_header::nfat_arch
uint32_t nfat_arch
Definition: MachO.h:938
is64Bit
static bool is64Bit(const char *name)
Definition: X86Disassembler.cpp:1018
llvm::MachOYAML::LinkEditData::ExportTrie
MachOYAML::ExportEntry ExportTrie
Definition: MachOYAML.h:121
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::MachOYAML::LoadCommand::ZeroPadBytes
uint64_t ZeroPadBytes
Definition: MachOYAML.h:80
llvm::MachO::dysymtab_command::indirectsymoff
uint32_t indirectsymoff
Definition: MachO.h:719
Content
T Content
Definition: ELFObjHandler.cpp:88
Error.h
llvm::MachOYAML::Section::nreloc
uint32_t nreloc
Definition: MachOYAML.h:52
llvm::yaml::YamlObjectFile
Definition: ObjectYAML.h:28
llvm::MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
@ EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
Definition: MachO.h:290
Errc.h
llvm::MachO::symtab_command
Definition: MachO.h:695
llvm::MachOYAML::LinkEditData::LazyBindOpcodes
std::vector< MachOYAML::BindOpcode > LazyBindOpcodes
Definition: MachOYAML.h:120
llvm::MachOYAML::NListEntry
Definition: MachOYAML.h:83
llvm::MachOYAML::LoadCommand::PayloadBytes
std::vector< llvm::yaml::Hex8 > PayloadBytes
Definition: MachOYAML.h:78
llvm::MachO::isVirtualSection
bool isVirtualSection(uint8_t type)
Definition: MachO.h:594
T
#define T
Definition: Mips16ISelLowering.cpp:341
llvm::MachO::dyld_info_command::export_off
uint32_t export_off
Definition: MachO.h:878
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:79
llvm::MachOYAML::Object::DWARF
DWARFYAML::Data DWARF
Definition: MachOYAML.h:137
llvm::MachOYAML::Section::addr
llvm::yaml::Hex64 addr
Definition: MachOYAML.h:47
llvm::MachOYAML::LinkEditData::FunctionStarts
std::vector< yaml::Hex64 > FunctionStarts
Definition: MachOYAML.h:125
Format.h
llvm::MachOYAML::LinkEditData::RebaseOpcodes
std::vector< MachOYAML::RebaseOpcode > RebaseOpcodes
Definition: MachOYAML.h:117
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:240
llvm::MachOYAML::LoadCommand::Content
std::string Content
Definition: MachOYAML.h:79
llvm::MachOYAML::FileHeader::sizeofcmds
uint32_t sizeofcmds
Definition: MachOYAML.h:67
llvm::MachO::dyld_info_command
Definition: MachO.h:867
llvm::MachOYAML::LinkEditData::IndirectSymbols
std::vector< yaml::Hex32 > IndirectSymbols
Definition: MachOYAML.h:124
llvm::MachOYAML::Section::size
uint64_t size
Definition: MachOYAML.h:48
llvm::yaml::yaml2macho
bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out, ErrorHandler EH)
Definition: MachOEmitter.cpp:699
llvm::MachO::fat_arch
Definition: MachO.h:941
llvm::MachOYAML::Section::sectname
char sectname[16]
Definition: MachOYAML.h:45
llvm::MachO::any_relocation_info::r_word1
uint32_t r_word1
Definition: MachO.h:978
llvm::encodeSLEB128
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
Definition: LEB128.h:23
llvm::less_first
Function object to check whether the first component of a std::pair compares less than the first comp...
Definition: STLExtras.h:1354
llvm::MachOYAML::FatArch::align
uint32_t align
Definition: MachOYAML.h:150
llvm::MachOYAML::NListEntry::n_value
uint64_t n_value
Definition: MachOYAML.h:88
llvm::MachOYAML::FatArch::cputype
llvm::yaml::Hex32 cputype
Definition: MachOYAML.h:146
llvm::MachO::fat_header::magic
uint32_t magic
Definition: MachO.h:937
llvm::MachO::linkedit_data_command
Definition: MachO.h:800
llvm::raw_ostream::write
raw_ostream & write(unsigned char C)
Definition: raw_ostream.cpp:219
llvm::MachOYAML::FileHeader::filetype
llvm::yaml::Hex32 filetype
Definition: MachOYAML.h:65
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
llvm::object::writeStringTable
static void writeStringTable(std::vector< uint8_t > &B, ArrayRef< const std::string > Strings)
Definition: COFFImportFile.cpp:70
llvm::MachOYAML::LoadCommand::Data
llvm::MachO::macho_load_command Data
Definition: MachOYAML.h:75
llvm::MachOYAML::Section::relocations
std::vector< Relocation > relocations
Definition: MachOYAML.h:58
ZeroFillBytes
static void ZeroFillBytes(raw_ostream &OS, size_t Size)
Definition: DWARFEmitter.cpp:65
llvm::ErrorInfoBase
Base class for error info classes.
Definition: Error.h:46
llvm::MachOYAML::LoadCommand
Definition: MachOYAML.h:72
llvm::MachOYAML::Object::LinkEdit
LinkEditData LinkEdit
Definition: MachOYAML.h:135
llvm::MachOYAML::LinkEditData::NameList
std::vector< NListEntry > NameList
Definition: MachOYAML.h:122
llvm::MachOYAML::Object::LoadCommands
std::vector< LoadCommand > LoadCommands
Definition: MachOYAML.h:133
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLFunctionalExtras.h:36
llvm::MachO::mach_header_64
Definition: MachO.h:521
llvm::DWARFYAML::Data::getNonEmptySectionNames
SetVector< StringRef > getNonEmptySectionNames() const
Definition: DWARFYAML.cpp:25
constructSection
Section constructSection(const MachO::section &Sec, uint32_t Index)
Definition: MachOReader.cpp:49
llvm::MachOYAML::FatArch::cpusubtype
llvm::yaml::Hex32 cpusubtype
Definition: MachOYAML.h:147
llvm::MachOYAML::FileHeader::reserved
llvm::yaml::Hex32 reserved
Definition: MachOYAML.h:69
BaseType
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
Definition: SafepointIRVerifier.cpp:314
llvm::MachO::FAT_MAGIC_64
@ FAT_MAGIC_64
Definition: MachO.h:36
uint64_t
llvm::MachO::MH_MAGIC_64
@ MH_MAGIC_64
Definition: MachO.h:32
llvm::MachOYAML::Section::offset
llvm::yaml::Hex32 offset
Definition: MachOYAML.h:49
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:78
llvm::DWARFYAML::getDWARFEmitterByName
std::function< Error(raw_ostream &, const Data &)> getDWARFEmitterByName(StringRef SecName)
Definition: DWARFEmitter.h:47
llvm::MachOYAML::FileHeader::flags
llvm::yaml::Hex32 flags
Definition: MachOYAML.h:68
llvm::yaml::BinaryRef::writeAsBinary
void writeAsBinary(raw_ostream &OS, uint64_t N=UINT64_MAX) const
Write the contents (regardless of whether it is binary or a hex string) as binary to the given raw_os...
Definition: YAML.cpp:39
llvm::MachO::build_tool_version
Definition: MachO.h:852
llvm::MachO::any_relocation_info::r_word0
uint32_t r_word0
Definition: MachO.h:978
LEB128.h
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::MachOYAML::NListEntry::n_sect
uint8_t n_sect
Definition: MachOYAML.h:86
llvm::MachO::dyld_info_command::lazy_bind_off
uint32_t lazy_bind_off
Definition: MachO.h:876
llvm::MachOYAML::FatArch::size
uint64_t size
Definition: MachOYAML.h:149
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MachOYAML::NListEntry::n_type
llvm::yaml::Hex8 n_type
Definition: MachOYAML.h:85
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
llvm::codeview::CodeViewContainer::ObjectFile
@ ObjectFile
llvm::MachOYAML::Object::IsLittleEndian
bool IsLittleEndian
Definition: MachOYAML.h:131
llvm::MachOYAML::Section::content
Optional< llvm::yaml::BinaryRef > content
Definition: MachOYAML.h:57
llvm::MachOYAML::NListEntry::n_strx
uint32_t n_strx
Definition: MachOYAML.h:84
YAMLTraits.h
llvm::MachOYAML::LinkEditData
Definition: MachOYAML.h:116
llvm::MachO::load_command
Definition: MachO.h:532
yaml2obj.h
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::yaml::BinaryRef
Specialized YAMLIO scalar type for representing a binary blob.
Definition: YAML.h:63
llvm::MachOYAML::FileHeader::cputype
llvm::yaml::Hex32 cputype
Definition: MachOYAML.h:63
uint32_t
llvm::MachOYAML::LinkEditData::WeakBindOpcodes
std::vector< MachOYAML::BindOpcode > WeakBindOpcodes
Definition: MachOYAML.h:119
llvm::MachOYAML::FileHeader::magic
llvm::yaml::Hex32 magic
Definition: MachOYAML.h:62
llvm::MachO::NListType
NListType
Definition: MachO.h:308
llvm::MachO::dyld_info_command::weak_bind_off
uint32_t weak_bind_off
Definition: MachO.h:874
llvm::MachOYAML::Object::Header
FileHeader Header
Definition: MachOYAML.h:132
llvm::MachOYAML::LinkEditData::BindOpcodes
std::vector< MachOYAML::BindOpcode > BindOpcodes
Definition: MachOYAML.h:118
DWARFEmitter.h
llvm::MachO::SECTION_TYPE
@ SECTION_TYPE
Definition: MachO.h:112
llvm::MachO::dysymtab_command
Definition: MachO.h:704
llvm::MachOYAML::LoadCommand::Tools
std::vector< MachO::build_tool_version > Tools
Definition: MachOYAML.h:77
llvm::MachO::section_64
Definition: MachO.h:579
llvm::MachOYAML::FileHeader::cpusubtype
llvm::yaml::Hex32 cpusubtype
Definition: MachOYAML.h:64
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1239
llvm::MachOYAML::Section::reserved3
llvm::yaml::Hex32 reserved3
Definition: MachOYAML.h:56
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::MachO::symtab_command::stroff
uint32_t stroff
Definition: MachO.h:700
llvm::MachO::R_SCATTERED
@ R_SCATTERED
Definition: MachO.h:396
llvm::MachOYAML::Object::RawLinkEditSegment
Optional< llvm::yaml::BinaryRef > RawLinkEditSegment
Definition: MachOYAML.h:136
llvm::MachOYAML::FatArch
Definition: MachOYAML.h:145
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1562
llvm::MachO::mach_header
Definition: MachO.h:511
llvm::MachOYAML::FatArch::reserved
llvm::yaml::Hex32 reserved
Definition: MachOYAML.h:151
llvm::MachOYAML::Section::reserved1
llvm::yaml::Hex32 reserved1
Definition: MachOYAML.h:54
llvm::MachO::EXPORT_SYMBOL_FLAGS_REEXPORT
@ EXPORT_SYMBOL_FLAGS_REEXPORT
Definition: MachO.h:289
llvm::sys::IsLittleEndianHost
static const bool IsLittleEndianHost
Definition: SwapByteOrder.h:101
writeNListEntry
void writeNListEntry(const SymbolEntry &SE, bool IsLittleEndian, char *&Out, uint32_t Nstrx)
Definition: MachOWriter.cpp:271
llvm::MachOYAML::LinkEditData::StringTable
std::vector< StringRef > StringTable
Definition: MachOYAML.h:123
llvm::MachOYAML::Section::reserved2
llvm::yaml::Hex32 reserved2
Definition: MachOYAML.h:55
llvm::encodeULEB128
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
Definition: LEB128.h:80
llvm::MachOYAML::FileHeader::ncmds
uint32_t ncmds
Definition: MachOYAML.h:66
llvm::MachO::fat_arch_64
Definition: MachO.h:949
llvm::MachO::symtab_command::symoff
uint32_t symoff
Definition: MachO.h:698
llvm::MachO::dyld_info_command::bind_off
uint32_t bind_off
Definition: MachO.h:872
llvm::MachO::dyld_info_command::rebase_off
uint32_t rebase_off
Definition: MachO.h:870
MachO.h
raw_ostream.h
llvm::MachO::linkedit_data_command::dataoff
uint32_t dataoff
Definition: MachO.h:803
llvm::MachO::swapStruct
void swapStruct(fat_header &mh)
Definition: MachO.h:1028
llvm::MachOYAML::Section::reloff
llvm::yaml::Hex32 reloff
Definition: MachOYAML.h:51
llvm::MachOYAML::Section::flags
llvm::yaml::Hex32 flags
Definition: MachOYAML.h:53
llvm::MachO::fat_header
Definition: MachO.h:936
llvm::handleAllErrors
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition: Error.h:966
llvm::MachOYAML::Relocation
Definition: MachOYAML.h:30
llvm::MachO::SectionType
SectionType
These are the section type and attributes fields.
Definition: MachO.h:120
llvm::MachOYAML::Section::align
uint32_t align
Definition: MachOYAML.h:50
llvm::MachO::macho_load_command
Definition: MachO.h:2028