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