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