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  for (auto &LC : Obj.LoadCommands) {
292  switch (LC.Data.load_command_data.cmd) {
293  case MachO::LC_SEGMENT:
294  case MachO::LC_SEGMENT_64:
295  uint64_t segOff = is64Bit ? LC.Data.segment_command_64_data.fileoff
296  : LC.Data.segment_command_data.fileoff;
297  if (0 ==
298  strncmp(&LC.Data.segment_command_data.segname[0], "__LINKEDIT", 16)) {
299  FoundLinkEditSeg = true;
300  writeLinkEditData(OS);
301  }
302  for (auto &Sec : LC.Sections) {
303  ZeroToOffset(OS, Sec.offset);
304  // Zero Fill any data between the end of the last thing we wrote and the
305  // start of this section.
306  if (OS.tell() - fileStart > Sec.offset && Sec.offset != (uint32_t)0)
307  return createStringError(
309  "wrote too much data somewhere, section offsets don't line up");
310 
311  StringRef SectName(Sec.sectname,
312  strnlen(Sec.sectname, sizeof(Sec.sectname)));
313  // If the section's content is specified in the 'DWARF' entry, we will
314  // emit it regardless of the section's segname.
315  if (Obj.DWARF.getNonEmptySectionNames().count(SectName.substr(2))) {
316  if (Sec.content)
318  "cannot specify section '" + SectName +
319  "' contents in the 'DWARF' entry and "
320  "the 'content' at the same time");
321  auto EmitFunc = DWARFYAML::getDWARFEmitterByName(SectName.substr(2));
322  if (Error Err = EmitFunc(OS, Obj.DWARF))
323  return Err;
324  continue;
325  }
326 
327  // Skip if it's a virtual section.
329  continue;
330 
331  if (Sec.content) {
333  Content.writeAsBinary(OS);
334  ZeroFillBytes(OS, Sec.size - Content.binary_size());
335  } else {
336  // Fill section data with 0xDEADBEEF.
337  Fill(OS, Sec.size, 0xDEADBEEFu);
338  }
339  }
340  uint64_t segSize = is64Bit ? LC.Data.segment_command_64_data.filesize
341  : LC.Data.segment_command_data.filesize;
342  ZeroToOffset(OS, segOff + segSize);
343  break;
344  }
345  }
346 
347  return Error::success();
348 }
349 
350 // The implementation of makeRelocationInfo and makeScatteredRelocationInfo is
351 // consistent with how libObject parses MachO binary files. For the reference
352 // see getStruct, getRelocation, getPlainRelocationPCRel,
353 // getPlainRelocationLength and related methods in MachOObjectFile.cpp
355 makeRelocationInfo(const MachOYAML::Relocation &R, bool IsLE) {
356  assert(!R.is_scattered && "non-scattered relocation expected");
358  MRE.r_word0 = R.address;
359  if (IsLE)
360  MRE.r_word1 = ((unsigned)R.symbolnum << 0) | ((unsigned)R.is_pcrel << 24) |
361  ((unsigned)R.length << 25) | ((unsigned)R.is_extern << 27) |
362  ((unsigned)R.type << 28);
363  else
364  MRE.r_word1 = ((unsigned)R.symbolnum << 8) | ((unsigned)R.is_pcrel << 7) |
365  ((unsigned)R.length << 5) | ((unsigned)R.is_extern << 4) |
366  ((unsigned)R.type << 0);
367  return MRE;
368 }
369 
371 makeScatteredRelocationInfo(const MachOYAML::Relocation &R) {
372  assert(R.is_scattered && "scattered relocation expected");
374  MRE.r_word0 = (((unsigned)R.address << 0) | ((unsigned)R.type << 24) |
375  ((unsigned)R.length << 28) | ((unsigned)R.is_pcrel << 30) |
377  MRE.r_word1 = R.value;
378  return MRE;
379 }
380 
381 void MachOWriter::writeRelocations(raw_ostream &OS) {
382  for (const MachOYAML::LoadCommand &LC : Obj.LoadCommands) {
383  switch (LC.Data.load_command_data.cmd) {
384  case MachO::LC_SEGMENT:
385  case MachO::LC_SEGMENT_64:
386  for (const MachOYAML::Section &Sec : LC.Sections) {
387  if (Sec.relocations.empty())
388  continue;
389  ZeroToOffset(OS, Sec.reloff);
390  for (const MachOYAML::Relocation &R : Sec.relocations) {
392  R.is_scattered ? makeScatteredRelocationInfo(R)
393  : makeRelocationInfo(R, Obj.IsLittleEndian);
395  MachO::swapStruct(MRE);
396  OS.write(reinterpret_cast<const char *>(&MRE),
398  }
399  }
400  }
401  }
402 }
403 
404 void MachOWriter::writeBindOpcodes(
405  raw_ostream &OS, std::vector<MachOYAML::BindOpcode> &BindOpcodes) {
406 
407  for (auto Opcode : BindOpcodes) {
408  uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
409  OS.write(reinterpret_cast<char *>(&OpByte), 1);
410  for (auto Data : Opcode.ULEBExtraData) {
411  encodeULEB128(Data, OS);
412  }
413  for (auto Data : Opcode.SLEBExtraData) {
414  encodeSLEB128(Data, OS);
415  }
416  if (!Opcode.Symbol.empty()) {
417  OS.write(Opcode.Symbol.data(), Opcode.Symbol.size());
418  OS.write('\0');
419  }
420  }
421 }
422 
423 void MachOWriter::dumpExportEntry(raw_ostream &OS,
424  MachOYAML::ExportEntry &Entry) {
425  encodeSLEB128(Entry.TerminalSize, OS);
426  if (Entry.TerminalSize > 0) {
427  encodeSLEB128(Entry.Flags, OS);
428  if (Entry.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
429  encodeSLEB128(Entry.Other, OS);
430  OS << Entry.ImportName;
431  OS.write('\0');
432  } else {
433  encodeSLEB128(Entry.Address, OS);
435  encodeSLEB128(Entry.Other, OS);
436  }
437  }
438  OS.write(static_cast<uint8_t>(Entry.Children.size()));
439  for (auto EE : Entry.Children) {
440  OS << EE.Name;
441  OS.write('\0');
442  encodeSLEB128(EE.NodeOffset, OS);
443  }
444  for (auto EE : Entry.Children)
445  dumpExportEntry(OS, EE);
446 }
447 
448 void MachOWriter::writeExportTrie(raw_ostream &OS) {
449  dumpExportEntry(OS, Obj.LinkEdit.ExportTrie);
450 }
451 
452 template <typename NListType>
453 void writeNListEntry(MachOYAML::NListEntry &NLE, raw_ostream &OS,
454  bool IsLittleEndian) {
455  NListType ListEntry;
456  ListEntry.n_strx = NLE.n_strx;
457  ListEntry.n_type = NLE.n_type;
458  ListEntry.n_sect = NLE.n_sect;
459  ListEntry.n_desc = NLE.n_desc;
460  ListEntry.n_value = NLE.n_value;
461 
462  if (IsLittleEndian != sys::IsLittleEndianHost)
463  MachO::swapStruct(ListEntry);
464  OS.write(reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
465 }
466 
467 void MachOWriter::writeLinkEditData(raw_ostream &OS) {
468  typedef void (MachOWriter::*writeHandler)(raw_ostream &);
469  typedef std::pair<uint64_t, writeHandler> writeOperation;
470  std::vector<writeOperation> WriteQueue;
471 
472  MachO::dyld_info_command *DyldInfoOnlyCmd = 0;
473  MachO::symtab_command *SymtabCmd = 0;
474  for (auto &LC : Obj.LoadCommands) {
475  switch (LC.Data.load_command_data.cmd) {
476  case MachO::LC_SYMTAB:
477  SymtabCmd = &LC.Data.symtab_command_data;
478  WriteQueue.push_back(
479  std::make_pair(SymtabCmd->symoff, &MachOWriter::writeNameList));
480  WriteQueue.push_back(
481  std::make_pair(SymtabCmd->stroff, &MachOWriter::writeStringTable));
482  break;
483  case MachO::LC_DYLD_INFO_ONLY:
484  DyldInfoOnlyCmd = &LC.Data.dyld_info_command_data;
485  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->rebase_off,
486  &MachOWriter::writeRebaseOpcodes));
487  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->bind_off,
488  &MachOWriter::writeBasicBindOpcodes));
489  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->weak_bind_off,
490  &MachOWriter::writeWeakBindOpcodes));
491  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->lazy_bind_off,
492  &MachOWriter::writeLazyBindOpcodes));
493  WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->export_off,
494  &MachOWriter::writeExportTrie));
495  break;
496  }
497  }
498 
499  llvm::sort(WriteQueue, [](const writeOperation &a, const writeOperation &b) {
500  return a.first < b.first;
501  });
502 
503  for (auto writeOp : WriteQueue) {
504  ZeroToOffset(OS, writeOp.first);
505  (this->*writeOp.second)(OS);
506  }
507 }
508 
509 void MachOWriter::writeRebaseOpcodes(raw_ostream &OS) {
510  MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
511 
512  for (auto Opcode : LinkEdit.RebaseOpcodes) {
513  uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
514  OS.write(reinterpret_cast<char *>(&OpByte), 1);
515  for (auto Data : Opcode.ExtraData)
516  encodeULEB128(Data, OS);
517  }
518 }
519 
520 void MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) {
521  writeBindOpcodes(OS, Obj.LinkEdit.BindOpcodes);
522 }
523 
524 void MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) {
525  writeBindOpcodes(OS, Obj.LinkEdit.WeakBindOpcodes);
526 }
527 
528 void MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) {
529  writeBindOpcodes(OS, Obj.LinkEdit.LazyBindOpcodes);
530 }
531 
532 void MachOWriter::writeNameList(raw_ostream &OS) {
533  for (auto NLE : Obj.LinkEdit.NameList) {
534  if (is64Bit)
535  writeNListEntry<MachO::nlist_64>(NLE, OS, Obj.IsLittleEndian);
536  else
537  writeNListEntry<MachO::nlist>(NLE, OS, Obj.IsLittleEndian);
538  }
539 }
540 
542  for (auto Str : Obj.LinkEdit.StringTable) {
543  OS.write(Str.data(), Str.size());
544  OS.write('\0');
545  }
546 }
547 
548 class UniversalWriter {
549 public:
550  UniversalWriter(yaml::YamlObjectFile &ObjectFile)
551  : ObjectFile(ObjectFile), fileStart(0) {}
552 
553  Error writeMachO(raw_ostream &OS);
554 
555 private:
556  void writeFatHeader(raw_ostream &OS);
557  void writeFatArchs(raw_ostream &OS);
558 
559  void ZeroToOffset(raw_ostream &OS, size_t offset);
560 
562  uint64_t fileStart;
563 };
564 
565 Error UniversalWriter::writeMachO(raw_ostream &OS) {
566  fileStart = OS.tell();
567  if (ObjectFile.MachO) {
568  MachOWriter Writer(*ObjectFile.MachO);
569  return Writer.writeMachO(OS);
570  }
571 
572  writeFatHeader(OS);
573  writeFatArchs(OS);
574 
575  auto &FatFile = *ObjectFile.FatMachO;
576  if (FatFile.FatArchs.size() < FatFile.Slices.size())
577  return createStringError(
579  "cannot write 'Slices' if not described in 'FatArches'");
580 
581  for (size_t i = 0; i < FatFile.Slices.size(); i++) {
582  ZeroToOffset(OS, FatFile.FatArchs[i].offset);
583  MachOWriter Writer(FatFile.Slices[i]);
584  if (Error Err = Writer.writeMachO(OS))
585  return Err;
586 
587  auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;
588  ZeroToOffset(OS, SliceEnd);
589  }
590 
591  return Error::success();
592 }
593 
594 void UniversalWriter::writeFatHeader(raw_ostream &OS) {
595  auto &FatFile = *ObjectFile.FatMachO;
596  MachO::fat_header header;
597  header.magic = FatFile.Header.magic;
598  header.nfat_arch = FatFile.Header.nfat_arch;
600  swapStruct(header);
601  OS.write(reinterpret_cast<const char *>(&header), sizeof(MachO::fat_header));
602 }
603 
604 template <typename FatArchType>
605 FatArchType constructFatArch(MachOYAML::FatArch &Arch) {
606  FatArchType FatArch;
607  FatArch.cputype = Arch.cputype;
608  FatArch.cpusubtype = Arch.cpusubtype;
609  FatArch.offset = Arch.offset;
610  FatArch.size = Arch.size;
611  FatArch.align = Arch.align;
612  return FatArch;
613 }
614 
615 template <typename StructType>
616 void writeFatArch(MachOYAML::FatArch &LC, raw_ostream &OS) {}
617 
618 template <>
619 void writeFatArch<MachO::fat_arch>(MachOYAML::FatArch &Arch, raw_ostream &OS) {
620  auto FatArch = constructFatArch<MachO::fat_arch>(Arch);
622  swapStruct(FatArch);
623  OS.write(reinterpret_cast<const char *>(&FatArch), sizeof(MachO::fat_arch));
624 }
625 
626 template <>
627 void writeFatArch<MachO::fat_arch_64>(MachOYAML::FatArch &Arch,
628  raw_ostream &OS) {
629  auto FatArch = constructFatArch<MachO::fat_arch_64>(Arch);
630  FatArch.reserved = Arch.reserved;
632  swapStruct(FatArch);
633  OS.write(reinterpret_cast<const char *>(&FatArch),
634  sizeof(MachO::fat_arch_64));
635 }
636 
637 void UniversalWriter::writeFatArchs(raw_ostream &OS) {
638  auto &FatFile = *ObjectFile.FatMachO;
639  bool is64Bit = FatFile.Header.magic == MachO::FAT_MAGIC_64;
640  for (auto Arch : FatFile.FatArchs) {
641  if (is64Bit)
642  writeFatArch<MachO::fat_arch_64>(Arch, OS);
643  else
644  writeFatArch<MachO::fat_arch>(Arch, OS);
645  }
646 }
647 
648 void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
649  auto currOffset = OS.tell() - fileStart;
650  if (currOffset < Offset)
651  ZeroFillBytes(OS, Offset - currOffset);
652 }
653 
654 } // end anonymous namespace
655 
656 namespace llvm {
657 namespace yaml {
658 
660  UniversalWriter Writer(Doc);
661  if (Error Err = Writer.writeMachO(Out)) {
663  [&](const ErrorInfoBase &Err) { EH(Err.message()); });
664  return false;
665  }
666  return true;
667 }
668 
669 } // namespace yaml
670 } // 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:145
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::section
Definition: MachO.h:563
llvm::MachOYAML::NListEntry::n_desc
uint16_t n_desc
Definition: MachOYAML.h:87
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
ObjectYAML.h
llvm::MachO::any_relocation_info
Definition: MachO.h:975
llvm::MachOYAML::Object
Definition: MachOYAML.h:128
llvm::MachOYAML::Section
Definition: MachOYAML.h:44
llvm::MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
@ EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
Definition: MachO.h:289
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
is64Bit
static bool is64Bit(const char *name)
Definition: X86Disassembler.cpp:1023
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::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:134
llvm::MachOYAML::Section::addr
llvm::yaml::Hex64 addr
Definition: MachOYAML.h:47
llvm::MachO::MH_CIGAM_64
@ MH_CIGAM_64
Definition: MachO.h:33
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:193
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:659
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
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:147
llvm::MachOYAML::NListEntry::n_value
uint64_t n_value
Definition: MachOYAML.h:88
llvm::MachOYAML::FatArch::cputype
llvm::yaml::Hex32 cputype
Definition: MachOYAML.h:143
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:144
llvm::MachOYAML::FileHeader::reserved
llvm::yaml::Hex32 reserved
Definition: MachOYAML.h:69
llvm::MachO::R_SCATTERED
@ R_SCATTERED
Definition: MachO.h:395
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::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:146
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: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: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::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:1231
llvm::MachO::FAT_MAGIC_64
@ FAT_MAGIC_64
Definition: MachO.h:36
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::FatArch
Definition: MachOYAML.h:142
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1490
llvm::MachO::mach_header
Definition: MachO.h:509
llvm::MachOYAML::FatArch::reserved
llvm::yaml::Hex32 reserved
Definition: MachOYAML.h:148
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::EXPORT_SYMBOL_FLAGS_REEXPORT
@ EXPORT_SYMBOL_FLAGS_REEXPORT
Definition: MachO.h:288
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::MH_MAGIC_64
@ MH_MAGIC_64
Definition: MachO.h:32
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:958
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
llvm::MachO::SECTION_TYPE
@ SECTION_TYPE
Definition: MachO.h:112