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