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