+Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
+ switch (CPUType) {
+ case MachO::CPU_TYPE_I386:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_I386_ALL:
+ return Triple("i386-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_X86_64:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_X86_64_ALL:
+ return Triple("x86_64-apple-darwin");
+ case MachO::CPU_SUBTYPE_X86_64_H:
+ return Triple("x86_64h-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_ARM:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_ARM_V4T:
+ return Triple("armv4t-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V5TEJ:
+ return Triple("armv5e-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_XSCALE:
+ return Triple("xscale-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V6:
+ return Triple("armv6-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V6M:
+ return Triple("armv6m-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7:
+ return Triple("armv7-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7EM:
+ return Triple("armv7em-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7K:
+ return Triple("armv7k-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7M:
+ return Triple("armv7m-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7S:
+ return Triple("armv7s-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_ARM64:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_ARM64_ALL:
+ return Triple("arm64-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_POWERPC:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_POWERPC_ALL:
+ return Triple("ppc-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_POWERPC64:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_POWERPC_ALL:
+ return Triple("ppc64-apple-darwin");
+ default:
+ return Triple();
+ }
+ default:
+ return Triple();
+ }
+}
+
+Triple MachOObjectFile::getHostArch() {
+ return Triple(sys::getDefaultTargetTriple());
+}
+
+bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
+ return StringSwitch<bool>(ArchFlag)
+ .Case("i386", true)
+ .Case("x86_64", true)
+ .Case("x86_64h", true)
+ .Case("armv4t", true)
+ .Case("arm", true)
+ .Case("armv5e", true)
+ .Case("armv6", true)
+ .Case("armv6m", true)
+ .Case("armv7em", true)
+ .Case("armv7k", true)
+ .Case("armv7m", true)
+ .Case("armv7s", true)
+ .Case("arm64", true)
+ .Case("ppc", true)
+ .Case("ppc64", true)
+ .Default(false);
+}
+
+unsigned MachOObjectFile::getArch() const {
+ return getArch(getCPUType(this));
+}
+
+relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
+ DataRefImpl DRI;
+ DRI.d.a = Index;
+ return section_rel_begin(DRI);
+}
+
+relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
+ DataRefImpl DRI;
+ DRI.d.a = Index;
+ return section_rel_end(DRI);
+}
+
+dice_iterator MachOObjectFile::begin_dices() const {
+ DataRefImpl DRI;
+ if (!DataInCodeLoadCmd)
+ return dice_iterator(DiceRef(DRI, this));
+
+ MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
+ DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
+ return dice_iterator(DiceRef(DRI, this));
+}
+
+dice_iterator MachOObjectFile::end_dices() const {
+ DataRefImpl DRI;
+ if (!DataInCodeLoadCmd)
+ return dice_iterator(DiceRef(DRI, this));
+
+ MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
+ unsigned Offset = DicLC.dataoff + DicLC.datasize;
+ DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
+ return dice_iterator(DiceRef(DRI, this));
+}
+
+StringRef
+MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
+ ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
+ return parseSegmentOrSectionName(Raw.data());
+}
+
+ArrayRef<char>
+MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
+ const section_base *Base =
+ reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
+ return ArrayRef<char>(Base->sectname);
+}
+
+ArrayRef<char>
+MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
+ const section_base *Base =
+ reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
+ return ArrayRef<char>(Base->segname);
+}
+
+bool
+MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
+ const {
+ if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
+ return false;
+ return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
+}
+
+unsigned MachOObjectFile::getPlainRelocationSymbolNum(
+ const MachO::any_relocation_info &RE) const {
+ if (isLittleEndian())
+ return RE.r_word1 & 0xffffff;
+ return RE.r_word1 >> 8;
+}
+
+bool MachOObjectFile::getPlainRelocationExternal(
+ const MachO::any_relocation_info &RE) const {
+ if (isLittleEndian())
+ return (RE.r_word1 >> 27) & 1;
+ return (RE.r_word1 >> 4) & 1;
+}
+
+bool MachOObjectFile::getScatteredRelocationScattered(
+ const MachO::any_relocation_info &RE) const {
+ return RE.r_word0 >> 31;
+}
+
+uint32_t MachOObjectFile::getScatteredRelocationValue(
+ const MachO::any_relocation_info &RE) const {
+ return RE.r_word1;
+}
+
+unsigned MachOObjectFile::getAnyRelocationAddress(
+ const MachO::any_relocation_info &RE) const {
+ if (isRelocationScattered(RE))
+ return getScatteredRelocationAddress(RE);
+ return getPlainRelocationAddress(RE);
+}
+
+unsigned MachOObjectFile::getAnyRelocationPCRel(
+ const MachO::any_relocation_info &RE) const {
+ if (isRelocationScattered(RE))
+ return getScatteredRelocationPCRel(this, RE);
+ return getPlainRelocationPCRel(this, RE);
+}
+
+unsigned MachOObjectFile::getAnyRelocationLength(
+ const MachO::any_relocation_info &RE) const {
+ if (isRelocationScattered(RE))
+ return getScatteredRelocationLength(RE);
+ return getPlainRelocationLength(this, RE);
+}
+
+unsigned
+MachOObjectFile::getAnyRelocationType(
+ const MachO::any_relocation_info &RE) const {
+ if (isRelocationScattered(RE))
+ return getScatteredRelocationType(RE);
+ return getPlainRelocationType(this, RE);
+}
+
+SectionRef
+MachOObjectFile::getRelocationSection(
+ const MachO::any_relocation_info &RE) const {
+ if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
+ return *section_end();
+ unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
+ DataRefImpl DRI;
+ DRI.d.a = SecNum;
+ return SectionRef(DRI, this);
+}
+
+MachOObjectFile::LoadCommandInfo
+MachOObjectFile::getFirstLoadCommandInfo() const {
+ MachOObjectFile::LoadCommandInfo Load;
+
+ unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
+ sizeof(MachO::mach_header);
+ Load.Ptr = getPtr(this, HeaderSize);
+ Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
+ return Load;
+}
+
+MachOObjectFile::LoadCommandInfo
+MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
+ MachOObjectFile::LoadCommandInfo Next;
+ Next.Ptr = L.Ptr + L.C.cmdsize;
+ Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
+ return Next;
+}
+
+MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
+ return getStruct<MachO::section>(this, Sections[DRI.d.a]);
+}
+
+MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
+ return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
+}
+
+MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
+ unsigned Index) const {
+ const char *Sec = getSectionPtr(this, L, Index);
+ return getStruct<MachO::section>(this, Sec);
+}
+
+MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
+ unsigned Index) const {
+ const char *Sec = getSectionPtr(this, L, Index);
+ return getStruct<MachO::section_64>(this, Sec);
+}
+
+MachO::nlist
+MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
+ const char *P = reinterpret_cast<const char *>(DRI.p);
+ return getStruct<MachO::nlist>(this, P);
+}
+
+MachO::nlist_64
+MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
+ const char *P = reinterpret_cast<const char *>(DRI.p);
+ return getStruct<MachO::nlist_64>(this, P);
+}
+
+MachO::linkedit_data_command
+MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
+}
+
+MachO::segment_command
+MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::segment_command>(this, L.Ptr);
+}
+
+MachO::segment_command_64
+MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::segment_command_64>(this, L.Ptr);
+}
+
+MachO::linker_options_command
+MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::linker_options_command>(this, L.Ptr);
+}
+
+MachO::version_min_command
+MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::version_min_command>(this, L.Ptr);
+}
+
+MachO::dylib_command
+MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::dylib_command>(this, L.Ptr);
+}
+
+
+MachO::any_relocation_info
+MachOObjectFile::getRelocation(DataRefImpl Rel) const {
+ DataRefImpl Sec;
+ Sec.d.a = Rel.d.a;
+ uint32_t Offset;
+ if (is64Bit()) {
+ MachO::section_64 Sect = getSection64(Sec);
+ Offset = Sect.reloff;
+ } else {
+ MachO::section Sect = getSection(Sec);
+ Offset = Sect.reloff;
+ }
+
+ auto P = reinterpret_cast<const MachO::any_relocation_info *>(
+ getPtr(this, Offset)) + Rel.d.b;
+ return getStruct<MachO::any_relocation_info>(
+ this, reinterpret_cast<const char *>(P));
+}
+
+MachO::data_in_code_entry
+MachOObjectFile::getDice(DataRefImpl Rel) const {
+ const char *P = reinterpret_cast<const char *>(Rel.p);
+ return getStruct<MachO::data_in_code_entry>(this, P);
+}
+
+MachO::mach_header MachOObjectFile::getHeader() const {
+ return getStruct<MachO::mach_header>(this, getPtr(this, 0));
+}
+
+MachO::mach_header_64 MachOObjectFile::getHeader64() const {
+ return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
+}
+
+uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
+ const MachO::dysymtab_command &DLC,
+ unsigned Index) const {
+ uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
+ return getStruct<uint32_t>(this, getPtr(this, Offset));
+}
+
+MachO::data_in_code_entry
+MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
+ unsigned Index) const {
+ uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
+ return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
+}
+
+MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
+ return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
+}
+
+MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
+ return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
+}
+
+MachO::linkedit_data_command
+MachOObjectFile::getDataInCodeLoadCommand() const {
+ if (DataInCodeLoadCmd)
+ return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
+
+ // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
+ MachO::linkedit_data_command Cmd;
+ Cmd.cmd = MachO::LC_DATA_IN_CODE;
+ Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
+ Cmd.dataoff = 0;
+ Cmd.datasize = 0;
+ return Cmd;
+}
+
+StringRef MachOObjectFile::getStringTableData() const {
+ MachO::symtab_command S = getSymtabLoadCommand();
+ return getData().substr(S.stroff, S.strsize);
+}
+
+bool MachOObjectFile::is64Bit() const {
+ return getType() == getMachOType(false, true) ||
+ getType() == getMachOType(true, true);
+}
+
+void MachOObjectFile::ReadULEB128s(uint64_t Index,
+ SmallVectorImpl<uint64_t> &Out) const {
+ DataExtractor extractor(ObjectFile::getData(), true, 0);
+
+ uint32_t offset = Index;
+ uint64_t data = 0;
+ while (uint64_t delta = extractor.getULEB128(&offset)) {
+ data += delta;
+ Out.push_back(data);
+ }
+}
+
+bool MachOObjectFile::isRelocatableObject() const {
+ return getHeader().filetype == MachO::MH_OBJECT;
+}
+
+ErrorOr<std::unique_ptr<MachOObjectFile>>
+ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) {
+ StringRef Magic = Buffer->getBuffer().slice(0, 4);
+ std::error_code EC;
+ std::unique_ptr<MachOObjectFile> Ret;
+ if (Magic == "\xFE\xED\xFA\xCE")
+ Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC));
+ else if (Magic == "\xCE\xFA\xED\xFE")
+ Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC));
+ else if (Magic == "\xFE\xED\xFA\xCF")
+ Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC));
+ else if (Magic == "\xCF\xFA\xED\xFE")
+ Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC));
+ else
+ return object_error::parse_failed;
+
+ if (EC)
+ return EC;
+ return std::move(Ret);
+}
+