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 (std::optional<size_t> LinkEditDataCommandIndex : 98 {O.CodeSignatureCommandIndex, O.DylibCodeSignDRsIndex, 99 O.DataInCodeCommandIndex, O.LinkerOptimizationHintCommandIndex, 100 O.FunctionStartsCommandIndex, O.ChainedFixupsCommandIndex, 101 O.ExportsTrieCommandIndex}) 102 if (LinkEditDataCommandIndex) { 103 const MachO::linkedit_data_command &LinkEditDataCommand = 104 O.LoadCommands[*LinkEditDataCommandIndex] 105 .MachOLoadCommand.linkedit_data_command_data; 106 if (LinkEditDataCommand.dataoff) 107 Ends.push_back(LinkEditDataCommand.dataoff + 108 LinkEditDataCommand.datasize); 109 } 110 111 // Otherwise, use the last section / reloction. 112 for (const LoadCommand &LC : O.LoadCommands) 113 for (const std::unique_ptr<Section> &S : LC.Sections) { 114 if (!S->hasValidOffset()) { 115 assert((S->Offset == 0) && "Skipped section's offset must be zero"); 116 assert((S->isVirtualSection() || S->Size == 0) && 117 "Non-zero-fill sections with zero offset must have zero size"); 118 continue; 119 } 120 assert((S->Offset != 0) && 121 "Non-zero-fill section's offset cannot be zero"); 122 Ends.push_back(S->Offset + S->Size); 123 if (S->RelOff) 124 Ends.push_back(S->RelOff + 125 S->NReloc * sizeof(MachO::any_relocation_info)); 126 } 127 128 if (!Ends.empty()) 129 return *llvm::max_element(Ends); 130 131 // Otherwise, we have only Mach header and load commands. 132 return headerSize() + loadCommandsSize(); 133 } 134 135 void MachOWriter::writeHeader() { 136 MachO::mach_header_64 Header; 137 138 Header.magic = O.Header.Magic; 139 Header.cputype = O.Header.CPUType; 140 Header.cpusubtype = O.Header.CPUSubType; 141 Header.filetype = O.Header.FileType; 142 Header.ncmds = O.Header.NCmds; 143 Header.sizeofcmds = O.Header.SizeOfCmds; 144 Header.flags = O.Header.Flags; 145 Header.reserved = O.Header.Reserved; 146 147 if (IsLittleEndian != sys::IsLittleEndianHost) 148 MachO::swapStruct(Header); 149 150 auto HeaderSize = 151 Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header); 152 memcpy(Buf->getBufferStart(), &Header, HeaderSize); 153 } 154 155 void MachOWriter::writeLoadCommands() { 156 uint8_t *Begin = 157 reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + headerSize(); 158 for (const LoadCommand &LC : O.LoadCommands) { 159 // Construct a load command. 160 MachO::macho_load_command MLC = LC.MachOLoadCommand; 161 switch (MLC.load_command_data.cmd) { 162 case MachO::LC_SEGMENT: 163 if (IsLittleEndian != sys::IsLittleEndianHost) 164 MachO::swapStruct(MLC.segment_command_data); 165 memcpy(Begin, &MLC.segment_command_data, sizeof(MachO::segment_command)); 166 Begin += sizeof(MachO::segment_command); 167 168 for (const std::unique_ptr<Section> &Sec : LC.Sections) 169 writeSectionInLoadCommand<MachO::section>(*Sec, Begin); 170 continue; 171 case MachO::LC_SEGMENT_64: 172 if (IsLittleEndian != sys::IsLittleEndianHost) 173 MachO::swapStruct(MLC.segment_command_64_data); 174 memcpy(Begin, &MLC.segment_command_64_data, 175 sizeof(MachO::segment_command_64)); 176 Begin += sizeof(MachO::segment_command_64); 177 178 for (const std::unique_ptr<Section> &Sec : LC.Sections) 179 writeSectionInLoadCommand<MachO::section_64>(*Sec, Begin); 180 continue; 181 } 182 183 #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ 184 case MachO::LCName: \ 185 assert(sizeof(MachO::LCStruct) + LC.Payload.size() == \ 186 MLC.load_command_data.cmdsize); \ 187 if (IsLittleEndian != sys::IsLittleEndianHost) \ 188 MachO::swapStruct(MLC.LCStruct##_data); \ 189 memcpy(Begin, &MLC.LCStruct##_data, sizeof(MachO::LCStruct)); \ 190 Begin += sizeof(MachO::LCStruct); \ 191 if (!LC.Payload.empty()) \ 192 memcpy(Begin, LC.Payload.data(), LC.Payload.size()); \ 193 Begin += LC.Payload.size(); \ 194 break; 195 196 // Copy the load command as it is. 197 switch (MLC.load_command_data.cmd) { 198 default: 199 assert(sizeof(MachO::load_command) + LC.Payload.size() == 200 MLC.load_command_data.cmdsize); 201 if (IsLittleEndian != sys::IsLittleEndianHost) 202 MachO::swapStruct(MLC.load_command_data); 203 memcpy(Begin, &MLC.load_command_data, sizeof(MachO::load_command)); 204 Begin += sizeof(MachO::load_command); 205 if (!LC.Payload.empty()) 206 memcpy(Begin, LC.Payload.data(), LC.Payload.size()); 207 Begin += LC.Payload.size(); 208 break; 209 #include "llvm/BinaryFormat/MachO.def" 210 } 211 } 212 } 213 214 template <typename StructType> 215 void MachOWriter::writeSectionInLoadCommand(const Section &Sec, uint8_t *&Out) { 216 StructType Temp; 217 assert(Sec.Segname.size() <= sizeof(Temp.segname) && "too long segment name"); 218 assert(Sec.Sectname.size() <= sizeof(Temp.sectname) && 219 "too long section name"); 220 memset(&Temp, 0, sizeof(StructType)); 221 memcpy(Temp.segname, Sec.Segname.data(), Sec.Segname.size()); 222 memcpy(Temp.sectname, Sec.Sectname.data(), Sec.Sectname.size()); 223 Temp.addr = Sec.Addr; 224 Temp.size = Sec.Size; 225 Temp.offset = Sec.Offset; 226 Temp.align = Sec.Align; 227 Temp.reloff = Sec.RelOff; 228 Temp.nreloc = Sec.NReloc; 229 Temp.flags = Sec.Flags; 230 Temp.reserved1 = Sec.Reserved1; 231 Temp.reserved2 = Sec.Reserved2; 232 233 if (IsLittleEndian != sys::IsLittleEndianHost) 234 MachO::swapStruct(Temp); 235 memcpy(Out, &Temp, sizeof(StructType)); 236 Out += sizeof(StructType); 237 } 238 239 void MachOWriter::writeSections() { 240 for (const LoadCommand &LC : O.LoadCommands) 241 for (const std::unique_ptr<Section> &Sec : LC.Sections) { 242 if (!Sec->hasValidOffset()) { 243 assert((Sec->Offset == 0) && "Skipped section's offset must be zero"); 244 assert((Sec->isVirtualSection() || Sec->Size == 0) && 245 "Non-zero-fill sections with zero offset must have zero size"); 246 continue; 247 } 248 249 assert(Sec->Offset && "Section offset can not be zero"); 250 assert((Sec->Size == Sec->Content.size()) && "Incorrect section size"); 251 memcpy(Buf->getBufferStart() + Sec->Offset, Sec->Content.data(), 252 Sec->Content.size()); 253 for (size_t Index = 0; Index < Sec->Relocations.size(); ++Index) { 254 RelocationInfo RelocInfo = Sec->Relocations[Index]; 255 if (!RelocInfo.Scattered && !RelocInfo.IsAddend) { 256 const uint32_t SymbolNum = RelocInfo.Extern 257 ? (*RelocInfo.Symbol)->Index 258 : (*RelocInfo.Sec)->Index; 259 RelocInfo.setPlainRelocationSymbolNum(SymbolNum, IsLittleEndian); 260 } 261 if (IsLittleEndian != sys::IsLittleEndianHost) 262 MachO::swapStruct( 263 reinterpret_cast<MachO::any_relocation_info &>(RelocInfo.Info)); 264 memcpy(Buf->getBufferStart() + Sec->RelOff + 265 Index * sizeof(MachO::any_relocation_info), 266 &RelocInfo.Info, sizeof(RelocInfo.Info)); 267 } 268 } 269 } 270 271 template <typename NListType> 272 void writeNListEntry(const SymbolEntry &SE, bool IsLittleEndian, char *&Out, 273 uint32_t Nstrx) { 274 NListType ListEntry; 275 ListEntry.n_strx = Nstrx; 276 ListEntry.n_type = SE.n_type; 277 ListEntry.n_sect = SE.n_sect; 278 ListEntry.n_desc = SE.n_desc; 279 ListEntry.n_value = SE.n_value; 280 281 if (IsLittleEndian != sys::IsLittleEndianHost) 282 MachO::swapStruct(ListEntry); 283 memcpy(Out, reinterpret_cast<const char *>(&ListEntry), sizeof(NListType)); 284 Out += sizeof(NListType); 285 } 286 287 void MachOWriter::writeStringTable() { 288 if (!O.SymTabCommandIndex) 289 return; 290 const MachO::symtab_command &SymTabCommand = 291 O.LoadCommands[*O.SymTabCommandIndex] 292 .MachOLoadCommand.symtab_command_data; 293 294 uint8_t *StrTable = (uint8_t *)Buf->getBufferStart() + SymTabCommand.stroff; 295 LayoutBuilder.getStringTableBuilder().write(StrTable); 296 } 297 298 void MachOWriter::writeSymbolTable() { 299 if (!O.SymTabCommandIndex) 300 return; 301 const MachO::symtab_command &SymTabCommand = 302 O.LoadCommands[*O.SymTabCommandIndex] 303 .MachOLoadCommand.symtab_command_data; 304 305 char *SymTable = (char *)Buf->getBufferStart() + SymTabCommand.symoff; 306 for (auto &Symbol : O.SymTable.Symbols) { 307 SymbolEntry *Sym = Symbol.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(std::optional<size_t> LCIndex, 396 const LinkData &LD) { 397 if (!LCIndex) 398 return; 399 const MachO::linkedit_data_command &LinkEditDataCommand = 400 O.LoadCommands[*LCIndex].MachOLoadCommand.linkedit_data_command_data; 401 char *Out = (char *)Buf->getBufferStart() + LinkEditDataCommand.dataoff; 402 assert((LinkEditDataCommand.datasize == LD.Data.size()) && 403 "Incorrect data size"); 404 memcpy(Out, LD.Data.data(), LD.Data.size()); 405 } 406 407 static uint64_t 408 getSegmentFileOffset(const LoadCommand &TextSegmentLoadCommand) { 409 const MachO::macho_load_command &MLC = 410 TextSegmentLoadCommand.MachOLoadCommand; 411 switch (MLC.load_command_data.cmd) { 412 case MachO::LC_SEGMENT: 413 return MLC.segment_command_data.fileoff; 414 case MachO::LC_SEGMENT_64: 415 return MLC.segment_command_64_data.fileoff; 416 default: 417 return 0; 418 } 419 } 420 421 static uint64_t getSegmentFileSize(const LoadCommand &TextSegmentLoadCommand) { 422 const MachO::macho_load_command &MLC = 423 TextSegmentLoadCommand.MachOLoadCommand; 424 switch (MLC.load_command_data.cmd) { 425 case MachO::LC_SEGMENT: 426 return MLC.segment_command_data.filesize; 427 case MachO::LC_SEGMENT_64: 428 return MLC.segment_command_64_data.filesize; 429 default: 430 return 0; 431 } 432 } 433 434 void MachOWriter::writeCodeSignatureData() { 435 // NOTE: This CodeSignature section behaviour must be kept in sync with that 436 // performed in LLD's CodeSignatureSection::write / 437 // CodeSignatureSection::writeHashes. Furthermore, this call must occur only 438 // after the rest of the binary has already been written to the buffer. This 439 // is because the buffer is read from to perform the necessary hashing. 440 441 // The CodeSignature section is the last section in the MachO binary and 442 // contains a hash of all content in the binary before it. Since llvm-objcopy 443 // has likely modified the target binary, the hash must be regenerated 444 // entirely. To generate this hash, we must read from the start of the binary 445 // (HashReadStart) to just before the start of the CodeSignature section 446 // (HashReadEnd). 447 448 const CodeSignatureInfo &CodeSignature = LayoutBuilder.getCodeSignature(); 449 450 uint8_t *BufferStart = reinterpret_cast<uint8_t *>(Buf->getBufferStart()); 451 uint8_t *HashReadStart = BufferStart; 452 uint8_t *HashReadEnd = BufferStart + CodeSignature.StartOffset; 453 454 // The CodeSignature section begins with a header, after which the hashes 455 // of each page of the binary are written. 456 uint8_t *HashWriteStart = HashReadEnd + CodeSignature.AllHeadersSize; 457 458 uint32_t TextSegmentFileOff = 0; 459 uint32_t TextSegmentFileSize = 0; 460 if (O.TextSegmentCommandIndex) { 461 const LoadCommand &TextSegmentLoadCommand = 462 O.LoadCommands[*O.TextSegmentCommandIndex]; 463 assert(TextSegmentLoadCommand.MachOLoadCommand.load_command_data.cmd == 464 MachO::LC_SEGMENT || 465 TextSegmentLoadCommand.MachOLoadCommand.load_command_data.cmd == 466 MachO::LC_SEGMENT_64); 467 assert(StringRef(TextSegmentLoadCommand.MachOLoadCommand 468 .segment_command_data.segname) == "__TEXT"); 469 TextSegmentFileOff = getSegmentFileOffset(TextSegmentLoadCommand); 470 TextSegmentFileSize = getSegmentFileSize(TextSegmentLoadCommand); 471 } 472 473 const uint32_t FileNamePad = CodeSignature.AllHeadersSize - 474 CodeSignature.FixedHeadersSize - 475 CodeSignature.OutputFileName.size(); 476 477 // Write code section header. 478 auto *SuperBlob = reinterpret_cast<MachO::CS_SuperBlob *>(HashReadEnd); 479 write32be(&SuperBlob->magic, MachO::CSMAGIC_EMBEDDED_SIGNATURE); 480 write32be(&SuperBlob->length, CodeSignature.Size); 481 write32be(&SuperBlob->count, 1); 482 auto *BlobIndex = reinterpret_cast<MachO::CS_BlobIndex *>(&SuperBlob[1]); 483 write32be(&BlobIndex->type, MachO::CSSLOT_CODEDIRECTORY); 484 write32be(&BlobIndex->offset, CodeSignature.BlobHeadersSize); 485 auto *CodeDirectory = reinterpret_cast<MachO::CS_CodeDirectory *>( 486 HashReadEnd + CodeSignature.BlobHeadersSize); 487 write32be(&CodeDirectory->magic, MachO::CSMAGIC_CODEDIRECTORY); 488 write32be(&CodeDirectory->length, 489 CodeSignature.Size - CodeSignature.BlobHeadersSize); 490 write32be(&CodeDirectory->version, MachO::CS_SUPPORTSEXECSEG); 491 write32be(&CodeDirectory->flags, MachO::CS_ADHOC | MachO::CS_LINKER_SIGNED); 492 write32be(&CodeDirectory->hashOffset, 493 sizeof(MachO::CS_CodeDirectory) + 494 CodeSignature.OutputFileName.size() + FileNamePad); 495 write32be(&CodeDirectory->identOffset, sizeof(MachO::CS_CodeDirectory)); 496 CodeDirectory->nSpecialSlots = 0; 497 write32be(&CodeDirectory->nCodeSlots, CodeSignature.BlockCount); 498 write32be(&CodeDirectory->codeLimit, CodeSignature.StartOffset); 499 CodeDirectory->hashSize = static_cast<uint8_t>(CodeSignature.HashSize); 500 CodeDirectory->hashType = MachO::kSecCodeSignatureHashSHA256; 501 CodeDirectory->platform = 0; 502 CodeDirectory->pageSize = CodeSignature.BlockSizeShift; 503 CodeDirectory->spare2 = 0; 504 CodeDirectory->scatterOffset = 0; 505 CodeDirectory->teamOffset = 0; 506 CodeDirectory->spare3 = 0; 507 CodeDirectory->codeLimit64 = 0; 508 write64be(&CodeDirectory->execSegBase, TextSegmentFileOff); 509 write64be(&CodeDirectory->execSegLimit, TextSegmentFileSize); 510 write64be(&CodeDirectory->execSegFlags, O.Header.FileType == MachO::MH_EXECUTE 511 ? MachO::CS_EXECSEG_MAIN_BINARY 512 : 0); 513 514 auto *Id = reinterpret_cast<char *>(&CodeDirectory[1]); 515 memcpy(Id, CodeSignature.OutputFileName.begin(), 516 CodeSignature.OutputFileName.size()); 517 memset(Id + CodeSignature.OutputFileName.size(), 0, FileNamePad); 518 519 // Write the hashes. 520 uint8_t *CurrHashReadPosition = HashReadStart; 521 uint8_t *CurrHashWritePosition = HashWriteStart; 522 while (CurrHashReadPosition < HashReadEnd) { 523 StringRef Block(reinterpret_cast<char *>(CurrHashReadPosition), 524 std::min(static_cast<size_t>(HashReadEnd 525 - CurrHashReadPosition), 526 static_cast<size_t>(CodeSignature.BlockSize))); 527 SHA256 Hasher; 528 Hasher.update(Block); 529 std::array<uint8_t, 32> Hash = Hasher.final(); 530 assert(Hash.size() == CodeSignature.HashSize); 531 memcpy(CurrHashWritePosition, Hash.data(), CodeSignature.HashSize); 532 CurrHashReadPosition += CodeSignature.BlockSize; 533 CurrHashWritePosition += CodeSignature.HashSize; 534 } 535 #if defined(__APPLE__) 536 // This is macOS-specific work-around and makes no sense for any 537 // other host OS. See https://openradar.appspot.com/FB8914231 538 // 539 // The macOS kernel maintains a signature-verification cache to 540 // quickly validate applications at time of execve(2). The trouble 541 // is that for the kernel creates the cache entry at the time of the 542 // mmap(2) call, before we have a chance to write either the code to 543 // sign or the signature header+hashes. The fix is to invalidate 544 // all cached data associated with the output file, thus discarding 545 // the bogus prematurely-cached signature. 546 msync(BufferStart, CodeSignature.StartOffset + CodeSignature.Size, 547 MS_INVALIDATE); 548 #endif 549 } 550 551 void MachOWriter::writeDataInCodeData() { 552 return writeLinkData(O.DataInCodeCommandIndex, O.DataInCode); 553 } 554 555 void MachOWriter::writeLinkerOptimizationHint() { 556 return writeLinkData(O.LinkerOptimizationHintCommandIndex, 557 O.LinkerOptimizationHint); 558 } 559 560 void MachOWriter::writeFunctionStartsData() { 561 return writeLinkData(O.FunctionStartsCommandIndex, O.FunctionStarts); 562 } 563 564 void MachOWriter::writeDylibCodeSignDRsData() { 565 return writeLinkData(O.DylibCodeSignDRsIndex, O.DylibCodeSignDRs); 566 } 567 568 void MachOWriter::writeChainedFixupsData() { 569 return writeLinkData(O.ChainedFixupsCommandIndex, O.ChainedFixups); 570 } 571 572 void MachOWriter::writeExportsTrieData() { 573 if (!O.ExportsTrieCommandIndex) 574 return; 575 const MachO::linkedit_data_command &ExportsTrieCmd = 576 O.LoadCommands[*O.ExportsTrieCommandIndex] 577 .MachOLoadCommand.linkedit_data_command_data; 578 char *Out = (char *)Buf->getBufferStart() + ExportsTrieCmd.dataoff; 579 assert((ExportsTrieCmd.datasize == O.Exports.Trie.size()) && 580 "Incorrect export trie size"); 581 memcpy(Out, O.Exports.Trie.data(), O.Exports.Trie.size()); 582 } 583 584 void MachOWriter::writeTail() { 585 typedef void (MachOWriter::*WriteHandlerType)(); 586 typedef std::pair<uint64_t, WriteHandlerType> WriteOperation; 587 SmallVector<WriteOperation, 7> Queue; 588 589 if (O.SymTabCommandIndex) { 590 const MachO::symtab_command &SymTabCommand = 591 O.LoadCommands[*O.SymTabCommandIndex] 592 .MachOLoadCommand.symtab_command_data; 593 if (SymTabCommand.symoff) 594 Queue.push_back({SymTabCommand.symoff, &MachOWriter::writeSymbolTable}); 595 if (SymTabCommand.stroff) 596 Queue.push_back({SymTabCommand.stroff, &MachOWriter::writeStringTable}); 597 } 598 599 if (O.DyLdInfoCommandIndex) { 600 const MachO::dyld_info_command &DyLdInfoCommand = 601 O.LoadCommands[*O.DyLdInfoCommandIndex] 602 .MachOLoadCommand.dyld_info_command_data; 603 if (DyLdInfoCommand.rebase_off) 604 Queue.push_back( 605 {DyLdInfoCommand.rebase_off, &MachOWriter::writeRebaseInfo}); 606 if (DyLdInfoCommand.bind_off) 607 Queue.push_back({DyLdInfoCommand.bind_off, &MachOWriter::writeBindInfo}); 608 if (DyLdInfoCommand.weak_bind_off) 609 Queue.push_back( 610 {DyLdInfoCommand.weak_bind_off, &MachOWriter::writeWeakBindInfo}); 611 if (DyLdInfoCommand.lazy_bind_off) 612 Queue.push_back( 613 {DyLdInfoCommand.lazy_bind_off, &MachOWriter::writeLazyBindInfo}); 614 if (DyLdInfoCommand.export_off) 615 Queue.push_back( 616 {DyLdInfoCommand.export_off, &MachOWriter::writeExportInfo}); 617 } 618 619 if (O.DySymTabCommandIndex) { 620 const MachO::dysymtab_command &DySymTabCommand = 621 O.LoadCommands[*O.DySymTabCommandIndex] 622 .MachOLoadCommand.dysymtab_command_data; 623 624 if (DySymTabCommand.indirectsymoff) 625 Queue.emplace_back(DySymTabCommand.indirectsymoff, 626 &MachOWriter::writeIndirectSymbolTable); 627 } 628 629 std::initializer_list<std::pair<std::optional<size_t>, WriteHandlerType>> 630 LinkEditDataCommandWriters = { 631 {O.CodeSignatureCommandIndex, &MachOWriter::writeCodeSignatureData}, 632 {O.DylibCodeSignDRsIndex, &MachOWriter::writeDylibCodeSignDRsData}, 633 {O.DataInCodeCommandIndex, &MachOWriter::writeDataInCodeData}, 634 {O.LinkerOptimizationHintCommandIndex, 635 &MachOWriter::writeLinkerOptimizationHint}, 636 {O.FunctionStartsCommandIndex, &MachOWriter::writeFunctionStartsData}, 637 {O.ChainedFixupsCommandIndex, &MachOWriter::writeChainedFixupsData}, 638 {O.ExportsTrieCommandIndex, &MachOWriter::writeExportsTrieData}}; 639 for (const auto &W : LinkEditDataCommandWriters) { 640 std::optional<size_t> LinkEditDataCommandIndex; 641 WriteHandlerType WriteHandler; 642 std::tie(LinkEditDataCommandIndex, WriteHandler) = W; 643 if (LinkEditDataCommandIndex) { 644 const MachO::linkedit_data_command &LinkEditDataCommand = 645 O.LoadCommands[*LinkEditDataCommandIndex] 646 .MachOLoadCommand.linkedit_data_command_data; 647 if (LinkEditDataCommand.dataoff) 648 Queue.emplace_back(LinkEditDataCommand.dataoff, WriteHandler); 649 } 650 } 651 652 llvm::sort(Queue, llvm::less_first()); 653 654 for (auto WriteOp : Queue) 655 (this->*WriteOp.second)(); 656 } 657 658 Error MachOWriter::finalize() { return LayoutBuilder.layout(); } 659 660 Error MachOWriter::write() { 661 size_t TotalSize = totalSize(); 662 Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize); 663 if (!Buf) 664 return createStringError(errc::not_enough_memory, 665 "failed to allocate memory buffer of " + 666 Twine::utohexstr(TotalSize) + " bytes"); 667 writeHeader(); 668 writeLoadCommands(); 669 writeSections(); 670 writeTail(); 671 672 // TODO: Implement direct writing to the output stream (without intermediate 673 // memory buffer Buf). 674 Out.write(Buf->getBufferStart(), Buf->getBufferSize()); 675 return Error::success(); 676 } 677