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