LLVM  14.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 
58  void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);
59  void ZeroToOffset(raw_ostream &OS, size_t offset);
60 
61  MachOYAML::Object &Obj;
62  bool is64Bit;
63  uint64_t fileStart;
64  MachO::mach_header_64 Header;
65 
66  // Old PPC Object Files didn't have __LINKEDIT segments, the data was just
67  // stuck at the end of the file.
68  bool FoundLinkEditSeg = false;
69 };
70 
71 Error MachOWriter::writeMachO(raw_ostream &OS) {
72  fileStart = OS.tell();
73  writeHeader(OS);
74  writeLoadCommands(OS);
75  if (Error Err = writeSectionData(OS))
76  return Err;
77  writeRelocations(OS);
78  if (!FoundLinkEditSeg)
79  writeLinkEditData(OS);
80  return Error::success();
81 }
82 
83 void MachOWriter::writeHeader(raw_ostream &OS) {
84  Header.magic = Obj.Header.magic;
85  Header.cputype = Obj.Header.cputype;
86  Header.cpusubtype = Obj.Header.cpusubtype;
87  Header.filetype = Obj.Header.filetype;
88  Header.ncmds = Obj.Header.ncmds;
89  Header.sizeofcmds = Obj.Header.sizeofcmds;
90  Header.flags = Obj.Header.flags;
91  Header.reserved = Obj.Header.reserved;
92 
94  MachO::swapStruct(Header);
95 
96  auto header_size =
98  OS.write((const char *)&Header, header_size);
99 }
100 
101 template <typename SectionType>
102 SectionType constructSection(MachOYAML::Section Sec) {
103  SectionType TempSec;
104  memcpy(reinterpret_cast<void *>(&TempSec.sectname[0]), &Sec.sectname[0], 16);
105  memcpy(reinterpret_cast<void *>(&TempSec.segname[0]), &Sec.segname[0], 16);
106  TempSec.addr = Sec.addr;
107  TempSec.size = Sec.size;
108  TempSec.offset = Sec.offset;
109  TempSec.align = Sec.align;
110  TempSec.reloff = Sec.reloff;
111  TempSec.nreloc = Sec.nreloc;
112  TempSec.flags = Sec.flags;
113  TempSec.reserved1 = Sec.reserved1;
114  TempSec.reserved2 = Sec.reserved2;
115  return TempSec;
116 }
117 
118 template <typename StructType>
119 size_t writeLoadCommandData(MachOYAML::LoadCommand &LC, raw_ostream &OS,
120  bool IsLittleEndian) {
121  return 0;
122 }
123 
124 template <>
125 size_t writeLoadCommandData<MachO::segment_command>(MachOYAML::LoadCommand &LC,
126  raw_ostream &OS,
127  bool IsLittleEndian) {
128  size_t BytesWritten = 0;
129  for (const auto &Sec : LC.Sections) {
130  auto TempSec = constructSection<MachO::section>(Sec);
131  if (IsLittleEndian != sys::IsLittleEndianHost)
132  MachO::swapStruct(TempSec);
133  OS.write(reinterpret_cast<const char *>(&(TempSec)),
134  sizeof(MachO::section));
135  BytesWritten += sizeof(MachO::section);
136  }
137  return BytesWritten;
138 }
139 
140 template <>
141 size_t writeLoadCommandData<MachO::segment_command_64>(
142  MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
143  size_t BytesWritten = 0;
144  for (const auto &Sec : LC.Sections) {
145  auto TempSec = constructSection<MachO::section_64>(Sec);
146  TempSec.reserved3 = Sec.reserved3;
147  if (IsLittleEndian != sys::IsLittleEndianHost)
148  MachO::swapStruct(TempSec);
149  OS.write(reinterpret_cast<const char *>(&(TempSec)),
150  sizeof(MachO::section_64));
151  BytesWritten += sizeof(MachO::section_64);
152  }
153  return BytesWritten;
154 }
155 
156 size_t writePayloadString(MachOYAML::LoadCommand &LC, raw_ostream &OS) {
157  size_t BytesWritten = 0;
158  if (!LC.Content.empty()) {
159  OS.write(LC.Content.c_str(), LC.Content.length());
160  BytesWritten = LC.Content.length();
161  }
162  return BytesWritten;
163 }
164 
165 template <>
166 size_t writeLoadCommandData<MachO::dylib_command>(MachOYAML::LoadCommand &LC,
167  raw_ostream &OS,
168  bool IsLittleEndian) {
169  return writePayloadString(LC, OS);
170 }
171 
172 template <>
173 size_t writeLoadCommandData<MachO::dylinker_command>(MachOYAML::LoadCommand &LC,
174  raw_ostream &OS,
175  bool IsLittleEndian) {
176  return writePayloadString(LC, OS);
177 }
178 
179 template <>
180 size_t writeLoadCommandData<MachO::rpath_command>(MachOYAML::LoadCommand &LC,
181  raw_ostream &OS,
182  bool IsLittleEndian) {
183  return writePayloadString(LC, OS);
184 }
185 
186 template <>
187 size_t writeLoadCommandData<MachO::sub_framework_command>(
188  MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
189  return writePayloadString(LC, OS);
190 }
191 
192 template <>
193 size_t writeLoadCommandData<MachO::sub_umbrella_command>(
194  MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
195  return writePayloadString(LC, OS);
196 }
197 
198 template <>
199 size_t writeLoadCommandData<MachO::sub_client_command>(
200  MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
201  return writePayloadString(LC, OS);
202 }
203 
204 template <>
205 size_t writeLoadCommandData<MachO::sub_library_command>(
206  MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
207  return writePayloadString(LC, OS);
208 }
209 
210 template <>
211 size_t writeLoadCommandData<MachO::build_version_command>(
212  MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) {
213  size_t BytesWritten = 0;
214  for (const auto &T : LC.Tools) {
215  struct MachO::build_tool_version tool = T;
216  if (IsLittleEndian != sys::IsLittleEndianHost)
217  MachO::swapStruct(tool);
218  OS.write(reinterpret_cast<const char *>(&tool),
219  sizeof(MachO::build_tool_version));
220  BytesWritten += sizeof(MachO::build_tool_version);
221  }
222  return BytesWritten;
223 }
224 
225 void ZeroFillBytes(raw_ostream &OS, size_t Size) {
226  std::vector<uint8_t> FillData(Size, 0);
227  OS.write(reinterpret_cast<char *>(FillData.data()), Size);
228 }
229 
230 void Fill(raw_ostream &OS, size_t Size, uint32_t Data) {
231  std::vector<uint32_t> FillData((Size / 4) + 1, Data);
232  OS.write(reinterpret_cast<char *>(FillData.data()), Size);
233 }
234 
235 void MachOWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
236  auto currOffset = OS.tell() - fileStart;
237  if (currOffset < Offset)
238  ZeroFillBytes(OS, Offset - currOffset);
239 }
240 
241 void MachOWriter::writeLoadCommands(raw_ostream &OS) {
242  for (auto &LC : Obj.LoadCommands) {
243  size_t BytesWritten = 0;
245 
246 #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
247  case MachO::LCName: \
248  if (Obj.IsLittleEndian != sys::IsLittleEndianHost) \
249  MachO::swapStruct(Data.LCStruct##_data); \
250  OS.write(reinterpret_cast<const char *>(&(Data.LCStruct##_data)), \
251  sizeof(MachO::LCStruct)); \
252  BytesWritten = sizeof(MachO::LCStruct); \
253  BytesWritten += \
254  writeLoadCommandData<MachO::LCStruct>(LC, OS, Obj.IsLittleEndian); \
255  break;
256 
257  switch (LC.Data.load_command_data.cmd) {
258  default:
260  MachO::swapStruct(Data.load_command_data);
261  OS.write(reinterpret_cast<const char *>(&(Data.load_command_data)),
262  sizeof(MachO::load_command));
263  BytesWritten = sizeof(MachO::load_command);
264  BytesWritten +=
265  writeLoadCommandData<MachO::load_command>(LC, OS, Obj.IsLittleEndian);
266  break;
267 #include "llvm/BinaryFormat/MachO.def"
268  }
269 
270  if (LC.PayloadBytes.size() > 0) {
271  OS.write(reinterpret_cast<const char *>(LC.PayloadBytes.data()),
272  LC.PayloadBytes.size());
273  BytesWritten += LC.PayloadBytes.size();
274  }
275 
276  if (LC.ZeroPadBytes > 0) {
277  ZeroFillBytes(OS, LC.ZeroPadBytes);
278  BytesWritten += LC.ZeroPadBytes;
279  }
280 
281  // Fill remaining bytes with 0. This will only get hit in partially
282  // specified test cases.
283  auto BytesRemaining = LC.Data.load_command_data.cmdsize - BytesWritten;
284  if (BytesRemaining > 0) {
285  ZeroFillBytes(OS, BytesRemaining);
286  }
287  }
288 }
289 
290 Error MachOWriter::writeSectionData(raw_ostream &OS) {
291  uint64_t LinkEditOff = 0;
292  for (auto &LC : Obj.LoadCommands) {
293  switch (LC.Data.load_command_data.cmd) {
294  case MachO::LC_SEGMENT:
295  case MachO::LC_SEGMENT_64:
296  uint64_t segOff = is64Bit ? LC.Data.segment_command_64_data.fileoff
297  : LC.Data.segment_command_data.fileoff;
298  if (0 ==
299  strncmp(&LC.Data.segment_command_data.segname[0], "__LINKEDIT", 16)) {
300  FoundLinkEditSeg = true;
301  LinkEditOff = segOff;
302  if (Obj.RawLinkEditSegment)
303  continue;
304  writeLinkEditData(OS);
305  }
306  for (auto &Sec : LC.Sections) {
307  ZeroToOffset(OS, Sec.offset);
308  // Zero Fill any data between the end of the last thing we wrote and the
309  // start of this section.
310  if (OS.tell() - fileStart > Sec.offset && Sec.offset != (uint32_t)0)
311  return createStringError(
313  "wrote too much data somewhere, section offsets don't line up");
314 
315  StringRef SectName(Sec.sectname,
316  strnlen(Sec.sectname, sizeof(Sec.sectname)));
317  // If the section's content is specified in the 'DWARF' entry, we will
318  // emit it regardless of the section's segname.
319  if (Obj.DWARF.getNonEmptySectionNames().count(SectName.substr(2))) {
320  if (Sec.content)
322  "cannot specify section '" + SectName +
323  "' contents in the 'DWARF' entry and "
324  "the 'content' at the same time");
325  auto EmitFunc = DWARFYAML::getDWARFEmitterByName(SectName.substr(2));
326  if (Error Err = EmitFunc(OS, Obj.DWARF))
327  return Err;
328  continue;
329  }
330 
331  // Skip if it's a virtual section.
333  continue;
334 
335  if (Sec.content) {
337  Content.writeAsBinary(OS);
338  ZeroFillBytes(OS, Sec.size - Content.binary_size());
339  } else {
340  // Fill section data with 0xDEADBEEF.
341  Fill(OS, Sec.size, 0xDEADBEEFu);
342  }
343  }
344  uint64_t segSize = is64Bit ? LC.Data.segment_command_64_data.filesize
345  : LC.Data.segment_command_data.filesize;
346  ZeroToOffset(OS, segOff + segSize);
347  break;
348  }
349  }
350 
351  if (Obj.RawLinkEditSegment) {
352  ZeroToOffset(OS, LinkEditOff);
353  if (OS.tell() - fileStart > LinkEditOff || !LinkEditOff)
355  "section offsets don't line up");
357  }
358  return Error::success();
359 }
360 
361 // The implementation of makeRelocationInfo and makeScatteredRelocationInfo is
362 // consistent with how libObject parses MachO binary files. For the reference
363 // see getStruct, getRelocation, getPlainRelocationPCRel,
364 // getPlainRelocationLength and related methods in MachOObjectFile.cpp
366 makeRelocationInfo(const MachOYAML::Relocation &R, bool IsLE) {
367  assert(!R.is_scattered && "non-scattered relocation expected");
369  MRE.r_word0 = R.address;
370  if (IsLE)
371  MRE.r_word1 = ((unsigned)R.symbolnum << 0) | ((unsigned)R.is_pcrel << 24) |
372  ((unsigned)R.length << 25) | ((unsigned)R.is_extern << 27) |
373  ((unsigned)R.type << 28);
374  else
375  MRE.r_word1 = ((unsigned)R.symbolnum << 8) | ((unsigned)R.is_pcrel << 7) |
376  ((unsigned)R.length << 5) | ((unsigned)R.is_extern << 4) |
377  ((unsigned)R.type << 0);
378  return MRE;
379 }
380 
382 makeScatteredRelocationInfo(const MachOYAML::Relocation &R) {
383  assert(R.is_scattered && "scattered relocation expected");
385  MRE.r_word0 = (((unsigned)R.address << 0) | ((unsigned)R.type << 24) |
386  ((unsigned)R.length << 28) | ((unsigned)R.is_pcrel << 30) |
388  MRE.r_word1 = R.value;
389  return MRE;
390 }
391 
392 void MachOWriter::writeRelocations(raw_ostream &OS) {
393  for (const MachOYAML::LoadCommand &LC : Obj.LoadCommands) {
394  switch (LC.Data.load_command_data.cmd) {
395  case MachO::LC_SEGMENT:
396  case MachO::LC_SEGMENT_64:
397  for (const MachOYAML::Section &Sec : LC.Sections) {
398  if (Sec.relocations.empty())
399  continue;
400  ZeroToOffset(OS, Sec.reloff);
401  for (const MachOYAML::Relocation &R : Sec.relocations) {
403  R.is_scattered ? makeScatteredRelocationInfo(R)
404  : makeRelocationInfo(R, Obj.IsLittleEndian);
406  MachO::swapStruct(MRE);
407  OS.write(reinterpret_cast<const char *>(&MRE),
409  }
410  }
411  }
412  }
413 }
414 
415 void MachOWriter::writeBindOpcodes(
416  raw_ostream &OS, std::vector<MachOYAML::BindOpcode> &BindOpcodes) {
417 
418  for (auto Opcode : BindOpcodes) {
419  uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
420  OS.write(reinterpret_cast<char *>(&OpByte), 1);
421  for (auto Data : Opcode.ULEBExtraData) {
422  encodeULEB128(Data, OS);
423  }
424  for (auto Data : Opcode.SLEBExtraData) {
425  encodeSLEB128(Data, OS);
426  }
427  if (!Opcode.Symbol.empty()) {
428  OS.write(Opcode.Symbol.data(), Opcode.Symbol.size());
429  OS.write('\0');
430  }
431  }
432 }
433 
434 void MachOWriter::dumpExportEntry(raw_ostream &OS,
435  MachOYAML::ExportEntry &Entry) {
436  encodeSLEB128(Entry.TerminalSize, OS);
437  if (Entry.TerminalSize > 0) {
438  encodeSLEB128(Entry.Flags, OS);
439  if (Entry.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
440  encodeSLEB128(Entry.Other, OS);
441  OS << Entry.ImportName;
442  OS.write('\0');
443  } else {
444  encodeSLEB128(Entry.Address, OS);
446  encodeSLEB128(Entry.Other, OS);
447  }
448  }
449  OS.write(static_cast<uint8_t>(Entry.Children.size()));
450  for (auto EE : Entry.Children) {
451  OS << EE.Name;
452  OS.write('\0');
453  encodeSLEB128(EE.NodeOffset, OS);
454  }
455  for (auto EE : Entry.Children)
456  dumpExportEntry(OS, EE);
457 }
458 
459 void MachOWriter::writeExportTrie(raw_ostream &OS) {
460  dumpExportEntry(OS, Obj.LinkEdit.ExportTrie);
461 }
462 
463 template <typename NListType>
464 void writeNListEntry(MachOYAML::NListEntry &NLE, raw_ostream &OS,
465  bool IsLittleEndian) {
466  NListType ListEntry;
467  ListEntry.n_strx = NLE.n_strx;
468  ListEntry.n_type = NLE.n_type;
469  ListEntry.n_sect = NLE.n_sect;
470  ListEntry.n_desc = NLE.n_desc;
471  ListEntry.n_value = NLE.n_value;
472 
473  if (IsLittleEndian != sys::IsLittleEndianHost)
474  MachO::swapStruct(ListEntry);
475  OS.write(reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
476 }
477 
478 void MachOWriter::writeLinkEditData(raw_ostream &OS) {
479  typedef void (MachOWriter::*writeHandler)(raw_ostream &);
480  typedef std::pair<uint64_t, writeHandler> writeOperation;
481  std::vector<writeOperation> WriteQueue;
482 
483  MachO::dyld_info_command *DyldInfoOnlyCmd = 0;
484  MachO::symtab_command *SymtabCmd = 0;
485  for (auto &LC : Obj.LoadCommands) {
486  switch (LC.Data.load_command_data.cmd) {
487  case MachO::LC_SYMTAB:
488  SymtabCmd = &LC.Data.symtab_command_data;
489  WriteQueue.push_back(
490  std::make_pair(SymtabCmd->symoff, &MachOWriter::writeNameList));
491  WriteQueue.push_back(
492  std::make_pair(SymtabCmd->stroff, &MachOWriter::writeStringTable));
493  break;
494  case MachO::LC_DYLD_INFO_ONLY:
495  DyldInfoOnlyCmd = &LC.Data.dyld_info_command_data;
496  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->rebase_off,
497  &MachOWriter::writeRebaseOpcodes));
498  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->bind_off,
499  &MachOWriter::writeBasicBindOpcodes));
500  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->weak_bind_off,
501  &MachOWriter::writeWeakBindOpcodes));
502  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->lazy_bind_off,
503  &MachOWriter::writeLazyBindOpcodes));
504  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->export_off,
505  &MachOWriter::writeExportTrie));
506  break;
507  }
508  }
509 
510  llvm::sort(WriteQueue, [](const writeOperation &a, const writeOperation &b) {
511  return a.first < b.first;
512  });
513 
514  for (auto writeOp : WriteQueue) {
515  ZeroToOffset(OS, writeOp.first);
516  (this->*writeOp.second)(OS);
517  }
518 }
519 
520 void MachOWriter::writeRebaseOpcodes(raw_ostream &OS) {
521  MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
522 
523  for (auto Opcode : LinkEdit.RebaseOpcodes) {
524  uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
525  OS.write(reinterpret_cast<char *>(&OpByte), 1);
526  for (auto Data : Opcode.ExtraData)
527  encodeULEB128(Data, OS);
528  }
529 }
530 
531 void MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) {
532  writeBindOpcodes(OS, Obj.LinkEdit.BindOpcodes);
533 }
534 
535 void MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) {
536  writeBindOpcodes(OS, Obj.LinkEdit.WeakBindOpcodes);
537 }
538 
539 void MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) {
540  writeBindOpcodes(OS, Obj.LinkEdit.LazyBindOpcodes);
541 }
542 
543 void MachOWriter::writeNameList(raw_ostream &OS) {
544  for (auto NLE : Obj.LinkEdit.NameList) {
545  if (is64Bit)
546  writeNListEntry<MachO::nlist_64>(NLE, OS, Obj.IsLittleEndian);
547  else
548  writeNListEntry<MachO::nlist>(NLE, OS, Obj.IsLittleEndian);
549  }
550 }
551 
553  for (auto Str : Obj.LinkEdit.StringTable) {
554  OS.write(Str.data(), Str.size());
555  OS.write('\0');
556  }
557 }
558 
559 class UniversalWriter {
560 public:
561  UniversalWriter(yaml::YamlObjectFile &ObjectFile)
562  : ObjectFile(ObjectFile), fileStart(0) {}
563 
564  Error writeMachO(raw_ostream &OS);
565 
566 private:
567  void writeFatHeader(raw_ostream &OS);
568  void writeFatArchs(raw_ostream &OS);
569 
570  void ZeroToOffset(raw_ostream &OS, size_t offset);
571 
573  uint64_t fileStart;
574 };
575 
576 Error UniversalWriter::writeMachO(raw_ostream &OS) {
577  fileStart = OS.tell();
578  if (ObjectFile.MachO) {
579  MachOWriter Writer(*ObjectFile.MachO);
580  return Writer.writeMachO(OS);
581  }
582 
583  writeFatHeader(OS);
584  writeFatArchs(OS);
585 
586  auto &FatFile = *ObjectFile.FatMachO;
587  if (FatFile.FatArchs.size() < FatFile.Slices.size())
588  return createStringError(
590  "cannot write 'Slices' if not described in 'FatArches'");
591 
592  for (size_t i = 0; i < FatFile.Slices.size(); i++) {
593  ZeroToOffset(OS, FatFile.FatArchs[i].offset);
594  MachOWriter Writer(FatFile.Slices[i]);
595  if (Error Err = Writer.writeMachO(OS))
596  return Err;
597 
598  auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;
599  ZeroToOffset(OS, SliceEnd);
600  }
601 
602  return Error::success();
603 }
604 
605 void UniversalWriter::writeFatHeader(raw_ostream &OS) {
606  auto &FatFile = *ObjectFile.FatMachO;
607  MachO::fat_header header;
608  header.magic = FatFile.Header.magic;
609  header.nfat_arch = FatFile.Header.nfat_arch;
611  swapStruct(header);
612  OS.write(reinterpret_cast<const char *>(&header), sizeof(MachO::fat_header));
613 }
614 
615 template <typename FatArchType>
616 FatArchType constructFatArch(MachOYAML::FatArch &Arch) {
617  FatArchType FatArch;
618  FatArch.cputype = Arch.cputype;
619  FatArch.cpusubtype = Arch.cpusubtype;
620  FatArch.offset = Arch.offset;
621  FatArch.size = Arch.size;
622  FatArch.align = Arch.align;
623  return FatArch;
624 }
625 
626 template <typename StructType>
627 void writeFatArch(MachOYAML::FatArch &LC, raw_ostream &OS) {}
628 
629 template <>
630 void writeFatArch<MachO::fat_arch>(MachOYAML::FatArch &Arch, raw_ostream &OS) {
631  auto FatArch = constructFatArch<MachO::fat_arch>(Arch);
633  swapStruct(FatArch);
634  OS.write(reinterpret_cast<const char *>(&FatArch), sizeof(MachO::fat_arch));
635 }
636 
637 template <>
638 void writeFatArch<MachO::fat_arch_64>(MachOYAML::FatArch &Arch,
639  raw_ostream &OS) {
640  auto FatArch = constructFatArch<MachO::fat_arch_64>(Arch);
641  FatArch.reserved = Arch.reserved;
643  swapStruct(FatArch);
644  OS.write(reinterpret_cast<const char *>(&FatArch),
645  sizeof(MachO::fat_arch_64));
646 }
647 
648 void UniversalWriter::writeFatArchs(raw_ostream &OS) {
649  auto &FatFile = *ObjectFile.FatMachO;
650  bool is64Bit = FatFile.Header.magic == MachO::FAT_MAGIC_64;
651  for (auto Arch : FatFile.FatArchs) {
652  if (is64Bit)
653  writeFatArch<MachO::fat_arch_64>(Arch, OS);
654  else
655  writeFatArch<MachO::fat_arch>(Arch, OS);
656  }
657 }
658 
659 void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
660  auto currOffset = OS.tell() - fileStart;
661  if (currOffset < Offset)
662  ZeroFillBytes(OS, Offset - currOffset);
663 }
664 
665 } // end anonymous namespace
666 
667 namespace llvm {
668 namespace yaml {
669 
671  UniversalWriter Writer(Doc);
672  if (Error Err = Writer.writeMachO(Out)) {
674  [&](const ErrorInfoBase &Err) { EH(Err.message()); });
675  return false;
676  }
677  return true;
678 }
679 
680 } // namespace yaml
681 } // namespace llvm
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
llvm::MachOYAML::ExportEntry
Definition: MachOYAML.h:105
llvm::MachOYAML::FatArch::offset
llvm::yaml::Hex64 offset
Definition: MachOYAML.h:146
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:135
llvm::MachOYAML::LoadCommand::Sections
std::vector< Section > Sections
Definition: MachOYAML.h:76
llvm::errc::invalid_argument
@ invalid_argument
llvm::MachO::MH_MAGIC_64
@ MH_MAGIC_64
Definition: MachO.h:32
llvm::MachO::section
Definition: MachO.h:563
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: AllocatorList.h:23
ObjectYAML.h
llvm::MachO::SECTION_TYPE
@ SECTION_TYPE
Definition: MachO.h:112
llvm::MachO::any_relocation_info
Definition: MachO.h:975
llvm::MachOYAML::Object
Definition: MachOYAML.h:128
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:936
T
is64Bit
static bool is64Bit(const char *name)
Definition: X86Disassembler.cpp:1019
llvm::MachOYAML::LinkEditData::ExportTrie
MachOYAML::ExportEntry ExportTrie
Definition: MachOYAML.h:121
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
llvm::MachOYAML::LoadCommand::ZeroPadBytes
uint64_t ZeroPadBytes
Definition: MachOYAML.h:80
Content
T Content
Definition: ELFObjHandler.cpp:90
Error.h
llvm::MachOYAML::Section::nreloc
uint32_t nreloc
Definition: MachOYAML.h:52
llvm::yaml::YamlObjectFile
Definition: ObjectYAML.h:27
Errc.h
llvm::MachO::symtab_command
Definition: MachO.h:693
llvm::MachO::EXPORT_SYMBOL_FLAGS_REEXPORT
@ EXPORT_SYMBOL_FLAGS_REEXPORT
Definition: MachO.h:288
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:592
T
#define T
Definition: Mips16ISelLowering.cpp:341
llvm::MachO::dyld_info_command::export_off
uint32_t export_off
Definition: MachO.h:876
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::MachOYAML::Object::DWARF
DWARFYAML::Data DWARF
Definition: MachOYAML.h:135
llvm::MachOYAML::Section::addr
llvm::yaml::Hex64 addr
Definition: MachOYAML.h:47
llvm::MachO::R_SCATTERED
@ R_SCATTERED
Definition: MachO.h:395
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:207
llvm::MachOYAML::LoadCommand::Content
std::string Content
Definition: MachOYAML.h:79
a
=0.0 ? 0.0 :(a > 0.0 ? 1.0 :-1.0) a
Definition: README.txt:489
llvm::MachOYAML::FileHeader::sizeofcmds
uint32_t sizeofcmds
Definition: MachOYAML.h:67
llvm::MachO::dyld_info_command
Definition: MachO.h:865
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:670
llvm::MachO::fat_arch
Definition: MachO.h:939
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:976
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::MachO::MH_CIGAM_64
@ MH_CIGAM_64
Definition: MachO.h:33
b
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int b
Definition: README.txt:418
llvm::MachOYAML::FatArch::align
uint32_t align
Definition: MachOYAML.h:148
llvm::MachOYAML::NListEntry::n_value
uint64_t n_value
Definition: MachOYAML.h:88
llvm::MachOYAML::FatArch::cputype
llvm::yaml::Hex32 cputype
Definition: MachOYAML.h:144
llvm::MachO::fat_header::magic
uint32_t magic
Definition: MachO.h:935
llvm::raw_ostream::write
raw_ostream & write(unsigned char C)
Definition: raw_ostream.cpp:220
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:53
llvm::object::writeStringTable
static void writeStringTable(std::vector< uint8_t > &B, ArrayRef< const std::string > Strings)
Definition: COFFImportFile.cpp:66
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:48
llvm::MachOYAML::LoadCommand
Definition: MachOYAML.h:72
llvm::MachOYAML::Object::LinkEdit
LinkEditData LinkEdit
Definition: MachOYAML.h:133
llvm::MachOYAML::LinkEditData::NameList
std::vector< NListEntry > NameList
Definition: MachOYAML.h:122
llvm::MachOYAML::Object::LoadCommands
std::vector< LoadCommand > LoadCommands
Definition: MachOYAML.h:131
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:168
llvm::MachO::mach_header_64
Definition: MachO.h:519
llvm::DWARFYAML::Data::getNonEmptySectionNames
SetVector< StringRef > getNonEmptySectionNames() const
Definition: DWARFYAML.cpp:25
llvm::MachOYAML::FatArch::cpusubtype
llvm::yaml::Hex32 cpusubtype
Definition: MachOYAML.h:145
llvm::MachOYAML::FileHeader::reserved
llvm::yaml::Hex32 reserved
Definition: MachOYAML.h:69
uint64_t
llvm::MachOYAML::Section::offset
llvm::yaml::Hex32 offset
Definition: MachOYAML.h:49
llvm::DWARFYAML::getDWARFEmitterByName
std::function< Error(raw_ostream &, const Data &)> getDWARFEmitterByName(StringRef SecName)
Definition: DWARFEmitter.h:48
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:40
llvm::MachO::build_tool_version
Definition: MachO.h:850
llvm::MachO::any_relocation_info::r_word0
uint32_t r_word0
Definition: MachO.h:976
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:874
llvm::MachOYAML::FatArch::size
uint64_t size
Definition: MachOYAML.h:147
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:129
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:530
yaml2obj.h
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
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
llvm::MachO::FAT_MAGIC_64
@ FAT_MAGIC_64
Definition: MachO.h:36
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:307
llvm::MachO::dyld_info_command::weak_bind_off
uint32_t weak_bind_off
Definition: MachO.h:872
llvm::MachOYAML::Object::Header
FileHeader Header
Definition: MachOYAML.h:130
llvm::MachOYAML::LinkEditData::BindOpcodes
std::vector< MachOYAML::BindOpcode > BindOpcodes
Definition: MachOYAML.h:118
DWARFEmitter.h
llvm::MachOYAML::LoadCommand::Tools
std::vector< MachO::build_tool_version > Tools
Definition: MachOYAML.h:77
llvm::MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
@ EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
Definition: MachO.h:289
llvm::MachO::section_64
Definition: MachO.h:577
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:1241
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:157
llvm::MachO::symtab_command::stroff
uint32_t stroff
Definition: MachO.h:698
llvm::MachOYAML::Object::RawLinkEditSegment
Optional< llvm::yaml::BinaryRef > RawLinkEditSegment
Definition: MachOYAML.h:134
llvm::MachOYAML::FatArch
Definition: MachOYAML.h:143
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1522
llvm::MachO::mach_header
Definition: MachO.h:509
llvm::MachOYAML::FatArch::reserved
llvm::yaml::Hex32 reserved
Definition: MachOYAML.h:149
llvm::MachOYAML::Section::reserved1
llvm::yaml::Hex32 reserved1
Definition: MachOYAML.h:54
llvm::sys::IsLittleEndianHost
static const bool IsLittleEndianHost
Definition: SwapByteOrder.h:101
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:947
llvm::MachO::symtab_command::symoff
uint32_t symoff
Definition: MachO.h:696
llvm::MachO::dyld_info_command::bind_off
uint32_t bind_off
Definition: MachO.h:870
llvm::MachO::dyld_info_command::rebase_off
uint32_t rebase_off
Definition: MachO.h:868
MachO.h
raw_ostream.h
llvm::MachO::swapStruct
void swapStruct(fat_header &mh)
Definition: MachO.h:1005
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:934
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:968
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:2005