1*81ad6265SDimitry Andric //===- MachOReader.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 "MachOReader.h" 10*81ad6265SDimitry Andric #include "MachOObject.h" 11*81ad6265SDimitry Andric #include "llvm/BinaryFormat/MachO.h" 12*81ad6265SDimitry Andric #include "llvm/Object/MachO.h" 13*81ad6265SDimitry Andric #include "llvm/Support/Errc.h" 14*81ad6265SDimitry Andric #include <memory> 15*81ad6265SDimitry Andric 16*81ad6265SDimitry Andric using namespace llvm; 17*81ad6265SDimitry Andric using namespace llvm::objcopy; 18*81ad6265SDimitry Andric using namespace llvm::objcopy::macho; 19*81ad6265SDimitry Andric 20*81ad6265SDimitry Andric void MachOReader::readHeader(Object &O) const { 21*81ad6265SDimitry Andric O.Header.Magic = MachOObj.getHeader().magic; 22*81ad6265SDimitry Andric O.Header.CPUType = MachOObj.getHeader().cputype; 23*81ad6265SDimitry Andric O.Header.CPUSubType = MachOObj.getHeader().cpusubtype; 24*81ad6265SDimitry Andric O.Header.FileType = MachOObj.getHeader().filetype; 25*81ad6265SDimitry Andric O.Header.NCmds = MachOObj.getHeader().ncmds; 26*81ad6265SDimitry Andric O.Header.SizeOfCmds = MachOObj.getHeader().sizeofcmds; 27*81ad6265SDimitry Andric O.Header.Flags = MachOObj.getHeader().flags; 28*81ad6265SDimitry Andric } 29*81ad6265SDimitry Andric 30*81ad6265SDimitry Andric template <typename SectionType> 31*81ad6265SDimitry Andric static Section constructSectionCommon(const SectionType &Sec, uint32_t Index) { 32*81ad6265SDimitry Andric StringRef SegName(Sec.segname, strnlen(Sec.segname, sizeof(Sec.segname))); 33*81ad6265SDimitry Andric StringRef SectName(Sec.sectname, strnlen(Sec.sectname, sizeof(Sec.sectname))); 34*81ad6265SDimitry Andric Section S(SegName, SectName); 35*81ad6265SDimitry Andric S.Index = Index; 36*81ad6265SDimitry Andric S.Addr = Sec.addr; 37*81ad6265SDimitry Andric S.Size = Sec.size; 38*81ad6265SDimitry Andric S.OriginalOffset = Sec.offset; 39*81ad6265SDimitry Andric S.Align = Sec.align; 40*81ad6265SDimitry Andric S.RelOff = Sec.reloff; 41*81ad6265SDimitry Andric S.NReloc = Sec.nreloc; 42*81ad6265SDimitry Andric S.Flags = Sec.flags; 43*81ad6265SDimitry Andric S.Reserved1 = Sec.reserved1; 44*81ad6265SDimitry Andric S.Reserved2 = Sec.reserved2; 45*81ad6265SDimitry Andric S.Reserved3 = 0; 46*81ad6265SDimitry Andric return S; 47*81ad6265SDimitry Andric } 48*81ad6265SDimitry Andric 49*81ad6265SDimitry Andric Section constructSection(const MachO::section &Sec, uint32_t Index) { 50*81ad6265SDimitry Andric return constructSectionCommon(Sec, Index); 51*81ad6265SDimitry Andric } 52*81ad6265SDimitry Andric 53*81ad6265SDimitry Andric Section constructSection(const MachO::section_64 &Sec, uint32_t Index) { 54*81ad6265SDimitry Andric Section S = constructSectionCommon(Sec, Index); 55*81ad6265SDimitry Andric S.Reserved3 = Sec.reserved3; 56*81ad6265SDimitry Andric return S; 57*81ad6265SDimitry Andric } 58*81ad6265SDimitry Andric 59*81ad6265SDimitry Andric template <typename SectionType, typename SegmentType> 60*81ad6265SDimitry Andric Expected<std::vector<std::unique_ptr<Section>>> static extractSections( 61*81ad6265SDimitry Andric const object::MachOObjectFile::LoadCommandInfo &LoadCmd, 62*81ad6265SDimitry Andric const object::MachOObjectFile &MachOObj, uint32_t &NextSectionIndex) { 63*81ad6265SDimitry Andric std::vector<std::unique_ptr<Section>> Sections; 64*81ad6265SDimitry Andric for (auto Curr = reinterpret_cast<const SectionType *>(LoadCmd.Ptr + 65*81ad6265SDimitry Andric sizeof(SegmentType)), 66*81ad6265SDimitry Andric End = reinterpret_cast<const SectionType *>(LoadCmd.Ptr + 67*81ad6265SDimitry Andric LoadCmd.C.cmdsize); 68*81ad6265SDimitry Andric Curr < End; ++Curr) { 69*81ad6265SDimitry Andric SectionType Sec; 70*81ad6265SDimitry Andric memcpy((void *)&Sec, Curr, sizeof(SectionType)); 71*81ad6265SDimitry Andric 72*81ad6265SDimitry Andric if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) 73*81ad6265SDimitry Andric MachO::swapStruct(Sec); 74*81ad6265SDimitry Andric 75*81ad6265SDimitry Andric Sections.push_back( 76*81ad6265SDimitry Andric std::make_unique<Section>(constructSection(Sec, NextSectionIndex))); 77*81ad6265SDimitry Andric 78*81ad6265SDimitry Andric Section &S = *Sections.back(); 79*81ad6265SDimitry Andric 80*81ad6265SDimitry Andric Expected<object::SectionRef> SecRef = 81*81ad6265SDimitry Andric MachOObj.getSection(NextSectionIndex++); 82*81ad6265SDimitry Andric if (!SecRef) 83*81ad6265SDimitry Andric return SecRef.takeError(); 84*81ad6265SDimitry Andric 85*81ad6265SDimitry Andric Expected<ArrayRef<uint8_t>> Data = 86*81ad6265SDimitry Andric MachOObj.getSectionContents(SecRef->getRawDataRefImpl()); 87*81ad6265SDimitry Andric if (!Data) 88*81ad6265SDimitry Andric return Data.takeError(); 89*81ad6265SDimitry Andric 90*81ad6265SDimitry Andric S.Content = 91*81ad6265SDimitry Andric StringRef(reinterpret_cast<const char *>(Data->data()), Data->size()); 92*81ad6265SDimitry Andric 93*81ad6265SDimitry Andric const uint32_t CPUType = MachOObj.getHeader().cputype; 94*81ad6265SDimitry Andric S.Relocations.reserve(S.NReloc); 95*81ad6265SDimitry Andric for (auto RI = MachOObj.section_rel_begin(SecRef->getRawDataRefImpl()), 96*81ad6265SDimitry Andric RE = MachOObj.section_rel_end(SecRef->getRawDataRefImpl()); 97*81ad6265SDimitry Andric RI != RE; ++RI) { 98*81ad6265SDimitry Andric RelocationInfo R; 99*81ad6265SDimitry Andric R.Symbol = nullptr; // We'll fill this field later. 100*81ad6265SDimitry Andric R.Info = MachOObj.getRelocation(RI->getRawDataRefImpl()); 101*81ad6265SDimitry Andric R.Scattered = MachOObj.isRelocationScattered(R.Info); 102*81ad6265SDimitry Andric unsigned Type = MachOObj.getAnyRelocationType(R.Info); 103*81ad6265SDimitry Andric // TODO Support CPU_TYPE_ARM. 104*81ad6265SDimitry Andric R.IsAddend = !R.Scattered && (CPUType == MachO::CPU_TYPE_ARM64 && 105*81ad6265SDimitry Andric Type == MachO::ARM64_RELOC_ADDEND); 106*81ad6265SDimitry Andric R.Extern = !R.Scattered && MachOObj.getPlainRelocationExternal(R.Info); 107*81ad6265SDimitry Andric S.Relocations.push_back(R); 108*81ad6265SDimitry Andric } 109*81ad6265SDimitry Andric 110*81ad6265SDimitry Andric assert(S.NReloc == S.Relocations.size() && 111*81ad6265SDimitry Andric "Incorrect number of relocations"); 112*81ad6265SDimitry Andric } 113*81ad6265SDimitry Andric return std::move(Sections); 114*81ad6265SDimitry Andric } 115*81ad6265SDimitry Andric 116*81ad6265SDimitry Andric Error MachOReader::readLoadCommands(Object &O) const { 117*81ad6265SDimitry Andric // For MachO sections indices start from 1. 118*81ad6265SDimitry Andric uint32_t NextSectionIndex = 1; 119*81ad6265SDimitry Andric static constexpr char TextSegmentName[] = "__TEXT"; 120*81ad6265SDimitry Andric for (auto LoadCmd : MachOObj.load_commands()) { 121*81ad6265SDimitry Andric LoadCommand LC; 122*81ad6265SDimitry Andric switch (LoadCmd.C.cmd) { 123*81ad6265SDimitry Andric case MachO::LC_CODE_SIGNATURE: 124*81ad6265SDimitry Andric O.CodeSignatureCommandIndex = O.LoadCommands.size(); 125*81ad6265SDimitry Andric break; 126*81ad6265SDimitry Andric case MachO::LC_SEGMENT: 127*81ad6265SDimitry Andric // LoadCmd.Ptr might not be aligned temporarily as 128*81ad6265SDimitry Andric // MachO::segment_command requires, but the segname char pointer do not 129*81ad6265SDimitry Andric // have alignment restrictions. 130*81ad6265SDimitry Andric if (StringRef(reinterpret_cast<const char *>( 131*81ad6265SDimitry Andric LoadCmd.Ptr + offsetof(MachO::segment_command, segname))) == 132*81ad6265SDimitry Andric TextSegmentName) 133*81ad6265SDimitry Andric O.TextSegmentCommandIndex = O.LoadCommands.size(); 134*81ad6265SDimitry Andric 135*81ad6265SDimitry Andric if (Expected<std::vector<std::unique_ptr<Section>>> Sections = 136*81ad6265SDimitry Andric extractSections<MachO::section, MachO::segment_command>( 137*81ad6265SDimitry Andric LoadCmd, MachOObj, NextSectionIndex)) 138*81ad6265SDimitry Andric LC.Sections = std::move(*Sections); 139*81ad6265SDimitry Andric else 140*81ad6265SDimitry Andric return Sections.takeError(); 141*81ad6265SDimitry Andric break; 142*81ad6265SDimitry Andric case MachO::LC_SEGMENT_64: 143*81ad6265SDimitry Andric // LoadCmd.Ptr might not be aligned temporarily as 144*81ad6265SDimitry Andric // MachO::segment_command_64 requires, but the segname char pointer do 145*81ad6265SDimitry Andric // not have alignment restrictions. 146*81ad6265SDimitry Andric if (StringRef(reinterpret_cast<const char *>( 147*81ad6265SDimitry Andric LoadCmd.Ptr + offsetof(MachO::segment_command_64, segname))) == 148*81ad6265SDimitry Andric TextSegmentName) 149*81ad6265SDimitry Andric O.TextSegmentCommandIndex = O.LoadCommands.size(); 150*81ad6265SDimitry Andric 151*81ad6265SDimitry Andric if (Expected<std::vector<std::unique_ptr<Section>>> Sections = 152*81ad6265SDimitry Andric extractSections<MachO::section_64, MachO::segment_command_64>( 153*81ad6265SDimitry Andric LoadCmd, MachOObj, NextSectionIndex)) 154*81ad6265SDimitry Andric LC.Sections = std::move(*Sections); 155*81ad6265SDimitry Andric else 156*81ad6265SDimitry Andric return Sections.takeError(); 157*81ad6265SDimitry Andric break; 158*81ad6265SDimitry Andric case MachO::LC_SYMTAB: 159*81ad6265SDimitry Andric O.SymTabCommandIndex = O.LoadCommands.size(); 160*81ad6265SDimitry Andric break; 161*81ad6265SDimitry Andric case MachO::LC_DYSYMTAB: 162*81ad6265SDimitry Andric O.DySymTabCommandIndex = O.LoadCommands.size(); 163*81ad6265SDimitry Andric break; 164*81ad6265SDimitry Andric case MachO::LC_DYLD_INFO: 165*81ad6265SDimitry Andric case MachO::LC_DYLD_INFO_ONLY: 166*81ad6265SDimitry Andric O.DyLdInfoCommandIndex = O.LoadCommands.size(); 167*81ad6265SDimitry Andric break; 168*81ad6265SDimitry Andric case MachO::LC_DATA_IN_CODE: 169*81ad6265SDimitry Andric O.DataInCodeCommandIndex = O.LoadCommands.size(); 170*81ad6265SDimitry Andric break; 171*81ad6265SDimitry Andric case MachO::LC_LINKER_OPTIMIZATION_HINT: 172*81ad6265SDimitry Andric O.LinkerOptimizationHintCommandIndex = O.LoadCommands.size(); 173*81ad6265SDimitry Andric break; 174*81ad6265SDimitry Andric case MachO::LC_FUNCTION_STARTS: 175*81ad6265SDimitry Andric O.FunctionStartsCommandIndex = O.LoadCommands.size(); 176*81ad6265SDimitry Andric break; 177*81ad6265SDimitry Andric case MachO::LC_DYLD_EXPORTS_TRIE: 178*81ad6265SDimitry Andric O.ExportsTrieCommandIndex = O.LoadCommands.size(); 179*81ad6265SDimitry Andric break; 180*81ad6265SDimitry Andric case MachO::LC_DYLD_CHAINED_FIXUPS: 181*81ad6265SDimitry Andric O.ChainedFixupsCommandIndex = O.LoadCommands.size(); 182*81ad6265SDimitry Andric break; 183*81ad6265SDimitry Andric } 184*81ad6265SDimitry Andric #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ 185*81ad6265SDimitry Andric case MachO::LCName: \ 186*81ad6265SDimitry Andric memcpy((void *)&(LC.MachOLoadCommand.LCStruct##_data), LoadCmd.Ptr, \ 187*81ad6265SDimitry Andric sizeof(MachO::LCStruct)); \ 188*81ad6265SDimitry Andric if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) \ 189*81ad6265SDimitry Andric MachO::swapStruct(LC.MachOLoadCommand.LCStruct##_data); \ 190*81ad6265SDimitry Andric if (LoadCmd.C.cmdsize > sizeof(MachO::LCStruct)) \ 191*81ad6265SDimitry Andric LC.Payload = ArrayRef<uint8_t>( \ 192*81ad6265SDimitry Andric reinterpret_cast<uint8_t *>(const_cast<char *>(LoadCmd.Ptr)) + \ 193*81ad6265SDimitry Andric sizeof(MachO::LCStruct), \ 194*81ad6265SDimitry Andric LoadCmd.C.cmdsize - sizeof(MachO::LCStruct)); \ 195*81ad6265SDimitry Andric break; 196*81ad6265SDimitry Andric 197*81ad6265SDimitry Andric switch (LoadCmd.C.cmd) { 198*81ad6265SDimitry Andric default: 199*81ad6265SDimitry Andric memcpy((void *)&(LC.MachOLoadCommand.load_command_data), LoadCmd.Ptr, 200*81ad6265SDimitry Andric sizeof(MachO::load_command)); 201*81ad6265SDimitry Andric if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) 202*81ad6265SDimitry Andric MachO::swapStruct(LC.MachOLoadCommand.load_command_data); 203*81ad6265SDimitry Andric if (LoadCmd.C.cmdsize > sizeof(MachO::load_command)) 204*81ad6265SDimitry Andric LC.Payload = ArrayRef<uint8_t>( 205*81ad6265SDimitry Andric reinterpret_cast<uint8_t *>(const_cast<char *>(LoadCmd.Ptr)) + 206*81ad6265SDimitry Andric sizeof(MachO::load_command), 207*81ad6265SDimitry Andric LoadCmd.C.cmdsize - sizeof(MachO::load_command)); 208*81ad6265SDimitry Andric break; 209*81ad6265SDimitry Andric #include "llvm/BinaryFormat/MachO.def" 210*81ad6265SDimitry Andric } 211*81ad6265SDimitry Andric O.LoadCommands.push_back(std::move(LC)); 212*81ad6265SDimitry Andric } 213*81ad6265SDimitry Andric return Error::success(); 214*81ad6265SDimitry Andric } 215*81ad6265SDimitry Andric 216*81ad6265SDimitry Andric template <typename nlist_t> 217*81ad6265SDimitry Andric SymbolEntry constructSymbolEntry(StringRef StrTable, const nlist_t &nlist) { 218*81ad6265SDimitry Andric assert(nlist.n_strx < StrTable.size() && 219*81ad6265SDimitry Andric "n_strx exceeds the size of the string table"); 220*81ad6265SDimitry Andric SymbolEntry SE; 221*81ad6265SDimitry Andric SE.Name = StringRef(StrTable.data() + nlist.n_strx).str(); 222*81ad6265SDimitry Andric SE.n_type = nlist.n_type; 223*81ad6265SDimitry Andric SE.n_sect = nlist.n_sect; 224*81ad6265SDimitry Andric SE.n_desc = nlist.n_desc; 225*81ad6265SDimitry Andric SE.n_value = nlist.n_value; 226*81ad6265SDimitry Andric return SE; 227*81ad6265SDimitry Andric } 228*81ad6265SDimitry Andric 229*81ad6265SDimitry Andric void MachOReader::readSymbolTable(Object &O) const { 230*81ad6265SDimitry Andric StringRef StrTable = MachOObj.getStringTableData(); 231*81ad6265SDimitry Andric for (auto Symbol : MachOObj.symbols()) { 232*81ad6265SDimitry Andric SymbolEntry SE = 233*81ad6265SDimitry Andric (MachOObj.is64Bit() 234*81ad6265SDimitry Andric ? constructSymbolEntry(StrTable, MachOObj.getSymbol64TableEntry( 235*81ad6265SDimitry Andric Symbol.getRawDataRefImpl())) 236*81ad6265SDimitry Andric : constructSymbolEntry(StrTable, MachOObj.getSymbolTableEntry( 237*81ad6265SDimitry Andric Symbol.getRawDataRefImpl()))); 238*81ad6265SDimitry Andric 239*81ad6265SDimitry Andric O.SymTable.Symbols.push_back(std::make_unique<SymbolEntry>(SE)); 240*81ad6265SDimitry Andric } 241*81ad6265SDimitry Andric } 242*81ad6265SDimitry Andric 243*81ad6265SDimitry Andric void MachOReader::setSymbolInRelocationInfo(Object &O) const { 244*81ad6265SDimitry Andric std::vector<const Section *> Sections; 245*81ad6265SDimitry Andric for (auto &LC : O.LoadCommands) 246*81ad6265SDimitry Andric for (std::unique_ptr<Section> &Sec : LC.Sections) 247*81ad6265SDimitry Andric Sections.push_back(Sec.get()); 248*81ad6265SDimitry Andric 249*81ad6265SDimitry Andric for (LoadCommand &LC : O.LoadCommands) 250*81ad6265SDimitry Andric for (std::unique_ptr<Section> &Sec : LC.Sections) 251*81ad6265SDimitry Andric for (auto &Reloc : Sec->Relocations) 252*81ad6265SDimitry Andric if (!Reloc.Scattered && !Reloc.IsAddend) { 253*81ad6265SDimitry Andric const uint32_t SymbolNum = 254*81ad6265SDimitry Andric Reloc.getPlainRelocationSymbolNum(MachOObj.isLittleEndian()); 255*81ad6265SDimitry Andric if (Reloc.Extern) { 256*81ad6265SDimitry Andric Reloc.Symbol = O.SymTable.getSymbolByIndex(SymbolNum); 257*81ad6265SDimitry Andric } else { 258*81ad6265SDimitry Andric // FIXME: Refactor error handling in MachOReader and report an error 259*81ad6265SDimitry Andric // if we encounter an invalid relocation. 260*81ad6265SDimitry Andric assert(SymbolNum >= 1 && SymbolNum <= Sections.size() && 261*81ad6265SDimitry Andric "Invalid section index."); 262*81ad6265SDimitry Andric Reloc.Sec = Sections[SymbolNum - 1]; 263*81ad6265SDimitry Andric } 264*81ad6265SDimitry Andric } 265*81ad6265SDimitry Andric } 266*81ad6265SDimitry Andric 267*81ad6265SDimitry Andric void MachOReader::readRebaseInfo(Object &O) const { 268*81ad6265SDimitry Andric O.Rebases.Opcodes = MachOObj.getDyldInfoRebaseOpcodes(); 269*81ad6265SDimitry Andric } 270*81ad6265SDimitry Andric 271*81ad6265SDimitry Andric void MachOReader::readBindInfo(Object &O) const { 272*81ad6265SDimitry Andric O.Binds.Opcodes = MachOObj.getDyldInfoBindOpcodes(); 273*81ad6265SDimitry Andric } 274*81ad6265SDimitry Andric 275*81ad6265SDimitry Andric void MachOReader::readWeakBindInfo(Object &O) const { 276*81ad6265SDimitry Andric O.WeakBinds.Opcodes = MachOObj.getDyldInfoWeakBindOpcodes(); 277*81ad6265SDimitry Andric } 278*81ad6265SDimitry Andric 279*81ad6265SDimitry Andric void MachOReader::readLazyBindInfo(Object &O) const { 280*81ad6265SDimitry Andric O.LazyBinds.Opcodes = MachOObj.getDyldInfoLazyBindOpcodes(); 281*81ad6265SDimitry Andric } 282*81ad6265SDimitry Andric 283*81ad6265SDimitry Andric void MachOReader::readExportInfo(Object &O) const { 284*81ad6265SDimitry Andric O.Exports.Trie = MachOObj.getDyldInfoExportsTrie(); 285*81ad6265SDimitry Andric } 286*81ad6265SDimitry Andric 287*81ad6265SDimitry Andric void MachOReader::readLinkData(Object &O, Optional<size_t> LCIndex, 288*81ad6265SDimitry Andric LinkData &LD) const { 289*81ad6265SDimitry Andric if (!LCIndex) 290*81ad6265SDimitry Andric return; 291*81ad6265SDimitry Andric const MachO::linkedit_data_command &LC = 292*81ad6265SDimitry Andric O.LoadCommands[*LCIndex].MachOLoadCommand.linkedit_data_command_data; 293*81ad6265SDimitry Andric LD.Data = 294*81ad6265SDimitry Andric arrayRefFromStringRef(MachOObj.getData().substr(LC.dataoff, LC.datasize)); 295*81ad6265SDimitry Andric } 296*81ad6265SDimitry Andric 297*81ad6265SDimitry Andric void MachOReader::readDataInCodeData(Object &O) const { 298*81ad6265SDimitry Andric return readLinkData(O, O.DataInCodeCommandIndex, O.DataInCode); 299*81ad6265SDimitry Andric } 300*81ad6265SDimitry Andric 301*81ad6265SDimitry Andric void MachOReader::readLinkerOptimizationHint(Object &O) const { 302*81ad6265SDimitry Andric return readLinkData(O, O.LinkerOptimizationHintCommandIndex, 303*81ad6265SDimitry Andric O.LinkerOptimizationHint); 304*81ad6265SDimitry Andric } 305*81ad6265SDimitry Andric 306*81ad6265SDimitry Andric void MachOReader::readFunctionStartsData(Object &O) const { 307*81ad6265SDimitry Andric return readLinkData(O, O.FunctionStartsCommandIndex, O.FunctionStarts); 308*81ad6265SDimitry Andric } 309*81ad6265SDimitry Andric 310*81ad6265SDimitry Andric void MachOReader::readExportsTrie(Object &O) const { 311*81ad6265SDimitry Andric return readLinkData(O, O.ExportsTrieCommandIndex, O.ExportsTrie); 312*81ad6265SDimitry Andric } 313*81ad6265SDimitry Andric 314*81ad6265SDimitry Andric void MachOReader::readChainedFixups(Object &O) const { 315*81ad6265SDimitry Andric return readLinkData(O, O.ChainedFixupsCommandIndex, O.ChainedFixups); 316*81ad6265SDimitry Andric } 317*81ad6265SDimitry Andric 318*81ad6265SDimitry Andric void MachOReader::readIndirectSymbolTable(Object &O) const { 319*81ad6265SDimitry Andric MachO::dysymtab_command DySymTab = MachOObj.getDysymtabLoadCommand(); 320*81ad6265SDimitry Andric constexpr uint32_t AbsOrLocalMask = 321*81ad6265SDimitry Andric MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS; 322*81ad6265SDimitry Andric for (uint32_t i = 0; i < DySymTab.nindirectsyms; ++i) { 323*81ad6265SDimitry Andric uint32_t Index = MachOObj.getIndirectSymbolTableEntry(DySymTab, i); 324*81ad6265SDimitry Andric if ((Index & AbsOrLocalMask) != 0) 325*81ad6265SDimitry Andric O.IndirectSymTable.Symbols.emplace_back(Index, None); 326*81ad6265SDimitry Andric else 327*81ad6265SDimitry Andric O.IndirectSymTable.Symbols.emplace_back( 328*81ad6265SDimitry Andric Index, O.SymTable.getSymbolByIndex(Index)); 329*81ad6265SDimitry Andric } 330*81ad6265SDimitry Andric } 331*81ad6265SDimitry Andric 332*81ad6265SDimitry Andric void MachOReader::readSwiftVersion(Object &O) const { 333*81ad6265SDimitry Andric struct ObjCImageInfo { 334*81ad6265SDimitry Andric uint32_t Version; 335*81ad6265SDimitry Andric uint32_t Flags; 336*81ad6265SDimitry Andric } ImageInfo; 337*81ad6265SDimitry Andric 338*81ad6265SDimitry Andric for (const LoadCommand &LC : O.LoadCommands) 339*81ad6265SDimitry Andric for (const std::unique_ptr<Section> &Sec : LC.Sections) 340*81ad6265SDimitry Andric if (Sec->Sectname == "__objc_imageinfo" && 341*81ad6265SDimitry Andric (Sec->Segname == "__DATA" || Sec->Segname == "__DATA_CONST" || 342*81ad6265SDimitry Andric Sec->Segname == "__DATA_DIRTY") && 343*81ad6265SDimitry Andric Sec->Content.size() >= sizeof(ObjCImageInfo)) { 344*81ad6265SDimitry Andric memcpy(&ImageInfo, Sec->Content.data(), sizeof(ObjCImageInfo)); 345*81ad6265SDimitry Andric if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) { 346*81ad6265SDimitry Andric sys::swapByteOrder(ImageInfo.Version); 347*81ad6265SDimitry Andric sys::swapByteOrder(ImageInfo.Flags); 348*81ad6265SDimitry Andric } 349*81ad6265SDimitry Andric O.SwiftVersion = (ImageInfo.Flags >> 8) & 0xff; 350*81ad6265SDimitry Andric return; 351*81ad6265SDimitry Andric } 352*81ad6265SDimitry Andric } 353*81ad6265SDimitry Andric 354*81ad6265SDimitry Andric Expected<std::unique_ptr<Object>> MachOReader::create() const { 355*81ad6265SDimitry Andric auto Obj = std::make_unique<Object>(); 356*81ad6265SDimitry Andric readHeader(*Obj); 357*81ad6265SDimitry Andric if (Error E = readLoadCommands(*Obj)) 358*81ad6265SDimitry Andric return std::move(E); 359*81ad6265SDimitry Andric readSymbolTable(*Obj); 360*81ad6265SDimitry Andric setSymbolInRelocationInfo(*Obj); 361*81ad6265SDimitry Andric readRebaseInfo(*Obj); 362*81ad6265SDimitry Andric readBindInfo(*Obj); 363*81ad6265SDimitry Andric readWeakBindInfo(*Obj); 364*81ad6265SDimitry Andric readLazyBindInfo(*Obj); 365*81ad6265SDimitry Andric readExportInfo(*Obj); 366*81ad6265SDimitry Andric readDataInCodeData(*Obj); 367*81ad6265SDimitry Andric readLinkerOptimizationHint(*Obj); 368*81ad6265SDimitry Andric readFunctionStartsData(*Obj); 369*81ad6265SDimitry Andric readExportsTrie(*Obj); 370*81ad6265SDimitry Andric readChainedFixups(*Obj); 371*81ad6265SDimitry Andric readIndirectSymbolTable(*Obj); 372*81ad6265SDimitry Andric readSwiftVersion(*Obj); 373*81ad6265SDimitry Andric return std::move(Obj); 374*81ad6265SDimitry Andric } 375