xref: /freebsd-src/contrib/llvm-project/llvm/lib/ObjCopy/MachO/MachOReader.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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