|  | //===-- llvm/BinaryFormat/MachO.cpp - The MachO file format -----*- C++/-*-===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/BinaryFormat/MachO.h" | 
|  | #include "llvm/TargetParser/ARMTargetParser.h" | 
|  | #include "llvm/TargetParser/Triple.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | static MachO::CPUSubTypeX86 getX86SubType(const Triple &T) { | 
|  | assert(T.isX86()); | 
|  | if (T.isArch32Bit()) | 
|  | return MachO::CPU_SUBTYPE_I386_ALL; | 
|  |  | 
|  | assert(T.isArch64Bit()); | 
|  | if (T.getArchName() == "x86_64h") | 
|  | return MachO::CPU_SUBTYPE_X86_64_H; | 
|  | return MachO::CPU_SUBTYPE_X86_64_ALL; | 
|  | } | 
|  |  | 
|  | static MachO::CPUSubTypeARM getARMSubType(const Triple &T) { | 
|  | assert(T.isARM() || T.isThumb()); | 
|  | StringRef Arch = T.getArchName(); | 
|  | ARM::ArchKind AK = ARM::parseArch(Arch); | 
|  | switch (AK) { | 
|  | default: | 
|  | return MachO::CPU_SUBTYPE_ARM_V7; | 
|  | case ARM::ArchKind::ARMV4T: | 
|  | return MachO::CPU_SUBTYPE_ARM_V4T; | 
|  | case ARM::ArchKind::ARMV5T: | 
|  | case ARM::ArchKind::ARMV5TE: | 
|  | case ARM::ArchKind::ARMV5TEJ: | 
|  | return MachO::CPU_SUBTYPE_ARM_V5; | 
|  | case ARM::ArchKind::ARMV6: | 
|  | case ARM::ArchKind::ARMV6K: | 
|  | return MachO::CPU_SUBTYPE_ARM_V6; | 
|  | case ARM::ArchKind::ARMV7A: | 
|  | return MachO::CPU_SUBTYPE_ARM_V7; | 
|  | case ARM::ArchKind::ARMV7S: | 
|  | return MachO::CPU_SUBTYPE_ARM_V7S; | 
|  | case ARM::ArchKind::ARMV7K: | 
|  | return MachO::CPU_SUBTYPE_ARM_V7K; | 
|  | case ARM::ArchKind::ARMV6M: | 
|  | return MachO::CPU_SUBTYPE_ARM_V6M; | 
|  | case ARM::ArchKind::ARMV7M: | 
|  | return MachO::CPU_SUBTYPE_ARM_V7M; | 
|  | case ARM::ArchKind::ARMV7EM: | 
|  | return MachO::CPU_SUBTYPE_ARM_V7EM; | 
|  | } | 
|  | } | 
|  |  | 
|  | static MachO::CPUSubTypeARM64 getARM64SubType(const Triple &T) { | 
|  | assert(T.isAArch64()); | 
|  | if (T.isArch32Bit()) | 
|  | return (MachO::CPUSubTypeARM64)MachO::CPU_SUBTYPE_ARM64_32_V8; | 
|  | if (T.isArm64e()) | 
|  | return MachO::CPU_SUBTYPE_ARM64E; | 
|  |  | 
|  | return MachO::CPU_SUBTYPE_ARM64_ALL; | 
|  | } | 
|  |  | 
|  | static MachO::CPUSubTypePowerPC getPowerPCSubType(const Triple &T) { | 
|  | return MachO::CPU_SUBTYPE_POWERPC_ALL; | 
|  | } | 
|  |  | 
|  | static Error unsupported(const char *Str, const Triple &T) { | 
|  | return createStringError(std::errc::invalid_argument, | 
|  | "Unsupported triple for mach-o cpu %s: %s", Str, | 
|  | T.str().c_str()); | 
|  | } | 
|  |  | 
|  | Expected<uint32_t> MachO::getCPUType(const Triple &T) { | 
|  | if (!T.isOSBinFormatMachO()) | 
|  | return unsupported("type", T); | 
|  | if (T.isX86() && T.isArch32Bit()) | 
|  | return MachO::CPU_TYPE_X86; | 
|  | if (T.isX86() && T.isArch64Bit()) | 
|  | return MachO::CPU_TYPE_X86_64; | 
|  | if (T.isARM() || T.isThumb()) | 
|  | return MachO::CPU_TYPE_ARM; | 
|  | if (T.isAArch64()) | 
|  | return T.isArch32Bit() ? MachO::CPU_TYPE_ARM64_32 : MachO::CPU_TYPE_ARM64; | 
|  | if (T.getArch() == Triple::ppc) | 
|  | return MachO::CPU_TYPE_POWERPC; | 
|  | if (T.getArch() == Triple::ppc64) | 
|  | return MachO::CPU_TYPE_POWERPC64; | 
|  | return unsupported("type", T); | 
|  | } | 
|  |  | 
|  | Expected<uint32_t> MachO::getCPUSubType(const Triple &T) { | 
|  | if (!T.isOSBinFormatMachO()) | 
|  | return unsupported("subtype", T); | 
|  | if (T.isX86()) | 
|  | return getX86SubType(T); | 
|  | if (T.isARM() || T.isThumb()) | 
|  | return getARMSubType(T); | 
|  | if (T.isAArch64() || T.getArch() == Triple::aarch64_32) | 
|  | return getARM64SubType(T); | 
|  | if (T.getArch() == Triple::ppc || T.getArch() == Triple::ppc64) | 
|  | return getPowerPCSubType(T); | 
|  | return unsupported("subtype", T); | 
|  | } | 
|  |  | 
|  | Expected<uint32_t> MachO::getCPUSubType(const Triple &T, | 
|  | unsigned PtrAuthABIVersion, | 
|  | bool PtrAuthKernelABIVersion) { | 
|  | Expected<uint32_t> Result = MachO::getCPUSubType(T); | 
|  | if (!Result) | 
|  | return Result.takeError(); | 
|  | if (*Result != MachO::CPU_SUBTYPE_ARM64E) | 
|  | return createStringError( | 
|  | std::errc::invalid_argument, | 
|  | "ptrauth ABI version is only supported on arm64e."); | 
|  | if (PtrAuthABIVersion > 0xF) | 
|  | return createStringError( | 
|  | std::errc::invalid_argument, | 
|  | "The ptrauth ABI version needs to fit within 4 bits."); | 
|  | return CPU_SUBTYPE_ARM64E_WITH_PTRAUTH_VERSION(PtrAuthABIVersion, | 
|  | PtrAuthKernelABIVersion); | 
|  | } |