Path: blob/main/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp
35232 views
//===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines the MachOObjectFile class, which binds the MachOObject9// class to the generic ObjectFile wrapper.10//11//===----------------------------------------------------------------------===//1213#include "llvm/ADT/ArrayRef.h"14#include "llvm/ADT/STLExtras.h"15#include "llvm/ADT/SmallVector.h"16#include "llvm/ADT/StringRef.h"17#include "llvm/ADT/StringSwitch.h"18#include "llvm/ADT/Twine.h"19#include "llvm/ADT/bit.h"20#include "llvm/BinaryFormat/MachO.h"21#include "llvm/BinaryFormat/Swift.h"22#include "llvm/Object/Error.h"23#include "llvm/Object/MachO.h"24#include "llvm/Object/ObjectFile.h"25#include "llvm/Object/SymbolicFile.h"26#include "llvm/Support/DataExtractor.h"27#include "llvm/Support/Debug.h"28#include "llvm/Support/Errc.h"29#include "llvm/Support/Error.h"30#include "llvm/Support/ErrorHandling.h"31#include "llvm/Support/FileSystem.h"32#include "llvm/Support/Format.h"33#include "llvm/Support/LEB128.h"34#include "llvm/Support/MemoryBufferRef.h"35#include "llvm/Support/Path.h"36#include "llvm/Support/SwapByteOrder.h"37#include "llvm/Support/raw_ostream.h"38#include "llvm/TargetParser/Host.h"39#include "llvm/TargetParser/Triple.h"40#include <algorithm>41#include <cassert>42#include <cstddef>43#include <cstdint>44#include <cstring>45#include <limits>46#include <list>47#include <memory>48#include <system_error>4950using namespace llvm;51using namespace object;5253namespace {5455struct section_base {56char sectname[16];57char segname[16];58};5960} // end anonymous namespace6162static Error malformedError(const Twine &Msg) {63return make_error<GenericBinaryError>("truncated or malformed object (" +64Msg + ")",65object_error::parse_failed);66}6768// FIXME: Replace all uses of this function with getStructOrErr.69template <typename T>70static T getStruct(const MachOObjectFile &O, const char *P) {71// Don't read before the beginning or past the end of the file72if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())73report_fatal_error("Malformed MachO file.");7475T Cmd;76memcpy(&Cmd, P, sizeof(T));77if (O.isLittleEndian() != sys::IsLittleEndianHost)78MachO::swapStruct(Cmd);79return Cmd;80}8182template <typename T>83static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {84// Don't read before the beginning or past the end of the file85if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())86return malformedError("Structure read out-of-range");8788T Cmd;89memcpy(&Cmd, P, sizeof(T));90if (O.isLittleEndian() != sys::IsLittleEndianHost)91MachO::swapStruct(Cmd);92return Cmd;93}9495static const char *96getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,97unsigned Sec) {98uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);99100bool Is64 = O.is64Bit();101unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :102sizeof(MachO::segment_command);103unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :104sizeof(MachO::section);105106uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;107return reinterpret_cast<const char*>(SectionAddr);108}109110static const char *getPtr(const MachOObjectFile &O, size_t Offset,111size_t MachOFilesetEntryOffset = 0) {112assert(Offset <= O.getData().size() &&113MachOFilesetEntryOffset <= O.getData().size());114return O.getData().data() + Offset + MachOFilesetEntryOffset;115}116117static MachO::nlist_base118getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {119const char *P = reinterpret_cast<const char *>(DRI.p);120return getStruct<MachO::nlist_base>(O, P);121}122123static StringRef parseSegmentOrSectionName(const char *P) {124if (P[15] == 0)125// Null terminated.126return P;127// Not null terminated, so this is a 16 char string.128return StringRef(P, 16);129}130131static unsigned getCPUType(const MachOObjectFile &O) {132return O.getHeader().cputype;133}134135static unsigned getCPUSubType(const MachOObjectFile &O) {136return O.getHeader().cpusubtype;137}138139static uint32_t140getPlainRelocationAddress(const MachO::any_relocation_info &RE) {141return RE.r_word0;142}143144static unsigned145getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {146return RE.r_word0 & 0xffffff;147}148149static bool getPlainRelocationPCRel(const MachOObjectFile &O,150const MachO::any_relocation_info &RE) {151if (O.isLittleEndian())152return (RE.r_word1 >> 24) & 1;153return (RE.r_word1 >> 7) & 1;154}155156static bool157getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {158return (RE.r_word0 >> 30) & 1;159}160161static unsigned getPlainRelocationLength(const MachOObjectFile &O,162const MachO::any_relocation_info &RE) {163if (O.isLittleEndian())164return (RE.r_word1 >> 25) & 3;165return (RE.r_word1 >> 5) & 3;166}167168static unsigned169getScatteredRelocationLength(const MachO::any_relocation_info &RE) {170return (RE.r_word0 >> 28) & 3;171}172173static unsigned getPlainRelocationType(const MachOObjectFile &O,174const MachO::any_relocation_info &RE) {175if (O.isLittleEndian())176return RE.r_word1 >> 28;177return RE.r_word1 & 0xf;178}179180static uint32_t getSectionFlags(const MachOObjectFile &O,181DataRefImpl Sec) {182if (O.is64Bit()) {183MachO::section_64 Sect = O.getSection64(Sec);184return Sect.flags;185}186MachO::section Sect = O.getSection(Sec);187return Sect.flags;188}189190static Expected<MachOObjectFile::LoadCommandInfo>191getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,192uint32_t LoadCommandIndex) {193if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {194if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())195return malformedError("load command " + Twine(LoadCommandIndex) +196" extends past end of file");197if (CmdOrErr->cmdsize < 8)198return malformedError("load command " + Twine(LoadCommandIndex) +199" with size less than 8 bytes");200return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});201} else202return CmdOrErr.takeError();203}204205static Expected<MachOObjectFile::LoadCommandInfo>206getFirstLoadCommandInfo(const MachOObjectFile &Obj) {207unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)208: sizeof(MachO::mach_header);209if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)210return malformedError("load command 0 extends past the end all load "211"commands in the file");212return getLoadCommandInfo(213Obj, getPtr(Obj, HeaderSize, Obj.getMachOFilesetEntryOffset()), 0);214}215216static Expected<MachOObjectFile::LoadCommandInfo>217getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,218const MachOObjectFile::LoadCommandInfo &L) {219unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)220: sizeof(MachO::mach_header);221if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >222Obj.getData().data() + Obj.getMachOFilesetEntryOffset() + HeaderSize +223Obj.getHeader().sizeofcmds)224return malformedError("load command " + Twine(LoadCommandIndex + 1) +225" extends past the end all load commands in the file");226return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);227}228229template <typename T>230static void parseHeader(const MachOObjectFile &Obj, T &Header,231Error &Err) {232if (sizeof(T) > Obj.getData().size()) {233Err = malformedError("the mach header extends past the end of the "234"file");235return;236}237if (auto HeaderOrErr = getStructOrErr<T>(238Obj, getPtr(Obj, 0, Obj.getMachOFilesetEntryOffset())))239Header = *HeaderOrErr;240else241Err = HeaderOrErr.takeError();242}243244// This is used to check for overlapping of Mach-O elements.245struct MachOElement {246uint64_t Offset;247uint64_t Size;248const char *Name;249};250251static Error checkOverlappingElement(std::list<MachOElement> &Elements,252uint64_t Offset, uint64_t Size,253const char *Name) {254if (Size == 0)255return Error::success();256257for (auto it = Elements.begin(); it != Elements.end(); ++it) {258const auto &E = *it;259if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||260(Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||261(Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))262return malformedError(Twine(Name) + " at offset " + Twine(Offset) +263" with a size of " + Twine(Size) + ", overlaps " +264E.Name + " at offset " + Twine(E.Offset) + " with "265"a size of " + Twine(E.Size));266auto nt = it;267nt++;268if (nt != Elements.end()) {269const auto &N = *nt;270if (Offset + Size <= N.Offset) {271Elements.insert(nt, {Offset, Size, Name});272return Error::success();273}274}275}276Elements.push_back({Offset, Size, Name});277return Error::success();278}279280// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all281// sections to \param Sections, and optionally sets282// \param IsPageZeroSegment to true.283template <typename Segment, typename Section>284static Error parseSegmentLoadCommand(285const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,286SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,287uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,288std::list<MachOElement> &Elements) {289const unsigned SegmentLoadSize = sizeof(Segment);290if (Load.C.cmdsize < SegmentLoadSize)291return malformedError("load command " + Twine(LoadCommandIndex) +292" " + CmdName + " cmdsize too small");293if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {294Segment S = SegOrErr.get();295const unsigned SectionSize = sizeof(Section);296uint64_t FileSize = Obj.getData().size();297if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||298S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)299return malformedError("load command " + Twine(LoadCommandIndex) +300" inconsistent cmdsize in " + CmdName +301" for the number of sections");302for (unsigned J = 0; J < S.nsects; ++J) {303const char *Sec = getSectionPtr(Obj, Load, J);304Sections.push_back(Sec);305auto SectionOrErr = getStructOrErr<Section>(Obj, Sec);306if (!SectionOrErr)307return SectionOrErr.takeError();308Section s = SectionOrErr.get();309if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&310Obj.getHeader().filetype != MachO::MH_DSYM &&311s.flags != MachO::S_ZEROFILL &&312s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&313s.offset > FileSize)314return malformedError("offset field of section " + Twine(J) + " in " +315CmdName + " command " + Twine(LoadCommandIndex) +316" extends past the end of the file");317if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&318Obj.getHeader().filetype != MachO::MH_DSYM &&319s.flags != MachO::S_ZEROFILL &&320s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&321s.offset < SizeOfHeaders && s.size != 0)322return malformedError("offset field of section " + Twine(J) + " in " +323CmdName + " command " + Twine(LoadCommandIndex) +324" not past the headers of the file");325uint64_t BigSize = s.offset;326BigSize += s.size;327if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&328Obj.getHeader().filetype != MachO::MH_DSYM &&329s.flags != MachO::S_ZEROFILL &&330s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&331BigSize > FileSize)332return malformedError("offset field plus size field of section " +333Twine(J) + " in " + CmdName + " command " +334Twine(LoadCommandIndex) +335" extends past the end of the file");336if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&337Obj.getHeader().filetype != MachO::MH_DSYM &&338s.flags != MachO::S_ZEROFILL &&339s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&340s.size > S.filesize)341return malformedError("size field of section " +342Twine(J) + " in " + CmdName + " command " +343Twine(LoadCommandIndex) +344" greater than the segment");345if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&346Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&347s.addr < S.vmaddr)348return malformedError("addr field of section " + Twine(J) + " in " +349CmdName + " command " + Twine(LoadCommandIndex) +350" less than the segment's vmaddr");351BigSize = s.addr;352BigSize += s.size;353uint64_t BigEnd = S.vmaddr;354BigEnd += S.vmsize;355if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)356return malformedError("addr field plus size of section " + Twine(J) +357" in " + CmdName + " command " +358Twine(LoadCommandIndex) +359" greater than than "360"the segment's vmaddr plus vmsize");361if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&362Obj.getHeader().filetype != MachO::MH_DSYM &&363s.flags != MachO::S_ZEROFILL &&364s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)365if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,366"section contents"))367return Err;368if (s.reloff > FileSize)369return malformedError("reloff field of section " + Twine(J) + " in " +370CmdName + " command " + Twine(LoadCommandIndex) +371" extends past the end of the file");372BigSize = s.nreloc;373BigSize *= sizeof(struct MachO::relocation_info);374BigSize += s.reloff;375if (BigSize > FileSize)376return malformedError("reloff field plus nreloc field times sizeof("377"struct relocation_info) of section " +378Twine(J) + " in " + CmdName + " command " +379Twine(LoadCommandIndex) +380" extends past the end of the file");381if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *382sizeof(struct383MachO::relocation_info),384"section relocation entries"))385return Err;386}387if (S.fileoff > FileSize)388return malformedError("load command " + Twine(LoadCommandIndex) +389" fileoff field in " + CmdName +390" extends past the end of the file");391uint64_t BigSize = S.fileoff;392BigSize += S.filesize;393if (BigSize > FileSize)394return malformedError("load command " + Twine(LoadCommandIndex) +395" fileoff field plus filesize field in " +396CmdName + " extends past the end of the file");397if (S.vmsize != 0 && S.filesize > S.vmsize)398return malformedError("load command " + Twine(LoadCommandIndex) +399" filesize field in " + CmdName +400" greater than vmsize field");401IsPageZeroSegment |= StringRef("__PAGEZERO") == S.segname;402} else403return SegOrErr.takeError();404405return Error::success();406}407408static Error checkSymtabCommand(const MachOObjectFile &Obj,409const MachOObjectFile::LoadCommandInfo &Load,410uint32_t LoadCommandIndex,411const char **SymtabLoadCmd,412std::list<MachOElement> &Elements) {413if (Load.C.cmdsize < sizeof(MachO::symtab_command))414return malformedError("load command " + Twine(LoadCommandIndex) +415" LC_SYMTAB cmdsize too small");416if (*SymtabLoadCmd != nullptr)417return malformedError("more than one LC_SYMTAB command");418auto SymtabOrErr = getStructOrErr<MachO::symtab_command>(Obj, Load.Ptr);419if (!SymtabOrErr)420return SymtabOrErr.takeError();421MachO::symtab_command Symtab = SymtabOrErr.get();422if (Symtab.cmdsize != sizeof(MachO::symtab_command))423return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +424" has incorrect cmdsize");425uint64_t FileSize = Obj.getData().size();426if (Symtab.symoff > FileSize)427return malformedError("symoff field of LC_SYMTAB command " +428Twine(LoadCommandIndex) + " extends past the end "429"of the file");430uint64_t SymtabSize = Symtab.nsyms;431const char *struct_nlist_name;432if (Obj.is64Bit()) {433SymtabSize *= sizeof(MachO::nlist_64);434struct_nlist_name = "struct nlist_64";435} else {436SymtabSize *= sizeof(MachO::nlist);437struct_nlist_name = "struct nlist";438}439uint64_t BigSize = SymtabSize;440BigSize += Symtab.symoff;441if (BigSize > FileSize)442return malformedError("symoff field plus nsyms field times sizeof(" +443Twine(struct_nlist_name) + ") of LC_SYMTAB command " +444Twine(LoadCommandIndex) + " extends past the end "445"of the file");446if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,447"symbol table"))448return Err;449if (Symtab.stroff > FileSize)450return malformedError("stroff field of LC_SYMTAB command " +451Twine(LoadCommandIndex) + " extends past the end "452"of the file");453BigSize = Symtab.stroff;454BigSize += Symtab.strsize;455if (BigSize > FileSize)456return malformedError("stroff field plus strsize field of LC_SYMTAB "457"command " + Twine(LoadCommandIndex) + " extends "458"past the end of the file");459if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,460Symtab.strsize, "string table"))461return Err;462*SymtabLoadCmd = Load.Ptr;463return Error::success();464}465466static Error checkDysymtabCommand(const MachOObjectFile &Obj,467const MachOObjectFile::LoadCommandInfo &Load,468uint32_t LoadCommandIndex,469const char **DysymtabLoadCmd,470std::list<MachOElement> &Elements) {471if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))472return malformedError("load command " + Twine(LoadCommandIndex) +473" LC_DYSYMTAB cmdsize too small");474if (*DysymtabLoadCmd != nullptr)475return malformedError("more than one LC_DYSYMTAB command");476auto DysymtabOrErr =477getStructOrErr<MachO::dysymtab_command>(Obj, Load.Ptr);478if (!DysymtabOrErr)479return DysymtabOrErr.takeError();480MachO::dysymtab_command Dysymtab = DysymtabOrErr.get();481if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))482return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +483" has incorrect cmdsize");484uint64_t FileSize = Obj.getData().size();485if (Dysymtab.tocoff > FileSize)486return malformedError("tocoff field of LC_DYSYMTAB command " +487Twine(LoadCommandIndex) + " extends past the end of "488"the file");489uint64_t BigSize = Dysymtab.ntoc;490BigSize *= sizeof(MachO::dylib_table_of_contents);491BigSize += Dysymtab.tocoff;492if (BigSize > FileSize)493return malformedError("tocoff field plus ntoc field times sizeof(struct "494"dylib_table_of_contents) of LC_DYSYMTAB command " +495Twine(LoadCommandIndex) + " extends past the end of "496"the file");497if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,498Dysymtab.ntoc * sizeof(struct499MachO::dylib_table_of_contents),500"table of contents"))501return Err;502if (Dysymtab.modtaboff > FileSize)503return malformedError("modtaboff field of LC_DYSYMTAB command " +504Twine(LoadCommandIndex) + " extends past the end of "505"the file");506BigSize = Dysymtab.nmodtab;507const char *struct_dylib_module_name;508uint64_t sizeof_modtab;509if (Obj.is64Bit()) {510sizeof_modtab = sizeof(MachO::dylib_module_64);511struct_dylib_module_name = "struct dylib_module_64";512} else {513sizeof_modtab = sizeof(MachO::dylib_module);514struct_dylib_module_name = "struct dylib_module";515}516BigSize *= sizeof_modtab;517BigSize += Dysymtab.modtaboff;518if (BigSize > FileSize)519return malformedError("modtaboff field plus nmodtab field times sizeof(" +520Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "521"command " + Twine(LoadCommandIndex) + " extends "522"past the end of the file");523if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,524Dysymtab.nmodtab * sizeof_modtab,525"module table"))526return Err;527if (Dysymtab.extrefsymoff > FileSize)528return malformedError("extrefsymoff field of LC_DYSYMTAB command " +529Twine(LoadCommandIndex) + " extends past the end of "530"the file");531BigSize = Dysymtab.nextrefsyms;532BigSize *= sizeof(MachO::dylib_reference);533BigSize += Dysymtab.extrefsymoff;534if (BigSize > FileSize)535return malformedError("extrefsymoff field plus nextrefsyms field times "536"sizeof(struct dylib_reference) of LC_DYSYMTAB "537"command " + Twine(LoadCommandIndex) + " extends "538"past the end of the file");539if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,540Dysymtab.nextrefsyms *541sizeof(MachO::dylib_reference),542"reference table"))543return Err;544if (Dysymtab.indirectsymoff > FileSize)545return malformedError("indirectsymoff field of LC_DYSYMTAB command " +546Twine(LoadCommandIndex) + " extends past the end of "547"the file");548BigSize = Dysymtab.nindirectsyms;549BigSize *= sizeof(uint32_t);550BigSize += Dysymtab.indirectsymoff;551if (BigSize > FileSize)552return malformedError("indirectsymoff field plus nindirectsyms field times "553"sizeof(uint32_t) of LC_DYSYMTAB command " +554Twine(LoadCommandIndex) + " extends past the end of "555"the file");556if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,557Dysymtab.nindirectsyms *558sizeof(uint32_t),559"indirect table"))560return Err;561if (Dysymtab.extreloff > FileSize)562return malformedError("extreloff field of LC_DYSYMTAB command " +563Twine(LoadCommandIndex) + " extends past the end of "564"the file");565BigSize = Dysymtab.nextrel;566BigSize *= sizeof(MachO::relocation_info);567BigSize += Dysymtab.extreloff;568if (BigSize > FileSize)569return malformedError("extreloff field plus nextrel field times sizeof"570"(struct relocation_info) of LC_DYSYMTAB command " +571Twine(LoadCommandIndex) + " extends past the end of "572"the file");573if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,574Dysymtab.nextrel *575sizeof(MachO::relocation_info),576"external relocation table"))577return Err;578if (Dysymtab.locreloff > FileSize)579return malformedError("locreloff field of LC_DYSYMTAB command " +580Twine(LoadCommandIndex) + " extends past the end of "581"the file");582BigSize = Dysymtab.nlocrel;583BigSize *= sizeof(MachO::relocation_info);584BigSize += Dysymtab.locreloff;585if (BigSize > FileSize)586return malformedError("locreloff field plus nlocrel field times sizeof"587"(struct relocation_info) of LC_DYSYMTAB command " +588Twine(LoadCommandIndex) + " extends past the end of "589"the file");590if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,591Dysymtab.nlocrel *592sizeof(MachO::relocation_info),593"local relocation table"))594return Err;595*DysymtabLoadCmd = Load.Ptr;596return Error::success();597}598599static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,600const MachOObjectFile::LoadCommandInfo &Load,601uint32_t LoadCommandIndex,602const char **LoadCmd, const char *CmdName,603std::list<MachOElement> &Elements,604const char *ElementName) {605if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))606return malformedError("load command " + Twine(LoadCommandIndex) + " " +607CmdName + " cmdsize too small");608if (*LoadCmd != nullptr)609return malformedError("more than one " + Twine(CmdName) + " command");610auto LinkDataOrError =611getStructOrErr<MachO::linkedit_data_command>(Obj, Load.Ptr);612if (!LinkDataOrError)613return LinkDataOrError.takeError();614MachO::linkedit_data_command LinkData = LinkDataOrError.get();615if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))616return malformedError(Twine(CmdName) + " command " +617Twine(LoadCommandIndex) + " has incorrect cmdsize");618uint64_t FileSize = Obj.getData().size();619if (LinkData.dataoff > FileSize)620return malformedError("dataoff field of " + Twine(CmdName) + " command " +621Twine(LoadCommandIndex) + " extends past the end of "622"the file");623uint64_t BigSize = LinkData.dataoff;624BigSize += LinkData.datasize;625if (BigSize > FileSize)626return malformedError("dataoff field plus datasize field of " +627Twine(CmdName) + " command " +628Twine(LoadCommandIndex) + " extends past the end of "629"the file");630if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,631LinkData.datasize, ElementName))632return Err;633*LoadCmd = Load.Ptr;634return Error::success();635}636637static Error checkDyldInfoCommand(const MachOObjectFile &Obj,638const MachOObjectFile::LoadCommandInfo &Load,639uint32_t LoadCommandIndex,640const char **LoadCmd, const char *CmdName,641std::list<MachOElement> &Elements) {642if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))643return malformedError("load command " + Twine(LoadCommandIndex) + " " +644CmdName + " cmdsize too small");645if (*LoadCmd != nullptr)646return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "647"command");648auto DyldInfoOrErr =649getStructOrErr<MachO::dyld_info_command>(Obj, Load.Ptr);650if (!DyldInfoOrErr)651return DyldInfoOrErr.takeError();652MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();653if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))654return malformedError(Twine(CmdName) + " command " +655Twine(LoadCommandIndex) + " has incorrect cmdsize");656uint64_t FileSize = Obj.getData().size();657if (DyldInfo.rebase_off > FileSize)658return malformedError("rebase_off field of " + Twine(CmdName) +659" command " + Twine(LoadCommandIndex) + " extends "660"past the end of the file");661uint64_t BigSize = DyldInfo.rebase_off;662BigSize += DyldInfo.rebase_size;663if (BigSize > FileSize)664return malformedError("rebase_off field plus rebase_size field of " +665Twine(CmdName) + " command " +666Twine(LoadCommandIndex) + " extends past the end of "667"the file");668if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,669DyldInfo.rebase_size,670"dyld rebase info"))671return Err;672if (DyldInfo.bind_off > FileSize)673return malformedError("bind_off field of " + Twine(CmdName) +674" command " + Twine(LoadCommandIndex) + " extends "675"past the end of the file");676BigSize = DyldInfo.bind_off;677BigSize += DyldInfo.bind_size;678if (BigSize > FileSize)679return malformedError("bind_off field plus bind_size field of " +680Twine(CmdName) + " command " +681Twine(LoadCommandIndex) + " extends past the end of "682"the file");683if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,684DyldInfo.bind_size,685"dyld bind info"))686return Err;687if (DyldInfo.weak_bind_off > FileSize)688return malformedError("weak_bind_off field of " + Twine(CmdName) +689" command " + Twine(LoadCommandIndex) + " extends "690"past the end of the file");691BigSize = DyldInfo.weak_bind_off;692BigSize += DyldInfo.weak_bind_size;693if (BigSize > FileSize)694return malformedError("weak_bind_off field plus weak_bind_size field of " +695Twine(CmdName) + " command " +696Twine(LoadCommandIndex) + " extends past the end of "697"the file");698if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,699DyldInfo.weak_bind_size,700"dyld weak bind info"))701return Err;702if (DyldInfo.lazy_bind_off > FileSize)703return malformedError("lazy_bind_off field of " + Twine(CmdName) +704" command " + Twine(LoadCommandIndex) + " extends "705"past the end of the file");706BigSize = DyldInfo.lazy_bind_off;707BigSize += DyldInfo.lazy_bind_size;708if (BigSize > FileSize)709return malformedError("lazy_bind_off field plus lazy_bind_size field of " +710Twine(CmdName) + " command " +711Twine(LoadCommandIndex) + " extends past the end of "712"the file");713if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,714DyldInfo.lazy_bind_size,715"dyld lazy bind info"))716return Err;717if (DyldInfo.export_off > FileSize)718return malformedError("export_off field of " + Twine(CmdName) +719" command " + Twine(LoadCommandIndex) + " extends "720"past the end of the file");721BigSize = DyldInfo.export_off;722BigSize += DyldInfo.export_size;723if (BigSize > FileSize)724return malformedError("export_off field plus export_size field of " +725Twine(CmdName) + " command " +726Twine(LoadCommandIndex) + " extends past the end of "727"the file");728if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,729DyldInfo.export_size,730"dyld export info"))731return Err;732*LoadCmd = Load.Ptr;733return Error::success();734}735736static Error checkDylibCommand(const MachOObjectFile &Obj,737const MachOObjectFile::LoadCommandInfo &Load,738uint32_t LoadCommandIndex, const char *CmdName) {739if (Load.C.cmdsize < sizeof(MachO::dylib_command))740return malformedError("load command " + Twine(LoadCommandIndex) + " " +741CmdName + " cmdsize too small");742auto CommandOrErr = getStructOrErr<MachO::dylib_command>(Obj, Load.Ptr);743if (!CommandOrErr)744return CommandOrErr.takeError();745MachO::dylib_command D = CommandOrErr.get();746if (D.dylib.name < sizeof(MachO::dylib_command))747return malformedError("load command " + Twine(LoadCommandIndex) + " " +748CmdName + " name.offset field too small, not past "749"the end of the dylib_command struct");750if (D.dylib.name >= D.cmdsize)751return malformedError("load command " + Twine(LoadCommandIndex) + " " +752CmdName + " name.offset field extends past the end "753"of the load command");754// Make sure there is a null between the starting offset of the name and755// the end of the load command.756uint32_t i;757const char *P = (const char *)Load.Ptr;758for (i = D.dylib.name; i < D.cmdsize; i++)759if (P[i] == '\0')760break;761if (i >= D.cmdsize)762return malformedError("load command " + Twine(LoadCommandIndex) + " " +763CmdName + " library name extends past the end of the "764"load command");765return Error::success();766}767768static Error checkDylibIdCommand(const MachOObjectFile &Obj,769const MachOObjectFile::LoadCommandInfo &Load,770uint32_t LoadCommandIndex,771const char **LoadCmd) {772if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,773"LC_ID_DYLIB"))774return Err;775if (*LoadCmd != nullptr)776return malformedError("more than one LC_ID_DYLIB command");777if (Obj.getHeader().filetype != MachO::MH_DYLIB &&778Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)779return malformedError("LC_ID_DYLIB load command in non-dynamic library "780"file type");781*LoadCmd = Load.Ptr;782return Error::success();783}784785static Error checkDyldCommand(const MachOObjectFile &Obj,786const MachOObjectFile::LoadCommandInfo &Load,787uint32_t LoadCommandIndex, const char *CmdName) {788if (Load.C.cmdsize < sizeof(MachO::dylinker_command))789return malformedError("load command " + Twine(LoadCommandIndex) + " " +790CmdName + " cmdsize too small");791auto CommandOrErr = getStructOrErr<MachO::dylinker_command>(Obj, Load.Ptr);792if (!CommandOrErr)793return CommandOrErr.takeError();794MachO::dylinker_command D = CommandOrErr.get();795if (D.name < sizeof(MachO::dylinker_command))796return malformedError("load command " + Twine(LoadCommandIndex) + " " +797CmdName + " name.offset field too small, not past "798"the end of the dylinker_command struct");799if (D.name >= D.cmdsize)800return malformedError("load command " + Twine(LoadCommandIndex) + " " +801CmdName + " name.offset field extends past the end "802"of the load command");803// Make sure there is a null between the starting offset of the name and804// the end of the load command.805uint32_t i;806const char *P = (const char *)Load.Ptr;807for (i = D.name; i < D.cmdsize; i++)808if (P[i] == '\0')809break;810if (i >= D.cmdsize)811return malformedError("load command " + Twine(LoadCommandIndex) + " " +812CmdName + " dyld name extends past the end of the "813"load command");814return Error::success();815}816817static Error checkVersCommand(const MachOObjectFile &Obj,818const MachOObjectFile::LoadCommandInfo &Load,819uint32_t LoadCommandIndex,820const char **LoadCmd, const char *CmdName) {821if (Load.C.cmdsize != sizeof(MachO::version_min_command))822return malformedError("load command " + Twine(LoadCommandIndex) + " " +823CmdName + " has incorrect cmdsize");824if (*LoadCmd != nullptr)825return malformedError("more than one LC_VERSION_MIN_MACOSX, "826"LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "827"LC_VERSION_MIN_WATCHOS command");828*LoadCmd = Load.Ptr;829return Error::success();830}831832static Error checkNoteCommand(const MachOObjectFile &Obj,833const MachOObjectFile::LoadCommandInfo &Load,834uint32_t LoadCommandIndex,835std::list<MachOElement> &Elements) {836if (Load.C.cmdsize != sizeof(MachO::note_command))837return malformedError("load command " + Twine(LoadCommandIndex) +838" LC_NOTE has incorrect cmdsize");839auto NoteCmdOrErr = getStructOrErr<MachO::note_command>(Obj, Load.Ptr);840if (!NoteCmdOrErr)841return NoteCmdOrErr.takeError();842MachO::note_command Nt = NoteCmdOrErr.get();843uint64_t FileSize = Obj.getData().size();844if (Nt.offset > FileSize)845return malformedError("offset field of LC_NOTE command " +846Twine(LoadCommandIndex) + " extends "847"past the end of the file");848uint64_t BigSize = Nt.offset;849BigSize += Nt.size;850if (BigSize > FileSize)851return malformedError("size field plus offset field of LC_NOTE command " +852Twine(LoadCommandIndex) + " extends past the end of "853"the file");854if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,855"LC_NOTE data"))856return Err;857return Error::success();858}859860static Error861parseBuildVersionCommand(const MachOObjectFile &Obj,862const MachOObjectFile::LoadCommandInfo &Load,863SmallVectorImpl<const char*> &BuildTools,864uint32_t LoadCommandIndex) {865auto BVCOrErr =866getStructOrErr<MachO::build_version_command>(Obj, Load.Ptr);867if (!BVCOrErr)868return BVCOrErr.takeError();869MachO::build_version_command BVC = BVCOrErr.get();870if (Load.C.cmdsize !=871sizeof(MachO::build_version_command) +872BVC.ntools * sizeof(MachO::build_tool_version))873return malformedError("load command " + Twine(LoadCommandIndex) +874" LC_BUILD_VERSION_COMMAND has incorrect cmdsize");875876auto Start = Load.Ptr + sizeof(MachO::build_version_command);877BuildTools.resize(BVC.ntools);878for (unsigned i = 0; i < BVC.ntools; ++i)879BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);880881return Error::success();882}883884static Error checkRpathCommand(const MachOObjectFile &Obj,885const MachOObjectFile::LoadCommandInfo &Load,886uint32_t LoadCommandIndex) {887if (Load.C.cmdsize < sizeof(MachO::rpath_command))888return malformedError("load command " + Twine(LoadCommandIndex) +889" LC_RPATH cmdsize too small");890auto ROrErr = getStructOrErr<MachO::rpath_command>(Obj, Load.Ptr);891if (!ROrErr)892return ROrErr.takeError();893MachO::rpath_command R = ROrErr.get();894if (R.path < sizeof(MachO::rpath_command))895return malformedError("load command " + Twine(LoadCommandIndex) +896" LC_RPATH path.offset field too small, not past "897"the end of the rpath_command struct");898if (R.path >= R.cmdsize)899return malformedError("load command " + Twine(LoadCommandIndex) +900" LC_RPATH path.offset field extends past the end "901"of the load command");902// Make sure there is a null between the starting offset of the path and903// the end of the load command.904uint32_t i;905const char *P = (const char *)Load.Ptr;906for (i = R.path; i < R.cmdsize; i++)907if (P[i] == '\0')908break;909if (i >= R.cmdsize)910return malformedError("load command " + Twine(LoadCommandIndex) +911" LC_RPATH library name extends past the end of the "912"load command");913return Error::success();914}915916static Error checkEncryptCommand(const MachOObjectFile &Obj,917const MachOObjectFile::LoadCommandInfo &Load,918uint32_t LoadCommandIndex,919uint64_t cryptoff, uint64_t cryptsize,920const char **LoadCmd, const char *CmdName) {921if (*LoadCmd != nullptr)922return malformedError("more than one LC_ENCRYPTION_INFO and or "923"LC_ENCRYPTION_INFO_64 command");924uint64_t FileSize = Obj.getData().size();925if (cryptoff > FileSize)926return malformedError("cryptoff field of " + Twine(CmdName) +927" command " + Twine(LoadCommandIndex) + " extends "928"past the end of the file");929uint64_t BigSize = cryptoff;930BigSize += cryptsize;931if (BigSize > FileSize)932return malformedError("cryptoff field plus cryptsize field of " +933Twine(CmdName) + " command " +934Twine(LoadCommandIndex) + " extends past the end of "935"the file");936*LoadCmd = Load.Ptr;937return Error::success();938}939940static Error checkLinkerOptCommand(const MachOObjectFile &Obj,941const MachOObjectFile::LoadCommandInfo &Load,942uint32_t LoadCommandIndex) {943if (Load.C.cmdsize < sizeof(MachO::linker_option_command))944return malformedError("load command " + Twine(LoadCommandIndex) +945" LC_LINKER_OPTION cmdsize too small");946auto LinkOptionOrErr =947getStructOrErr<MachO::linker_option_command>(Obj, Load.Ptr);948if (!LinkOptionOrErr)949return LinkOptionOrErr.takeError();950MachO::linker_option_command L = LinkOptionOrErr.get();951// Make sure the count of strings is correct.952const char *string = (const char *)Load.Ptr +953sizeof(struct MachO::linker_option_command);954uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);955uint32_t i = 0;956while (left > 0) {957while (*string == '\0' && left > 0) {958string++;959left--;960}961if (left > 0) {962i++;963uint32_t NullPos = StringRef(string, left).find('\0');964if (0xffffffff == NullPos)965return malformedError("load command " + Twine(LoadCommandIndex) +966" LC_LINKER_OPTION string #" + Twine(i) +967" is not NULL terminated");968uint32_t len = std::min(NullPos, left) + 1;969string += len;970left -= len;971}972}973if (L.count != i)974return malformedError("load command " + Twine(LoadCommandIndex) +975" LC_LINKER_OPTION string count " + Twine(L.count) +976" does not match number of strings");977return Error::success();978}979980static Error checkSubCommand(const MachOObjectFile &Obj,981const MachOObjectFile::LoadCommandInfo &Load,982uint32_t LoadCommandIndex, const char *CmdName,983size_t SizeOfCmd, const char *CmdStructName,984uint32_t PathOffset, const char *PathFieldName) {985if (PathOffset < SizeOfCmd)986return malformedError("load command " + Twine(LoadCommandIndex) + " " +987CmdName + " " + PathFieldName + ".offset field too "988"small, not past the end of the " + CmdStructName);989if (PathOffset >= Load.C.cmdsize)990return malformedError("load command " + Twine(LoadCommandIndex) + " " +991CmdName + " " + PathFieldName + ".offset field "992"extends past the end of the load command");993// Make sure there is a null between the starting offset of the path and994// the end of the load command.995uint32_t i;996const char *P = (const char *)Load.Ptr;997for (i = PathOffset; i < Load.C.cmdsize; i++)998if (P[i] == '\0')999break;1000if (i >= Load.C.cmdsize)1001return malformedError("load command " + Twine(LoadCommandIndex) + " " +1002CmdName + " " + PathFieldName + " name extends past "1003"the end of the load command");1004return Error::success();1005}10061007static Error checkThreadCommand(const MachOObjectFile &Obj,1008const MachOObjectFile::LoadCommandInfo &Load,1009uint32_t LoadCommandIndex,1010const char *CmdName) {1011if (Load.C.cmdsize < sizeof(MachO::thread_command))1012return malformedError("load command " + Twine(LoadCommandIndex) +1013CmdName + " cmdsize too small");1014auto ThreadCommandOrErr =1015getStructOrErr<MachO::thread_command>(Obj, Load.Ptr);1016if (!ThreadCommandOrErr)1017return ThreadCommandOrErr.takeError();1018MachO::thread_command T = ThreadCommandOrErr.get();1019const char *state = Load.Ptr + sizeof(MachO::thread_command);1020const char *end = Load.Ptr + T.cmdsize;1021uint32_t nflavor = 0;1022uint32_t cputype = getCPUType(Obj);1023while (state < end) {1024if(state + sizeof(uint32_t) > end)1025return malformedError("load command " + Twine(LoadCommandIndex) +1026"flavor in " + CmdName + " extends past end of "1027"command");1028uint32_t flavor;1029memcpy(&flavor, state, sizeof(uint32_t));1030if (Obj.isLittleEndian() != sys::IsLittleEndianHost)1031sys::swapByteOrder(flavor);1032state += sizeof(uint32_t);10331034if(state + sizeof(uint32_t) > end)1035return malformedError("load command " + Twine(LoadCommandIndex) +1036" count in " + CmdName + " extends past end of "1037"command");1038uint32_t count;1039memcpy(&count, state, sizeof(uint32_t));1040if (Obj.isLittleEndian() != sys::IsLittleEndianHost)1041sys::swapByteOrder(count);1042state += sizeof(uint32_t);10431044if (cputype == MachO::CPU_TYPE_I386) {1045if (flavor == MachO::x86_THREAD_STATE32) {1046if (count != MachO::x86_THREAD_STATE32_COUNT)1047return malformedError("load command " + Twine(LoadCommandIndex) +1048" count not x86_THREAD_STATE32_COUNT for "1049"flavor number " + Twine(nflavor) + " which is "1050"a x86_THREAD_STATE32 flavor in " + CmdName +1051" command");1052if (state + sizeof(MachO::x86_thread_state32_t) > end)1053return malformedError("load command " + Twine(LoadCommandIndex) +1054" x86_THREAD_STATE32 extends past end of "1055"command in " + CmdName + " command");1056state += sizeof(MachO::x86_thread_state32_t);1057} else {1058return malformedError("load command " + Twine(LoadCommandIndex) +1059" unknown flavor (" + Twine(flavor) + ") for "1060"flavor number " + Twine(nflavor) + " in " +1061CmdName + " command");1062}1063} else if (cputype == MachO::CPU_TYPE_X86_64) {1064if (flavor == MachO::x86_THREAD_STATE) {1065if (count != MachO::x86_THREAD_STATE_COUNT)1066return malformedError("load command " + Twine(LoadCommandIndex) +1067" count not x86_THREAD_STATE_COUNT for "1068"flavor number " + Twine(nflavor) + " which is "1069"a x86_THREAD_STATE flavor in " + CmdName +1070" command");1071if (state + sizeof(MachO::x86_thread_state_t) > end)1072return malformedError("load command " + Twine(LoadCommandIndex) +1073" x86_THREAD_STATE extends past end of "1074"command in " + CmdName + " command");1075state += sizeof(MachO::x86_thread_state_t);1076} else if (flavor == MachO::x86_FLOAT_STATE) {1077if (count != MachO::x86_FLOAT_STATE_COUNT)1078return malformedError("load command " + Twine(LoadCommandIndex) +1079" count not x86_FLOAT_STATE_COUNT for "1080"flavor number " + Twine(nflavor) + " which is "1081"a x86_FLOAT_STATE flavor in " + CmdName +1082" command");1083if (state + sizeof(MachO::x86_float_state_t) > end)1084return malformedError("load command " + Twine(LoadCommandIndex) +1085" x86_FLOAT_STATE extends past end of "1086"command in " + CmdName + " command");1087state += sizeof(MachO::x86_float_state_t);1088} else if (flavor == MachO::x86_EXCEPTION_STATE) {1089if (count != MachO::x86_EXCEPTION_STATE_COUNT)1090return malformedError("load command " + Twine(LoadCommandIndex) +1091" count not x86_EXCEPTION_STATE_COUNT for "1092"flavor number " + Twine(nflavor) + " which is "1093"a x86_EXCEPTION_STATE flavor in " + CmdName +1094" command");1095if (state + sizeof(MachO::x86_exception_state_t) > end)1096return malformedError("load command " + Twine(LoadCommandIndex) +1097" x86_EXCEPTION_STATE extends past end of "1098"command in " + CmdName + " command");1099state += sizeof(MachO::x86_exception_state_t);1100} else if (flavor == MachO::x86_THREAD_STATE64) {1101if (count != MachO::x86_THREAD_STATE64_COUNT)1102return malformedError("load command " + Twine(LoadCommandIndex) +1103" count not x86_THREAD_STATE64_COUNT for "1104"flavor number " + Twine(nflavor) + " which is "1105"a x86_THREAD_STATE64 flavor in " + CmdName +1106" command");1107if (state + sizeof(MachO::x86_thread_state64_t) > end)1108return malformedError("load command " + Twine(LoadCommandIndex) +1109" x86_THREAD_STATE64 extends past end of "1110"command in " + CmdName + " command");1111state += sizeof(MachO::x86_thread_state64_t);1112} else if (flavor == MachO::x86_EXCEPTION_STATE64) {1113if (count != MachO::x86_EXCEPTION_STATE64_COUNT)1114return malformedError("load command " + Twine(LoadCommandIndex) +1115" count not x86_EXCEPTION_STATE64_COUNT for "1116"flavor number " + Twine(nflavor) + " which is "1117"a x86_EXCEPTION_STATE64 flavor in " + CmdName +1118" command");1119if (state + sizeof(MachO::x86_exception_state64_t) > end)1120return malformedError("load command " + Twine(LoadCommandIndex) +1121" x86_EXCEPTION_STATE64 extends past end of "1122"command in " + CmdName + " command");1123state += sizeof(MachO::x86_exception_state64_t);1124} else {1125return malformedError("load command " + Twine(LoadCommandIndex) +1126" unknown flavor (" + Twine(flavor) + ") for "1127"flavor number " + Twine(nflavor) + " in " +1128CmdName + " command");1129}1130} else if (cputype == MachO::CPU_TYPE_ARM) {1131if (flavor == MachO::ARM_THREAD_STATE) {1132if (count != MachO::ARM_THREAD_STATE_COUNT)1133return malformedError("load command " + Twine(LoadCommandIndex) +1134" count not ARM_THREAD_STATE_COUNT for "1135"flavor number " + Twine(nflavor) + " which is "1136"a ARM_THREAD_STATE flavor in " + CmdName +1137" command");1138if (state + sizeof(MachO::arm_thread_state32_t) > end)1139return malformedError("load command " + Twine(LoadCommandIndex) +1140" ARM_THREAD_STATE extends past end of "1141"command in " + CmdName + " command");1142state += sizeof(MachO::arm_thread_state32_t);1143} else {1144return malformedError("load command " + Twine(LoadCommandIndex) +1145" unknown flavor (" + Twine(flavor) + ") for "1146"flavor number " + Twine(nflavor) + " in " +1147CmdName + " command");1148}1149} else if (cputype == MachO::CPU_TYPE_ARM64 ||1150cputype == MachO::CPU_TYPE_ARM64_32) {1151if (flavor == MachO::ARM_THREAD_STATE64) {1152if (count != MachO::ARM_THREAD_STATE64_COUNT)1153return malformedError("load command " + Twine(LoadCommandIndex) +1154" count not ARM_THREAD_STATE64_COUNT for "1155"flavor number " + Twine(nflavor) + " which is "1156"a ARM_THREAD_STATE64 flavor in " + CmdName +1157" command");1158if (state + sizeof(MachO::arm_thread_state64_t) > end)1159return malformedError("load command " + Twine(LoadCommandIndex) +1160" ARM_THREAD_STATE64 extends past end of "1161"command in " + CmdName + " command");1162state += sizeof(MachO::arm_thread_state64_t);1163} else {1164return malformedError("load command " + Twine(LoadCommandIndex) +1165" unknown flavor (" + Twine(flavor) + ") for "1166"flavor number " + Twine(nflavor) + " in " +1167CmdName + " command");1168}1169} else if (cputype == MachO::CPU_TYPE_POWERPC) {1170if (flavor == MachO::PPC_THREAD_STATE) {1171if (count != MachO::PPC_THREAD_STATE_COUNT)1172return malformedError("load command " + Twine(LoadCommandIndex) +1173" count not PPC_THREAD_STATE_COUNT for "1174"flavor number " + Twine(nflavor) + " which is "1175"a PPC_THREAD_STATE flavor in " + CmdName +1176" command");1177if (state + sizeof(MachO::ppc_thread_state32_t) > end)1178return malformedError("load command " + Twine(LoadCommandIndex) +1179" PPC_THREAD_STATE extends past end of "1180"command in " + CmdName + " command");1181state += sizeof(MachO::ppc_thread_state32_t);1182} else {1183return malformedError("load command " + Twine(LoadCommandIndex) +1184" unknown flavor (" + Twine(flavor) + ") for "1185"flavor number " + Twine(nflavor) + " in " +1186CmdName + " command");1187}1188} else {1189return malformedError("unknown cputype (" + Twine(cputype) + ") load "1190"command " + Twine(LoadCommandIndex) + " for " +1191CmdName + " command can't be checked");1192}1193nflavor++;1194}1195return Error::success();1196}11971198static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,1199const MachOObjectFile::LoadCommandInfo1200&Load,1201uint32_t LoadCommandIndex,1202const char **LoadCmd,1203std::list<MachOElement> &Elements) {1204if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))1205return malformedError("load command " + Twine(LoadCommandIndex) +1206" LC_TWOLEVEL_HINTS has incorrect cmdsize");1207if (*LoadCmd != nullptr)1208return malformedError("more than one LC_TWOLEVEL_HINTS command");1209auto HintsOrErr = getStructOrErr<MachO::twolevel_hints_command>(Obj, Load.Ptr);1210if(!HintsOrErr)1211return HintsOrErr.takeError();1212MachO::twolevel_hints_command Hints = HintsOrErr.get();1213uint64_t FileSize = Obj.getData().size();1214if (Hints.offset > FileSize)1215return malformedError("offset field of LC_TWOLEVEL_HINTS command " +1216Twine(LoadCommandIndex) + " extends past the end of "1217"the file");1218uint64_t BigSize = Hints.nhints;1219BigSize *= sizeof(MachO::twolevel_hint);1220BigSize += Hints.offset;1221if (BigSize > FileSize)1222return malformedError("offset field plus nhints times sizeof(struct "1223"twolevel_hint) field of LC_TWOLEVEL_HINTS command " +1224Twine(LoadCommandIndex) + " extends past the end of "1225"the file");1226if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *1227sizeof(MachO::twolevel_hint),1228"two level hints"))1229return Err;1230*LoadCmd = Load.Ptr;1231return Error::success();1232}12331234// Returns true if the libObject code does not support the load command and its1235// contents. The cmd value it is treated as an unknown load command but with1236// an error message that says the cmd value is obsolete.1237static bool isLoadCommandObsolete(uint32_t cmd) {1238if (cmd == MachO::LC_SYMSEG ||1239cmd == MachO::LC_LOADFVMLIB ||1240cmd == MachO::LC_IDFVMLIB ||1241cmd == MachO::LC_IDENT ||1242cmd == MachO::LC_FVMFILE ||1243cmd == MachO::LC_PREPAGE ||1244cmd == MachO::LC_PREBOUND_DYLIB ||1245cmd == MachO::LC_TWOLEVEL_HINTS ||1246cmd == MachO::LC_PREBIND_CKSUM)1247return true;1248return false;1249}12501251Expected<std::unique_ptr<MachOObjectFile>>1252MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,1253bool Is64Bits, uint32_t UniversalCputype,1254uint32_t UniversalIndex,1255size_t MachOFilesetEntryOffset) {1256Error Err = Error::success();1257std::unique_ptr<MachOObjectFile> Obj(new MachOObjectFile(1258std::move(Object), IsLittleEndian, Is64Bits, Err, UniversalCputype,1259UniversalIndex, MachOFilesetEntryOffset));1260if (Err)1261return std::move(Err);1262return std::move(Obj);1263}12641265MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,1266bool Is64bits, Error &Err,1267uint32_t UniversalCputype,1268uint32_t UniversalIndex,1269size_t MachOFilesetEntryOffset)1270: ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),1271MachOFilesetEntryOffset(MachOFilesetEntryOffset) {1272ErrorAsOutParameter ErrAsOutParam(&Err);1273uint64_t SizeOfHeaders;1274uint32_t cputype;1275if (is64Bit()) {1276parseHeader(*this, Header64, Err);1277SizeOfHeaders = sizeof(MachO::mach_header_64);1278cputype = Header64.cputype;1279} else {1280parseHeader(*this, Header, Err);1281SizeOfHeaders = sizeof(MachO::mach_header);1282cputype = Header.cputype;1283}1284if (Err)1285return;1286SizeOfHeaders += getHeader().sizeofcmds;1287if (getData().data() + SizeOfHeaders > getData().end()) {1288Err = malformedError("load commands extend past the end of the file");1289return;1290}1291if (UniversalCputype != 0 && cputype != UniversalCputype) {1292Err = malformedError("universal header architecture: " +1293Twine(UniversalIndex) + "'s cputype does not match "1294"object file's mach header");1295return;1296}1297std::list<MachOElement> Elements;1298Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});12991300uint32_t LoadCommandCount = getHeader().ncmds;1301LoadCommandInfo Load;1302if (LoadCommandCount != 0) {1303if (auto LoadOrErr = getFirstLoadCommandInfo(*this))1304Load = *LoadOrErr;1305else {1306Err = LoadOrErr.takeError();1307return;1308}1309}13101311const char *DyldIdLoadCmd = nullptr;1312const char *SplitInfoLoadCmd = nullptr;1313const char *CodeSignDrsLoadCmd = nullptr;1314const char *CodeSignLoadCmd = nullptr;1315const char *VersLoadCmd = nullptr;1316const char *SourceLoadCmd = nullptr;1317const char *EntryPointLoadCmd = nullptr;1318const char *EncryptLoadCmd = nullptr;1319const char *RoutinesLoadCmd = nullptr;1320const char *UnixThreadLoadCmd = nullptr;1321const char *TwoLevelHintsLoadCmd = nullptr;1322for (unsigned I = 0; I < LoadCommandCount; ++I) {1323if (is64Bit()) {1324if (Load.C.cmdsize % 8 != 0) {1325// We have a hack here to allow 64-bit Mach-O core files to have1326// LC_THREAD commands that are only a multiple of 4 and not 8 to be1327// allowed since the macOS kernel produces them.1328if (getHeader().filetype != MachO::MH_CORE ||1329Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {1330Err = malformedError("load command " + Twine(I) + " cmdsize not a "1331"multiple of 8");1332return;1333}1334}1335} else {1336if (Load.C.cmdsize % 4 != 0) {1337Err = malformedError("load command " + Twine(I) + " cmdsize not a "1338"multiple of 4");1339return;1340}1341}1342LoadCommands.push_back(Load);1343if (Load.C.cmd == MachO::LC_SYMTAB) {1344if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))1345return;1346} else if (Load.C.cmd == MachO::LC_DYSYMTAB) {1347if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,1348Elements)))1349return;1350} else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {1351if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,1352"LC_DATA_IN_CODE", Elements,1353"data in code info")))1354return;1355} else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {1356if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,1357"LC_LINKER_OPTIMIZATION_HINT",1358Elements, "linker optimization "1359"hints")))1360return;1361} else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {1362if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,1363"LC_FUNCTION_STARTS", Elements,1364"function starts data")))1365return;1366} else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {1367if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,1368"LC_SEGMENT_SPLIT_INFO", Elements,1369"split info data")))1370return;1371} else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {1372if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,1373"LC_DYLIB_CODE_SIGN_DRS", Elements,1374"code signing RDs data")))1375return;1376} else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {1377if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,1378"LC_CODE_SIGNATURE", Elements,1379"code signature data")))1380return;1381} else if (Load.C.cmd == MachO::LC_DYLD_INFO) {1382if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,1383"LC_DYLD_INFO", Elements)))1384return;1385} else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {1386if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,1387"LC_DYLD_INFO_ONLY", Elements)))1388return;1389} else if (Load.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS) {1390if ((Err = checkLinkeditDataCommand(1391*this, Load, I, &DyldChainedFixupsLoadCmd,1392"LC_DYLD_CHAINED_FIXUPS", Elements, "chained fixups")))1393return;1394} else if (Load.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE) {1395if ((Err = checkLinkeditDataCommand(1396*this, Load, I, &DyldExportsTrieLoadCmd, "LC_DYLD_EXPORTS_TRIE",1397Elements, "exports trie")))1398return;1399} else if (Load.C.cmd == MachO::LC_UUID) {1400if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {1401Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "1402"cmdsize");1403return;1404}1405if (UuidLoadCmd) {1406Err = malformedError("more than one LC_UUID command");1407return;1408}1409UuidLoadCmd = Load.Ptr;1410} else if (Load.C.cmd == MachO::LC_SEGMENT_64) {1411if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,1412MachO::section_64>(1413*this, Load, Sections, HasPageZeroSegment, I,1414"LC_SEGMENT_64", SizeOfHeaders, Elements)))1415return;1416} else if (Load.C.cmd == MachO::LC_SEGMENT) {1417if ((Err = parseSegmentLoadCommand<MachO::segment_command,1418MachO::section>(1419*this, Load, Sections, HasPageZeroSegment, I,1420"LC_SEGMENT", SizeOfHeaders, Elements)))1421return;1422} else if (Load.C.cmd == MachO::LC_ID_DYLIB) {1423if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))1424return;1425} else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {1426if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))1427return;1428Libraries.push_back(Load.Ptr);1429} else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {1430if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))1431return;1432Libraries.push_back(Load.Ptr);1433} else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {1434if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))1435return;1436Libraries.push_back(Load.Ptr);1437} else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {1438if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))1439return;1440Libraries.push_back(Load.Ptr);1441} else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {1442if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))1443return;1444Libraries.push_back(Load.Ptr);1445} else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {1446if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))1447return;1448} else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {1449if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))1450return;1451} else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {1452if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))1453return;1454} else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {1455if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,1456"LC_VERSION_MIN_MACOSX")))1457return;1458} else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {1459if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,1460"LC_VERSION_MIN_IPHONEOS")))1461return;1462} else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {1463if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,1464"LC_VERSION_MIN_TVOS")))1465return;1466} else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {1467if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,1468"LC_VERSION_MIN_WATCHOS")))1469return;1470} else if (Load.C.cmd == MachO::LC_NOTE) {1471if ((Err = checkNoteCommand(*this, Load, I, Elements)))1472return;1473} else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {1474if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))1475return;1476} else if (Load.C.cmd == MachO::LC_RPATH) {1477if ((Err = checkRpathCommand(*this, Load, I)))1478return;1479} else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {1480if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {1481Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +1482" has incorrect cmdsize");1483return;1484}1485if (SourceLoadCmd) {1486Err = malformedError("more than one LC_SOURCE_VERSION command");1487return;1488}1489SourceLoadCmd = Load.Ptr;1490} else if (Load.C.cmd == MachO::LC_MAIN) {1491if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {1492Err = malformedError("LC_MAIN command " + Twine(I) +1493" has incorrect cmdsize");1494return;1495}1496if (EntryPointLoadCmd) {1497Err = malformedError("more than one LC_MAIN command");1498return;1499}1500EntryPointLoadCmd = Load.Ptr;1501} else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {1502if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {1503Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +1504" has incorrect cmdsize");1505return;1506}1507MachO::encryption_info_command E =1508getStruct<MachO::encryption_info_command>(*this, Load.Ptr);1509if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,1510&EncryptLoadCmd, "LC_ENCRYPTION_INFO")))1511return;1512} else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {1513if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {1514Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +1515" has incorrect cmdsize");1516return;1517}1518MachO::encryption_info_command_64 E =1519getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);1520if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,1521&EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))1522return;1523} else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {1524if ((Err = checkLinkerOptCommand(*this, Load, I)))1525return;1526} else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {1527if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {1528Err = malformedError("load command " + Twine(I) +1529" LC_SUB_FRAMEWORK cmdsize too small");1530return;1531}1532MachO::sub_framework_command S =1533getStruct<MachO::sub_framework_command>(*this, Load.Ptr);1534if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",1535sizeof(MachO::sub_framework_command),1536"sub_framework_command", S.umbrella,1537"umbrella")))1538return;1539} else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {1540if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {1541Err = malformedError("load command " + Twine(I) +1542" LC_SUB_UMBRELLA cmdsize too small");1543return;1544}1545MachO::sub_umbrella_command S =1546getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);1547if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",1548sizeof(MachO::sub_umbrella_command),1549"sub_umbrella_command", S.sub_umbrella,1550"sub_umbrella")))1551return;1552} else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {1553if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {1554Err = malformedError("load command " + Twine(I) +1555" LC_SUB_LIBRARY cmdsize too small");1556return;1557}1558MachO::sub_library_command S =1559getStruct<MachO::sub_library_command>(*this, Load.Ptr);1560if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",1561sizeof(MachO::sub_library_command),1562"sub_library_command", S.sub_library,1563"sub_library")))1564return;1565} else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {1566if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {1567Err = malformedError("load command " + Twine(I) +1568" LC_SUB_CLIENT cmdsize too small");1569return;1570}1571MachO::sub_client_command S =1572getStruct<MachO::sub_client_command>(*this, Load.Ptr);1573if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",1574sizeof(MachO::sub_client_command),1575"sub_client_command", S.client, "client")))1576return;1577} else if (Load.C.cmd == MachO::LC_ROUTINES) {1578if (Load.C.cmdsize != sizeof(MachO::routines_command)) {1579Err = malformedError("LC_ROUTINES command " + Twine(I) +1580" has incorrect cmdsize");1581return;1582}1583if (RoutinesLoadCmd) {1584Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "1585"command");1586return;1587}1588RoutinesLoadCmd = Load.Ptr;1589} else if (Load.C.cmd == MachO::LC_ROUTINES_64) {1590if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {1591Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +1592" has incorrect cmdsize");1593return;1594}1595if (RoutinesLoadCmd) {1596Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "1597"command");1598return;1599}1600RoutinesLoadCmd = Load.Ptr;1601} else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {1602if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))1603return;1604if (UnixThreadLoadCmd) {1605Err = malformedError("more than one LC_UNIXTHREAD command");1606return;1607}1608UnixThreadLoadCmd = Load.Ptr;1609} else if (Load.C.cmd == MachO::LC_THREAD) {1610if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))1611return;1612// Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.1613} else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {1614if ((Err = checkTwoLevelHintsCommand(*this, Load, I,1615&TwoLevelHintsLoadCmd, Elements)))1616return;1617} else if (Load.C.cmd == MachO::LC_IDENT) {1618// Note: LC_IDENT is ignored.1619continue;1620} else if (isLoadCommandObsolete(Load.C.cmd)) {1621Err = malformedError("load command " + Twine(I) + " for cmd value of: " +1622Twine(Load.C.cmd) + " is obsolete and not "1623"supported");1624return;1625}1626// TODO: generate a error for unknown load commands by default. But still1627// need work out an approach to allow or not allow unknown values like this1628// as an option for some uses like lldb.1629if (I < LoadCommandCount - 1) {1630if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))1631Load = *LoadOrErr;1632else {1633Err = LoadOrErr.takeError();1634return;1635}1636}1637}1638if (!SymtabLoadCmd) {1639if (DysymtabLoadCmd) {1640Err = malformedError("contains LC_DYSYMTAB load command without a "1641"LC_SYMTAB load command");1642return;1643}1644} else if (DysymtabLoadCmd) {1645MachO::symtab_command Symtab =1646getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);1647MachO::dysymtab_command Dysymtab =1648getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);1649if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {1650Err = malformedError("ilocalsym in LC_DYSYMTAB load command "1651"extends past the end of the symbol table");1652return;1653}1654uint64_t BigSize = Dysymtab.ilocalsym;1655BigSize += Dysymtab.nlocalsym;1656if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {1657Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "1658"command extends past the end of the symbol table");1659return;1660}1661if (Dysymtab.nextdefsym != 0 && Dysymtab.iextdefsym > Symtab.nsyms) {1662Err = malformedError("iextdefsym in LC_DYSYMTAB load command "1663"extends past the end of the symbol table");1664return;1665}1666BigSize = Dysymtab.iextdefsym;1667BigSize += Dysymtab.nextdefsym;1668if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {1669Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "1670"load command extends past the end of the symbol "1671"table");1672return;1673}1674if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {1675Err = malformedError("iundefsym in LC_DYSYMTAB load command "1676"extends past the end of the symbol table");1677return;1678}1679BigSize = Dysymtab.iundefsym;1680BigSize += Dysymtab.nundefsym;1681if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {1682Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "1683" command extends past the end of the symbol table");1684return;1685}1686}1687if ((getHeader().filetype == MachO::MH_DYLIB ||1688getHeader().filetype == MachO::MH_DYLIB_STUB) &&1689DyldIdLoadCmd == nullptr) {1690Err = malformedError("no LC_ID_DYLIB load command in dynamic library "1691"filetype");1692return;1693}1694assert(LoadCommands.size() == LoadCommandCount);16951696Err = Error::success();1697}16981699Error MachOObjectFile::checkSymbolTable() const {1700uint32_t Flags = 0;1701if (is64Bit()) {1702MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();1703Flags = H_64.flags;1704} else {1705MachO::mach_header H = MachOObjectFile::getHeader();1706Flags = H.flags;1707}1708uint8_t NType = 0;1709uint8_t NSect = 0;1710uint16_t NDesc = 0;1711uint32_t NStrx = 0;1712uint64_t NValue = 0;1713uint32_t SymbolIndex = 0;1714MachO::symtab_command S = getSymtabLoadCommand();1715for (const SymbolRef &Symbol : symbols()) {1716DataRefImpl SymDRI = Symbol.getRawDataRefImpl();1717if (is64Bit()) {1718MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);1719NType = STE_64.n_type;1720NSect = STE_64.n_sect;1721NDesc = STE_64.n_desc;1722NStrx = STE_64.n_strx;1723NValue = STE_64.n_value;1724} else {1725MachO::nlist STE = getSymbolTableEntry(SymDRI);1726NType = STE.n_type;1727NSect = STE.n_sect;1728NDesc = STE.n_desc;1729NStrx = STE.n_strx;1730NValue = STE.n_value;1731}1732if ((NType & MachO::N_STAB) == 0) {1733if ((NType & MachO::N_TYPE) == MachO::N_SECT) {1734if (NSect == 0 || NSect > Sections.size())1735return malformedError("bad section index: " + Twine((int)NSect) +1736" for symbol at index " + Twine(SymbolIndex));1737}1738if ((NType & MachO::N_TYPE) == MachO::N_INDR) {1739if (NValue >= S.strsize)1740return malformedError("bad n_value: " + Twine((int)NValue) + " past "1741"the end of string table, for N_INDR symbol at "1742"index " + Twine(SymbolIndex));1743}1744if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&1745(((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||1746(NType & MachO::N_TYPE) == MachO::N_PBUD)) {1747uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);1748if (LibraryOrdinal != 0 &&1749LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&1750LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&1751LibraryOrdinal - 1 >= Libraries.size() ) {1752return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +1753" for symbol at index " + Twine(SymbolIndex));1754}1755}1756}1757if (NStrx >= S.strsize)1758return malformedError("bad string table index: " + Twine((int)NStrx) +1759" past the end of string table, for symbol at "1760"index " + Twine(SymbolIndex));1761SymbolIndex++;1762}1763return Error::success();1764}17651766void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {1767unsigned SymbolTableEntrySize = is64Bit() ?1768sizeof(MachO::nlist_64) :1769sizeof(MachO::nlist);1770Symb.p += SymbolTableEntrySize;1771}17721773Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {1774StringRef StringTable = getStringTableData();1775MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);1776if (Entry.n_strx == 0)1777// A n_strx value of 0 indicates that no name is associated with a1778// particular symbol table entry.1779return StringRef();1780const char *Start = &StringTable.data()[Entry.n_strx];1781if (Start < getData().begin() || Start >= getData().end()) {1782return malformedError("bad string index: " + Twine(Entry.n_strx) +1783" for symbol at index " + Twine(getSymbolIndex(Symb)));1784}1785return StringRef(Start);1786}17871788unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {1789DataRefImpl DRI = Sec.getRawDataRefImpl();1790uint32_t Flags = getSectionFlags(*this, DRI);1791return Flags & MachO::SECTION_TYPE;1792}17931794uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {1795if (is64Bit()) {1796MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);1797return Entry.n_value;1798}1799MachO::nlist Entry = getSymbolTableEntry(Sym);1800return Entry.n_value;1801}18021803// getIndirectName() returns the name of the alias'ed symbol who's string table1804// index is in the n_value field.1805std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,1806StringRef &Res) const {1807StringRef StringTable = getStringTableData();1808MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);1809if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)1810return object_error::parse_failed;1811uint64_t NValue = getNValue(Symb);1812if (NValue >= StringTable.size())1813return object_error::parse_failed;1814const char *Start = &StringTable.data()[NValue];1815Res = StringRef(Start);1816return std::error_code();1817}18181819uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {1820return getNValue(Sym);1821}18221823Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {1824return getSymbolValue(Sym);1825}18261827uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {1828uint32_t Flags = cantFail(getSymbolFlags(DRI));1829if (Flags & SymbolRef::SF_Common) {1830MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);1831return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);1832}1833return 0;1834}18351836uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {1837return getNValue(DRI);1838}18391840Expected<SymbolRef::Type>1841MachOObjectFile::getSymbolType(DataRefImpl Symb) const {1842MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);1843uint8_t n_type = Entry.n_type;18441845// If this is a STAB debugging symbol, we can do nothing more.1846if (n_type & MachO::N_STAB)1847return SymbolRef::ST_Debug;18481849switch (n_type & MachO::N_TYPE) {1850case MachO::N_UNDF :1851return SymbolRef::ST_Unknown;1852case MachO::N_SECT :1853Expected<section_iterator> SecOrError = getSymbolSection(Symb);1854if (!SecOrError)1855return SecOrError.takeError();1856section_iterator Sec = *SecOrError;1857if (Sec == section_end())1858return SymbolRef::ST_Other;1859if (Sec->isData() || Sec->isBSS())1860return SymbolRef::ST_Data;1861return SymbolRef::ST_Function;1862}1863return SymbolRef::ST_Other;1864}18651866Expected<uint32_t> MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {1867MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);18681869uint8_t MachOType = Entry.n_type;1870uint16_t MachOFlags = Entry.n_desc;18711872uint32_t Result = SymbolRef::SF_None;18731874if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)1875Result |= SymbolRef::SF_Indirect;18761877if (MachOType & MachO::N_STAB)1878Result |= SymbolRef::SF_FormatSpecific;18791880if (MachOType & MachO::N_EXT) {1881Result |= SymbolRef::SF_Global;1882if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {1883if (getNValue(DRI))1884Result |= SymbolRef::SF_Common;1885else1886Result |= SymbolRef::SF_Undefined;1887}18881889if (MachOType & MachO::N_PEXT)1890Result |= SymbolRef::SF_Hidden;1891else1892Result |= SymbolRef::SF_Exported;18931894} else if (MachOType & MachO::N_PEXT)1895Result |= SymbolRef::SF_Hidden;18961897if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))1898Result |= SymbolRef::SF_Weak;18991900if (MachOFlags & (MachO::N_ARM_THUMB_DEF))1901Result |= SymbolRef::SF_Thumb;19021903if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)1904Result |= SymbolRef::SF_Absolute;19051906return Result;1907}19081909Expected<section_iterator>1910MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {1911MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);1912uint8_t index = Entry.n_sect;19131914if (index == 0)1915return section_end();1916DataRefImpl DRI;1917DRI.d.a = index - 1;1918if (DRI.d.a >= Sections.size()){1919return malformedError("bad section index: " + Twine((int)index) +1920" for symbol at index " + Twine(getSymbolIndex(Symb)));1921}1922return section_iterator(SectionRef(DRI, this));1923}19241925unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {1926MachO::nlist_base Entry =1927getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());1928return Entry.n_sect - 1;1929}19301931void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {1932Sec.d.a++;1933}19341935Expected<StringRef> MachOObjectFile::getSectionName(DataRefImpl Sec) const {1936ArrayRef<char> Raw = getSectionRawName(Sec);1937return parseSegmentOrSectionName(Raw.data());1938}19391940uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {1941if (is64Bit())1942return getSection64(Sec).addr;1943return getSection(Sec).addr;1944}19451946uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {1947return Sec.d.a;1948}19491950uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {1951// In the case if a malformed Mach-O file where the section offset is past1952// the end of the file or some part of the section size is past the end of1953// the file return a size of zero or a size that covers the rest of the file1954// but does not extend past the end of the file.1955uint32_t SectOffset, SectType;1956uint64_t SectSize;19571958if (is64Bit()) {1959MachO::section_64 Sect = getSection64(Sec);1960SectOffset = Sect.offset;1961SectSize = Sect.size;1962SectType = Sect.flags & MachO::SECTION_TYPE;1963} else {1964MachO::section Sect = getSection(Sec);1965SectOffset = Sect.offset;1966SectSize = Sect.size;1967SectType = Sect.flags & MachO::SECTION_TYPE;1968}1969if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)1970return SectSize;1971uint64_t FileSize = getData().size();1972if (SectOffset > FileSize)1973return 0;1974if (FileSize - SectOffset < SectSize)1975return FileSize - SectOffset;1976return SectSize;1977}19781979ArrayRef<uint8_t> MachOObjectFile::getSectionContents(uint32_t Offset,1980uint64_t Size) const {1981return arrayRefFromStringRef(getData().substr(Offset, Size));1982}19831984Expected<ArrayRef<uint8_t>>1985MachOObjectFile::getSectionContents(DataRefImpl Sec) const {1986uint32_t Offset;1987uint64_t Size;19881989if (is64Bit()) {1990MachO::section_64 Sect = getSection64(Sec);1991Offset = Sect.offset;1992Size = Sect.size;1993} else {1994MachO::section Sect = getSection(Sec);1995Offset = Sect.offset;1996Size = Sect.size;1997}19981999return getSectionContents(Offset, Size);2000}20012002uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {2003uint32_t Align;2004if (is64Bit()) {2005MachO::section_64 Sect = getSection64(Sec);2006Align = Sect.align;2007} else {2008MachO::section Sect = getSection(Sec);2009Align = Sect.align;2010}20112012return uint64_t(1) << Align;2013}20142015Expected<SectionRef> MachOObjectFile::getSection(unsigned SectionIndex) const {2016if (SectionIndex < 1 || SectionIndex > Sections.size())2017return malformedError("bad section index: " + Twine((int)SectionIndex));20182019DataRefImpl DRI;2020DRI.d.a = SectionIndex - 1;2021return SectionRef(DRI, this);2022}20232024Expected<SectionRef> MachOObjectFile::getSection(StringRef SectionName) const {2025for (const SectionRef &Section : sections()) {2026auto NameOrErr = Section.getName();2027if (!NameOrErr)2028return NameOrErr.takeError();2029if (*NameOrErr == SectionName)2030return Section;2031}2032return errorCodeToError(object_error::parse_failed);2033}20342035bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {2036return false;2037}20382039bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {2040uint32_t Flags = getSectionFlags(*this, Sec);2041return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;2042}20432044bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {2045uint32_t Flags = getSectionFlags(*this, Sec);2046unsigned SectionType = Flags & MachO::SECTION_TYPE;2047return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&2048!(SectionType == MachO::S_ZEROFILL ||2049SectionType == MachO::S_GB_ZEROFILL);2050}20512052bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {2053uint32_t Flags = getSectionFlags(*this, Sec);2054unsigned SectionType = Flags & MachO::SECTION_TYPE;2055return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&2056(SectionType == MachO::S_ZEROFILL ||2057SectionType == MachO::S_GB_ZEROFILL);2058}20592060bool MachOObjectFile::isDebugSection(DataRefImpl Sec) const {2061Expected<StringRef> SectionNameOrErr = getSectionName(Sec);2062if (!SectionNameOrErr) {2063// TODO: Report the error message properly.2064consumeError(SectionNameOrErr.takeError());2065return false;2066}2067StringRef SectionName = SectionNameOrErr.get();2068return SectionName.starts_with("__debug") ||2069SectionName.starts_with("__zdebug") ||2070SectionName.starts_with("__apple") || SectionName == "__gdb_index" ||2071SectionName == "__swift_ast";2072}20732074namespace {2075template <typename LoadCommandType>2076ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj,2077MachOObjectFile::LoadCommandInfo LoadCmd,2078StringRef SegmentName) {2079auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.Ptr);2080if (!SegmentOrErr) {2081consumeError(SegmentOrErr.takeError());2082return {};2083}2084auto &Segment = SegmentOrErr.get();2085if (StringRef(Segment.segname, 16).starts_with(SegmentName))2086return arrayRefFromStringRef(Obj.getData().slice(2087Segment.fileoff, Segment.fileoff + Segment.filesize));2088return {};2089}20902091template <typename LoadCommandType>2092ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj,2093MachOObjectFile::LoadCommandInfo LoadCmd) {2094auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.Ptr);2095if (!SegmentOrErr) {2096consumeError(SegmentOrErr.takeError());2097return {};2098}2099auto &Segment = SegmentOrErr.get();2100return arrayRefFromStringRef(2101Obj.getData().slice(Segment.fileoff, Segment.fileoff + Segment.filesize));2102}2103} // namespace21042105ArrayRef<uint8_t>2106MachOObjectFile::getSegmentContents(StringRef SegmentName) const {2107for (auto LoadCmd : load_commands()) {2108ArrayRef<uint8_t> Contents;2109switch (LoadCmd.C.cmd) {2110case MachO::LC_SEGMENT:2111Contents = ::getSegmentContents<MachO::segment_command>(*this, LoadCmd,2112SegmentName);2113break;2114case MachO::LC_SEGMENT_64:2115Contents = ::getSegmentContents<MachO::segment_command_64>(*this, LoadCmd,2116SegmentName);2117break;2118default:2119continue;2120}2121if (!Contents.empty())2122return Contents;2123}2124return {};2125}21262127ArrayRef<uint8_t>2128MachOObjectFile::getSegmentContents(size_t SegmentIndex) const {2129size_t Idx = 0;2130for (auto LoadCmd : load_commands()) {2131switch (LoadCmd.C.cmd) {2132case MachO::LC_SEGMENT:2133if (Idx == SegmentIndex)2134return ::getSegmentContents<MachO::segment_command>(*this, LoadCmd);2135++Idx;2136break;2137case MachO::LC_SEGMENT_64:2138if (Idx == SegmentIndex)2139return ::getSegmentContents<MachO::segment_command_64>(*this, LoadCmd);2140++Idx;2141break;2142default:2143continue;2144}2145}2146return {};2147}21482149unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {2150return Sec.getRawDataRefImpl().d.a;2151}21522153bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {2154uint32_t Flags = getSectionFlags(*this, Sec);2155unsigned SectionType = Flags & MachO::SECTION_TYPE;2156return SectionType == MachO::S_ZEROFILL ||2157SectionType == MachO::S_GB_ZEROFILL;2158}21592160bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {2161StringRef SegmentName = getSectionFinalSegmentName(Sec);2162if (Expected<StringRef> NameOrErr = getSectionName(Sec))2163return (SegmentName == "__LLVM" && *NameOrErr == "__bitcode");2164return false;2165}21662167bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {2168if (is64Bit())2169return getSection64(Sec).offset == 0;2170return getSection(Sec).offset == 0;2171}21722173relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {2174DataRefImpl Ret;2175Ret.d.a = Sec.d.a;2176Ret.d.b = 0;2177return relocation_iterator(RelocationRef(Ret, this));2178}21792180relocation_iterator2181MachOObjectFile::section_rel_end(DataRefImpl Sec) const {2182uint32_t Num;2183if (is64Bit()) {2184MachO::section_64 Sect = getSection64(Sec);2185Num = Sect.nreloc;2186} else {2187MachO::section Sect = getSection(Sec);2188Num = Sect.nreloc;2189}21902191DataRefImpl Ret;2192Ret.d.a = Sec.d.a;2193Ret.d.b = Num;2194return relocation_iterator(RelocationRef(Ret, this));2195}21962197relocation_iterator MachOObjectFile::extrel_begin() const {2198DataRefImpl Ret;2199// for DYSYMTAB symbols, Ret.d.a == 0 for external relocations2200Ret.d.a = 0; // Would normally be a section index.2201Ret.d.b = 0; // Index into the external relocations2202return relocation_iterator(RelocationRef(Ret, this));2203}22042205relocation_iterator MachOObjectFile::extrel_end() const {2206MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();2207DataRefImpl Ret;2208// for DYSYMTAB symbols, Ret.d.a == 0 for external relocations2209Ret.d.a = 0; // Would normally be a section index.2210Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations2211return relocation_iterator(RelocationRef(Ret, this));2212}22132214relocation_iterator MachOObjectFile::locrel_begin() const {2215DataRefImpl Ret;2216// for DYSYMTAB symbols, Ret.d.a == 1 for local relocations2217Ret.d.a = 1; // Would normally be a section index.2218Ret.d.b = 0; // Index into the local relocations2219return relocation_iterator(RelocationRef(Ret, this));2220}22212222relocation_iterator MachOObjectFile::locrel_end() const {2223MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();2224DataRefImpl Ret;2225// for DYSYMTAB symbols, Ret.d.a == 1 for local relocations2226Ret.d.a = 1; // Would normally be a section index.2227Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations2228return relocation_iterator(RelocationRef(Ret, this));2229}22302231void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {2232++Rel.d.b;2233}22342235uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {2236assert((getHeader().filetype == MachO::MH_OBJECT ||2237getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&2238"Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");2239MachO::any_relocation_info RE = getRelocation(Rel);2240return getAnyRelocationAddress(RE);2241}22422243symbol_iterator2244MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {2245MachO::any_relocation_info RE = getRelocation(Rel);2246if (isRelocationScattered(RE))2247return symbol_end();22482249uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);2250bool isExtern = getPlainRelocationExternal(RE);2251if (!isExtern)2252return symbol_end();22532254MachO::symtab_command S = getSymtabLoadCommand();2255unsigned SymbolTableEntrySize = is64Bit() ?2256sizeof(MachO::nlist_64) :2257sizeof(MachO::nlist);2258uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;2259DataRefImpl Sym;2260Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));2261return symbol_iterator(SymbolRef(Sym, this));2262}22632264section_iterator2265MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {2266return section_iterator(getAnyRelocationSection(getRelocation(Rel)));2267}22682269uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {2270MachO::any_relocation_info RE = getRelocation(Rel);2271return getAnyRelocationType(RE);2272}22732274void MachOObjectFile::getRelocationTypeName(2275DataRefImpl Rel, SmallVectorImpl<char> &Result) const {2276StringRef res;2277uint64_t RType = getRelocationType(Rel);22782279unsigned Arch = this->getArch();22802281switch (Arch) {2282case Triple::x86: {2283static const char *const Table[] = {2284"GENERIC_RELOC_VANILLA",2285"GENERIC_RELOC_PAIR",2286"GENERIC_RELOC_SECTDIFF",2287"GENERIC_RELOC_PB_LA_PTR",2288"GENERIC_RELOC_LOCAL_SECTDIFF",2289"GENERIC_RELOC_TLV" };22902291if (RType > 5)2292res = "Unknown";2293else2294res = Table[RType];2295break;2296}2297case Triple::x86_64: {2298static const char *const Table[] = {2299"X86_64_RELOC_UNSIGNED",2300"X86_64_RELOC_SIGNED",2301"X86_64_RELOC_BRANCH",2302"X86_64_RELOC_GOT_LOAD",2303"X86_64_RELOC_GOT",2304"X86_64_RELOC_SUBTRACTOR",2305"X86_64_RELOC_SIGNED_1",2306"X86_64_RELOC_SIGNED_2",2307"X86_64_RELOC_SIGNED_4",2308"X86_64_RELOC_TLV" };23092310if (RType > 9)2311res = "Unknown";2312else2313res = Table[RType];2314break;2315}2316case Triple::arm: {2317static const char *const Table[] = {2318"ARM_RELOC_VANILLA",2319"ARM_RELOC_PAIR",2320"ARM_RELOC_SECTDIFF",2321"ARM_RELOC_LOCAL_SECTDIFF",2322"ARM_RELOC_PB_LA_PTR",2323"ARM_RELOC_BR24",2324"ARM_THUMB_RELOC_BR22",2325"ARM_THUMB_32BIT_BRANCH",2326"ARM_RELOC_HALF",2327"ARM_RELOC_HALF_SECTDIFF" };23282329if (RType > 9)2330res = "Unknown";2331else2332res = Table[RType];2333break;2334}2335case Triple::aarch64:2336case Triple::aarch64_32: {2337static const char *const Table[] = {2338"ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",2339"ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",2340"ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",2341"ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",2342"ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",2343"ARM64_RELOC_ADDEND"2344};23452346if (RType >= std::size(Table))2347res = "Unknown";2348else2349res = Table[RType];2350break;2351}2352case Triple::ppc: {2353static const char *const Table[] = {2354"PPC_RELOC_VANILLA",2355"PPC_RELOC_PAIR",2356"PPC_RELOC_BR14",2357"PPC_RELOC_BR24",2358"PPC_RELOC_HI16",2359"PPC_RELOC_LO16",2360"PPC_RELOC_HA16",2361"PPC_RELOC_LO14",2362"PPC_RELOC_SECTDIFF",2363"PPC_RELOC_PB_LA_PTR",2364"PPC_RELOC_HI16_SECTDIFF",2365"PPC_RELOC_LO16_SECTDIFF",2366"PPC_RELOC_HA16_SECTDIFF",2367"PPC_RELOC_JBSR",2368"PPC_RELOC_LO14_SECTDIFF",2369"PPC_RELOC_LOCAL_SECTDIFF" };23702371if (RType > 15)2372res = "Unknown";2373else2374res = Table[RType];2375break;2376}2377case Triple::UnknownArch:2378res = "Unknown";2379break;2380}2381Result.append(res.begin(), res.end());2382}23832384uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {2385MachO::any_relocation_info RE = getRelocation(Rel);2386return getAnyRelocationLength(RE);2387}23882389//2390// guessLibraryShortName() is passed a name of a dynamic library and returns a2391// guess on what the short name is. Then name is returned as a substring of the2392// StringRef Name passed in. The name of the dynamic library is recognized as2393// a framework if it has one of the two following forms:2394// Foo.framework/Versions/A/Foo2395// Foo.framework/Foo2396// Where A and Foo can be any string. And may contain a trailing suffix2397// starting with an underbar. If the Name is recognized as a framework then2398// isFramework is set to true else it is set to false. If the Name has a2399// suffix then Suffix is set to the substring in Name that contains the suffix2400// else it is set to a NULL StringRef.2401//2402// The Name of the dynamic library is recognized as a library name if it has2403// one of the two following forms:2404// libFoo.A.dylib2405// libFoo.dylib2406//2407// The library may have a suffix trailing the name Foo of the form:2408// libFoo_profile.A.dylib2409// libFoo_profile.dylib2410// These dyld image suffixes are separated from the short name by a '_'2411// character. Because the '_' character is commonly used to separate words in2412// filenames guessLibraryShortName() cannot reliably separate a dylib's short2413// name from an arbitrary image suffix; imagine if both the short name and the2414// suffix contains an '_' character! To better deal with this ambiguity,2415// guessLibraryShortName() will recognize only "_debug" and "_profile" as valid2416// Suffix values. Calling code needs to be tolerant of guessLibraryShortName()2417// guessing incorrectly.2418//2419// The Name of the dynamic library is also recognized as a library name if it2420// has the following form:2421// Foo.qtx2422//2423// If the Name of the dynamic library is none of the forms above then a NULL2424// StringRef is returned.2425StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,2426bool &isFramework,2427StringRef &Suffix) {2428StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;2429size_t a, b, c, d, Idx;24302431isFramework = false;2432Suffix = StringRef();24332434// Pull off the last component and make Foo point to it2435a = Name.rfind('/');2436if (a == Name.npos || a == 0)2437goto guess_library;2438Foo = Name.slice(a+1, Name.npos);24392440// Look for a suffix starting with a '_'2441Idx = Foo.rfind('_');2442if (Idx != Foo.npos && Foo.size() >= 2) {2443Suffix = Foo.slice(Idx, Foo.npos);2444if (Suffix != "_debug" && Suffix != "_profile")2445Suffix = StringRef();2446else2447Foo = Foo.slice(0, Idx);2448}24492450// First look for the form Foo.framework/Foo2451b = Name.rfind('/', a);2452if (b == Name.npos)2453Idx = 0;2454else2455Idx = b+1;2456F = Name.slice(Idx, Idx + Foo.size());2457DotFramework = Name.slice(Idx + Foo.size(),2458Idx + Foo.size() + sizeof(".framework/")-1);2459if (F == Foo && DotFramework == ".framework/") {2460isFramework = true;2461return Foo;2462}24632464// Next look for the form Foo.framework/Versions/A/Foo2465if (b == Name.npos)2466goto guess_library;2467c = Name.rfind('/', b);2468if (c == Name.npos || c == 0)2469goto guess_library;2470V = Name.slice(c+1, Name.npos);2471if (!V.starts_with("Versions/"))2472goto guess_library;2473d = Name.rfind('/', c);2474if (d == Name.npos)2475Idx = 0;2476else2477Idx = d+1;2478F = Name.slice(Idx, Idx + Foo.size());2479DotFramework = Name.slice(Idx + Foo.size(),2480Idx + Foo.size() + sizeof(".framework/")-1);2481if (F == Foo && DotFramework == ".framework/") {2482isFramework = true;2483return Foo;2484}24852486guess_library:2487// pull off the suffix after the "." and make a point to it2488a = Name.rfind('.');2489if (a == Name.npos || a == 0)2490return StringRef();2491Dylib = Name.slice(a, Name.npos);2492if (Dylib != ".dylib")2493goto guess_qtx;24942495// First pull off the version letter for the form Foo.A.dylib if any.2496if (a >= 3) {2497Dot = Name.slice(a-2, a-1);2498if (Dot == ".")2499a = a - 2;2500}25012502b = Name.rfind('/', a);2503if (b == Name.npos)2504b = 0;2505else2506b = b+1;2507// ignore any suffix after an underbar like Foo_profile.A.dylib2508Idx = Name.rfind('_');2509if (Idx != Name.npos && Idx != b) {2510Lib = Name.slice(b, Idx);2511Suffix = Name.slice(Idx, a);2512if (Suffix != "_debug" && Suffix != "_profile") {2513Suffix = StringRef();2514Lib = Name.slice(b, a);2515}2516}2517else2518Lib = Name.slice(b, a);2519// There are incorrect library names of the form:2520// libATS.A_profile.dylib so check for these.2521if (Lib.size() >= 3) {2522Dot = Lib.slice(Lib.size()-2, Lib.size()-1);2523if (Dot == ".")2524Lib = Lib.slice(0, Lib.size()-2);2525}2526return Lib;25272528guess_qtx:2529Qtx = Name.slice(a, Name.npos);2530if (Qtx != ".qtx")2531return StringRef();2532b = Name.rfind('/', a);2533if (b == Name.npos)2534Lib = Name.slice(0, a);2535else2536Lib = Name.slice(b+1, a);2537// There are library names of the form: QT.A.qtx so check for these.2538if (Lib.size() >= 3) {2539Dot = Lib.slice(Lib.size()-2, Lib.size()-1);2540if (Dot == ".")2541Lib = Lib.slice(0, Lib.size()-2);2542}2543return Lib;2544}25452546// getLibraryShortNameByIndex() is used to get the short name of the library2547// for an undefined symbol in a linked Mach-O binary that was linked with the2548// normal two-level namespace default (that is MH_TWOLEVEL in the header).2549// It is passed the index (0 - based) of the library as translated from2550// GET_LIBRARY_ORDINAL (1 - based).2551std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,2552StringRef &Res) const {2553if (Index >= Libraries.size())2554return object_error::parse_failed;25552556// If the cache of LibrariesShortNames is not built up do that first for2557// all the Libraries.2558if (LibrariesShortNames.size() == 0) {2559for (unsigned i = 0; i < Libraries.size(); i++) {2560auto CommandOrErr =2561getStructOrErr<MachO::dylib_command>(*this, Libraries[i]);2562if (!CommandOrErr)2563return object_error::parse_failed;2564MachO::dylib_command D = CommandOrErr.get();2565if (D.dylib.name >= D.cmdsize)2566return object_error::parse_failed;2567const char *P = (const char *)(Libraries[i]) + D.dylib.name;2568StringRef Name = StringRef(P);2569if (D.dylib.name+Name.size() >= D.cmdsize)2570return object_error::parse_failed;2571StringRef Suffix;2572bool isFramework;2573StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);2574if (shortName.empty())2575LibrariesShortNames.push_back(Name);2576else2577LibrariesShortNames.push_back(shortName);2578}2579}25802581Res = LibrariesShortNames[Index];2582return std::error_code();2583}25842585uint32_t MachOObjectFile::getLibraryCount() const {2586return Libraries.size();2587}25882589section_iterator2590MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {2591DataRefImpl Sec;2592Sec.d.a = Rel->getRawDataRefImpl().d.a;2593return section_iterator(SectionRef(Sec, this));2594}25952596basic_symbol_iterator MachOObjectFile::symbol_begin() const {2597DataRefImpl DRI;2598MachO::symtab_command Symtab = getSymtabLoadCommand();2599if (!SymtabLoadCmd || Symtab.nsyms == 0)2600return basic_symbol_iterator(SymbolRef(DRI, this));26012602return getSymbolByIndex(0);2603}26042605basic_symbol_iterator MachOObjectFile::symbol_end() const {2606DataRefImpl DRI;2607MachO::symtab_command Symtab = getSymtabLoadCommand();2608if (!SymtabLoadCmd || Symtab.nsyms == 0)2609return basic_symbol_iterator(SymbolRef(DRI, this));26102611unsigned SymbolTableEntrySize = is64Bit() ?2612sizeof(MachO::nlist_64) :2613sizeof(MachO::nlist);2614unsigned Offset = Symtab.symoff +2615Symtab.nsyms * SymbolTableEntrySize;2616DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));2617return basic_symbol_iterator(SymbolRef(DRI, this));2618}26192620symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {2621MachO::symtab_command Symtab = getSymtabLoadCommand();2622if (!SymtabLoadCmd || Index >= Symtab.nsyms)2623report_fatal_error("Requested symbol index is out of range.");2624unsigned SymbolTableEntrySize =2625is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);2626DataRefImpl DRI;2627DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));2628DRI.p += Index * SymbolTableEntrySize;2629return basic_symbol_iterator(SymbolRef(DRI, this));2630}26312632uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {2633MachO::symtab_command Symtab = getSymtabLoadCommand();2634if (!SymtabLoadCmd)2635report_fatal_error("getSymbolIndex() called with no symbol table symbol");2636unsigned SymbolTableEntrySize =2637is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);2638DataRefImpl DRIstart;2639DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));2640uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;2641return Index;2642}26432644section_iterator MachOObjectFile::section_begin() const {2645DataRefImpl DRI;2646return section_iterator(SectionRef(DRI, this));2647}26482649section_iterator MachOObjectFile::section_end() const {2650DataRefImpl DRI;2651DRI.d.a = Sections.size();2652return section_iterator(SectionRef(DRI, this));2653}26542655uint8_t MachOObjectFile::getBytesInAddress() const {2656return is64Bit() ? 8 : 4;2657}26582659StringRef MachOObjectFile::getFileFormatName() const {2660unsigned CPUType = getCPUType(*this);2661if (!is64Bit()) {2662switch (CPUType) {2663case MachO::CPU_TYPE_I386:2664return "Mach-O 32-bit i386";2665case MachO::CPU_TYPE_ARM:2666return "Mach-O arm";2667case MachO::CPU_TYPE_ARM64_32:2668return "Mach-O arm64 (ILP32)";2669case MachO::CPU_TYPE_POWERPC:2670return "Mach-O 32-bit ppc";2671default:2672return "Mach-O 32-bit unknown";2673}2674}26752676switch (CPUType) {2677case MachO::CPU_TYPE_X86_64:2678return "Mach-O 64-bit x86-64";2679case MachO::CPU_TYPE_ARM64:2680return "Mach-O arm64";2681case MachO::CPU_TYPE_POWERPC64:2682return "Mach-O 64-bit ppc64";2683default:2684return "Mach-O 64-bit unknown";2685}2686}26872688Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {2689switch (CPUType) {2690case MachO::CPU_TYPE_I386:2691return Triple::x86;2692case MachO::CPU_TYPE_X86_64:2693return Triple::x86_64;2694case MachO::CPU_TYPE_ARM:2695return Triple::arm;2696case MachO::CPU_TYPE_ARM64:2697return Triple::aarch64;2698case MachO::CPU_TYPE_ARM64_32:2699return Triple::aarch64_32;2700case MachO::CPU_TYPE_POWERPC:2701return Triple::ppc;2702case MachO::CPU_TYPE_POWERPC64:2703return Triple::ppc64;2704default:2705return Triple::UnknownArch;2706}2707}27082709Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,2710const char **McpuDefault,2711const char **ArchFlag) {2712if (McpuDefault)2713*McpuDefault = nullptr;2714if (ArchFlag)2715*ArchFlag = nullptr;27162717switch (CPUType) {2718case MachO::CPU_TYPE_I386:2719switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {2720case MachO::CPU_SUBTYPE_I386_ALL:2721if (ArchFlag)2722*ArchFlag = "i386";2723return Triple("i386-apple-darwin");2724default:2725return Triple();2726}2727case MachO::CPU_TYPE_X86_64:2728switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {2729case MachO::CPU_SUBTYPE_X86_64_ALL:2730if (ArchFlag)2731*ArchFlag = "x86_64";2732return Triple("x86_64-apple-darwin");2733case MachO::CPU_SUBTYPE_X86_64_H:2734if (ArchFlag)2735*ArchFlag = "x86_64h";2736return Triple("x86_64h-apple-darwin");2737default:2738return Triple();2739}2740case MachO::CPU_TYPE_ARM:2741switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {2742case MachO::CPU_SUBTYPE_ARM_V4T:2743if (ArchFlag)2744*ArchFlag = "armv4t";2745return Triple("armv4t-apple-darwin");2746case MachO::CPU_SUBTYPE_ARM_V5TEJ:2747if (ArchFlag)2748*ArchFlag = "armv5e";2749return Triple("armv5e-apple-darwin");2750case MachO::CPU_SUBTYPE_ARM_XSCALE:2751if (ArchFlag)2752*ArchFlag = "xscale";2753return Triple("xscale-apple-darwin");2754case MachO::CPU_SUBTYPE_ARM_V6:2755if (ArchFlag)2756*ArchFlag = "armv6";2757return Triple("armv6-apple-darwin");2758case MachO::CPU_SUBTYPE_ARM_V6M:2759if (McpuDefault)2760*McpuDefault = "cortex-m0";2761if (ArchFlag)2762*ArchFlag = "armv6m";2763return Triple("armv6m-apple-darwin");2764case MachO::CPU_SUBTYPE_ARM_V7:2765if (ArchFlag)2766*ArchFlag = "armv7";2767return Triple("armv7-apple-darwin");2768case MachO::CPU_SUBTYPE_ARM_V7EM:2769if (McpuDefault)2770*McpuDefault = "cortex-m4";2771if (ArchFlag)2772*ArchFlag = "armv7em";2773return Triple("thumbv7em-apple-darwin");2774case MachO::CPU_SUBTYPE_ARM_V7K:2775if (McpuDefault)2776*McpuDefault = "cortex-a7";2777if (ArchFlag)2778*ArchFlag = "armv7k";2779return Triple("armv7k-apple-darwin");2780case MachO::CPU_SUBTYPE_ARM_V7M:2781if (McpuDefault)2782*McpuDefault = "cortex-m3";2783if (ArchFlag)2784*ArchFlag = "armv7m";2785return Triple("thumbv7m-apple-darwin");2786case MachO::CPU_SUBTYPE_ARM_V7S:2787if (McpuDefault)2788*McpuDefault = "cortex-a7";2789if (ArchFlag)2790*ArchFlag = "armv7s";2791return Triple("armv7s-apple-darwin");2792default:2793return Triple();2794}2795case MachO::CPU_TYPE_ARM64:2796switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {2797case MachO::CPU_SUBTYPE_ARM64_ALL:2798if (McpuDefault)2799*McpuDefault = "cyclone";2800if (ArchFlag)2801*ArchFlag = "arm64";2802return Triple("arm64-apple-darwin");2803case MachO::CPU_SUBTYPE_ARM64E:2804if (McpuDefault)2805*McpuDefault = "apple-a12";2806if (ArchFlag)2807*ArchFlag = "arm64e";2808return Triple("arm64e-apple-darwin");2809default:2810return Triple();2811}2812case MachO::CPU_TYPE_ARM64_32:2813switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {2814case MachO::CPU_SUBTYPE_ARM64_32_V8:2815if (McpuDefault)2816*McpuDefault = "cyclone";2817if (ArchFlag)2818*ArchFlag = "arm64_32";2819return Triple("arm64_32-apple-darwin");2820default:2821return Triple();2822}2823case MachO::CPU_TYPE_POWERPC:2824switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {2825case MachO::CPU_SUBTYPE_POWERPC_ALL:2826if (ArchFlag)2827*ArchFlag = "ppc";2828return Triple("ppc-apple-darwin");2829default:2830return Triple();2831}2832case MachO::CPU_TYPE_POWERPC64:2833switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {2834case MachO::CPU_SUBTYPE_POWERPC_ALL:2835if (ArchFlag)2836*ArchFlag = "ppc64";2837return Triple("ppc64-apple-darwin");2838default:2839return Triple();2840}2841default:2842return Triple();2843}2844}28452846Triple MachOObjectFile::getHostArch() {2847return Triple(sys::getDefaultTargetTriple());2848}28492850bool MachOObjectFile::isValidArch(StringRef ArchFlag) {2851auto validArchs = getValidArchs();2852return llvm::is_contained(validArchs, ArchFlag);2853}28542855ArrayRef<StringRef> MachOObjectFile::getValidArchs() {2856static const std::array<StringRef, 18> ValidArchs = {{2857"i386",2858"x86_64",2859"x86_64h",2860"armv4t",2861"arm",2862"armv5e",2863"armv6",2864"armv6m",2865"armv7",2866"armv7em",2867"armv7k",2868"armv7m",2869"armv7s",2870"arm64",2871"arm64e",2872"arm64_32",2873"ppc",2874"ppc64",2875}};28762877return ValidArchs;2878}28792880Triple::ArchType MachOObjectFile::getArch() const {2881return getArch(getCPUType(*this), getCPUSubType(*this));2882}28832884Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {2885return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);2886}28872888relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {2889DataRefImpl DRI;2890DRI.d.a = Index;2891return section_rel_begin(DRI);2892}28932894relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {2895DataRefImpl DRI;2896DRI.d.a = Index;2897return section_rel_end(DRI);2898}28992900dice_iterator MachOObjectFile::begin_dices() const {2901DataRefImpl DRI;2902if (!DataInCodeLoadCmd)2903return dice_iterator(DiceRef(DRI, this));29042905MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();2906DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));2907return dice_iterator(DiceRef(DRI, this));2908}29092910dice_iterator MachOObjectFile::end_dices() const {2911DataRefImpl DRI;2912if (!DataInCodeLoadCmd)2913return dice_iterator(DiceRef(DRI, this));29142915MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();2916unsigned Offset = DicLC.dataoff + DicLC.datasize;2917DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));2918return dice_iterator(DiceRef(DRI, this));2919}29202921ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,2922ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}29232924void ExportEntry::moveToFirst() {2925ErrorAsOutParameter ErrAsOutParam(E);2926pushNode(0);2927if (*E)2928return;2929pushDownUntilBottom();2930}29312932void ExportEntry::moveToEnd() {2933Stack.clear();2934Done = true;2935}29362937bool ExportEntry::operator==(const ExportEntry &Other) const {2938// Common case, one at end, other iterating from begin.2939if (Done || Other.Done)2940return (Done == Other.Done);2941// Not equal if different stack sizes.2942if (Stack.size() != Other.Stack.size())2943return false;2944// Not equal if different cumulative strings.2945if (!CumulativeString.equals(Other.CumulativeString))2946return false;2947// Equal if all nodes in both stacks match.2948for (unsigned i=0; i < Stack.size(); ++i) {2949if (Stack[i].Start != Other.Stack[i].Start)2950return false;2951}2952return true;2953}29542955uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {2956unsigned Count;2957uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);2958Ptr += Count;2959if (Ptr > Trie.end())2960Ptr = Trie.end();2961return Result;2962}29632964StringRef ExportEntry::name() const {2965return CumulativeString;2966}29672968uint64_t ExportEntry::flags() const {2969return Stack.back().Flags;2970}29712972uint64_t ExportEntry::address() const {2973return Stack.back().Address;2974}29752976uint64_t ExportEntry::other() const {2977return Stack.back().Other;2978}29792980StringRef ExportEntry::otherName() const {2981const char* ImportName = Stack.back().ImportName;2982if (ImportName)2983return StringRef(ImportName);2984return StringRef();2985}29862987uint32_t ExportEntry::nodeOffset() const {2988return Stack.back().Start - Trie.begin();2989}29902991ExportEntry::NodeState::NodeState(const uint8_t *Ptr)2992: Start(Ptr), Current(Ptr) {}29932994void ExportEntry::pushNode(uint64_t offset) {2995ErrorAsOutParameter ErrAsOutParam(E);2996const uint8_t *Ptr = Trie.begin() + offset;2997NodeState State(Ptr);2998const char *error = nullptr;2999uint64_t ExportInfoSize = readULEB128(State.Current, &error);3000if (error) {3001*E = malformedError("export info size " + Twine(error) +3002" in export trie data at node: 0x" +3003Twine::utohexstr(offset));3004moveToEnd();3005return;3006}3007State.IsExportNode = (ExportInfoSize != 0);3008const uint8_t* Children = State.Current + ExportInfoSize;3009if (Children > Trie.end()) {3010*E = malformedError(3011"export info size: 0x" + Twine::utohexstr(ExportInfoSize) +3012" in export trie data at node: 0x" + Twine::utohexstr(offset) +3013" too big and extends past end of trie data");3014moveToEnd();3015return;3016}3017if (State.IsExportNode) {3018const uint8_t *ExportStart = State.Current;3019State.Flags = readULEB128(State.Current, &error);3020if (error) {3021*E = malformedError("flags " + Twine(error) +3022" in export trie data at node: 0x" +3023Twine::utohexstr(offset));3024moveToEnd();3025return;3026}3027uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;3028if (State.Flags != 0 &&3029(Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&3030Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&3031Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {3032*E = malformedError(3033"unsupported exported symbol kind: " + Twine((int)Kind) +3034" in flags: 0x" + Twine::utohexstr(State.Flags) +3035" in export trie data at node: 0x" + Twine::utohexstr(offset));3036moveToEnd();3037return;3038}3039if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {3040State.Address = 0;3041State.Other = readULEB128(State.Current, &error); // dylib ordinal3042if (error) {3043*E = malformedError("dylib ordinal of re-export " + Twine(error) +3044" in export trie data at node: 0x" +3045Twine::utohexstr(offset));3046moveToEnd();3047return;3048}3049if (O != nullptr) {3050// Only positive numbers represent library ordinals. Zero and negative3051// numbers have special meaning (see BindSpecialDylib).3052if ((int64_t)State.Other > 0 && State.Other > O->getLibraryCount()) {3053*E = malformedError(3054"bad library ordinal: " + Twine((int)State.Other) + " (max " +3055Twine((int)O->getLibraryCount()) +3056") in export trie data at node: 0x" + Twine::utohexstr(offset));3057moveToEnd();3058return;3059}3060}3061State.ImportName = reinterpret_cast<const char*>(State.Current);3062if (*State.ImportName == '\0') {3063State.Current++;3064} else {3065const uint8_t *End = State.Current + 1;3066if (End >= Trie.end()) {3067*E = malformedError("import name of re-export in export trie data at "3068"node: 0x" +3069Twine::utohexstr(offset) +3070" starts past end of trie data");3071moveToEnd();3072return;3073}3074while(*End != '\0' && End < Trie.end())3075End++;3076if (*End != '\0') {3077*E = malformedError("import name of re-export in export trie data at "3078"node: 0x" +3079Twine::utohexstr(offset) +3080" extends past end of trie data");3081moveToEnd();3082return;3083}3084State.Current = End + 1;3085}3086} else {3087State.Address = readULEB128(State.Current, &error);3088if (error) {3089*E = malformedError("address " + Twine(error) +3090" in export trie data at node: 0x" +3091Twine::utohexstr(offset));3092moveToEnd();3093return;3094}3095if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {3096State.Other = readULEB128(State.Current, &error);3097if (error) {3098*E = malformedError("resolver of stub and resolver " + Twine(error) +3099" in export trie data at node: 0x" +3100Twine::utohexstr(offset));3101moveToEnd();3102return;3103}3104}3105}3106if (ExportStart + ExportInfoSize < State.Current) {3107*E = malformedError(3108"inconsistent export info size: 0x" +3109Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +3110Twine::utohexstr(State.Current - ExportStart) +3111" in export trie data at node: 0x" + Twine::utohexstr(offset));3112moveToEnd();3113return;3114}3115}3116State.ChildCount = *Children;3117if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {3118*E = malformedError("byte for count of childern in export trie data at "3119"node: 0x" +3120Twine::utohexstr(offset) +3121" extends past end of trie data");3122moveToEnd();3123return;3124}3125State.Current = Children + 1;3126State.NextChildIndex = 0;3127State.ParentStringLength = CumulativeString.size();3128Stack.push_back(State);3129}31303131void ExportEntry::pushDownUntilBottom() {3132ErrorAsOutParameter ErrAsOutParam(E);3133const char *error = nullptr;3134while (Stack.back().NextChildIndex < Stack.back().ChildCount) {3135NodeState &Top = Stack.back();3136CumulativeString.resize(Top.ParentStringLength);3137for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {3138char C = *Top.Current;3139CumulativeString.push_back(C);3140}3141if (Top.Current >= Trie.end()) {3142*E = malformedError("edge sub-string in export trie data at node: 0x" +3143Twine::utohexstr(Top.Start - Trie.begin()) +3144" for child #" + Twine((int)Top.NextChildIndex) +3145" extends past end of trie data");3146moveToEnd();3147return;3148}3149Top.Current += 1;3150uint64_t childNodeIndex = readULEB128(Top.Current, &error);3151if (error) {3152*E = malformedError("child node offset " + Twine(error) +3153" in export trie data at node: 0x" +3154Twine::utohexstr(Top.Start - Trie.begin()));3155moveToEnd();3156return;3157}3158for (const NodeState &node : nodes()) {3159if (node.Start == Trie.begin() + childNodeIndex){3160*E = malformedError("loop in childern in export trie data at node: 0x" +3161Twine::utohexstr(Top.Start - Trie.begin()) +3162" back to node: 0x" +3163Twine::utohexstr(childNodeIndex));3164moveToEnd();3165return;3166}3167}3168Top.NextChildIndex += 1;3169pushNode(childNodeIndex);3170if (*E)3171return;3172}3173if (!Stack.back().IsExportNode) {3174*E = malformedError("node is not an export node in export trie data at "3175"node: 0x" +3176Twine::utohexstr(Stack.back().Start - Trie.begin()));3177moveToEnd();3178return;3179}3180}31813182// We have a trie data structure and need a way to walk it that is compatible3183// with the C++ iterator model. The solution is a non-recursive depth first3184// traversal where the iterator contains a stack of parent nodes along with a3185// string that is the accumulation of all edge strings along the parent chain3186// to this point.3187//3188// There is one "export" node for each exported symbol. But because some3189// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export3190// node may have child nodes too.3191//3192// The algorithm for moveNext() is to keep moving down the leftmost unvisited3193// child until hitting a node with no children (which is an export node or3194// else the trie is malformed). On the way down, each node is pushed on the3195// stack ivar. If there is no more ways down, it pops up one and tries to go3196// down a sibling path until a childless node is reached.3197void ExportEntry::moveNext() {3198assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");3199if (!Stack.back().IsExportNode) {3200*E = malformedError("node is not an export node in export trie data at "3201"node: 0x" +3202Twine::utohexstr(Stack.back().Start - Trie.begin()));3203moveToEnd();3204return;3205}32063207Stack.pop_back();3208while (!Stack.empty()) {3209NodeState &Top = Stack.back();3210if (Top.NextChildIndex < Top.ChildCount) {3211pushDownUntilBottom();3212// Now at the next export node.3213return;3214} else {3215if (Top.IsExportNode) {3216// This node has no children but is itself an export node.3217CumulativeString.resize(Top.ParentStringLength);3218return;3219}3220Stack.pop_back();3221}3222}3223Done = true;3224}32253226iterator_range<export_iterator>3227MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,3228const MachOObjectFile *O) {3229ExportEntry Start(&E, O, Trie);3230if (Trie.empty())3231Start.moveToEnd();3232else3233Start.moveToFirst();32343235ExportEntry Finish(&E, O, Trie);3236Finish.moveToEnd();32373238return make_range(export_iterator(Start), export_iterator(Finish));3239}32403241iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {3242ArrayRef<uint8_t> Trie;3243if (DyldInfoLoadCmd)3244Trie = getDyldInfoExportsTrie();3245else if (DyldExportsTrieLoadCmd)3246Trie = getDyldExportsTrie();32473248return exports(Err, Trie, this);3249}32503251MachOAbstractFixupEntry::MachOAbstractFixupEntry(Error *E,3252const MachOObjectFile *O)3253: E(E), O(O) {3254// Cache the vmaddress of __TEXT3255for (const auto &Command : O->load_commands()) {3256if (Command.C.cmd == MachO::LC_SEGMENT) {3257MachO::segment_command SLC = O->getSegmentLoadCommand(Command);3258if (StringRef(SLC.segname) == "__TEXT") {3259TextAddress = SLC.vmaddr;3260break;3261}3262} else if (Command.C.cmd == MachO::LC_SEGMENT_64) {3263MachO::segment_command_64 SLC_64 = O->getSegment64LoadCommand(Command);3264if (StringRef(SLC_64.segname) == "__TEXT") {3265TextAddress = SLC_64.vmaddr;3266break;3267}3268}3269}3270}32713272int32_t MachOAbstractFixupEntry::segmentIndex() const { return SegmentIndex; }32733274uint64_t MachOAbstractFixupEntry::segmentOffset() const {3275return SegmentOffset;3276}32773278uint64_t MachOAbstractFixupEntry::segmentAddress() const {3279return O->BindRebaseAddress(SegmentIndex, 0);3280}32813282StringRef MachOAbstractFixupEntry::segmentName() const {3283return O->BindRebaseSegmentName(SegmentIndex);3284}32853286StringRef MachOAbstractFixupEntry::sectionName() const {3287return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);3288}32893290uint64_t MachOAbstractFixupEntry::address() const {3291return O->BindRebaseAddress(SegmentIndex, SegmentOffset);3292}32933294StringRef MachOAbstractFixupEntry::symbolName() const { return SymbolName; }32953296int64_t MachOAbstractFixupEntry::addend() const { return Addend; }32973298uint32_t MachOAbstractFixupEntry::flags() const { return Flags; }32993300int MachOAbstractFixupEntry::ordinal() const { return Ordinal; }33013302StringRef MachOAbstractFixupEntry::typeName() const { return "unknown"; }33033304void MachOAbstractFixupEntry::moveToFirst() {3305SegmentOffset = 0;3306SegmentIndex = -1;3307Ordinal = 0;3308Flags = 0;3309Addend = 0;3310Done = false;3311}33123313void MachOAbstractFixupEntry::moveToEnd() { Done = true; }33143315void MachOAbstractFixupEntry::moveNext() {}33163317MachOChainedFixupEntry::MachOChainedFixupEntry(Error *E,3318const MachOObjectFile *O,3319bool Parse)3320: MachOAbstractFixupEntry(E, O) {3321ErrorAsOutParameter e(E);3322if (!Parse)3323return;33243325if (auto FixupTargetsOrErr = O->getDyldChainedFixupTargets()) {3326FixupTargets = *FixupTargetsOrErr;3327} else {3328*E = FixupTargetsOrErr.takeError();3329return;3330}33313332if (auto SegmentsOrErr = O->getChainedFixupsSegments()) {3333Segments = std::move(SegmentsOrErr->second);3334} else {3335*E = SegmentsOrErr.takeError();3336return;3337}3338}33393340void MachOChainedFixupEntry::findNextPageWithFixups() {3341auto FindInSegment = [this]() {3342const ChainedFixupsSegment &SegInfo = Segments[InfoSegIndex];3343while (PageIndex < SegInfo.PageStarts.size() &&3344SegInfo.PageStarts[PageIndex] == MachO::DYLD_CHAINED_PTR_START_NONE)3345++PageIndex;3346return PageIndex < SegInfo.PageStarts.size();3347};33483349while (InfoSegIndex < Segments.size()) {3350if (FindInSegment()) {3351PageOffset = Segments[InfoSegIndex].PageStarts[PageIndex];3352SegmentData = O->getSegmentContents(Segments[InfoSegIndex].SegIdx);3353return;3354}33553356InfoSegIndex++;3357PageIndex = 0;3358}3359}33603361void MachOChainedFixupEntry::moveToFirst() {3362MachOAbstractFixupEntry::moveToFirst();3363if (Segments.empty()) {3364Done = true;3365return;3366}33673368InfoSegIndex = 0;3369PageIndex = 0;33703371findNextPageWithFixups();3372moveNext();3373}33743375void MachOChainedFixupEntry::moveToEnd() {3376MachOAbstractFixupEntry::moveToEnd();3377}33783379void MachOChainedFixupEntry::moveNext() {3380ErrorAsOutParameter ErrAsOutParam(E);33813382if (InfoSegIndex == Segments.size()) {3383Done = true;3384return;3385}33863387const ChainedFixupsSegment &SegInfo = Segments[InfoSegIndex];3388SegmentIndex = SegInfo.SegIdx;3389SegmentOffset = SegInfo.Header.page_size * PageIndex + PageOffset;33903391// FIXME: Handle other pointer formats.3392uint16_t PointerFormat = SegInfo.Header.pointer_format;3393if (PointerFormat != MachO::DYLD_CHAINED_PTR_64 &&3394PointerFormat != MachO::DYLD_CHAINED_PTR_64_OFFSET) {3395*E = createError("segment " + Twine(SegmentIndex) +3396" has unsupported chained fixup pointer_format " +3397Twine(PointerFormat));3398moveToEnd();3399return;3400}34013402Ordinal = 0;3403Flags = 0;3404Addend = 0;3405PointerValue = 0;3406SymbolName = {};34073408if (SegmentOffset + sizeof(RawValue) > SegmentData.size()) {3409*E = malformedError("fixup in segment " + Twine(SegmentIndex) +3410" at offset " + Twine(SegmentOffset) +3411" extends past segment's end");3412moveToEnd();3413return;3414}34153416static_assert(sizeof(RawValue) == sizeof(MachO::dyld_chained_import_addend));3417memcpy(&RawValue, SegmentData.data() + SegmentOffset, sizeof(RawValue));3418if (O->isLittleEndian() != sys::IsLittleEndianHost)3419sys::swapByteOrder(RawValue);34203421// The bit extraction below assumes little-endian fixup entries.3422assert(O->isLittleEndian() && "big-endian object should have been rejected "3423"by getDyldChainedFixupTargets()");3424auto Field = [this](uint8_t Right, uint8_t Count) {3425return (RawValue >> Right) & ((1ULL << Count) - 1);3426};34273428// The `bind` field (most significant bit) of the encoded fixup determines3429// whether it is dyld_chained_ptr_64_bind or dyld_chained_ptr_64_rebase.3430bool IsBind = Field(63, 1);3431Kind = IsBind ? FixupKind::Bind : FixupKind::Rebase;3432uint32_t Next = Field(51, 12);3433if (IsBind) {3434uint32_t ImportOrdinal = Field(0, 24);3435uint8_t InlineAddend = Field(24, 8);34363437if (ImportOrdinal >= FixupTargets.size()) {3438*E = malformedError("fixup in segment " + Twine(SegmentIndex) +3439" at offset " + Twine(SegmentOffset) +3440" has out-of range import ordinal " +3441Twine(ImportOrdinal));3442moveToEnd();3443return;3444}34453446ChainedFixupTarget &Target = FixupTargets[ImportOrdinal];3447Ordinal = Target.libOrdinal();3448Addend = InlineAddend ? InlineAddend : Target.addend();3449Flags = Target.weakImport() ? MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0;3450SymbolName = Target.symbolName();3451} else {3452uint64_t Target = Field(0, 36);3453uint64_t High8 = Field(36, 8);34543455PointerValue = Target | (High8 << 56);3456if (PointerFormat == MachO::DYLD_CHAINED_PTR_64_OFFSET)3457PointerValue += textAddress();3458}34593460// The stride is 4 bytes for DYLD_CHAINED_PTR_64(_OFFSET).3461if (Next != 0) {3462PageOffset += 4 * Next;3463} else {3464++PageIndex;3465findNextPageWithFixups();3466}3467}34683469bool MachOChainedFixupEntry::operator==(3470const MachOChainedFixupEntry &Other) const {3471if (Done && Other.Done)3472return true;3473if (Done != Other.Done)3474return false;3475return InfoSegIndex == Other.InfoSegIndex && PageIndex == Other.PageIndex &&3476PageOffset == Other.PageOffset;3477}34783479MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,3480ArrayRef<uint8_t> Bytes, bool is64Bit)3481: E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),3482PointerSize(is64Bit ? 8 : 4) {}34833484void MachORebaseEntry::moveToFirst() {3485Ptr = Opcodes.begin();3486moveNext();3487}34883489void MachORebaseEntry::moveToEnd() {3490Ptr = Opcodes.end();3491RemainingLoopCount = 0;3492Done = true;3493}34943495void MachORebaseEntry::moveNext() {3496ErrorAsOutParameter ErrAsOutParam(E);3497// If in the middle of some loop, move to next rebasing in loop.3498SegmentOffset += AdvanceAmount;3499if (RemainingLoopCount) {3500--RemainingLoopCount;3501return;3502}35033504bool More = true;3505while (More) {3506// REBASE_OPCODE_DONE is only used for padding if we are not aligned to3507// pointer size. Therefore it is possible to reach the end without ever3508// having seen REBASE_OPCODE_DONE.3509if (Ptr == Opcodes.end()) {3510Done = true;3511return;3512}35133514// Parse next opcode and set up next loop.3515const uint8_t *OpcodeStart = Ptr;3516uint8_t Byte = *Ptr++;3517uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;3518uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;3519uint64_t Count, Skip;3520const char *error = nullptr;3521switch (Opcode) {3522case MachO::REBASE_OPCODE_DONE:3523More = false;3524Done = true;3525moveToEnd();3526DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");3527break;3528case MachO::REBASE_OPCODE_SET_TYPE_IMM:3529RebaseType = ImmValue;3530if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {3531*E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +3532Twine((int)RebaseType) + " for opcode at: 0x" +3533Twine::utohexstr(OpcodeStart - Opcodes.begin()));3534moveToEnd();3535return;3536}3537DEBUG_WITH_TYPE(3538"mach-o-rebase",3539dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "3540<< "RebaseType=" << (int) RebaseType << "\n");3541break;3542case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:3543SegmentIndex = ImmValue;3544SegmentOffset = readULEB128(&error);3545if (error) {3546*E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +3547Twine(error) + " for opcode at: 0x" +3548Twine::utohexstr(OpcodeStart - Opcodes.begin()));3549moveToEnd();3550return;3551}3552error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,3553PointerSize);3554if (error) {3555*E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +3556Twine(error) + " for opcode at: 0x" +3557Twine::utohexstr(OpcodeStart - Opcodes.begin()));3558moveToEnd();3559return;3560}3561DEBUG_WITH_TYPE(3562"mach-o-rebase",3563dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "3564<< "SegmentIndex=" << SegmentIndex << ", "3565<< format("SegmentOffset=0x%06X", SegmentOffset)3566<< "\n");3567break;3568case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:3569SegmentOffset += readULEB128(&error);3570if (error) {3571*E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +3572" for opcode at: 0x" +3573Twine::utohexstr(OpcodeStart - Opcodes.begin()));3574moveToEnd();3575return;3576}3577error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,3578PointerSize);3579if (error) {3580*E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +3581" for opcode at: 0x" +3582Twine::utohexstr(OpcodeStart - Opcodes.begin()));3583moveToEnd();3584return;3585}3586DEBUG_WITH_TYPE("mach-o-rebase",3587dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "3588<< format("SegmentOffset=0x%06X",3589SegmentOffset) << "\n");3590break;3591case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:3592SegmentOffset += ImmValue * PointerSize;3593error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,3594PointerSize);3595if (error) {3596*E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +3597Twine(error) + " for opcode at: 0x" +3598Twine::utohexstr(OpcodeStart - Opcodes.begin()));3599moveToEnd();3600return;3601}3602DEBUG_WITH_TYPE("mach-o-rebase",3603dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "3604<< format("SegmentOffset=0x%06X",3605SegmentOffset) << "\n");3606break;3607case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:3608AdvanceAmount = PointerSize;3609Skip = 0;3610Count = ImmValue;3611if (ImmValue != 0)3612RemainingLoopCount = ImmValue - 1;3613else3614RemainingLoopCount = 0;3615error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,3616PointerSize, Count, Skip);3617if (error) {3618*E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +3619Twine(error) + " for opcode at: 0x" +3620Twine::utohexstr(OpcodeStart - Opcodes.begin()));3621moveToEnd();3622return;3623}3624DEBUG_WITH_TYPE(3625"mach-o-rebase",3626dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "3627<< format("SegmentOffset=0x%06X", SegmentOffset)3628<< ", AdvanceAmount=" << AdvanceAmount3629<< ", RemainingLoopCount=" << RemainingLoopCount3630<< "\n");3631return;3632case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:3633AdvanceAmount = PointerSize;3634Skip = 0;3635Count = readULEB128(&error);3636if (error) {3637*E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +3638Twine(error) + " for opcode at: 0x" +3639Twine::utohexstr(OpcodeStart - Opcodes.begin()));3640moveToEnd();3641return;3642}3643if (Count != 0)3644RemainingLoopCount = Count - 1;3645else3646RemainingLoopCount = 0;3647error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,3648PointerSize, Count, Skip);3649if (error) {3650*E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +3651Twine(error) + " for opcode at: 0x" +3652Twine::utohexstr(OpcodeStart - Opcodes.begin()));3653moveToEnd();3654return;3655}3656DEBUG_WITH_TYPE(3657"mach-o-rebase",3658dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "3659<< format("SegmentOffset=0x%06X", SegmentOffset)3660<< ", AdvanceAmount=" << AdvanceAmount3661<< ", RemainingLoopCount=" << RemainingLoopCount3662<< "\n");3663return;3664case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:3665Skip = readULEB128(&error);3666if (error) {3667*E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +3668Twine(error) + " for opcode at: 0x" +3669Twine::utohexstr(OpcodeStart - Opcodes.begin()));3670moveToEnd();3671return;3672}3673AdvanceAmount = Skip + PointerSize;3674Count = 1;3675RemainingLoopCount = 0;3676error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,3677PointerSize, Count, Skip);3678if (error) {3679*E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +3680Twine(error) + " for opcode at: 0x" +3681Twine::utohexstr(OpcodeStart - Opcodes.begin()));3682moveToEnd();3683return;3684}3685DEBUG_WITH_TYPE(3686"mach-o-rebase",3687dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "3688<< format("SegmentOffset=0x%06X", SegmentOffset)3689<< ", AdvanceAmount=" << AdvanceAmount3690<< ", RemainingLoopCount=" << RemainingLoopCount3691<< "\n");3692return;3693case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:3694Count = readULEB128(&error);3695if (error) {3696*E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"3697"ULEB " +3698Twine(error) + " for opcode at: 0x" +3699Twine::utohexstr(OpcodeStart - Opcodes.begin()));3700moveToEnd();3701return;3702}3703if (Count != 0)3704RemainingLoopCount = Count - 1;3705else3706RemainingLoopCount = 0;3707Skip = readULEB128(&error);3708if (error) {3709*E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"3710"ULEB " +3711Twine(error) + " for opcode at: 0x" +3712Twine::utohexstr(OpcodeStart - Opcodes.begin()));3713moveToEnd();3714return;3715}3716AdvanceAmount = Skip + PointerSize;37173718error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,3719PointerSize, Count, Skip);3720if (error) {3721*E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"3722"ULEB " +3723Twine(error) + " for opcode at: 0x" +3724Twine::utohexstr(OpcodeStart - Opcodes.begin()));3725moveToEnd();3726return;3727}3728DEBUG_WITH_TYPE(3729"mach-o-rebase",3730dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "3731<< format("SegmentOffset=0x%06X", SegmentOffset)3732<< ", AdvanceAmount=" << AdvanceAmount3733<< ", RemainingLoopCount=" << RemainingLoopCount3734<< "\n");3735return;3736default:3737*E = malformedError("bad rebase info (bad opcode value 0x" +3738Twine::utohexstr(Opcode) + " for opcode at: 0x" +3739Twine::utohexstr(OpcodeStart - Opcodes.begin()));3740moveToEnd();3741return;3742}3743}3744}37453746uint64_t MachORebaseEntry::readULEB128(const char **error) {3747unsigned Count;3748uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);3749Ptr += Count;3750if (Ptr > Opcodes.end())3751Ptr = Opcodes.end();3752return Result;3753}37543755int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }37563757uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }37583759StringRef MachORebaseEntry::typeName() const {3760switch (RebaseType) {3761case MachO::REBASE_TYPE_POINTER:3762return "pointer";3763case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:3764return "text abs32";3765case MachO::REBASE_TYPE_TEXT_PCREL32:3766return "text rel32";3767}3768return "unknown";3769}37703771// For use with the SegIndex of a checked Mach-O Rebase entry3772// to get the segment name.3773StringRef MachORebaseEntry::segmentName() const {3774return O->BindRebaseSegmentName(SegmentIndex);3775}37763777// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry3778// to get the section name.3779StringRef MachORebaseEntry::sectionName() const {3780return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);3781}37823783// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry3784// to get the address.3785uint64_t MachORebaseEntry::address() const {3786return O->BindRebaseAddress(SegmentIndex, SegmentOffset);3787}37883789bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {3790#ifdef EXPENSIVE_CHECKS3791assert(Opcodes == Other.Opcodes && "compare iterators of different files");3792#else3793assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");3794#endif3795return (Ptr == Other.Ptr) &&3796(RemainingLoopCount == Other.RemainingLoopCount) &&3797(Done == Other.Done);3798}37993800iterator_range<rebase_iterator>3801MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,3802ArrayRef<uint8_t> Opcodes, bool is64) {3803if (O->BindRebaseSectionTable == nullptr)3804O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);3805MachORebaseEntry Start(&Err, O, Opcodes, is64);3806Start.moveToFirst();38073808MachORebaseEntry Finish(&Err, O, Opcodes, is64);3809Finish.moveToEnd();38103811return make_range(rebase_iterator(Start), rebase_iterator(Finish));3812}38133814iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {3815return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());3816}38173818MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,3819ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)3820: E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),3821PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}38223823void MachOBindEntry::moveToFirst() {3824Ptr = Opcodes.begin();3825moveNext();3826}38273828void MachOBindEntry::moveToEnd() {3829Ptr = Opcodes.end();3830RemainingLoopCount = 0;3831Done = true;3832}38333834void MachOBindEntry::moveNext() {3835ErrorAsOutParameter ErrAsOutParam(E);3836// If in the middle of some loop, move to next binding in loop.3837SegmentOffset += AdvanceAmount;3838if (RemainingLoopCount) {3839--RemainingLoopCount;3840return;3841}38423843bool More = true;3844while (More) {3845// BIND_OPCODE_DONE is only used for padding if we are not aligned to3846// pointer size. Therefore it is possible to reach the end without ever3847// having seen BIND_OPCODE_DONE.3848if (Ptr == Opcodes.end()) {3849Done = true;3850return;3851}38523853// Parse next opcode and set up next loop.3854const uint8_t *OpcodeStart = Ptr;3855uint8_t Byte = *Ptr++;3856uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;3857uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;3858int8_t SignExtended;3859const uint8_t *SymStart;3860uint64_t Count, Skip;3861const char *error = nullptr;3862switch (Opcode) {3863case MachO::BIND_OPCODE_DONE:3864if (TableKind == Kind::Lazy) {3865// Lazying bindings have a DONE opcode between entries. Need to ignore3866// it to advance to next entry. But need not if this is last entry.3867bool NotLastEntry = false;3868for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {3869if (*P) {3870NotLastEntry = true;3871}3872}3873if (NotLastEntry)3874break;3875}3876More = false;3877moveToEnd();3878DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");3879break;3880case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:3881if (TableKind == Kind::Weak) {3882*E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "3883"weak bind table for opcode at: 0x" +3884Twine::utohexstr(OpcodeStart - Opcodes.begin()));3885moveToEnd();3886return;3887}3888Ordinal = ImmValue;3889LibraryOrdinalSet = true;3890if (ImmValue > O->getLibraryCount()) {3891*E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "3892"library ordinal: " +3893Twine((int)ImmValue) + " (max " +3894Twine((int)O->getLibraryCount()) +3895") for opcode at: 0x" +3896Twine::utohexstr(OpcodeStart - Opcodes.begin()));3897moveToEnd();3898return;3899}3900DEBUG_WITH_TYPE(3901"mach-o-bind",3902dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "3903<< "Ordinal=" << Ordinal << "\n");3904break;3905case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:3906if (TableKind == Kind::Weak) {3907*E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "3908"weak bind table for opcode at: 0x" +3909Twine::utohexstr(OpcodeStart - Opcodes.begin()));3910moveToEnd();3911return;3912}3913Ordinal = readULEB128(&error);3914LibraryOrdinalSet = true;3915if (error) {3916*E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +3917Twine(error) + " for opcode at: 0x" +3918Twine::utohexstr(OpcodeStart - Opcodes.begin()));3919moveToEnd();3920return;3921}3922if (Ordinal > (int)O->getLibraryCount()) {3923*E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "3924"library ordinal: " +3925Twine((int)Ordinal) + " (max " +3926Twine((int)O->getLibraryCount()) +3927") for opcode at: 0x" +3928Twine::utohexstr(OpcodeStart - Opcodes.begin()));3929moveToEnd();3930return;3931}3932DEBUG_WITH_TYPE(3933"mach-o-bind",3934dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "3935<< "Ordinal=" << Ordinal << "\n");3936break;3937case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:3938if (TableKind == Kind::Weak) {3939*E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "3940"weak bind table for opcode at: 0x" +3941Twine::utohexstr(OpcodeStart - Opcodes.begin()));3942moveToEnd();3943return;3944}3945if (ImmValue) {3946SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;3947Ordinal = SignExtended;3948if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {3949*E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "3950"special ordinal: " +3951Twine((int)Ordinal) + " for opcode at: 0x" +3952Twine::utohexstr(OpcodeStart - Opcodes.begin()));3953moveToEnd();3954return;3955}3956} else3957Ordinal = 0;3958LibraryOrdinalSet = true;3959DEBUG_WITH_TYPE(3960"mach-o-bind",3961dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "3962<< "Ordinal=" << Ordinal << "\n");3963break;3964case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:3965Flags = ImmValue;3966SymStart = Ptr;3967while (*Ptr && (Ptr < Opcodes.end())) {3968++Ptr;3969}3970if (Ptr == Opcodes.end()) {3971*E = malformedError(3972"for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "3973"symbol name extends past opcodes for opcode at: 0x" +3974Twine::utohexstr(OpcodeStart - Opcodes.begin()));3975moveToEnd();3976return;3977}3978SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),3979Ptr-SymStart);3980++Ptr;3981DEBUG_WITH_TYPE(3982"mach-o-bind",3983dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "3984<< "SymbolName=" << SymbolName << "\n");3985if (TableKind == Kind::Weak) {3986if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)3987return;3988}3989break;3990case MachO::BIND_OPCODE_SET_TYPE_IMM:3991BindType = ImmValue;3992if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {3993*E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +3994Twine((int)ImmValue) + " for opcode at: 0x" +3995Twine::utohexstr(OpcodeStart - Opcodes.begin()));3996moveToEnd();3997return;3998}3999DEBUG_WITH_TYPE(4000"mach-o-bind",4001dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "4002<< "BindType=" << (int)BindType << "\n");4003break;4004case MachO::BIND_OPCODE_SET_ADDEND_SLEB:4005Addend = readSLEB128(&error);4006if (error) {4007*E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +4008" for opcode at: 0x" +4009Twine::utohexstr(OpcodeStart - Opcodes.begin()));4010moveToEnd();4011return;4012}4013DEBUG_WITH_TYPE(4014"mach-o-bind",4015dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "4016<< "Addend=" << Addend << "\n");4017break;4018case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:4019SegmentIndex = ImmValue;4020SegmentOffset = readULEB128(&error);4021if (error) {4022*E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +4023Twine(error) + " for opcode at: 0x" +4024Twine::utohexstr(OpcodeStart - Opcodes.begin()));4025moveToEnd();4026return;4027}4028error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,4029PointerSize);4030if (error) {4031*E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +4032Twine(error) + " for opcode at: 0x" +4033Twine::utohexstr(OpcodeStart - Opcodes.begin()));4034moveToEnd();4035return;4036}4037DEBUG_WITH_TYPE(4038"mach-o-bind",4039dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "4040<< "SegmentIndex=" << SegmentIndex << ", "4041<< format("SegmentOffset=0x%06X", SegmentOffset)4042<< "\n");4043break;4044case MachO::BIND_OPCODE_ADD_ADDR_ULEB:4045SegmentOffset += readULEB128(&error);4046if (error) {4047*E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +4048" for opcode at: 0x" +4049Twine::utohexstr(OpcodeStart - Opcodes.begin()));4050moveToEnd();4051return;4052}4053error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,4054PointerSize);4055if (error) {4056*E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +4057" for opcode at: 0x" +4058Twine::utohexstr(OpcodeStart - Opcodes.begin()));4059moveToEnd();4060return;4061}4062DEBUG_WITH_TYPE("mach-o-bind",4063dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "4064<< format("SegmentOffset=0x%06X",4065SegmentOffset) << "\n");4066break;4067case MachO::BIND_OPCODE_DO_BIND:4068AdvanceAmount = PointerSize;4069RemainingLoopCount = 0;4070error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,4071PointerSize);4072if (error) {4073*E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +4074" for opcode at: 0x" +4075Twine::utohexstr(OpcodeStart - Opcodes.begin()));4076moveToEnd();4077return;4078}4079if (SymbolName == StringRef()) {4080*E = malformedError(4081"for BIND_OPCODE_DO_BIND missing preceding "4082"BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +4083Twine::utohexstr(OpcodeStart - Opcodes.begin()));4084moveToEnd();4085return;4086}4087if (!LibraryOrdinalSet && TableKind != Kind::Weak) {4088*E =4089malformedError("for BIND_OPCODE_DO_BIND missing preceding "4090"BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +4091Twine::utohexstr(OpcodeStart - Opcodes.begin()));4092moveToEnd();4093return;4094}4095DEBUG_WITH_TYPE("mach-o-bind",4096dbgs() << "BIND_OPCODE_DO_BIND: "4097<< format("SegmentOffset=0x%06X",4098SegmentOffset) << "\n");4099return;4100case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:4101if (TableKind == Kind::Lazy) {4102*E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "4103"lazy bind table for opcode at: 0x" +4104Twine::utohexstr(OpcodeStart - Opcodes.begin()));4105moveToEnd();4106return;4107}4108error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,4109PointerSize);4110if (error) {4111*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +4112Twine(error) + " for opcode at: 0x" +4113Twine::utohexstr(OpcodeStart - Opcodes.begin()));4114moveToEnd();4115return;4116}4117if (SymbolName == StringRef()) {4118*E = malformedError(4119"for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "4120"preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "4121"at: 0x" +4122Twine::utohexstr(OpcodeStart - Opcodes.begin()));4123moveToEnd();4124return;4125}4126if (!LibraryOrdinalSet && TableKind != Kind::Weak) {4127*E = malformedError(4128"for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "4129"preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +4130Twine::utohexstr(OpcodeStart - Opcodes.begin()));4131moveToEnd();4132return;4133}4134AdvanceAmount = readULEB128(&error) + PointerSize;4135if (error) {4136*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +4137Twine(error) + " for opcode at: 0x" +4138Twine::utohexstr(OpcodeStart - Opcodes.begin()));4139moveToEnd();4140return;4141}4142// Note, this is not really an error until the next bind but make no sense4143// for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another4144// bind operation.4145error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +4146AdvanceAmount, PointerSize);4147if (error) {4148*E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "4149"ULEB) " +4150Twine(error) + " for opcode at: 0x" +4151Twine::utohexstr(OpcodeStart - Opcodes.begin()));4152moveToEnd();4153return;4154}4155RemainingLoopCount = 0;4156DEBUG_WITH_TYPE(4157"mach-o-bind",4158dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "4159<< format("SegmentOffset=0x%06X", SegmentOffset)4160<< ", AdvanceAmount=" << AdvanceAmount4161<< ", RemainingLoopCount=" << RemainingLoopCount4162<< "\n");4163return;4164case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:4165if (TableKind == Kind::Lazy) {4166*E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "4167"allowed in lazy bind table for opcode at: 0x" +4168Twine::utohexstr(OpcodeStart - Opcodes.begin()));4169moveToEnd();4170return;4171}4172if (SymbolName == StringRef()) {4173*E = malformedError(4174"for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "4175"missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "4176"opcode at: 0x" +4177Twine::utohexstr(OpcodeStart - Opcodes.begin()));4178moveToEnd();4179return;4180}4181if (!LibraryOrdinalSet && TableKind != Kind::Weak) {4182*E = malformedError(4183"for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "4184"missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "4185"at: 0x" +4186Twine::utohexstr(OpcodeStart - Opcodes.begin()));4187moveToEnd();4188return;4189}4190AdvanceAmount = ImmValue * PointerSize + PointerSize;4191RemainingLoopCount = 0;4192error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +4193AdvanceAmount, PointerSize);4194if (error) {4195*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +4196Twine(error) + " for opcode at: 0x" +4197Twine::utohexstr(OpcodeStart - Opcodes.begin()));4198moveToEnd();4199return;4200}4201DEBUG_WITH_TYPE("mach-o-bind",4202dbgs()4203<< "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "4204<< format("SegmentOffset=0x%06X", SegmentOffset) << "\n");4205return;4206case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:4207if (TableKind == Kind::Lazy) {4208*E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "4209"allowed in lazy bind table for opcode at: 0x" +4210Twine::utohexstr(OpcodeStart - Opcodes.begin()));4211moveToEnd();4212return;4213}4214Count = readULEB128(&error);4215if (Count != 0)4216RemainingLoopCount = Count - 1;4217else4218RemainingLoopCount = 0;4219if (error) {4220*E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "4221" (count value) " +4222Twine(error) + " for opcode at: 0x" +4223Twine::utohexstr(OpcodeStart - Opcodes.begin()));4224moveToEnd();4225return;4226}4227Skip = readULEB128(&error);4228AdvanceAmount = Skip + PointerSize;4229if (error) {4230*E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "4231" (skip value) " +4232Twine(error) + " for opcode at: 0x" +4233Twine::utohexstr(OpcodeStart - Opcodes.begin()));4234moveToEnd();4235return;4236}4237if (SymbolName == StringRef()) {4238*E = malformedError(4239"for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "4240"missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "4241"opcode at: 0x" +4242Twine::utohexstr(OpcodeStart - Opcodes.begin()));4243moveToEnd();4244return;4245}4246if (!LibraryOrdinalSet && TableKind != Kind::Weak) {4247*E = malformedError(4248"for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "4249"missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "4250"at: 0x" +4251Twine::utohexstr(OpcodeStart - Opcodes.begin()));4252moveToEnd();4253return;4254}4255error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,4256PointerSize, Count, Skip);4257if (error) {4258*E =4259malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +4260Twine(error) + " for opcode at: 0x" +4261Twine::utohexstr(OpcodeStart - Opcodes.begin()));4262moveToEnd();4263return;4264}4265DEBUG_WITH_TYPE(4266"mach-o-bind",4267dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "4268<< format("SegmentOffset=0x%06X", SegmentOffset)4269<< ", AdvanceAmount=" << AdvanceAmount4270<< ", RemainingLoopCount=" << RemainingLoopCount4271<< "\n");4272return;4273default:4274*E = malformedError("bad bind info (bad opcode value 0x" +4275Twine::utohexstr(Opcode) + " for opcode at: 0x" +4276Twine::utohexstr(OpcodeStart - Opcodes.begin()));4277moveToEnd();4278return;4279}4280}4281}42824283uint64_t MachOBindEntry::readULEB128(const char **error) {4284unsigned Count;4285uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);4286Ptr += Count;4287if (Ptr > Opcodes.end())4288Ptr = Opcodes.end();4289return Result;4290}42914292int64_t MachOBindEntry::readSLEB128(const char **error) {4293unsigned Count;4294int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);4295Ptr += Count;4296if (Ptr > Opcodes.end())4297Ptr = Opcodes.end();4298return Result;4299}43004301int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }43024303uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }43044305StringRef MachOBindEntry::typeName() const {4306switch (BindType) {4307case MachO::BIND_TYPE_POINTER:4308return "pointer";4309case MachO::BIND_TYPE_TEXT_ABSOLUTE32:4310return "text abs32";4311case MachO::BIND_TYPE_TEXT_PCREL32:4312return "text rel32";4313}4314return "unknown";4315}43164317StringRef MachOBindEntry::symbolName() const { return SymbolName; }43184319int64_t MachOBindEntry::addend() const { return Addend; }43204321uint32_t MachOBindEntry::flags() const { return Flags; }43224323int MachOBindEntry::ordinal() const { return Ordinal; }43244325// For use with the SegIndex of a checked Mach-O Bind entry4326// to get the segment name.4327StringRef MachOBindEntry::segmentName() const {4328return O->BindRebaseSegmentName(SegmentIndex);4329}43304331// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry4332// to get the section name.4333StringRef MachOBindEntry::sectionName() const {4334return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);4335}43364337// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry4338// to get the address.4339uint64_t MachOBindEntry::address() const {4340return O->BindRebaseAddress(SegmentIndex, SegmentOffset);4341}43424343bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {4344#ifdef EXPENSIVE_CHECKS4345assert(Opcodes == Other.Opcodes && "compare iterators of different files");4346#else4347assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");4348#endif4349return (Ptr == Other.Ptr) &&4350(RemainingLoopCount == Other.RemainingLoopCount) &&4351(Done == Other.Done);4352}43534354// Build table of sections so SegIndex/SegOffset pairs can be translated.4355BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {4356uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;4357StringRef CurSegName;4358uint64_t CurSegAddress;4359for (const SectionRef &Section : Obj->sections()) {4360SectionInfo Info;4361Expected<StringRef> NameOrErr = Section.getName();4362if (!NameOrErr)4363consumeError(NameOrErr.takeError());4364else4365Info.SectionName = *NameOrErr;4366Info.Address = Section.getAddress();4367Info.Size = Section.getSize();4368Info.SegmentName =4369Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());4370if (Info.SegmentName != CurSegName) {4371++CurSegIndex;4372CurSegName = Info.SegmentName;4373CurSegAddress = Info.Address;4374}4375Info.SegmentIndex = CurSegIndex - 1;4376Info.OffsetInSegment = Info.Address - CurSegAddress;4377Info.SegmentStartAddress = CurSegAddress;4378Sections.push_back(Info);4379}4380MaxSegIndex = CurSegIndex;4381}43824383// For use with a SegIndex, SegOffset, and PointerSize triple in4384// MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.4385//4386// Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists4387// that fully contains a pointer at that location. Multiple fixups in a bind4388// (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can4389// be tested via the Count and Skip parameters.4390const char *BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex,4391uint64_t SegOffset,4392uint8_t PointerSize,4393uint64_t Count,4394uint64_t Skip) {4395if (SegIndex == -1)4396return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";4397if (SegIndex >= MaxSegIndex)4398return "bad segIndex (too large)";4399for (uint64_t i = 0; i < Count; ++i) {4400uint64_t Start = SegOffset + i * (PointerSize + Skip);4401uint64_t End = Start + PointerSize;4402bool Found = false;4403for (const SectionInfo &SI : Sections) {4404if (SI.SegmentIndex != SegIndex)4405continue;4406if ((SI.OffsetInSegment<=Start) && (Start<(SI.OffsetInSegment+SI.Size))) {4407if (End <= SI.OffsetInSegment + SI.Size) {4408Found = true;4409break;4410}4411else4412return "bad offset, extends beyond section boundary";4413}4414}4415if (!Found)4416return "bad offset, not in section";4417}4418return nullptr;4419}44204421// For use with the SegIndex of a checked Mach-O Bind or Rebase entry4422// to get the segment name.4423StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {4424for (const SectionInfo &SI : Sections) {4425if (SI.SegmentIndex == SegIndex)4426return SI.SegmentName;4427}4428llvm_unreachable("invalid SegIndex");4429}44304431// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase4432// to get the SectionInfo.4433const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(4434int32_t SegIndex, uint64_t SegOffset) {4435for (const SectionInfo &SI : Sections) {4436if (SI.SegmentIndex != SegIndex)4437continue;4438if (SI.OffsetInSegment > SegOffset)4439continue;4440if (SegOffset >= (SI.OffsetInSegment + SI.Size))4441continue;4442return SI;4443}4444llvm_unreachable("SegIndex and SegOffset not in any section");4445}44464447// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase4448// entry to get the section name.4449StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,4450uint64_t SegOffset) {4451return findSection(SegIndex, SegOffset).SectionName;4452}44534454// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase4455// entry to get the address.4456uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {4457const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);4458return SI.SegmentStartAddress + OffsetInSeg;4459}44604461iterator_range<bind_iterator>4462MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,4463ArrayRef<uint8_t> Opcodes, bool is64,4464MachOBindEntry::Kind BKind) {4465if (O->BindRebaseSectionTable == nullptr)4466O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);4467MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);4468Start.moveToFirst();44694470MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);4471Finish.moveToEnd();44724473return make_range(bind_iterator(Start), bind_iterator(Finish));4474}44754476iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {4477return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),4478MachOBindEntry::Kind::Regular);4479}44804481iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {4482return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),4483MachOBindEntry::Kind::Lazy);4484}44854486iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {4487return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),4488MachOBindEntry::Kind::Weak);4489}44904491iterator_range<fixup_iterator> MachOObjectFile::fixupTable(Error &Err) {4492if (BindRebaseSectionTable == nullptr)4493BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(this);44944495MachOChainedFixupEntry Start(&Err, this, true);4496Start.moveToFirst();44974498MachOChainedFixupEntry Finish(&Err, this, false);4499Finish.moveToEnd();45004501return make_range(fixup_iterator(Start), fixup_iterator(Finish));4502}45034504MachOObjectFile::load_command_iterator4505MachOObjectFile::begin_load_commands() const {4506return LoadCommands.begin();4507}45084509MachOObjectFile::load_command_iterator4510MachOObjectFile::end_load_commands() const {4511return LoadCommands.end();4512}45134514iterator_range<MachOObjectFile::load_command_iterator>4515MachOObjectFile::load_commands() const {4516return make_range(begin_load_commands(), end_load_commands());4517}45184519StringRef4520MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {4521ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);4522return parseSegmentOrSectionName(Raw.data());4523}45244525ArrayRef<char>4526MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {4527assert(Sec.d.a < Sections.size() && "Should have detected this earlier");4528const section_base *Base =4529reinterpret_cast<const section_base *>(Sections[Sec.d.a]);4530return ArrayRef(Base->sectname);4531}45324533ArrayRef<char>4534MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {4535assert(Sec.d.a < Sections.size() && "Should have detected this earlier");4536const section_base *Base =4537reinterpret_cast<const section_base *>(Sections[Sec.d.a]);4538return ArrayRef(Base->segname);4539}45404541bool4542MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)4543const {4544if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)4545return false;4546return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;4547}45484549unsigned MachOObjectFile::getPlainRelocationSymbolNum(4550const MachO::any_relocation_info &RE) const {4551if (isLittleEndian())4552return RE.r_word1 & 0xffffff;4553return RE.r_word1 >> 8;4554}45554556bool MachOObjectFile::getPlainRelocationExternal(4557const MachO::any_relocation_info &RE) const {4558if (isLittleEndian())4559return (RE.r_word1 >> 27) & 1;4560return (RE.r_word1 >> 4) & 1;4561}45624563bool MachOObjectFile::getScatteredRelocationScattered(4564const MachO::any_relocation_info &RE) const {4565return RE.r_word0 >> 31;4566}45674568uint32_t MachOObjectFile::getScatteredRelocationValue(4569const MachO::any_relocation_info &RE) const {4570return RE.r_word1;4571}45724573uint32_t MachOObjectFile::getScatteredRelocationType(4574const MachO::any_relocation_info &RE) const {4575return (RE.r_word0 >> 24) & 0xf;4576}45774578unsigned MachOObjectFile::getAnyRelocationAddress(4579const MachO::any_relocation_info &RE) const {4580if (isRelocationScattered(RE))4581return getScatteredRelocationAddress(RE);4582return getPlainRelocationAddress(RE);4583}45844585unsigned MachOObjectFile::getAnyRelocationPCRel(4586const MachO::any_relocation_info &RE) const {4587if (isRelocationScattered(RE))4588return getScatteredRelocationPCRel(RE);4589return getPlainRelocationPCRel(*this, RE);4590}45914592unsigned MachOObjectFile::getAnyRelocationLength(4593const MachO::any_relocation_info &RE) const {4594if (isRelocationScattered(RE))4595return getScatteredRelocationLength(RE);4596return getPlainRelocationLength(*this, RE);4597}45984599unsigned4600MachOObjectFile::getAnyRelocationType(4601const MachO::any_relocation_info &RE) const {4602if (isRelocationScattered(RE))4603return getScatteredRelocationType(RE);4604return getPlainRelocationType(*this, RE);4605}46064607SectionRef4608MachOObjectFile::getAnyRelocationSection(4609const MachO::any_relocation_info &RE) const {4610if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))4611return *section_end();4612unsigned SecNum = getPlainRelocationSymbolNum(RE);4613if (SecNum == MachO::R_ABS || SecNum > Sections.size())4614return *section_end();4615DataRefImpl DRI;4616DRI.d.a = SecNum - 1;4617return SectionRef(DRI, this);4618}46194620MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {4621assert(DRI.d.a < Sections.size() && "Should have detected this earlier");4622return getStruct<MachO::section>(*this, Sections[DRI.d.a]);4623}46244625MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {4626assert(DRI.d.a < Sections.size() && "Should have detected this earlier");4627return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);4628}46294630MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,4631unsigned Index) const {4632const char *Sec = getSectionPtr(*this, L, Index);4633return getStruct<MachO::section>(*this, Sec);4634}46354636MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,4637unsigned Index) const {4638const char *Sec = getSectionPtr(*this, L, Index);4639return getStruct<MachO::section_64>(*this, Sec);4640}46414642MachO::nlist4643MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {4644const char *P = reinterpret_cast<const char *>(DRI.p);4645return getStruct<MachO::nlist>(*this, P);4646}46474648MachO::nlist_644649MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {4650const char *P = reinterpret_cast<const char *>(DRI.p);4651return getStruct<MachO::nlist_64>(*this, P);4652}46534654MachO::linkedit_data_command4655MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {4656return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);4657}46584659MachO::segment_command4660MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {4661return getStruct<MachO::segment_command>(*this, L.Ptr);4662}46634664MachO::segment_command_644665MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {4666return getStruct<MachO::segment_command_64>(*this, L.Ptr);4667}46684669MachO::linker_option_command4670MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {4671return getStruct<MachO::linker_option_command>(*this, L.Ptr);4672}46734674MachO::version_min_command4675MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {4676return getStruct<MachO::version_min_command>(*this, L.Ptr);4677}46784679MachO::note_command4680MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {4681return getStruct<MachO::note_command>(*this, L.Ptr);4682}46834684MachO::build_version_command4685MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {4686return getStruct<MachO::build_version_command>(*this, L.Ptr);4687}46884689MachO::build_tool_version4690MachOObjectFile::getBuildToolVersion(unsigned index) const {4691return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);4692}46934694MachO::dylib_command4695MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {4696return getStruct<MachO::dylib_command>(*this, L.Ptr);4697}46984699MachO::dyld_info_command4700MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {4701return getStruct<MachO::dyld_info_command>(*this, L.Ptr);4702}47034704MachO::dylinker_command4705MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {4706return getStruct<MachO::dylinker_command>(*this, L.Ptr);4707}47084709MachO::uuid_command4710MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {4711return getStruct<MachO::uuid_command>(*this, L.Ptr);4712}47134714MachO::rpath_command4715MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {4716return getStruct<MachO::rpath_command>(*this, L.Ptr);4717}47184719MachO::source_version_command4720MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {4721return getStruct<MachO::source_version_command>(*this, L.Ptr);4722}47234724MachO::entry_point_command4725MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {4726return getStruct<MachO::entry_point_command>(*this, L.Ptr);4727}47284729MachO::encryption_info_command4730MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {4731return getStruct<MachO::encryption_info_command>(*this, L.Ptr);4732}47334734MachO::encryption_info_command_644735MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {4736return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);4737}47384739MachO::sub_framework_command4740MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {4741return getStruct<MachO::sub_framework_command>(*this, L.Ptr);4742}47434744MachO::sub_umbrella_command4745MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {4746return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);4747}47484749MachO::sub_library_command4750MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {4751return getStruct<MachO::sub_library_command>(*this, L.Ptr);4752}47534754MachO::sub_client_command4755MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {4756return getStruct<MachO::sub_client_command>(*this, L.Ptr);4757}47584759MachO::routines_command4760MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {4761return getStruct<MachO::routines_command>(*this, L.Ptr);4762}47634764MachO::routines_command_644765MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {4766return getStruct<MachO::routines_command_64>(*this, L.Ptr);4767}47684769MachO::thread_command4770MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {4771return getStruct<MachO::thread_command>(*this, L.Ptr);4772}47734774MachO::fileset_entry_command4775MachOObjectFile::getFilesetEntryLoadCommand(const LoadCommandInfo &L) const {4776return getStruct<MachO::fileset_entry_command>(*this, L.Ptr);4777}47784779MachO::any_relocation_info4780MachOObjectFile::getRelocation(DataRefImpl Rel) const {4781uint32_t Offset;4782if (getHeader().filetype == MachO::MH_OBJECT) {4783DataRefImpl Sec;4784Sec.d.a = Rel.d.a;4785if (is64Bit()) {4786MachO::section_64 Sect = getSection64(Sec);4787Offset = Sect.reloff;4788} else {4789MachO::section Sect = getSection(Sec);4790Offset = Sect.reloff;4791}4792} else {4793MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();4794if (Rel.d.a == 0)4795Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations4796else4797Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations4798}47994800auto P = reinterpret_cast<const MachO::any_relocation_info *>(4801getPtr(*this, Offset)) + Rel.d.b;4802return getStruct<MachO::any_relocation_info>(4803*this, reinterpret_cast<const char *>(P));4804}48054806MachO::data_in_code_entry4807MachOObjectFile::getDice(DataRefImpl Rel) const {4808const char *P = reinterpret_cast<const char *>(Rel.p);4809return getStruct<MachO::data_in_code_entry>(*this, P);4810}48114812const MachO::mach_header &MachOObjectFile::getHeader() const {4813return Header;4814}48154816const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {4817assert(is64Bit());4818return Header64;4819}48204821uint32_t MachOObjectFile::getIndirectSymbolTableEntry(4822const MachO::dysymtab_command &DLC,4823unsigned Index) const {4824uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);4825return getStruct<uint32_t>(*this, getPtr(*this, Offset));4826}48274828MachO::data_in_code_entry4829MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,4830unsigned Index) const {4831uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);4832return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));4833}48344835MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {4836if (SymtabLoadCmd)4837return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);48384839// If there is no SymtabLoadCmd return a load command with zero'ed fields.4840MachO::symtab_command Cmd;4841Cmd.cmd = MachO::LC_SYMTAB;4842Cmd.cmdsize = sizeof(MachO::symtab_command);4843Cmd.symoff = 0;4844Cmd.nsyms = 0;4845Cmd.stroff = 0;4846Cmd.strsize = 0;4847return Cmd;4848}48494850MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {4851if (DysymtabLoadCmd)4852return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);48534854// If there is no DysymtabLoadCmd return a load command with zero'ed fields.4855MachO::dysymtab_command Cmd;4856Cmd.cmd = MachO::LC_DYSYMTAB;4857Cmd.cmdsize = sizeof(MachO::dysymtab_command);4858Cmd.ilocalsym = 0;4859Cmd.nlocalsym = 0;4860Cmd.iextdefsym = 0;4861Cmd.nextdefsym = 0;4862Cmd.iundefsym = 0;4863Cmd.nundefsym = 0;4864Cmd.tocoff = 0;4865Cmd.ntoc = 0;4866Cmd.modtaboff = 0;4867Cmd.nmodtab = 0;4868Cmd.extrefsymoff = 0;4869Cmd.nextrefsyms = 0;4870Cmd.indirectsymoff = 0;4871Cmd.nindirectsyms = 0;4872Cmd.extreloff = 0;4873Cmd.nextrel = 0;4874Cmd.locreloff = 0;4875Cmd.nlocrel = 0;4876return Cmd;4877}48784879MachO::linkedit_data_command4880MachOObjectFile::getDataInCodeLoadCommand() const {4881if (DataInCodeLoadCmd)4882return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);48834884// If there is no DataInCodeLoadCmd return a load command with zero'ed fields.4885MachO::linkedit_data_command Cmd;4886Cmd.cmd = MachO::LC_DATA_IN_CODE;4887Cmd.cmdsize = sizeof(MachO::linkedit_data_command);4888Cmd.dataoff = 0;4889Cmd.datasize = 0;4890return Cmd;4891}48924893MachO::linkedit_data_command4894MachOObjectFile::getLinkOptHintsLoadCommand() const {4895if (LinkOptHintsLoadCmd)4896return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);48974898// If there is no LinkOptHintsLoadCmd return a load command with zero'ed4899// fields.4900MachO::linkedit_data_command Cmd;4901Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;4902Cmd.cmdsize = sizeof(MachO::linkedit_data_command);4903Cmd.dataoff = 0;4904Cmd.datasize = 0;4905return Cmd;4906}49074908ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {4909if (!DyldInfoLoadCmd)4910return std::nullopt;49114912auto DyldInfoOrErr =4913getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);4914if (!DyldInfoOrErr)4915return std::nullopt;4916MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();4917const uint8_t *Ptr =4918reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));4919return ArrayRef(Ptr, DyldInfo.rebase_size);4920}49214922ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {4923if (!DyldInfoLoadCmd)4924return std::nullopt;49254926auto DyldInfoOrErr =4927getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);4928if (!DyldInfoOrErr)4929return std::nullopt;4930MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();4931const uint8_t *Ptr =4932reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));4933return ArrayRef(Ptr, DyldInfo.bind_size);4934}49354936ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {4937if (!DyldInfoLoadCmd)4938return std::nullopt;49394940auto DyldInfoOrErr =4941getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);4942if (!DyldInfoOrErr)4943return std::nullopt;4944MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();4945const uint8_t *Ptr =4946reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));4947return ArrayRef(Ptr, DyldInfo.weak_bind_size);4948}49494950ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {4951if (!DyldInfoLoadCmd)4952return std::nullopt;49534954auto DyldInfoOrErr =4955getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);4956if (!DyldInfoOrErr)4957return std::nullopt;4958MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();4959const uint8_t *Ptr =4960reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));4961return ArrayRef(Ptr, DyldInfo.lazy_bind_size);4962}49634964ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {4965if (!DyldInfoLoadCmd)4966return std::nullopt;49674968auto DyldInfoOrErr =4969getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);4970if (!DyldInfoOrErr)4971return std::nullopt;4972MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();4973const uint8_t *Ptr =4974reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));4975return ArrayRef(Ptr, DyldInfo.export_size);4976}49774978Expected<std::optional<MachO::linkedit_data_command>>4979MachOObjectFile::getChainedFixupsLoadCommand() const {4980// Load the dyld chained fixups load command.4981if (!DyldChainedFixupsLoadCmd)4982return std::nullopt;4983auto DyldChainedFixupsOrErr = getStructOrErr<MachO::linkedit_data_command>(4984*this, DyldChainedFixupsLoadCmd);4985if (!DyldChainedFixupsOrErr)4986return DyldChainedFixupsOrErr.takeError();4987const MachO::linkedit_data_command &DyldChainedFixups =4988*DyldChainedFixupsOrErr;49894990// If the load command is present but the data offset has been zeroed out,4991// as is the case for dylib stubs, return std::nullopt (no error).4992if (!DyldChainedFixups.dataoff)4993return std::nullopt;4994return DyldChainedFixups;4995}49964997Expected<std::optional<MachO::dyld_chained_fixups_header>>4998MachOObjectFile::getChainedFixupsHeader() const {4999auto CFOrErr = getChainedFixupsLoadCommand();5000if (!CFOrErr)5001return CFOrErr.takeError();5002if (!CFOrErr->has_value())5003return std::nullopt;50045005const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr;50065007uint64_t CFHeaderOffset = DyldChainedFixups.dataoff;5008uint64_t CFSize = DyldChainedFixups.datasize;50095010// Load the dyld chained fixups header.5011const char *CFHeaderPtr = getPtr(*this, CFHeaderOffset);5012auto CFHeaderOrErr =5013getStructOrErr<MachO::dyld_chained_fixups_header>(*this, CFHeaderPtr);5014if (!CFHeaderOrErr)5015return CFHeaderOrErr.takeError();5016MachO::dyld_chained_fixups_header CFHeader = CFHeaderOrErr.get();50175018// Reject unknown chained fixup formats.5019if (CFHeader.fixups_version != 0)5020return malformedError(Twine("bad chained fixups: unknown version: ") +5021Twine(CFHeader.fixups_version));5022if (CFHeader.imports_format < 1 || CFHeader.imports_format > 3)5023return malformedError(5024Twine("bad chained fixups: unknown imports format: ") +5025Twine(CFHeader.imports_format));50265027// Validate the image format.5028//5029// Load the image starts.5030uint64_t CFImageStartsOffset = (CFHeaderOffset + CFHeader.starts_offset);5031if (CFHeader.starts_offset < sizeof(MachO::dyld_chained_fixups_header)) {5032return malformedError(Twine("bad chained fixups: image starts offset ") +5033Twine(CFHeader.starts_offset) +5034" overlaps with chained fixups header");5035}5036uint32_t EndOffset = CFHeaderOffset + CFSize;5037if (CFImageStartsOffset + sizeof(MachO::dyld_chained_starts_in_image) >5038EndOffset) {5039return malformedError(Twine("bad chained fixups: image starts end ") +5040Twine(CFImageStartsOffset +5041sizeof(MachO::dyld_chained_starts_in_image)) +5042" extends past end " + Twine(EndOffset));5043}50445045return CFHeader;5046}50475048Expected<std::pair<size_t, std::vector<ChainedFixupsSegment>>>5049MachOObjectFile::getChainedFixupsSegments() const {5050auto CFOrErr = getChainedFixupsLoadCommand();5051if (!CFOrErr)5052return CFOrErr.takeError();50535054std::vector<ChainedFixupsSegment> Segments;5055if (!CFOrErr->has_value())5056return std::make_pair(0, Segments);50575058const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr;50595060auto HeaderOrErr = getChainedFixupsHeader();5061if (!HeaderOrErr)5062return HeaderOrErr.takeError();5063if (!HeaderOrErr->has_value())5064return std::make_pair(0, Segments);5065const MachO::dyld_chained_fixups_header &Header = **HeaderOrErr;50665067const char *Contents = getPtr(*this, DyldChainedFixups.dataoff);50685069auto ImageStartsOrErr = getStructOrErr<MachO::dyld_chained_starts_in_image>(5070*this, Contents + Header.starts_offset);5071if (!ImageStartsOrErr)5072return ImageStartsOrErr.takeError();5073const MachO::dyld_chained_starts_in_image &ImageStarts = *ImageStartsOrErr;50745075const char *SegOffsPtr =5076Contents + Header.starts_offset +5077offsetof(MachO::dyld_chained_starts_in_image, seg_info_offset);5078const char *SegOffsEnd =5079SegOffsPtr + ImageStarts.seg_count * sizeof(uint32_t);5080if (SegOffsEnd > Contents + DyldChainedFixups.datasize)5081return malformedError(5082"bad chained fixups: seg_info_offset extends past end");50835084const char *LastSegEnd = nullptr;5085for (size_t I = 0, N = ImageStarts.seg_count; I < N; ++I) {5086auto OffOrErr =5087getStructOrErr<uint32_t>(*this, SegOffsPtr + I * sizeof(uint32_t));5088if (!OffOrErr)5089return OffOrErr.takeError();5090// seg_info_offset == 0 means there is no associated starts_in_segment5091// entry.5092if (!*OffOrErr)5093continue;50945095auto Fail = [&](Twine Message) {5096return malformedError("bad chained fixups: segment info" + Twine(I) +5097" at offset " + Twine(*OffOrErr) + Message);5098};50995100const char *SegPtr = Contents + Header.starts_offset + *OffOrErr;5101if (LastSegEnd && SegPtr < LastSegEnd)5102return Fail(" overlaps with previous segment info");51035104auto SegOrErr =5105getStructOrErr<MachO::dyld_chained_starts_in_segment>(*this, SegPtr);5106if (!SegOrErr)5107return SegOrErr.takeError();5108const MachO::dyld_chained_starts_in_segment &Seg = *SegOrErr;51095110LastSegEnd = SegPtr + Seg.size;5111if (Seg.pointer_format < 1 || Seg.pointer_format > 12)5112return Fail(" has unknown pointer format: " + Twine(Seg.pointer_format));51135114const char *PageStart =5115SegPtr + offsetof(MachO::dyld_chained_starts_in_segment, page_start);5116const char *PageEnd = PageStart + Seg.page_count * sizeof(uint16_t);5117if (PageEnd > SegPtr + Seg.size)5118return Fail(" : page_starts extend past seg_info size");51195120// FIXME: This does not account for multiple offsets on a single page5121// (DYLD_CHAINED_PTR_START_MULTI; 32-bit only).5122std::vector<uint16_t> PageStarts;5123for (size_t PageIdx = 0; PageIdx < Seg.page_count; ++PageIdx) {5124uint16_t Start;5125memcpy(&Start, PageStart + PageIdx * sizeof(uint16_t), sizeof(uint16_t));5126if (isLittleEndian() != sys::IsLittleEndianHost)5127sys::swapByteOrder(Start);5128PageStarts.push_back(Start);5129}51305131Segments.emplace_back(I, *OffOrErr, Seg, std::move(PageStarts));5132}51335134return std::make_pair(ImageStarts.seg_count, Segments);5135}51365137// The special library ordinals have a negative value, but they are encoded in5138// an unsigned bitfield, so we need to sign extend the value.5139template <typename T> static int getEncodedOrdinal(T Value) {5140if (Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE) ||5141Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) ||5142Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP))5143return SignExtend32<sizeof(T) * CHAR_BIT>(Value);5144return Value;5145}51465147template <typename T, unsigned N>5148static std::array<T, N> getArray(const MachOObjectFile &O, const void *Ptr) {5149std::array<T, N> RawValue;5150memcpy(RawValue.data(), Ptr, N * sizeof(T));5151if (O.isLittleEndian() != sys::IsLittleEndianHost)5152for (auto &Element : RawValue)5153sys::swapByteOrder(Element);5154return RawValue;5155}51565157Expected<std::vector<ChainedFixupTarget>>5158MachOObjectFile::getDyldChainedFixupTargets() const {5159auto CFOrErr = getChainedFixupsLoadCommand();5160if (!CFOrErr)5161return CFOrErr.takeError();51625163std::vector<ChainedFixupTarget> Targets;5164if (!CFOrErr->has_value())5165return Targets;51665167const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr;51685169auto CFHeaderOrErr = getChainedFixupsHeader();5170if (!CFHeaderOrErr)5171return CFHeaderOrErr.takeError();5172if (!(*CFHeaderOrErr))5173return Targets;5174const MachO::dyld_chained_fixups_header &Header = **CFHeaderOrErr;51755176size_t ImportSize = 0;5177if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT)5178ImportSize = sizeof(MachO::dyld_chained_import);5179else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND)5180ImportSize = sizeof(MachO::dyld_chained_import_addend);5181else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND64)5182ImportSize = sizeof(MachO::dyld_chained_import_addend64);5183else5184return malformedError("bad chained fixups: unknown imports format: " +5185Twine(Header.imports_format));51865187const char *Contents = getPtr(*this, DyldChainedFixups.dataoff);5188const char *Imports = Contents + Header.imports_offset;5189size_t ImportsEndOffset =5190Header.imports_offset + ImportSize * Header.imports_count;5191const char *ImportsEnd = Contents + ImportsEndOffset;5192const char *Symbols = Contents + Header.symbols_offset;5193const char *SymbolsEnd = Contents + DyldChainedFixups.datasize;51945195if (ImportsEnd > Symbols)5196return malformedError("bad chained fixups: imports end " +5197Twine(ImportsEndOffset) + " extends past end " +5198Twine(DyldChainedFixups.datasize));51995200if (ImportsEnd > Symbols)5201return malformedError("bad chained fixups: imports end " +5202Twine(ImportsEndOffset) + " overlaps with symbols");52035204// We use bit manipulation to extract data from the bitfields. This is correct5205// for both LE and BE hosts, but we assume that the object is little-endian.5206if (!isLittleEndian())5207return createError("parsing big-endian chained fixups is not implemented");5208for (const char *ImportPtr = Imports; ImportPtr < ImportsEnd;5209ImportPtr += ImportSize) {5210int LibOrdinal;5211bool WeakImport;5212uint32_t NameOffset;5213uint64_t Addend;5214if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT) {5215static_assert(sizeof(uint32_t) == sizeof(MachO::dyld_chained_import));5216auto RawValue = getArray<uint32_t, 1>(*this, ImportPtr);52175218LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF);5219WeakImport = (RawValue[0] >> 8) & 1;5220NameOffset = RawValue[0] >> 9;5221Addend = 0;5222} else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND) {5223static_assert(sizeof(uint64_t) ==5224sizeof(MachO::dyld_chained_import_addend));5225auto RawValue = getArray<uint32_t, 2>(*this, ImportPtr);52265227LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF);5228WeakImport = (RawValue[0] >> 8) & 1;5229NameOffset = RawValue[0] >> 9;5230Addend = bit_cast<int32_t>(RawValue[1]);5231} else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND64) {5232static_assert(2 * sizeof(uint64_t) ==5233sizeof(MachO::dyld_chained_import_addend64));5234auto RawValue = getArray<uint64_t, 2>(*this, ImportPtr);52355236LibOrdinal = getEncodedOrdinal<uint16_t>(RawValue[0] & 0xFFFF);5237NameOffset = (RawValue[0] >> 16) & 1;5238WeakImport = RawValue[0] >> 17;5239Addend = RawValue[1];5240} else {5241llvm_unreachable("Import format should have been checked");5242}52435244const char *Str = Symbols + NameOffset;5245if (Str >= SymbolsEnd)5246return malformedError("bad chained fixups: symbol offset " +5247Twine(NameOffset) + " extends past end " +5248Twine(DyldChainedFixups.datasize));5249Targets.emplace_back(LibOrdinal, NameOffset, Str, Addend, WeakImport);5250}52515252return std::move(Targets);5253}52545255ArrayRef<uint8_t> MachOObjectFile::getDyldExportsTrie() const {5256if (!DyldExportsTrieLoadCmd)5257return std::nullopt;52585259auto DyldExportsTrieOrError = getStructOrErr<MachO::linkedit_data_command>(5260*this, DyldExportsTrieLoadCmd);5261if (!DyldExportsTrieOrError)5262return std::nullopt;5263MachO::linkedit_data_command DyldExportsTrie = DyldExportsTrieOrError.get();5264const uint8_t *Ptr =5265reinterpret_cast<const uint8_t *>(getPtr(*this, DyldExportsTrie.dataoff));5266return ArrayRef(Ptr, DyldExportsTrie.datasize);5267}52685269SmallVector<uint64_t> MachOObjectFile::getFunctionStarts() const {5270if (!FuncStartsLoadCmd)5271return {};52725273auto InfoOrErr =5274getStructOrErr<MachO::linkedit_data_command>(*this, FuncStartsLoadCmd);5275if (!InfoOrErr)5276return {};52775278MachO::linkedit_data_command Info = InfoOrErr.get();5279SmallVector<uint64_t, 8> FunctionStarts;5280this->ReadULEB128s(Info.dataoff, FunctionStarts);5281return std::move(FunctionStarts);5282}52835284ArrayRef<uint8_t> MachOObjectFile::getUuid() const {5285if (!UuidLoadCmd)5286return std::nullopt;5287// Returning a pointer is fine as uuid doesn't need endian swapping.5288const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);5289return ArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);5290}52915292StringRef MachOObjectFile::getStringTableData() const {5293MachO::symtab_command S = getSymtabLoadCommand();5294return getData().substr(S.stroff, S.strsize);5295}52965297bool MachOObjectFile::is64Bit() const {5298return getType() == getMachOType(false, true) ||5299getType() == getMachOType(true, true);5300}53015302void MachOObjectFile::ReadULEB128s(uint64_t Index,5303SmallVectorImpl<uint64_t> &Out) const {5304DataExtractor extractor(ObjectFile::getData(), true, 0);53055306uint64_t offset = Index;5307uint64_t data = 0;5308while (uint64_t delta = extractor.getULEB128(&offset)) {5309data += delta;5310Out.push_back(data);5311}5312}53135314bool MachOObjectFile::isRelocatableObject() const {5315return getHeader().filetype == MachO::MH_OBJECT;5316}53175318/// Create a MachOObjectFile instance from a given buffer.5319///5320/// \param Buffer Memory buffer containing the MachO binary data.5321/// \param UniversalCputype CPU type when the MachO part of a universal binary.5322/// \param UniversalIndex Index of the MachO within a universal binary.5323/// \param MachOFilesetEntryOffset Offset of the MachO entry in a fileset MachO.5324/// \returns A std::unique_ptr to a MachOObjectFile instance on success.5325Expected<std::unique_ptr<MachOObjectFile>> ObjectFile::createMachOObjectFile(5326MemoryBufferRef Buffer, uint32_t UniversalCputype, uint32_t UniversalIndex,5327size_t MachOFilesetEntryOffset) {5328StringRef Magic = Buffer.getBuffer().slice(0, 4);5329if (Magic == "\xFE\xED\xFA\xCE")5330return MachOObjectFile::create(Buffer, false, false, UniversalCputype,5331UniversalIndex, MachOFilesetEntryOffset);5332if (Magic == "\xCE\xFA\xED\xFE")5333return MachOObjectFile::create(Buffer, true, false, UniversalCputype,5334UniversalIndex, MachOFilesetEntryOffset);5335if (Magic == "\xFE\xED\xFA\xCF")5336return MachOObjectFile::create(Buffer, false, true, UniversalCputype,5337UniversalIndex, MachOFilesetEntryOffset);5338if (Magic == "\xCF\xFA\xED\xFE")5339return MachOObjectFile::create(Buffer, true, true, UniversalCputype,5340UniversalIndex, MachOFilesetEntryOffset);5341return make_error<GenericBinaryError>("Unrecognized MachO magic number",5342object_error::invalid_file_type);5343}53445345StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {5346return StringSwitch<StringRef>(Name)5347.Case("debug_str_offs", "debug_str_offsets")5348.Default(Name);5349}53505351Expected<std::vector<std::string>>5352MachOObjectFile::findDsymObjectMembers(StringRef Path) {5353SmallString<256> BundlePath(Path);5354// Normalize input path. This is necessary to accept `bundle.dSYM/`.5355sys::path::remove_dots(BundlePath);5356if (!sys::fs::is_directory(BundlePath) ||5357sys::path::extension(BundlePath) != ".dSYM")5358return std::vector<std::string>();5359sys::path::append(BundlePath, "Contents", "Resources", "DWARF");5360bool IsDir;5361auto EC = sys::fs::is_directory(BundlePath, IsDir);5362if (EC == errc::no_such_file_or_directory || (!EC && !IsDir))5363return createStringError(5364EC, "%s: expected directory 'Contents/Resources/DWARF' in dSYM bundle",5365Path.str().c_str());5366if (EC)5367return createFileError(BundlePath, errorCodeToError(EC));53685369std::vector<std::string> ObjectPaths;5370for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd;5371Dir != DirEnd && !EC; Dir.increment(EC)) {5372StringRef ObjectPath = Dir->path();5373sys::fs::file_status Status;5374if (auto EC = sys::fs::status(ObjectPath, Status))5375return createFileError(ObjectPath, errorCodeToError(EC));5376switch (Status.type()) {5377case sys::fs::file_type::regular_file:5378case sys::fs::file_type::symlink_file:5379case sys::fs::file_type::type_unknown:5380ObjectPaths.push_back(ObjectPath.str());5381break;5382default: /*ignore*/;5383}5384}5385if (EC)5386return createFileError(BundlePath, errorCodeToError(EC));5387if (ObjectPaths.empty())5388return createStringError(std::error_code(),5389"%s: no objects found in dSYM bundle",5390Path.str().c_str());5391return ObjectPaths;5392}53935394llvm::binaryformat::Swift5ReflectionSectionKind5395MachOObjectFile::mapReflectionSectionNameToEnumValue(5396StringRef SectionName) const {5397#define HANDLE_SWIFT_SECTION(KIND, MACHO, ELF, COFF) \5398.Case(MACHO, llvm::binaryformat::Swift5ReflectionSectionKind::KIND)5399return StringSwitch<llvm::binaryformat::Swift5ReflectionSectionKind>(5400SectionName)5401#include "llvm/BinaryFormat/Swift.def"5402.Default(llvm::binaryformat::Swift5ReflectionSectionKind::unknown);5403#undef HANDLE_SWIFT_SECTION5404}54055406bool MachOObjectFile::isMachOPairedReloc(uint64_t RelocType, uint64_t Arch) {5407switch (Arch) {5408case Triple::x86:5409return RelocType == MachO::GENERIC_RELOC_SECTDIFF ||5410RelocType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF;5411case Triple::x86_64:5412return RelocType == MachO::X86_64_RELOC_SUBTRACTOR;5413case Triple::arm:5414case Triple::thumb:5415return RelocType == MachO::ARM_RELOC_SECTDIFF ||5416RelocType == MachO::ARM_RELOC_LOCAL_SECTDIFF ||5417RelocType == MachO::ARM_RELOC_HALF ||5418RelocType == MachO::ARM_RELOC_HALF_SECTDIFF;5419case Triple::aarch64:5420return RelocType == MachO::ARM64_RELOC_SUBTRACTOR;5421default:5422return false;5423}5424}542554265427