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