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" 13 #include "llvm/BinaryFormat/MachO.h" 14 #include "llvm/Object/MachO.h" 15 #include "llvm/Support/Errc.h" 16 #include "llvm/Support/ErrorHandling.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 44 SmallVector<size_t, 7> Ends; 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. 159 MachO::macho_load_command MLC = LC.MachOLoadCommand; 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) 261 MachO::swapStruct( 262 reinterpret_cast<MachO::any_relocation_info &>(RelocInfo.Info)); 263 memcpy(Buf->getBufferStart() + Sec->RelOff + 264 Index * sizeof(MachO::any_relocation_info), 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 510 ? MachO::CS_EXECSEG_MAIN_BINARY 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; 574 SmallVector<WriteOperation, 7> Queue; 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 646 Error MachOWriter::write() { 647 size_t TotalSize = totalSize(); 648 Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize); 649 if (!Buf) 650 return createStringError(errc::not_enough_memory, 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 } 663