LLVM  15.0.0git
MachOWriter.cpp
Go to the documentation of this file.
1 //===- MachOWriter.cpp ------------------------------------------*- C++ -*-===//
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 #include "MachOWriter.h"
10 #include "MachOLayoutBuilder.h"
11 #include "MachOObject.h"
12 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/Object/MachO.h"
15 #include "llvm/Support/Errc.h"
17 #include "llvm/Support/SHA256.h"
18 #include <memory>
19 
20 #if defined(__APPLE__)
21 #include <sys/mman.h>
22 #endif
23 
24 using namespace llvm;
25 using namespace llvm::objcopy::macho;
26 using namespace llvm::support::endian;
27 
28 size_t MachOWriter::headerSize() const {
29  return Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
30 }
31 
32 size_t MachOWriter::loadCommandsSize() const { return O.Header.SizeOfCmds; }
33 
34 size_t MachOWriter::symTableSize() const {
35  return O.SymTable.Symbols.size() *
36  (Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist));
37 }
38 
39 size_t MachOWriter::totalSize() const {
40  // Going from tail to head and looking for an appropriate "anchor" to
41  // calculate the total size assuming that all the offsets are either valid
42  // ("true") or 0 (0 indicates that the corresponding part is missing).
43 
45  if (O.SymTabCommandIndex) {
46  const MachO::symtab_command &SymTabCommand =
47  O.LoadCommands[*O.SymTabCommandIndex]
48  .MachOLoadCommand.symtab_command_data;
49  if (SymTabCommand.symoff)
50  Ends.push_back(SymTabCommand.symoff + symTableSize());
51  if (SymTabCommand.stroff)
52  Ends.push_back(SymTabCommand.stroff + SymTabCommand.strsize);
53  }
54  if (O.DyLdInfoCommandIndex) {
55  const MachO::dyld_info_command &DyLdInfoCommand =
56  O.LoadCommands[*O.DyLdInfoCommandIndex]
57  .MachOLoadCommand.dyld_info_command_data;
58  if (DyLdInfoCommand.rebase_off) {
59  assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
60  "Incorrect rebase opcodes size");
61  Ends.push_back(DyLdInfoCommand.rebase_off + DyLdInfoCommand.rebase_size);
62  }
63  if (DyLdInfoCommand.bind_off) {
64  assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
65  "Incorrect bind opcodes size");
66  Ends.push_back(DyLdInfoCommand.bind_off + DyLdInfoCommand.bind_size);
67  }
68  if (DyLdInfoCommand.weak_bind_off) {
69  assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
70  "Incorrect weak bind opcodes size");
71  Ends.push_back(DyLdInfoCommand.weak_bind_off +
72  DyLdInfoCommand.weak_bind_size);
73  }
74  if (DyLdInfoCommand.lazy_bind_off) {
75  assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
76  "Incorrect lazy bind opcodes size");
77  Ends.push_back(DyLdInfoCommand.lazy_bind_off +
78  DyLdInfoCommand.lazy_bind_size);
79  }
80  if (DyLdInfoCommand.export_off) {
81  assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
82  "Incorrect trie size");
83  Ends.push_back(DyLdInfoCommand.export_off + DyLdInfoCommand.export_size);
84  }
85  }
86 
87  if (O.DySymTabCommandIndex) {
88  const MachO::dysymtab_command &DySymTabCommand =
89  O.LoadCommands[*O.DySymTabCommandIndex]
90  .MachOLoadCommand.dysymtab_command_data;
91 
92  if (DySymTabCommand.indirectsymoff)
93  Ends.push_back(DySymTabCommand.indirectsymoff +
94  sizeof(uint32_t) * O.IndirectSymTable.Symbols.size());
95  }
96 
97  for (Optional<size_t> LinkEditDataCommandIndex :
98  {O.CodeSignatureCommandIndex, O.DataInCodeCommandIndex,
99  O.LinkerOptimizationHintCommandIndex, O.FunctionStartsCommandIndex,
100  O.ChainedFixupsCommandIndex, O.ExportsTrieCommandIndex})
101  if (LinkEditDataCommandIndex) {
102  const MachO::linkedit_data_command &LinkEditDataCommand =
103  O.LoadCommands[*LinkEditDataCommandIndex]
104  .MachOLoadCommand.linkedit_data_command_data;
105  if (LinkEditDataCommand.dataoff)
106  Ends.push_back(LinkEditDataCommand.dataoff +
107  LinkEditDataCommand.datasize);
108  }
109 
110  // Otherwise, use the last section / reloction.
111  for (const LoadCommand &LC : O.LoadCommands)
112  for (const std::unique_ptr<Section> &S : LC.Sections) {
113  if (!S->hasValidOffset()) {
114  assert((S->Offset == 0) && "Skipped section's offset must be zero");
115  assert((S->isVirtualSection() || S->Size == 0) &&
116  "Non-zero-fill sections with zero offset must have zero size");
117  continue;
118  }
119  assert((S->Offset != 0) &&
120  "Non-zero-fill section's offset cannot be zero");
121  Ends.push_back(S->Offset + S->Size);
122  if (S->RelOff)
123  Ends.push_back(S->RelOff +
124  S->NReloc * sizeof(MachO::any_relocation_info));
125  }
126 
127  if (!Ends.empty())
128  return *std::max_element(Ends.begin(), Ends.end());
129 
130  // Otherwise, we have only Mach header and load commands.
131  return headerSize() + loadCommandsSize();
132 }
133 
134 void MachOWriter::writeHeader() {
135  MachO::mach_header_64 Header;
136 
137  Header.magic = O.Header.Magic;
138  Header.cputype = O.Header.CPUType;
139  Header.cpusubtype = O.Header.CPUSubType;
140  Header.filetype = O.Header.FileType;
141  Header.ncmds = O.Header.NCmds;
142  Header.sizeofcmds = O.Header.SizeOfCmds;
143  Header.flags = O.Header.Flags;
144  Header.reserved = O.Header.Reserved;
145 
146  if (IsLittleEndian != sys::IsLittleEndianHost)
147  MachO::swapStruct(Header);
148 
149  auto HeaderSize =
150  Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
151  memcpy(Buf->getBufferStart(), &Header, HeaderSize);
152 }
153 
154 void MachOWriter::writeLoadCommands() {
155  uint8_t *Begin =
156  reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + headerSize();
157  for (const LoadCommand &LC : O.LoadCommands) {
158  // Construct a load command.
160  switch (MLC.load_command_data.cmd) {
161  case MachO::LC_SEGMENT:
162  if (IsLittleEndian != sys::IsLittleEndianHost)
163  MachO::swapStruct(MLC.segment_command_data);
164  memcpy(Begin, &MLC.segment_command_data, sizeof(MachO::segment_command));
165  Begin += sizeof(MachO::segment_command);
166 
167  for (const std::unique_ptr<Section> &Sec : LC.Sections)
168  writeSectionInLoadCommand<MachO::section>(*Sec, Begin);
169  continue;
170  case MachO::LC_SEGMENT_64:
171  if (IsLittleEndian != sys::IsLittleEndianHost)
172  MachO::swapStruct(MLC.segment_command_64_data);
173  memcpy(Begin, &MLC.segment_command_64_data,
174  sizeof(MachO::segment_command_64));
175  Begin += sizeof(MachO::segment_command_64);
176 
177  for (const std::unique_ptr<Section> &Sec : LC.Sections)
178  writeSectionInLoadCommand<MachO::section_64>(*Sec, Begin);
179  continue;
180  }
181 
182 #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
183  case MachO::LCName: \
184  assert(sizeof(MachO::LCStruct) + LC.Payload.size() == \
185  MLC.load_command_data.cmdsize); \
186  if (IsLittleEndian != sys::IsLittleEndianHost) \
187  MachO::swapStruct(MLC.LCStruct##_data); \
188  memcpy(Begin, &MLC.LCStruct##_data, sizeof(MachO::LCStruct)); \
189  Begin += sizeof(MachO::LCStruct); \
190  if (!LC.Payload.empty()) \
191  memcpy(Begin, LC.Payload.data(), LC.Payload.size()); \
192  Begin += LC.Payload.size(); \
193  break;
194 
195  // Copy the load command as it is.
196  switch (MLC.load_command_data.cmd) {
197  default:
198  assert(sizeof(MachO::load_command) + LC.Payload.size() ==
199  MLC.load_command_data.cmdsize);
200  if (IsLittleEndian != sys::IsLittleEndianHost)
201  MachO::swapStruct(MLC.load_command_data);
202  memcpy(Begin, &MLC.load_command_data, sizeof(MachO::load_command));
203  Begin += sizeof(MachO::load_command);
204  if (!LC.Payload.empty())
205  memcpy(Begin, LC.Payload.data(), LC.Payload.size());
206  Begin += LC.Payload.size();
207  break;
208 #include "llvm/BinaryFormat/MachO.def"
209  }
210  }
211 }
212 
213 template <typename StructType>
214 void MachOWriter::writeSectionInLoadCommand(const Section &Sec, uint8_t *&Out) {
215  StructType Temp;
216  assert(Sec.Segname.size() <= sizeof(Temp.segname) && "too long segment name");
217  assert(Sec.Sectname.size() <= sizeof(Temp.sectname) &&
218  "too long section name");
219  memset(&Temp, 0, sizeof(StructType));
220  memcpy(Temp.segname, Sec.Segname.data(), Sec.Segname.size());
221  memcpy(Temp.sectname, Sec.Sectname.data(), Sec.Sectname.size());
222  Temp.addr = Sec.Addr;
223  Temp.size = Sec.Size;
224  Temp.offset = Sec.Offset;
225  Temp.align = Sec.Align;
226  Temp.reloff = Sec.RelOff;
227  Temp.nreloc = Sec.NReloc;
228  Temp.flags = Sec.Flags;
229  Temp.reserved1 = Sec.Reserved1;
230  Temp.reserved2 = Sec.Reserved2;
231 
232  if (IsLittleEndian != sys::IsLittleEndianHost)
233  MachO::swapStruct(Temp);
234  memcpy(Out, &Temp, sizeof(StructType));
235  Out += sizeof(StructType);
236 }
237 
238 void MachOWriter::writeSections() {
239  for (const LoadCommand &LC : O.LoadCommands)
240  for (const std::unique_ptr<Section> &Sec : LC.Sections) {
241  if (!Sec->hasValidOffset()) {
242  assert((Sec->Offset == 0) && "Skipped section's offset must be zero");
243  assert((Sec->isVirtualSection() || Sec->Size == 0) &&
244  "Non-zero-fill sections with zero offset must have zero size");
245  continue;
246  }
247 
248  assert(Sec->Offset && "Section offset can not be zero");
249  assert((Sec->Size == Sec->Content.size()) && "Incorrect section size");
250  memcpy(Buf->getBufferStart() + Sec->Offset, Sec->Content.data(),
251  Sec->Content.size());
252  for (size_t Index = 0; Index < Sec->Relocations.size(); ++Index) {
253  RelocationInfo RelocInfo = Sec->Relocations[Index];
254  if (!RelocInfo.Scattered && !RelocInfo.IsAddend) {
255  const uint32_t SymbolNum = RelocInfo.Extern
256  ? (*RelocInfo.Symbol)->Index
257  : (*RelocInfo.Sec)->Index;
258  RelocInfo.setPlainRelocationSymbolNum(SymbolNum, IsLittleEndian);
259  }
260  if (IsLittleEndian != sys::IsLittleEndianHost)
262  reinterpret_cast<MachO::any_relocation_info &>(RelocInfo.Info));
263  memcpy(Buf->getBufferStart() + Sec->RelOff +
265  &RelocInfo.Info, sizeof(RelocInfo.Info));
266  }
267  }
268 }
269 
270 template <typename NListType>
271 void writeNListEntry(const SymbolEntry &SE, bool IsLittleEndian, char *&Out,
272  uint32_t Nstrx) {
273  NListType ListEntry;
274  ListEntry.n_strx = Nstrx;
275  ListEntry.n_type = SE.n_type;
276  ListEntry.n_sect = SE.n_sect;
277  ListEntry.n_desc = SE.n_desc;
278  ListEntry.n_value = SE.n_value;
279 
280  if (IsLittleEndian != sys::IsLittleEndianHost)
281  MachO::swapStruct(ListEntry);
282  memcpy(Out, reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
283  Out += sizeof(NListType);
284 }
285 
286 void MachOWriter::writeStringTable() {
287  if (!O.SymTabCommandIndex)
288  return;
289  const MachO::symtab_command &SymTabCommand =
290  O.LoadCommands[*O.SymTabCommandIndex]
291  .MachOLoadCommand.symtab_command_data;
292 
293  uint8_t *StrTable = (uint8_t *)Buf->getBufferStart() + SymTabCommand.stroff;
294  LayoutBuilder.getStringTableBuilder().write(StrTable);
295 }
296 
297 void MachOWriter::writeSymbolTable() {
298  if (!O.SymTabCommandIndex)
299  return;
300  const MachO::symtab_command &SymTabCommand =
301  O.LoadCommands[*O.SymTabCommandIndex]
302  .MachOLoadCommand.symtab_command_data;
303 
304  char *SymTable = (char *)Buf->getBufferStart() + SymTabCommand.symoff;
305  for (auto Iter = O.SymTable.Symbols.begin(), End = O.SymTable.Symbols.end();
306  Iter != End; Iter++) {
307  SymbolEntry *Sym = Iter->get();
308  uint32_t Nstrx = LayoutBuilder.getStringTableBuilder().getOffset(Sym->Name);
309 
310  if (Is64Bit)
311  writeNListEntry<MachO::nlist_64>(*Sym, IsLittleEndian, SymTable, Nstrx);
312  else
313  writeNListEntry<MachO::nlist>(*Sym, IsLittleEndian, SymTable, Nstrx);
314  }
315 }
316 
317 void MachOWriter::writeRebaseInfo() {
318  if (!O.DyLdInfoCommandIndex)
319  return;
320  const MachO::dyld_info_command &DyLdInfoCommand =
321  O.LoadCommands[*O.DyLdInfoCommandIndex]
322  .MachOLoadCommand.dyld_info_command_data;
323  char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.rebase_off;
324  assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
325  "Incorrect rebase opcodes size");
326  memcpy(Out, O.Rebases.Opcodes.data(), O.Rebases.Opcodes.size());
327 }
328 
329 void MachOWriter::writeBindInfo() {
330  if (!O.DyLdInfoCommandIndex)
331  return;
332  const MachO::dyld_info_command &DyLdInfoCommand =
333  O.LoadCommands[*O.DyLdInfoCommandIndex]
334  .MachOLoadCommand.dyld_info_command_data;
335  char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.bind_off;
336  assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
337  "Incorrect bind opcodes size");
338  memcpy(Out, O.Binds.Opcodes.data(), O.Binds.Opcodes.size());
339 }
340 
341 void MachOWriter::writeWeakBindInfo() {
342  if (!O.DyLdInfoCommandIndex)
343  return;
344  const MachO::dyld_info_command &DyLdInfoCommand =
345  O.LoadCommands[*O.DyLdInfoCommandIndex]
346  .MachOLoadCommand.dyld_info_command_data;
347  char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.weak_bind_off;
348  assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
349  "Incorrect weak bind opcodes size");
350  memcpy(Out, O.WeakBinds.Opcodes.data(), O.WeakBinds.Opcodes.size());
351 }
352 
353 void MachOWriter::writeLazyBindInfo() {
354  if (!O.DyLdInfoCommandIndex)
355  return;
356  const MachO::dyld_info_command &DyLdInfoCommand =
357  O.LoadCommands[*O.DyLdInfoCommandIndex]
358  .MachOLoadCommand.dyld_info_command_data;
359  char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.lazy_bind_off;
360  assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
361  "Incorrect lazy bind opcodes size");
362  memcpy(Out, O.LazyBinds.Opcodes.data(), O.LazyBinds.Opcodes.size());
363 }
364 
365 void MachOWriter::writeExportInfo() {
366  if (!O.DyLdInfoCommandIndex)
367  return;
368  const MachO::dyld_info_command &DyLdInfoCommand =
369  O.LoadCommands[*O.DyLdInfoCommandIndex]
370  .MachOLoadCommand.dyld_info_command_data;
371  char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.export_off;
372  assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
373  "Incorrect export trie size");
374  memcpy(Out, O.Exports.Trie.data(), O.Exports.Trie.size());
375 }
376 
377 void MachOWriter::writeIndirectSymbolTable() {
378  if (!O.DySymTabCommandIndex)
379  return;
380 
381  const MachO::dysymtab_command &DySymTabCommand =
382  O.LoadCommands[*O.DySymTabCommandIndex]
383  .MachOLoadCommand.dysymtab_command_data;
384 
385  uint32_t *Out =
386  (uint32_t *)(Buf->getBufferStart() + DySymTabCommand.indirectsymoff);
387  for (const IndirectSymbolEntry &Sym : O.IndirectSymTable.Symbols) {
388  uint32_t Entry = (Sym.Symbol) ? (*Sym.Symbol)->Index : Sym.OriginalIndex;
389  if (IsLittleEndian != sys::IsLittleEndianHost)
390  sys::swapByteOrder(Entry);
391  *Out++ = Entry;
392  }
393 }
394 
395 void MachOWriter::writeLinkData(Optional<size_t> LCIndex, const LinkData &LD) {
396  if (!LCIndex)
397  return;
398  const MachO::linkedit_data_command &LinkEditDataCommand =
399  O.LoadCommands[*LCIndex].MachOLoadCommand.linkedit_data_command_data;
400  char *Out = (char *)Buf->getBufferStart() + LinkEditDataCommand.dataoff;
401  assert((LinkEditDataCommand.datasize == LD.Data.size()) &&
402  "Incorrect data size");
403  memcpy(Out, LD.Data.data(), LD.Data.size());
404 }
405 
406 static uint64_t
407 getSegmentFileOffset(const LoadCommand &TextSegmentLoadCommand) {
408  const MachO::macho_load_command &MLC =
409  TextSegmentLoadCommand.MachOLoadCommand;
410  switch (MLC.load_command_data.cmd) {
411  case MachO::LC_SEGMENT:
412  return MLC.segment_command_data.fileoff;
413  case MachO::LC_SEGMENT_64:
414  return MLC.segment_command_64_data.fileoff;
415  default:
416  return 0;
417  }
418 }
419 
420 static uint64_t getSegmentFileSize(const LoadCommand &TextSegmentLoadCommand) {
421  const MachO::macho_load_command &MLC =
422  TextSegmentLoadCommand.MachOLoadCommand;
423  switch (MLC.load_command_data.cmd) {
424  case MachO::LC_SEGMENT:
425  return MLC.segment_command_data.filesize;
426  case MachO::LC_SEGMENT_64:
427  return MLC.segment_command_64_data.filesize;
428  default:
429  return 0;
430  }
431 }
432 
433 void MachOWriter::writeCodeSignatureData() {
434  // NOTE: This CodeSignature section behaviour must be kept in sync with that
435  // performed in LLD's CodeSignatureSection::write /
436  // CodeSignatureSection::writeHashes. Furthermore, this call must occur only
437  // after the rest of the binary has already been written to the buffer. This
438  // is because the buffer is read from to perform the necessary hashing.
439 
440  // The CodeSignature section is the last section in the MachO binary and
441  // contains a hash of all content in the binary before it. Since llvm-objcopy
442  // has likely modified the target binary, the hash must be regenerated
443  // entirely. To generate this hash, we must read from the start of the binary
444  // (HashReadStart) to just before the start of the CodeSignature section
445  // (HashReadEnd).
446 
447  const CodeSignatureInfo &CodeSignature = LayoutBuilder.getCodeSignature();
448 
449  uint8_t *BufferStart = reinterpret_cast<uint8_t *>(Buf->getBufferStart());
450  uint8_t *HashReadStart = BufferStart;
451  uint8_t *HashReadEnd = BufferStart + CodeSignature.StartOffset;
452 
453  // The CodeSignature section begins with a header, after which the hashes
454  // of each page of the binary are written.
455  uint8_t *HashWriteStart = HashReadEnd + CodeSignature.AllHeadersSize;
456 
457  uint32_t TextSegmentFileOff = 0;
458  uint32_t TextSegmentFileSize = 0;
459  if (O.TextSegmentCommandIndex) {
460  const LoadCommand &TextSegmentLoadCommand =
461  O.LoadCommands[*O.TextSegmentCommandIndex];
462  assert(TextSegmentLoadCommand.MachOLoadCommand.load_command_data.cmd ==
463  MachO::LC_SEGMENT ||
464  TextSegmentLoadCommand.MachOLoadCommand.load_command_data.cmd ==
465  MachO::LC_SEGMENT_64);
466  assert(StringRef(TextSegmentLoadCommand.MachOLoadCommand
467  .segment_command_data.segname) == "__TEXT");
468  TextSegmentFileOff = getSegmentFileOffset(TextSegmentLoadCommand);
469  TextSegmentFileSize = getSegmentFileSize(TextSegmentLoadCommand);
470  }
471 
472  const uint32_t FileNamePad = CodeSignature.AllHeadersSize -
473  CodeSignature.FixedHeadersSize -
474  CodeSignature.OutputFileName.size();
475 
476  // Write code section header.
477  auto *SuperBlob = reinterpret_cast<MachO::CS_SuperBlob *>(HashReadEnd);
478  write32be(&SuperBlob->magic, MachO::CSMAGIC_EMBEDDED_SIGNATURE);
479  write32be(&SuperBlob->length, CodeSignature.Size);
480  write32be(&SuperBlob->count, 1);
481  auto *BlobIndex = reinterpret_cast<MachO::CS_BlobIndex *>(&SuperBlob[1]);
482  write32be(&BlobIndex->type, MachO::CSSLOT_CODEDIRECTORY);
483  write32be(&BlobIndex->offset, CodeSignature.BlobHeadersSize);
484  auto *CodeDirectory = reinterpret_cast<MachO::CS_CodeDirectory *>(
485  HashReadEnd + CodeSignature.BlobHeadersSize);
486  write32be(&CodeDirectory->magic, MachO::CSMAGIC_CODEDIRECTORY);
487  write32be(&CodeDirectory->length,
488  CodeSignature.Size - CodeSignature.BlobHeadersSize);
489  write32be(&CodeDirectory->version, MachO::CS_SUPPORTSEXECSEG);
490  write32be(&CodeDirectory->flags, MachO::CS_ADHOC | MachO::CS_LINKER_SIGNED);
491  write32be(&CodeDirectory->hashOffset,
492  sizeof(MachO::CS_CodeDirectory) +
493  CodeSignature.OutputFileName.size() + FileNamePad);
494  write32be(&CodeDirectory->identOffset, sizeof(MachO::CS_CodeDirectory));
495  CodeDirectory->nSpecialSlots = 0;
496  write32be(&CodeDirectory->nCodeSlots, CodeSignature.BlockCount);
497  write32be(&CodeDirectory->codeLimit, CodeSignature.StartOffset);
498  CodeDirectory->hashSize = static_cast<uint8_t>(CodeSignature.HashSize);
499  CodeDirectory->hashType = MachO::kSecCodeSignatureHashSHA256;
500  CodeDirectory->platform = 0;
501  CodeDirectory->pageSize = CodeSignature.BlockSizeShift;
502  CodeDirectory->spare2 = 0;
503  CodeDirectory->scatterOffset = 0;
504  CodeDirectory->teamOffset = 0;
505  CodeDirectory->spare3 = 0;
506  CodeDirectory->codeLimit64 = 0;
507  write64be(&CodeDirectory->execSegBase, TextSegmentFileOff);
508  write64be(&CodeDirectory->execSegLimit, TextSegmentFileSize);
509  write64be(&CodeDirectory->execSegFlags, O.Header.FileType == MachO::MH_EXECUTE
511  : 0);
512 
513  auto *Id = reinterpret_cast<char *>(&CodeDirectory[1]);
514  memcpy(Id, CodeSignature.OutputFileName.begin(),
515  CodeSignature.OutputFileName.size());
516  memset(Id + CodeSignature.OutputFileName.size(), 0, FileNamePad);
517 
518  // Write the hashes.
519  uint8_t *CurrHashReadPosition = HashReadStart;
520  uint8_t *CurrHashWritePosition = HashWriteStart;
521  while (CurrHashReadPosition < HashReadEnd) {
522  StringRef Block(reinterpret_cast<char *>(CurrHashReadPosition),
523  std::min(static_cast<size_t>(HashReadEnd
524  - CurrHashReadPosition),
525  static_cast<size_t>(CodeSignature.BlockSize)));
526  SHA256 Hasher;
527  Hasher.update(Block);
528  std::array<uint8_t, 32> Hash = Hasher.final();
529  assert(Hash.size() == CodeSignature.HashSize);
530  memcpy(CurrHashWritePosition, Hash.data(), CodeSignature.HashSize);
531  CurrHashReadPosition += CodeSignature.BlockSize;
532  CurrHashWritePosition += CodeSignature.HashSize;
533  }
534 #if defined(__APPLE__)
535  // This is macOS-specific work-around and makes no sense for any
536  // other host OS. See https://openradar.appspot.com/FB8914231
537  //
538  // The macOS kernel maintains a signature-verification cache to
539  // quickly validate applications at time of execve(2). The trouble
540  // is that for the kernel creates the cache entry at the time of the
541  // mmap(2) call, before we have a chance to write either the code to
542  // sign or the signature header+hashes. The fix is to invalidate
543  // all cached data associated with the output file, thus discarding
544  // the bogus prematurely-cached signature.
545  msync(BufferStart, CodeSignature.StartOffset + CodeSignature.Size,
546  MS_INVALIDATE);
547 #endif
548 }
549 
550 void MachOWriter::writeDataInCodeData() {
551  return writeLinkData(O.DataInCodeCommandIndex, O.DataInCode);
552 }
553 
554 void MachOWriter::writeLinkerOptimizationHint() {
555  return writeLinkData(O.LinkerOptimizationHintCommandIndex,
556  O.LinkerOptimizationHint);
557 }
558 
559 void MachOWriter::writeFunctionStartsData() {
560  return writeLinkData(O.FunctionStartsCommandIndex, O.FunctionStarts);
561 }
562 
563 void MachOWriter::writeChainedFixupsData() {
564  return writeLinkData(O.ChainedFixupsCommandIndex, O.ChainedFixups);
565 }
566 
567 void MachOWriter::writeExportsTrieData() {
568  return writeLinkData(O.ExportsTrieCommandIndex, O.ExportsTrie);
569 }
570 
571 void MachOWriter::writeTail() {
572  typedef void (MachOWriter::*WriteHandlerType)();
573  typedef std::pair<uint64_t, WriteHandlerType> WriteOperation;
575 
576  if (O.SymTabCommandIndex) {
577  const MachO::symtab_command &SymTabCommand =
578  O.LoadCommands[*O.SymTabCommandIndex]
579  .MachOLoadCommand.symtab_command_data;
580  if (SymTabCommand.symoff)
581  Queue.push_back({SymTabCommand.symoff, &MachOWriter::writeSymbolTable});
582  if (SymTabCommand.stroff)
583  Queue.push_back({SymTabCommand.stroff, &MachOWriter::writeStringTable});
584  }
585 
586  if (O.DyLdInfoCommandIndex) {
587  const MachO::dyld_info_command &DyLdInfoCommand =
588  O.LoadCommands[*O.DyLdInfoCommandIndex]
589  .MachOLoadCommand.dyld_info_command_data;
590  if (DyLdInfoCommand.rebase_off)
591  Queue.push_back(
592  {DyLdInfoCommand.rebase_off, &MachOWriter::writeRebaseInfo});
593  if (DyLdInfoCommand.bind_off)
594  Queue.push_back({DyLdInfoCommand.bind_off, &MachOWriter::writeBindInfo});
595  if (DyLdInfoCommand.weak_bind_off)
596  Queue.push_back(
597  {DyLdInfoCommand.weak_bind_off, &MachOWriter::writeWeakBindInfo});
598  if (DyLdInfoCommand.lazy_bind_off)
599  Queue.push_back(
600  {DyLdInfoCommand.lazy_bind_off, &MachOWriter::writeLazyBindInfo});
601  if (DyLdInfoCommand.export_off)
602  Queue.push_back(
603  {DyLdInfoCommand.export_off, &MachOWriter::writeExportInfo});
604  }
605 
606  if (O.DySymTabCommandIndex) {
607  const MachO::dysymtab_command &DySymTabCommand =
608  O.LoadCommands[*O.DySymTabCommandIndex]
609  .MachOLoadCommand.dysymtab_command_data;
610 
611  if (DySymTabCommand.indirectsymoff)
612  Queue.emplace_back(DySymTabCommand.indirectsymoff,
613  &MachOWriter::writeIndirectSymbolTable);
614  }
615 
616  std::initializer_list<std::pair<Optional<size_t>, WriteHandlerType>>
617  LinkEditDataCommandWriters = {
618  {O.CodeSignatureCommandIndex, &MachOWriter::writeCodeSignatureData},
619  {O.DataInCodeCommandIndex, &MachOWriter::writeDataInCodeData},
620  {O.LinkerOptimizationHintCommandIndex,
621  &MachOWriter::writeLinkerOptimizationHint},
622  {O.FunctionStartsCommandIndex, &MachOWriter::writeFunctionStartsData},
623  {O.ChainedFixupsCommandIndex, &MachOWriter::writeChainedFixupsData},
624  {O.ExportsTrieCommandIndex, &MachOWriter::writeExportsTrieData}};
625  for (const auto &W : LinkEditDataCommandWriters) {
626  Optional<size_t> LinkEditDataCommandIndex;
627  WriteHandlerType WriteHandler;
628  std::tie(LinkEditDataCommandIndex, WriteHandler) = W;
629  if (LinkEditDataCommandIndex) {
630  const MachO::linkedit_data_command &LinkEditDataCommand =
631  O.LoadCommands[*LinkEditDataCommandIndex]
632  .MachOLoadCommand.linkedit_data_command_data;
633  if (LinkEditDataCommand.dataoff)
634  Queue.emplace_back(LinkEditDataCommand.dataoff, WriteHandler);
635  }
636  }
637 
638  llvm::sort(Queue, llvm::less_first());
639 
640  for (auto WriteOp : Queue)
641  (this->*WriteOp.second)();
642 }
643 
644 Error MachOWriter::finalize() { return LayoutBuilder.layout(); }
645 
647  size_t TotalSize = totalSize();
648  Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
649  if (!Buf)
651  "failed to allocate memory buffer of " +
652  Twine::utohexstr(TotalSize) + " bytes");
653  writeHeader();
654  writeLoadCommands();
655  writeSections();
656  writeTail();
657 
658  // TODO: Implement direct writing to the output stream (without intermediate
659  // memory buffer Buf).
660  Out.write(Buf->getBufferStart(), Buf->getBufferSize());
661  return Error::success();
662 }
llvm::MachO::CSMAGIC_CODEDIRECTORY
@ CSMAGIC_CODEDIRECTORY
Definition: MachO.h:2123
llvm::objcopy::macho::RelocationInfo::Symbol
Optional< const SymbolEntry * > Symbol
Definition: MachOObject.h:178
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::MachO::any_relocation_info
Definition: MachO.h:977
llvm::MachO::CS_EXECSEG_MAIN_BINARY
@ CS_EXECSEG_MAIN_BINARY
Definition: MachO.h:2107
llvm::sys::swapByteOrder
void swapByteOrder(T &Value)
Definition: SwapByteOrder.h:158
llvm::MachO::mach_header_64::flags
uint32_t flags
Definition: MachO.h:528
llvm::BTF::HeaderSize
@ HeaderSize
Definition: BTF.h:58
llvm::support::endian::write32be
void write32be(void *P, uint32_t V)
Definition: Endian.h:419
llvm::MachO::nlist
Definition: MachO.h:989
MachOWriter.h
llvm::MachO::symtab_command::strsize
uint32_t strsize
Definition: MachO.h:701
llvm::ARM_MB::LD
@ LD
Definition: ARMBaseInfo.h:72
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1185
llvm::RISCVFenceField::W
@ W
Definition: RISCVBaseInfo.h:242
llvm::SHA256
Definition: SHA256.h:33
ErrorHandling.h
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::MachO::MH_EXECUTE
@ MH_EXECUTE
Definition: MachO.h:44
llvm::objcopy::macho::Section::Reserved1
uint32_t Reserved1
Definition: MachOObject.h:54
llvm::MachO::dysymtab_command::indirectsymoff
uint32_t indirectsymoff
Definition: MachO.h:719
llvm::objcopy::macho::Section::NReloc
uint32_t NReloc
Definition: MachOObject.h:52
llvm::objcopy::macho::IndirectSymbolEntry::Symbol
Optional< SymbolEntry * > Symbol
The Symbol referenced by this entry.
Definition: MachOObject.h:160
Errc.h
llvm::MachO::symtab_command
Definition: MachO.h:695
llvm::objcopy::macho::RelocationInfo
Definition: MachOObject.h:176
llvm::Optional< size_t >
llvm::MachO::dyld_info_command::export_off
uint32_t export_off
Definition: MachO.h:878
llvm::objcopy::macho
Definition: MachOObjcopy.h:26
llvm::MachO::mach_header_64::ncmds
uint32_t ncmds
Definition: MachO.h:526
STLExtras.h
llvm::objcopy::macho::CodeSignatureInfo::BlockCount
uint32_t BlockCount
Definition: MachOLayoutBuilder.h:49
llvm::objcopy::macho::SymbolEntry::n_type
uint8_t n_type
Definition: MachOObject.h:114
llvm::AMDGPU::HSAMD::ValueKind::Queue
@ Queue
llvm::objcopy::macho::RelocationInfo::Info
MachO::any_relocation_info Info
Definition: MachOObject.h:188
llvm::objcopy::macho::IndirectSymbolEntry::OriginalIndex
uint32_t OriginalIndex
Definition: MachOObject.h:157
llvm::objcopy::macho::CodeSignatureInfo::BlockSizeShift
static constexpr uint8_t BlockSizeShift
Definition: MachOLayoutBuilder.h:30
llvm::objcopy::macho::Section::Sectname
std::string Sectname
Definition: MachOObject.h:42
MachO.h
llvm::MachO::dyld_info_command
Definition: MachO.h:867
llvm::support::endian
Definition: Endian.h:42
llvm::objcopy::macho::RelocationInfo::Extern
bool Extern
Definition: MachOObject.h:187
llvm::objcopy::macho::IndirectSymbolEntry
Definition: MachOObject.h:154
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::MachO::CS_BlobIndex
Definition: MachO.h:2218
llvm::objcopy::macho::LoadCommand
Definition: MachOObject.h:84
llvm::objcopy::macho::LinkData
Definition: MachOObject.h:298
llvm::MachO::CS_SUPPORTSEXECSEG
@ CS_SUPPORTSEXECSEG
Definition: MachO.h:2134
llvm::objcopy::macho::CodeSignatureInfo::Size
uint32_t Size
Definition: MachOLayoutBuilder.h:53
llvm::dwarf::Index
Index
Definition: Dwarf.h:472
llvm::objcopy::macho::SymbolEntry::Name
std::string Name
Definition: MachOObject.h:111
llvm::MachO::mach_header_64::reserved
uint32_t reserved
Definition: MachO.h:529
llvm::MachO::linkedit_data_command
Definition: MachO.h:800
llvm::MachO::kSecCodeSignatureHashSHA256
@ kSecCodeSignatureHashSHA256
Definition: MachO.h:2233
llvm::objcopy::macho::SymbolEntry::n_sect
uint8_t n_sect
Definition: MachOObject.h:115
llvm::objcopy::macho::Section::Size
uint64_t Size
Definition: MachOObject.h:46
getSegmentFileOffset
static uint64_t getSegmentFileOffset(const LoadCommand &TextSegmentLoadCommand)
Definition: MachOWriter.cpp:407
llvm::WritableMemoryBuffer::getNewMemBuffer
static std::unique_ptr< WritableMemoryBuffer > getNewMemBuffer(size_t Size, const Twine &BufferName="")
Allocate a new zero-initialized MemoryBuffer of the specified size.
Definition: MemoryBuffer.cpp:310
llvm::MachO::CS_LINKER_SIGNED
@ CS_LINKER_SIGNED
Definition: MachO.h:2070
llvm::MachO::mach_header_64::magic
uint32_t magic
Definition: MachO.h:522
llvm::objcopy::macho::SymbolEntry::n_desc
uint16_t n_desc
Definition: MachOObject.h:116
llvm::objcopy::macho::CodeSignatureInfo::StartOffset
uint32_t StartOffset
Definition: MachOLayoutBuilder.h:45
llvm::MachO::mach_header_64
Definition: MachO.h:521
llvm::errc::not_enough_memory
@ not_enough_memory
SHA256.h
llvm::objcopy::macho::LoadCommand::Sections
std::vector< std::unique_ptr< Section > > Sections
Definition: MachOObject.h:99
llvm::objcopy::macho::CodeSignatureInfo::FixedHeadersSize
static constexpr uint32_t FixedHeadersSize
Definition: MachOLayoutBuilder.h:40
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:240
llvm::MachO::linkedit_data_command::datasize
uint32_t datasize
Definition: MachO.h:804
llvm::objcopy::macho::Section::Addr
uint64_t Addr
Definition: MachOObject.h:45
llvm::Twine::utohexstr
static Twine utohexstr(const uint64_t &Val)
Definition: Twine.h:408
llvm::objcopy::macho::MachOWriter
Definition: MachOWriter.h:24
llvm::objcopy::macho::Section::Segname
std::string Segname
Definition: MachOObject.h:41
uint64_t
llvm::objcopy::macho::LoadCommand::MachOLoadCommand
MachO::macho_load_command MachOLoadCommand
Definition: MachOObject.h:88
llvm::MachO::CS_ADHOC
@ CS_ADHOC
Definition: MachO.h:2047
llvm::MachO::dyld_info_command::weak_bind_size
uint32_t weak_bind_size
Definition: MachO.h:875
llvm::MachO::dyld_info_command::lazy_bind_off
uint32_t lazy_bind_off
Definition: MachO.h:876
llvm::MachO::dyld_info_command::bind_size
uint32_t bind_size
Definition: MachO.h:873
llvm::objcopy::macho::RelocationInfo::Sec
Optional< const Section * > Sec
Definition: MachOObject.h:180
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::objcopy::macho::RelocationInfo::IsAddend
bool IsAddend
Definition: MachOObject.h:185
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::MachO::segment_command
Definition: MachO.h:537
llvm::objcopy::macho::SymbolEntry
Definition: MachOObject.h:110
llvm::MachO::load_command
Definition: MachO.h:532
llvm::min
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
Definition: FileCheck.cpp:357
llvm::StructType
Class to represent struct types.
Definition: DerivedTypes.h:213
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::objcopy::macho::Section::RelOff
uint32_t RelOff
Definition: MachOObject.h:51
llvm::objcopy::macho::Section::Align
uint32_t Align
Definition: MachOObject.h:50
llvm::objcopy::macho::SymbolEntry::n_value
uint64_t n_value
Definition: MachOObject.h:117
uint32_t
llvm::MachO::dyld_info_command::rebase_size
uint32_t rebase_size
Definition: MachO.h:871
llvm::objcopy::macho::MachOWriter::write
Error write()
Definition: MachOWriter.cpp:646
llvm::MachO::segment_command_64
Definition: MachO.h:551
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::objcopy::macho::CodeSignatureInfo::HashSize
static constexpr size_t HashSize
Definition: MachOLayoutBuilder.h:35
getSegmentFileSize
static uint64_t getSegmentFileSize(const LoadCommand &TextSegmentLoadCommand)
Definition: MachOWriter.cpp:420
llvm::objcopy::macho::RelocationInfo::Scattered
bool Scattered
Definition: MachOObject.h:182
llvm::MachO::NListType
NListType
Definition: MachO.h:308
llvm::objcopy::macho::LoadCommand::Payload
std::vector< uint8_t > Payload
Definition: MachOObject.h:93
llvm::MachO::dyld_info_command::weak_bind_off
uint32_t weak_bind_off
Definition: MachO.h:874
MachOObject.h
llvm::objcopy::macho::MachOWriter::finalize
Error finalize()
Definition: MachOWriter.cpp:644
llvm::objcopy::macho::MachOWriter::totalSize
size_t totalSize() const
Definition: MachOWriter.cpp:39
llvm::MachO::dysymtab_command
Definition: MachO.h:704
llvm::StringRef::size
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:157
llvm::MachO::CS_CodeDirectory
Definition: MachO.h:2184
llvm::objcopy::macho::CodeSignatureInfo::BlobHeadersSize
static constexpr size_t BlobHeadersSize
Definition: MachOLayoutBuilder.h:36
llvm::objcopy::macho::CodeSignatureInfo::OutputFileName
StringRef OutputFileName
Definition: MachOLayoutBuilder.h:50
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1239
llvm::SHA256::update
void update(ArrayRef< uint8_t > Data)
Digest more data.
Definition: SHA256.cpp:192
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
MachOLayoutBuilder.h
llvm::MachO::symtab_command::stroff
uint32_t stroff
Definition: MachO.h:700
llvm::objcopy::macho::CodeSignatureInfo::BlockSize
static constexpr size_t BlockSize
Definition: MachOLayoutBuilder.h:32
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1562
llvm::MachO::mach_header
Definition: MachO.h:511
llvm::objcopy::macho::Section::Reserved2
uint32_t Reserved2
Definition: MachOObject.h:55
llvm::objcopy::macho::Section::Offset
uint32_t Offset
Definition: MachOObject.h:49
llvm::MachO::mach_header_64::sizeofcmds
uint32_t sizeofcmds
Definition: MachO.h:527
llvm::MachO::nlist_64
Definition: MachO.h:997
llvm::MachO::CS_SuperBlob
Definition: MachO.h:2223
llvm::MachO::mach_header_64::cpusubtype
uint32_t cpusubtype
Definition: MachO.h:524
llvm::objcopy::macho::Section
Definition: MachOObject.h:39
llvm::sys::IsLittleEndianHost
static const bool IsLittleEndianHost
Definition: SwapByteOrder.h:101
llvm::support::endian::write64be
void write64be(void *P, uint64_t V)
Definition: Endian.h:420
writeNListEntry
void writeNListEntry(const SymbolEntry &SE, bool IsLittleEndian, char *&Out, uint32_t Nstrx)
Definition: MachOWriter.cpp:271
llvm::MachO::CSSLOT_CODEDIRECTORY
@ CSSLOT_CODEDIRECTORY
Definition: MachO.h:2138
llvm::MachO::symtab_command::symoff
uint32_t symoff
Definition: MachO.h:698
llvm::MachO::CSMAGIC_EMBEDDED_SIGNATURE
@ CSMAGIC_EMBEDDED_SIGNATURE
Definition: MachO.h:2124
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
llvm::MachO::dyld_info_command::lazy_bind_size
uint32_t lazy_bind_size
Definition: MachO.h:877
MachO.h
llvm::objcopy::macho::RelocationInfo::setPlainRelocationSymbolNum
void setPlainRelocationSymbolNum(unsigned SymbolNum, bool IsLittleEndian)
Definition: MachOObject.h:196
llvm::MachO::dyld_info_command::export_size
uint32_t export_size
Definition: MachO.h:879
llvm::AMDGPU::VGPRIndexMode::Id
Id
Definition: SIDefines.h:241
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::StringRef::begin
iterator begin() const
Definition: StringRef.h:128
llvm::pdb::PDB_SymType::Block
@ Block
llvm::MachO::mach_header_64::cputype
uint32_t cputype
Definition: MachO.h:523
llvm::MachO::mach_header_64::filetype
uint32_t filetype
Definition: MachO.h:525
llvm::objcopy::macho::CodeSignatureInfo::AllHeadersSize
uint32_t AllHeadersSize
Definition: MachOLayoutBuilder.h:47
llvm::objcopy::macho::CodeSignatureInfo
When MachO binaries include a LC_CODE_SIGNATURE load command, the __LINKEDIT data segment will includ...
Definition: MachOLayoutBuilder.h:25
llvm::objcopy::macho::Section::Flags
uint32_t Flags
Definition: MachOObject.h:53
llvm::MachO::macho_load_command
Definition: MachO.h:2028
llvm::SHA256::final
std::array< uint8_t, 32 > final()
Return the current raw 256-bits SHA256 for the digested data since the last call to init().
Definition: SHA256.cpp:266