181ad6265SDimitry Andric //===- MachOReader.cpp ------------------------------------------*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #include "MachOReader.h" 1081ad6265SDimitry Andric #include "MachOObject.h" 1181ad6265SDimitry Andric #include "llvm/BinaryFormat/MachO.h" 1281ad6265SDimitry Andric #include "llvm/Object/MachO.h" 1381ad6265SDimitry Andric #include "llvm/Support/Errc.h" 1481ad6265SDimitry Andric #include <memory> 1581ad6265SDimitry Andric 1681ad6265SDimitry Andric using namespace llvm; 1781ad6265SDimitry Andric using namespace llvm::objcopy; 1881ad6265SDimitry Andric using namespace llvm::objcopy::macho; 1981ad6265SDimitry Andric 2081ad6265SDimitry Andric void MachOReader::readHeader(Object &O) const { 2181ad6265SDimitry Andric O.Header.Magic = MachOObj.getHeader().magic; 2281ad6265SDimitry Andric O.Header.CPUType = MachOObj.getHeader().cputype; 2381ad6265SDimitry Andric O.Header.CPUSubType = MachOObj.getHeader().cpusubtype; 2481ad6265SDimitry Andric O.Header.FileType = MachOObj.getHeader().filetype; 2581ad6265SDimitry Andric O.Header.NCmds = MachOObj.getHeader().ncmds; 2681ad6265SDimitry Andric O.Header.SizeOfCmds = MachOObj.getHeader().sizeofcmds; 2781ad6265SDimitry Andric O.Header.Flags = MachOObj.getHeader().flags; 2881ad6265SDimitry Andric } 2981ad6265SDimitry Andric 3081ad6265SDimitry Andric template <typename SectionType> 3181ad6265SDimitry Andric static Section constructSectionCommon(const SectionType &Sec, uint32_t Index) { 3281ad6265SDimitry Andric StringRef SegName(Sec.segname, strnlen(Sec.segname, sizeof(Sec.segname))); 3381ad6265SDimitry Andric StringRef SectName(Sec.sectname, strnlen(Sec.sectname, sizeof(Sec.sectname))); 3481ad6265SDimitry Andric Section S(SegName, SectName); 3581ad6265SDimitry Andric S.Index = Index; 3681ad6265SDimitry Andric S.Addr = Sec.addr; 3781ad6265SDimitry Andric S.Size = Sec.size; 3881ad6265SDimitry Andric S.OriginalOffset = Sec.offset; 3981ad6265SDimitry Andric S.Align = Sec.align; 4081ad6265SDimitry Andric S.RelOff = Sec.reloff; 4181ad6265SDimitry Andric S.NReloc = Sec.nreloc; 4281ad6265SDimitry Andric S.Flags = Sec.flags; 4381ad6265SDimitry Andric S.Reserved1 = Sec.reserved1; 4481ad6265SDimitry Andric S.Reserved2 = Sec.reserved2; 4581ad6265SDimitry Andric S.Reserved3 = 0; 4681ad6265SDimitry Andric return S; 4781ad6265SDimitry Andric } 4881ad6265SDimitry Andric 4981ad6265SDimitry Andric Section constructSection(const MachO::section &Sec, uint32_t Index) { 5081ad6265SDimitry Andric return constructSectionCommon(Sec, Index); 5181ad6265SDimitry Andric } 5281ad6265SDimitry Andric 5381ad6265SDimitry Andric Section constructSection(const MachO::section_64 &Sec, uint32_t Index) { 5481ad6265SDimitry Andric Section S = constructSectionCommon(Sec, Index); 5581ad6265SDimitry Andric S.Reserved3 = Sec.reserved3; 5681ad6265SDimitry Andric return S; 5781ad6265SDimitry Andric } 5881ad6265SDimitry Andric 5981ad6265SDimitry Andric template <typename SectionType, typename SegmentType> 6081ad6265SDimitry Andric Expected<std::vector<std::unique_ptr<Section>>> static extractSections( 6181ad6265SDimitry Andric const object::MachOObjectFile::LoadCommandInfo &LoadCmd, 6281ad6265SDimitry Andric const object::MachOObjectFile &MachOObj, uint32_t &NextSectionIndex) { 6381ad6265SDimitry Andric std::vector<std::unique_ptr<Section>> Sections; 6481ad6265SDimitry Andric for (auto Curr = reinterpret_cast<const SectionType *>(LoadCmd.Ptr + 6581ad6265SDimitry Andric sizeof(SegmentType)), 6681ad6265SDimitry Andric End = reinterpret_cast<const SectionType *>(LoadCmd.Ptr + 6781ad6265SDimitry Andric LoadCmd.C.cmdsize); 6881ad6265SDimitry Andric Curr < End; ++Curr) { 6981ad6265SDimitry Andric SectionType Sec; 7081ad6265SDimitry Andric memcpy((void *)&Sec, Curr, sizeof(SectionType)); 7181ad6265SDimitry Andric 7281ad6265SDimitry Andric if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) 7381ad6265SDimitry Andric MachO::swapStruct(Sec); 7481ad6265SDimitry Andric 7581ad6265SDimitry Andric Sections.push_back( 7681ad6265SDimitry Andric std::make_unique<Section>(constructSection(Sec, NextSectionIndex))); 7781ad6265SDimitry Andric 7881ad6265SDimitry Andric Section &S = *Sections.back(); 7981ad6265SDimitry Andric 8081ad6265SDimitry Andric Expected<object::SectionRef> SecRef = 8181ad6265SDimitry Andric MachOObj.getSection(NextSectionIndex++); 8281ad6265SDimitry Andric if (!SecRef) 8381ad6265SDimitry Andric return SecRef.takeError(); 8481ad6265SDimitry Andric 8581ad6265SDimitry Andric Expected<ArrayRef<uint8_t>> Data = 8681ad6265SDimitry Andric MachOObj.getSectionContents(SecRef->getRawDataRefImpl()); 8781ad6265SDimitry Andric if (!Data) 8881ad6265SDimitry Andric return Data.takeError(); 8981ad6265SDimitry Andric 9081ad6265SDimitry Andric S.Content = 9181ad6265SDimitry Andric StringRef(reinterpret_cast<const char *>(Data->data()), Data->size()); 9281ad6265SDimitry Andric 9381ad6265SDimitry Andric const uint32_t CPUType = MachOObj.getHeader().cputype; 9481ad6265SDimitry Andric S.Relocations.reserve(S.NReloc); 9581ad6265SDimitry Andric for (auto RI = MachOObj.section_rel_begin(SecRef->getRawDataRefImpl()), 9681ad6265SDimitry Andric RE = MachOObj.section_rel_end(SecRef->getRawDataRefImpl()); 9781ad6265SDimitry Andric RI != RE; ++RI) { 9881ad6265SDimitry Andric RelocationInfo R; 9981ad6265SDimitry Andric R.Symbol = nullptr; // We'll fill this field later. 10081ad6265SDimitry Andric R.Info = MachOObj.getRelocation(RI->getRawDataRefImpl()); 10181ad6265SDimitry Andric R.Scattered = MachOObj.isRelocationScattered(R.Info); 10281ad6265SDimitry Andric unsigned Type = MachOObj.getAnyRelocationType(R.Info); 10381ad6265SDimitry Andric // TODO Support CPU_TYPE_ARM. 10481ad6265SDimitry Andric R.IsAddend = !R.Scattered && (CPUType == MachO::CPU_TYPE_ARM64 && 10581ad6265SDimitry Andric Type == MachO::ARM64_RELOC_ADDEND); 10681ad6265SDimitry Andric R.Extern = !R.Scattered && MachOObj.getPlainRelocationExternal(R.Info); 10781ad6265SDimitry Andric S.Relocations.push_back(R); 10881ad6265SDimitry Andric } 10981ad6265SDimitry Andric 11081ad6265SDimitry Andric assert(S.NReloc == S.Relocations.size() && 11181ad6265SDimitry Andric "Incorrect number of relocations"); 11281ad6265SDimitry Andric } 11381ad6265SDimitry Andric return std::move(Sections); 11481ad6265SDimitry Andric } 11581ad6265SDimitry Andric 11681ad6265SDimitry Andric Error MachOReader::readLoadCommands(Object &O) const { 11781ad6265SDimitry Andric // For MachO sections indices start from 1. 11881ad6265SDimitry Andric uint32_t NextSectionIndex = 1; 11981ad6265SDimitry Andric static constexpr char TextSegmentName[] = "__TEXT"; 12081ad6265SDimitry Andric for (auto LoadCmd : MachOObj.load_commands()) { 12181ad6265SDimitry Andric LoadCommand LC; 12281ad6265SDimitry Andric switch (LoadCmd.C.cmd) { 12381ad6265SDimitry Andric case MachO::LC_CODE_SIGNATURE: 12481ad6265SDimitry Andric O.CodeSignatureCommandIndex = O.LoadCommands.size(); 12581ad6265SDimitry Andric break; 12681ad6265SDimitry Andric case MachO::LC_SEGMENT: 12781ad6265SDimitry Andric // LoadCmd.Ptr might not be aligned temporarily as 12881ad6265SDimitry Andric // MachO::segment_command requires, but the segname char pointer do not 12981ad6265SDimitry Andric // have alignment restrictions. 13081ad6265SDimitry Andric if (StringRef(reinterpret_cast<const char *>( 13181ad6265SDimitry Andric LoadCmd.Ptr + offsetof(MachO::segment_command, segname))) == 13281ad6265SDimitry Andric TextSegmentName) 13381ad6265SDimitry Andric O.TextSegmentCommandIndex = O.LoadCommands.size(); 13481ad6265SDimitry Andric 13581ad6265SDimitry Andric if (Expected<std::vector<std::unique_ptr<Section>>> Sections = 13681ad6265SDimitry Andric extractSections<MachO::section, MachO::segment_command>( 13781ad6265SDimitry Andric LoadCmd, MachOObj, NextSectionIndex)) 13881ad6265SDimitry Andric LC.Sections = std::move(*Sections); 13981ad6265SDimitry Andric else 14081ad6265SDimitry Andric return Sections.takeError(); 14181ad6265SDimitry Andric break; 14281ad6265SDimitry Andric case MachO::LC_SEGMENT_64: 14381ad6265SDimitry Andric // LoadCmd.Ptr might not be aligned temporarily as 14481ad6265SDimitry Andric // MachO::segment_command_64 requires, but the segname char pointer do 14581ad6265SDimitry Andric // not have alignment restrictions. 14681ad6265SDimitry Andric if (StringRef(reinterpret_cast<const char *>( 14781ad6265SDimitry Andric LoadCmd.Ptr + offsetof(MachO::segment_command_64, segname))) == 14881ad6265SDimitry Andric TextSegmentName) 14981ad6265SDimitry Andric O.TextSegmentCommandIndex = O.LoadCommands.size(); 15081ad6265SDimitry Andric 15181ad6265SDimitry Andric if (Expected<std::vector<std::unique_ptr<Section>>> Sections = 15281ad6265SDimitry Andric extractSections<MachO::section_64, MachO::segment_command_64>( 15381ad6265SDimitry Andric LoadCmd, MachOObj, NextSectionIndex)) 15481ad6265SDimitry Andric LC.Sections = std::move(*Sections); 15581ad6265SDimitry Andric else 15681ad6265SDimitry Andric return Sections.takeError(); 15781ad6265SDimitry Andric break; 15881ad6265SDimitry Andric case MachO::LC_SYMTAB: 15981ad6265SDimitry Andric O.SymTabCommandIndex = O.LoadCommands.size(); 16081ad6265SDimitry Andric break; 16181ad6265SDimitry Andric case MachO::LC_DYSYMTAB: 16281ad6265SDimitry Andric O.DySymTabCommandIndex = O.LoadCommands.size(); 16381ad6265SDimitry Andric break; 16481ad6265SDimitry Andric case MachO::LC_DYLD_INFO: 16581ad6265SDimitry Andric case MachO::LC_DYLD_INFO_ONLY: 16681ad6265SDimitry Andric O.DyLdInfoCommandIndex = O.LoadCommands.size(); 16781ad6265SDimitry Andric break; 16881ad6265SDimitry Andric case MachO::LC_DATA_IN_CODE: 16981ad6265SDimitry Andric O.DataInCodeCommandIndex = O.LoadCommands.size(); 17081ad6265SDimitry Andric break; 17181ad6265SDimitry Andric case MachO::LC_LINKER_OPTIMIZATION_HINT: 17281ad6265SDimitry Andric O.LinkerOptimizationHintCommandIndex = O.LoadCommands.size(); 17381ad6265SDimitry Andric break; 17481ad6265SDimitry Andric case MachO::LC_FUNCTION_STARTS: 17581ad6265SDimitry Andric O.FunctionStartsCommandIndex = O.LoadCommands.size(); 17681ad6265SDimitry Andric break; 177*bdd1243dSDimitry Andric case MachO::LC_DYLIB_CODE_SIGN_DRS: 178*bdd1243dSDimitry Andric O.DylibCodeSignDRsIndex = O.LoadCommands.size(); 179*bdd1243dSDimitry Andric break; 18081ad6265SDimitry Andric case MachO::LC_DYLD_EXPORTS_TRIE: 18181ad6265SDimitry Andric O.ExportsTrieCommandIndex = O.LoadCommands.size(); 18281ad6265SDimitry Andric break; 18381ad6265SDimitry Andric case MachO::LC_DYLD_CHAINED_FIXUPS: 18481ad6265SDimitry Andric O.ChainedFixupsCommandIndex = O.LoadCommands.size(); 18581ad6265SDimitry Andric break; 18681ad6265SDimitry Andric } 18781ad6265SDimitry Andric #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ 18881ad6265SDimitry Andric case MachO::LCName: \ 18981ad6265SDimitry Andric memcpy((void *)&(LC.MachOLoadCommand.LCStruct##_data), LoadCmd.Ptr, \ 19081ad6265SDimitry Andric sizeof(MachO::LCStruct)); \ 19181ad6265SDimitry Andric if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) \ 19281ad6265SDimitry Andric MachO::swapStruct(LC.MachOLoadCommand.LCStruct##_data); \ 19381ad6265SDimitry Andric if (LoadCmd.C.cmdsize > sizeof(MachO::LCStruct)) \ 19481ad6265SDimitry Andric LC.Payload = ArrayRef<uint8_t>( \ 19581ad6265SDimitry Andric reinterpret_cast<uint8_t *>(const_cast<char *>(LoadCmd.Ptr)) + \ 19681ad6265SDimitry Andric sizeof(MachO::LCStruct), \ 19781ad6265SDimitry Andric LoadCmd.C.cmdsize - sizeof(MachO::LCStruct)); \ 19881ad6265SDimitry Andric break; 19981ad6265SDimitry Andric 20081ad6265SDimitry Andric switch (LoadCmd.C.cmd) { 20181ad6265SDimitry Andric default: 20281ad6265SDimitry Andric memcpy((void *)&(LC.MachOLoadCommand.load_command_data), LoadCmd.Ptr, 20381ad6265SDimitry Andric sizeof(MachO::load_command)); 20481ad6265SDimitry Andric if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) 20581ad6265SDimitry Andric MachO::swapStruct(LC.MachOLoadCommand.load_command_data); 20681ad6265SDimitry Andric if (LoadCmd.C.cmdsize > sizeof(MachO::load_command)) 20781ad6265SDimitry Andric LC.Payload = ArrayRef<uint8_t>( 20881ad6265SDimitry Andric reinterpret_cast<uint8_t *>(const_cast<char *>(LoadCmd.Ptr)) + 20981ad6265SDimitry Andric sizeof(MachO::load_command), 21081ad6265SDimitry Andric LoadCmd.C.cmdsize - sizeof(MachO::load_command)); 21181ad6265SDimitry Andric break; 21281ad6265SDimitry Andric #include "llvm/BinaryFormat/MachO.def" 21381ad6265SDimitry Andric } 21481ad6265SDimitry Andric O.LoadCommands.push_back(std::move(LC)); 21581ad6265SDimitry Andric } 21681ad6265SDimitry Andric return Error::success(); 21781ad6265SDimitry Andric } 21881ad6265SDimitry Andric 21981ad6265SDimitry Andric template <typename nlist_t> 22081ad6265SDimitry Andric SymbolEntry constructSymbolEntry(StringRef StrTable, const nlist_t &nlist) { 22181ad6265SDimitry Andric assert(nlist.n_strx < StrTable.size() && 22281ad6265SDimitry Andric "n_strx exceeds the size of the string table"); 22381ad6265SDimitry Andric SymbolEntry SE; 22481ad6265SDimitry Andric SE.Name = StringRef(StrTable.data() + nlist.n_strx).str(); 22581ad6265SDimitry Andric SE.n_type = nlist.n_type; 22681ad6265SDimitry Andric SE.n_sect = nlist.n_sect; 22781ad6265SDimitry Andric SE.n_desc = nlist.n_desc; 22881ad6265SDimitry Andric SE.n_value = nlist.n_value; 22981ad6265SDimitry Andric return SE; 23081ad6265SDimitry Andric } 23181ad6265SDimitry Andric 23281ad6265SDimitry Andric void MachOReader::readSymbolTable(Object &O) const { 23381ad6265SDimitry Andric StringRef StrTable = MachOObj.getStringTableData(); 23481ad6265SDimitry Andric for (auto Symbol : MachOObj.symbols()) { 23581ad6265SDimitry Andric SymbolEntry SE = 23681ad6265SDimitry Andric (MachOObj.is64Bit() 23781ad6265SDimitry Andric ? constructSymbolEntry(StrTable, MachOObj.getSymbol64TableEntry( 23881ad6265SDimitry Andric Symbol.getRawDataRefImpl())) 23981ad6265SDimitry Andric : constructSymbolEntry(StrTable, MachOObj.getSymbolTableEntry( 24081ad6265SDimitry Andric Symbol.getRawDataRefImpl()))); 24181ad6265SDimitry Andric 24281ad6265SDimitry Andric O.SymTable.Symbols.push_back(std::make_unique<SymbolEntry>(SE)); 24381ad6265SDimitry Andric } 24481ad6265SDimitry Andric } 24581ad6265SDimitry Andric 24681ad6265SDimitry Andric void MachOReader::setSymbolInRelocationInfo(Object &O) const { 24781ad6265SDimitry Andric std::vector<const Section *> Sections; 24881ad6265SDimitry Andric for (auto &LC : O.LoadCommands) 24981ad6265SDimitry Andric for (std::unique_ptr<Section> &Sec : LC.Sections) 25081ad6265SDimitry Andric Sections.push_back(Sec.get()); 25181ad6265SDimitry Andric 25281ad6265SDimitry Andric for (LoadCommand &LC : O.LoadCommands) 25381ad6265SDimitry Andric for (std::unique_ptr<Section> &Sec : LC.Sections) 25481ad6265SDimitry Andric for (auto &Reloc : Sec->Relocations) 25581ad6265SDimitry Andric if (!Reloc.Scattered && !Reloc.IsAddend) { 25681ad6265SDimitry Andric const uint32_t SymbolNum = 25781ad6265SDimitry Andric Reloc.getPlainRelocationSymbolNum(MachOObj.isLittleEndian()); 25881ad6265SDimitry Andric if (Reloc.Extern) { 25981ad6265SDimitry Andric Reloc.Symbol = O.SymTable.getSymbolByIndex(SymbolNum); 26081ad6265SDimitry Andric } else { 26181ad6265SDimitry Andric // FIXME: Refactor error handling in MachOReader and report an error 26281ad6265SDimitry Andric // if we encounter an invalid relocation. 26381ad6265SDimitry Andric assert(SymbolNum >= 1 && SymbolNum <= Sections.size() && 26481ad6265SDimitry Andric "Invalid section index."); 26581ad6265SDimitry Andric Reloc.Sec = Sections[SymbolNum - 1]; 26681ad6265SDimitry Andric } 26781ad6265SDimitry Andric } 26881ad6265SDimitry Andric } 26981ad6265SDimitry Andric 27081ad6265SDimitry Andric void MachOReader::readRebaseInfo(Object &O) const { 27181ad6265SDimitry Andric O.Rebases.Opcodes = MachOObj.getDyldInfoRebaseOpcodes(); 27281ad6265SDimitry Andric } 27381ad6265SDimitry Andric 27481ad6265SDimitry Andric void MachOReader::readBindInfo(Object &O) const { 27581ad6265SDimitry Andric O.Binds.Opcodes = MachOObj.getDyldInfoBindOpcodes(); 27681ad6265SDimitry Andric } 27781ad6265SDimitry Andric 27881ad6265SDimitry Andric void MachOReader::readWeakBindInfo(Object &O) const { 27981ad6265SDimitry Andric O.WeakBinds.Opcodes = MachOObj.getDyldInfoWeakBindOpcodes(); 28081ad6265SDimitry Andric } 28181ad6265SDimitry Andric 28281ad6265SDimitry Andric void MachOReader::readLazyBindInfo(Object &O) const { 28381ad6265SDimitry Andric O.LazyBinds.Opcodes = MachOObj.getDyldInfoLazyBindOpcodes(); 28481ad6265SDimitry Andric } 28581ad6265SDimitry Andric 28681ad6265SDimitry Andric void MachOReader::readExportInfo(Object &O) const { 287*bdd1243dSDimitry Andric // This information can be in LC_DYLD_INFO or in LC_DYLD_EXPORTS_TRIE 288*bdd1243dSDimitry Andric ArrayRef<uint8_t> Trie = MachOObj.getDyldInfoExportsTrie(); 289*bdd1243dSDimitry Andric if (Trie.empty()) 290*bdd1243dSDimitry Andric Trie = MachOObj.getDyldExportsTrie(); 291*bdd1243dSDimitry Andric O.Exports.Trie = Trie; 29281ad6265SDimitry Andric } 29381ad6265SDimitry Andric 294*bdd1243dSDimitry Andric void MachOReader::readLinkData(Object &O, std::optional<size_t> LCIndex, 29581ad6265SDimitry Andric LinkData &LD) const { 29681ad6265SDimitry Andric if (!LCIndex) 29781ad6265SDimitry Andric return; 29881ad6265SDimitry Andric const MachO::linkedit_data_command &LC = 29981ad6265SDimitry Andric O.LoadCommands[*LCIndex].MachOLoadCommand.linkedit_data_command_data; 30081ad6265SDimitry Andric LD.Data = 30181ad6265SDimitry Andric arrayRefFromStringRef(MachOObj.getData().substr(LC.dataoff, LC.datasize)); 30281ad6265SDimitry Andric } 30381ad6265SDimitry Andric 30481ad6265SDimitry Andric void MachOReader::readDataInCodeData(Object &O) const { 30581ad6265SDimitry Andric return readLinkData(O, O.DataInCodeCommandIndex, O.DataInCode); 30681ad6265SDimitry Andric } 30781ad6265SDimitry Andric 30881ad6265SDimitry Andric void MachOReader::readLinkerOptimizationHint(Object &O) const { 30981ad6265SDimitry Andric return readLinkData(O, O.LinkerOptimizationHintCommandIndex, 31081ad6265SDimitry Andric O.LinkerOptimizationHint); 31181ad6265SDimitry Andric } 31281ad6265SDimitry Andric 31381ad6265SDimitry Andric void MachOReader::readFunctionStartsData(Object &O) const { 31481ad6265SDimitry Andric return readLinkData(O, O.FunctionStartsCommandIndex, O.FunctionStarts); 31581ad6265SDimitry Andric } 31681ad6265SDimitry Andric 317*bdd1243dSDimitry Andric void MachOReader::readDylibCodeSignDRs(Object &O) const { 318*bdd1243dSDimitry Andric return readLinkData(O, O.DylibCodeSignDRsIndex, O.DylibCodeSignDRs); 319*bdd1243dSDimitry Andric } 320*bdd1243dSDimitry Andric 32181ad6265SDimitry Andric void MachOReader::readExportsTrie(Object &O) const { 32281ad6265SDimitry Andric return readLinkData(O, O.ExportsTrieCommandIndex, O.ExportsTrie); 32381ad6265SDimitry Andric } 32481ad6265SDimitry Andric 32581ad6265SDimitry Andric void MachOReader::readChainedFixups(Object &O) const { 32681ad6265SDimitry Andric return readLinkData(O, O.ChainedFixupsCommandIndex, O.ChainedFixups); 32781ad6265SDimitry Andric } 32881ad6265SDimitry Andric 32981ad6265SDimitry Andric void MachOReader::readIndirectSymbolTable(Object &O) const { 33081ad6265SDimitry Andric MachO::dysymtab_command DySymTab = MachOObj.getDysymtabLoadCommand(); 33181ad6265SDimitry Andric constexpr uint32_t AbsOrLocalMask = 33281ad6265SDimitry Andric MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS; 33381ad6265SDimitry Andric for (uint32_t i = 0; i < DySymTab.nindirectsyms; ++i) { 33481ad6265SDimitry Andric uint32_t Index = MachOObj.getIndirectSymbolTableEntry(DySymTab, i); 33581ad6265SDimitry Andric if ((Index & AbsOrLocalMask) != 0) 336*bdd1243dSDimitry Andric O.IndirectSymTable.Symbols.emplace_back(Index, std::nullopt); 33781ad6265SDimitry Andric else 33881ad6265SDimitry Andric O.IndirectSymTable.Symbols.emplace_back( 33981ad6265SDimitry Andric Index, O.SymTable.getSymbolByIndex(Index)); 34081ad6265SDimitry Andric } 34181ad6265SDimitry Andric } 34281ad6265SDimitry Andric 34381ad6265SDimitry Andric void MachOReader::readSwiftVersion(Object &O) const { 34481ad6265SDimitry Andric struct ObjCImageInfo { 34581ad6265SDimitry Andric uint32_t Version; 34681ad6265SDimitry Andric uint32_t Flags; 34781ad6265SDimitry Andric } ImageInfo; 34881ad6265SDimitry Andric 34981ad6265SDimitry Andric for (const LoadCommand &LC : O.LoadCommands) 35081ad6265SDimitry Andric for (const std::unique_ptr<Section> &Sec : LC.Sections) 35181ad6265SDimitry Andric if (Sec->Sectname == "__objc_imageinfo" && 35281ad6265SDimitry Andric (Sec->Segname == "__DATA" || Sec->Segname == "__DATA_CONST" || 35381ad6265SDimitry Andric Sec->Segname == "__DATA_DIRTY") && 35481ad6265SDimitry Andric Sec->Content.size() >= sizeof(ObjCImageInfo)) { 35581ad6265SDimitry Andric memcpy(&ImageInfo, Sec->Content.data(), sizeof(ObjCImageInfo)); 35681ad6265SDimitry Andric if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) { 35781ad6265SDimitry Andric sys::swapByteOrder(ImageInfo.Version); 35881ad6265SDimitry Andric sys::swapByteOrder(ImageInfo.Flags); 35981ad6265SDimitry Andric } 36081ad6265SDimitry Andric O.SwiftVersion = (ImageInfo.Flags >> 8) & 0xff; 36181ad6265SDimitry Andric return; 36281ad6265SDimitry Andric } 36381ad6265SDimitry Andric } 36481ad6265SDimitry Andric 36581ad6265SDimitry Andric Expected<std::unique_ptr<Object>> MachOReader::create() const { 36681ad6265SDimitry Andric auto Obj = std::make_unique<Object>(); 36781ad6265SDimitry Andric readHeader(*Obj); 36881ad6265SDimitry Andric if (Error E = readLoadCommands(*Obj)) 36981ad6265SDimitry Andric return std::move(E); 37081ad6265SDimitry Andric readSymbolTable(*Obj); 37181ad6265SDimitry Andric setSymbolInRelocationInfo(*Obj); 37281ad6265SDimitry Andric readRebaseInfo(*Obj); 37381ad6265SDimitry Andric readBindInfo(*Obj); 37481ad6265SDimitry Andric readWeakBindInfo(*Obj); 37581ad6265SDimitry Andric readLazyBindInfo(*Obj); 37681ad6265SDimitry Andric readExportInfo(*Obj); 37781ad6265SDimitry Andric readDataInCodeData(*Obj); 37881ad6265SDimitry Andric readLinkerOptimizationHint(*Obj); 37981ad6265SDimitry Andric readFunctionStartsData(*Obj); 380*bdd1243dSDimitry Andric readDylibCodeSignDRs(*Obj); 38181ad6265SDimitry Andric readExportsTrie(*Obj); 38281ad6265SDimitry Andric readChainedFixups(*Obj); 38381ad6265SDimitry Andric readIndirectSymbolTable(*Obj); 38481ad6265SDimitry Andric readSwiftVersion(*Obj); 38581ad6265SDimitry Andric return std::move(Obj); 38681ad6265SDimitry Andric } 387