xref: /llvm-project/llvm/lib/ObjCopy/MachO/MachOReader.cpp (revision 1a830aa1fe1e88749b563fefe18382842e0cff90)
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