11874dee5SFrancis Visoiu Mistrih //===-- llvm/BinaryFormat/MachO.cpp - The MachO file format -----*- C++/-*-===// 21874dee5SFrancis Visoiu Mistrih // 31874dee5SFrancis Visoiu Mistrih // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41874dee5SFrancis Visoiu Mistrih // See https://llvm.org/LICENSE.txt for license information. 51874dee5SFrancis Visoiu Mistrih // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61874dee5SFrancis Visoiu Mistrih // 71874dee5SFrancis Visoiu Mistrih //===----------------------------------------------------------------------===// 81874dee5SFrancis Visoiu Mistrih 91874dee5SFrancis Visoiu Mistrih #include "llvm/BinaryFormat/MachO.h" 1027aeb58cSArchibald Elliott #include "llvm/TargetParser/ARMTargetParser.h" 1162c7f035SArchibald Elliott #include "llvm/TargetParser/Triple.h" 121874dee5SFrancis Visoiu Mistrih 131874dee5SFrancis Visoiu Mistrih using namespace llvm; 141874dee5SFrancis Visoiu Mistrih 151874dee5SFrancis Visoiu Mistrih static MachO::CPUSubTypeX86 getX86SubType(const Triple &T) { 161874dee5SFrancis Visoiu Mistrih assert(T.isX86()); 171874dee5SFrancis Visoiu Mistrih if (T.isArch32Bit()) 181874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_I386_ALL; 191874dee5SFrancis Visoiu Mistrih 201874dee5SFrancis Visoiu Mistrih assert(T.isArch64Bit()); 211874dee5SFrancis Visoiu Mistrih if (T.getArchName() == "x86_64h") 221874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_X86_64_H; 231874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_X86_64_ALL; 241874dee5SFrancis Visoiu Mistrih } 251874dee5SFrancis Visoiu Mistrih 261874dee5SFrancis Visoiu Mistrih static MachO::CPUSubTypeARM getARMSubType(const Triple &T) { 271874dee5SFrancis Visoiu Mistrih assert(T.isARM() || T.isThumb()); 281874dee5SFrancis Visoiu Mistrih StringRef Arch = T.getArchName(); 291874dee5SFrancis Visoiu Mistrih ARM::ArchKind AK = ARM::parseArch(Arch); 301874dee5SFrancis Visoiu Mistrih switch (AK) { 311874dee5SFrancis Visoiu Mistrih default: 321874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_ARM_V7; 331874dee5SFrancis Visoiu Mistrih case ARM::ArchKind::ARMV4T: 341874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_ARM_V4T; 351874dee5SFrancis Visoiu Mistrih case ARM::ArchKind::ARMV5T: 361874dee5SFrancis Visoiu Mistrih case ARM::ArchKind::ARMV5TE: 371874dee5SFrancis Visoiu Mistrih case ARM::ArchKind::ARMV5TEJ: 381874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_ARM_V5; 391874dee5SFrancis Visoiu Mistrih case ARM::ArchKind::ARMV6: 401874dee5SFrancis Visoiu Mistrih case ARM::ArchKind::ARMV6K: 411874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_ARM_V6; 421874dee5SFrancis Visoiu Mistrih case ARM::ArchKind::ARMV7A: 431874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_ARM_V7; 441874dee5SFrancis Visoiu Mistrih case ARM::ArchKind::ARMV7S: 451874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_ARM_V7S; 461874dee5SFrancis Visoiu Mistrih case ARM::ArchKind::ARMV7K: 471874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_ARM_V7K; 481874dee5SFrancis Visoiu Mistrih case ARM::ArchKind::ARMV6M: 491874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_ARM_V6M; 501874dee5SFrancis Visoiu Mistrih case ARM::ArchKind::ARMV7M: 511874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_ARM_V7M; 521874dee5SFrancis Visoiu Mistrih case ARM::ArchKind::ARMV7EM: 531874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_ARM_V7EM; 541874dee5SFrancis Visoiu Mistrih } 551874dee5SFrancis Visoiu Mistrih } 561874dee5SFrancis Visoiu Mistrih 571874dee5SFrancis Visoiu Mistrih static MachO::CPUSubTypeARM64 getARM64SubType(const Triple &T) { 58152df3adSTim Northover assert(T.isAArch64()); 591874dee5SFrancis Visoiu Mistrih if (T.isArch32Bit()) 601874dee5SFrancis Visoiu Mistrih return (MachO::CPUSubTypeARM64)MachO::CPU_SUBTYPE_ARM64_32_V8; 61f77c948dSAhmed Bougacha if (T.isArm64e()) 621874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_ARM64E; 631874dee5SFrancis Visoiu Mistrih 641874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_ARM64_ALL; 651874dee5SFrancis Visoiu Mistrih } 661874dee5SFrancis Visoiu Mistrih 671874dee5SFrancis Visoiu Mistrih static MachO::CPUSubTypePowerPC getPowerPCSubType(const Triple &T) { 681874dee5SFrancis Visoiu Mistrih return MachO::CPU_SUBTYPE_POWERPC_ALL; 691874dee5SFrancis Visoiu Mistrih } 701874dee5SFrancis Visoiu Mistrih 717b0a5683SFrancis Visoiu Mistrih static Error unsupported(const char *Str, const Triple &T) { 727b0a5683SFrancis Visoiu Mistrih return createStringError(std::errc::invalid_argument, 737b0a5683SFrancis Visoiu Mistrih "Unsupported triple for mach-o cpu %s: %s", Str, 747b0a5683SFrancis Visoiu Mistrih T.str().c_str()); 757b0a5683SFrancis Visoiu Mistrih } 767b0a5683SFrancis Visoiu Mistrih 771874dee5SFrancis Visoiu Mistrih Expected<uint32_t> MachO::getCPUType(const Triple &T) { 787b0a5683SFrancis Visoiu Mistrih if (!T.isOSBinFormatMachO()) 797b0a5683SFrancis Visoiu Mistrih return unsupported("type", T); 801874dee5SFrancis Visoiu Mistrih if (T.isX86() && T.isArch32Bit()) 811874dee5SFrancis Visoiu Mistrih return MachO::CPU_TYPE_X86; 821874dee5SFrancis Visoiu Mistrih if (T.isX86() && T.isArch64Bit()) 831874dee5SFrancis Visoiu Mistrih return MachO::CPU_TYPE_X86_64; 841874dee5SFrancis Visoiu Mistrih if (T.isARM() || T.isThumb()) 851874dee5SFrancis Visoiu Mistrih return MachO::CPU_TYPE_ARM; 861874dee5SFrancis Visoiu Mistrih if (T.isAArch64()) 87152df3adSTim Northover return T.isArch32Bit() ? MachO::CPU_TYPE_ARM64_32 : MachO::CPU_TYPE_ARM64; 881874dee5SFrancis Visoiu Mistrih if (T.getArch() == Triple::ppc) 891874dee5SFrancis Visoiu Mistrih return MachO::CPU_TYPE_POWERPC; 901874dee5SFrancis Visoiu Mistrih if (T.getArch() == Triple::ppc64) 911874dee5SFrancis Visoiu Mistrih return MachO::CPU_TYPE_POWERPC64; 927b0a5683SFrancis Visoiu Mistrih return unsupported("type", T); 931874dee5SFrancis Visoiu Mistrih } 941874dee5SFrancis Visoiu Mistrih 951874dee5SFrancis Visoiu Mistrih Expected<uint32_t> MachO::getCPUSubType(const Triple &T) { 967b0a5683SFrancis Visoiu Mistrih if (!T.isOSBinFormatMachO()) 977b0a5683SFrancis Visoiu Mistrih return unsupported("subtype", T); 981874dee5SFrancis Visoiu Mistrih if (T.isX86()) 991874dee5SFrancis Visoiu Mistrih return getX86SubType(T); 1001874dee5SFrancis Visoiu Mistrih if (T.isARM() || T.isThumb()) 1011874dee5SFrancis Visoiu Mistrih return getARMSubType(T); 1021874dee5SFrancis Visoiu Mistrih if (T.isAArch64() || T.getArch() == Triple::aarch64_32) 1031874dee5SFrancis Visoiu Mistrih return getARM64SubType(T); 1041874dee5SFrancis Visoiu Mistrih if (T.getArch() == Triple::ppc || T.getArch() == Triple::ppc64) 1051874dee5SFrancis Visoiu Mistrih return getPowerPCSubType(T); 1067b0a5683SFrancis Visoiu Mistrih return unsupported("subtype", T); 1071874dee5SFrancis Visoiu Mistrih } 108*fd4f9520SAhmed Bougacha 109*fd4f9520SAhmed Bougacha Expected<uint32_t> MachO::getCPUSubType(const Triple &T, 110*fd4f9520SAhmed Bougacha unsigned PtrAuthABIVersion, 111*fd4f9520SAhmed Bougacha bool PtrAuthKernelABIVersion) { 112*fd4f9520SAhmed Bougacha Expected<uint32_t> Result = MachO::getCPUSubType(T); 113*fd4f9520SAhmed Bougacha if (!Result) 114*fd4f9520SAhmed Bougacha return Result.takeError(); 115*fd4f9520SAhmed Bougacha if (*Result != MachO::CPU_SUBTYPE_ARM64E) 116*fd4f9520SAhmed Bougacha return createStringError( 117*fd4f9520SAhmed Bougacha std::errc::invalid_argument, 118*fd4f9520SAhmed Bougacha "ptrauth ABI version is only supported on arm64e."); 119*fd4f9520SAhmed Bougacha if (PtrAuthABIVersion > 0xF) 120*fd4f9520SAhmed Bougacha return createStringError( 121*fd4f9520SAhmed Bougacha std::errc::invalid_argument, 122*fd4f9520SAhmed Bougacha "The ptrauth ABI version needs to fit within 4 bits."); 123*fd4f9520SAhmed Bougacha return CPU_SUBTYPE_ARM64E_WITH_PTRAUTH_VERSION(PtrAuthABIVersion, 124*fd4f9520SAhmed Bougacha PtrAuthKernelABIVersion); 125*fd4f9520SAhmed Bougacha } 126