126 lines · cpp
1//===-- llvm/BinaryFormat/MachO.cpp - The MachO file format -----*- C++/-*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/BinaryFormat/MachO.h"10#include "llvm/TargetParser/ARMTargetParser.h"11#include "llvm/TargetParser/Triple.h"12 13using namespace llvm;14 15static MachO::CPUSubTypeX86 getX86SubType(const Triple &T) {16 assert(T.isX86());17 if (T.isArch32Bit())18 return MachO::CPU_SUBTYPE_I386_ALL;19 20 assert(T.isArch64Bit());21 if (T.getArchName() == "x86_64h")22 return MachO::CPU_SUBTYPE_X86_64_H;23 return MachO::CPU_SUBTYPE_X86_64_ALL;24}25 26static MachO::CPUSubTypeARM getARMSubType(const Triple &T) {27 assert(T.isARM() || T.isThumb());28 StringRef Arch = T.getArchName();29 ARM::ArchKind AK = ARM::parseArch(Arch);30 switch (AK) {31 default:32 return MachO::CPU_SUBTYPE_ARM_V7;33 case ARM::ArchKind::ARMV4T:34 return MachO::CPU_SUBTYPE_ARM_V4T;35 case ARM::ArchKind::ARMV5T:36 case ARM::ArchKind::ARMV5TE:37 case ARM::ArchKind::ARMV5TEJ:38 return MachO::CPU_SUBTYPE_ARM_V5;39 case ARM::ArchKind::ARMV6:40 case ARM::ArchKind::ARMV6K:41 return MachO::CPU_SUBTYPE_ARM_V6;42 case ARM::ArchKind::ARMV7A:43 return MachO::CPU_SUBTYPE_ARM_V7;44 case ARM::ArchKind::ARMV7S:45 return MachO::CPU_SUBTYPE_ARM_V7S;46 case ARM::ArchKind::ARMV7K:47 return MachO::CPU_SUBTYPE_ARM_V7K;48 case ARM::ArchKind::ARMV6M:49 return MachO::CPU_SUBTYPE_ARM_V6M;50 case ARM::ArchKind::ARMV7M:51 return MachO::CPU_SUBTYPE_ARM_V7M;52 case ARM::ArchKind::ARMV7EM:53 return MachO::CPU_SUBTYPE_ARM_V7EM;54 }55}56 57static MachO::CPUSubTypeARM64 getARM64SubType(const Triple &T) {58 assert(T.isAArch64());59 if (T.isArch32Bit())60 return (MachO::CPUSubTypeARM64)MachO::CPU_SUBTYPE_ARM64_32_V8;61 if (T.isArm64e())62 return MachO::CPU_SUBTYPE_ARM64E;63 64 return MachO::CPU_SUBTYPE_ARM64_ALL;65}66 67static MachO::CPUSubTypePowerPC getPowerPCSubType(const Triple &T) {68 return MachO::CPU_SUBTYPE_POWERPC_ALL;69}70 71static Error unsupported(const char *Str, const Triple &T) {72 return createStringError(std::errc::invalid_argument,73 "Unsupported triple for mach-o cpu %s: %s", Str,74 T.str().c_str());75}76 77Expected<uint32_t> MachO::getCPUType(const Triple &T) {78 if (!T.isOSBinFormatMachO())79 return unsupported("type", T);80 if (T.isX86() && T.isArch32Bit())81 return MachO::CPU_TYPE_X86;82 if (T.isX86() && T.isArch64Bit())83 return MachO::CPU_TYPE_X86_64;84 if (T.isARM() || T.isThumb())85 return MachO::CPU_TYPE_ARM;86 if (T.isAArch64())87 return T.isArch32Bit() ? MachO::CPU_TYPE_ARM64_32 : MachO::CPU_TYPE_ARM64;88 if (T.getArch() == Triple::ppc)89 return MachO::CPU_TYPE_POWERPC;90 if (T.getArch() == Triple::ppc64)91 return MachO::CPU_TYPE_POWERPC64;92 return unsupported("type", T);93}94 95Expected<uint32_t> MachO::getCPUSubType(const Triple &T) {96 if (!T.isOSBinFormatMachO())97 return unsupported("subtype", T);98 if (T.isX86())99 return getX86SubType(T);100 if (T.isARM() || T.isThumb())101 return getARMSubType(T);102 if (T.isAArch64() || T.getArch() == Triple::aarch64_32)103 return getARM64SubType(T);104 if (T.getArch() == Triple::ppc || T.getArch() == Triple::ppc64)105 return getPowerPCSubType(T);106 return unsupported("subtype", T);107}108 109Expected<uint32_t> MachO::getCPUSubType(const Triple &T,110 unsigned PtrAuthABIVersion,111 bool PtrAuthKernelABIVersion) {112 Expected<uint32_t> Result = MachO::getCPUSubType(T);113 if (!Result)114 return Result.takeError();115 if (*Result != MachO::CPU_SUBTYPE_ARM64E)116 return createStringError(117 std::errc::invalid_argument,118 "ptrauth ABI version is only supported on arm64e.");119 if (PtrAuthABIVersion > 0xF)120 return createStringError(121 std::errc::invalid_argument,122 "The ptrauth ABI version needs to fit within 4 bits.");123 return CPU_SUBTYPE_ARM64E_WITH_PTRAUTH_VERSION(PtrAuthABIVersion,124 PtrAuthKernelABIVersion);125}126