xref: /llvm-project/llvm/lib/BinaryFormat/MachO.cpp (revision fd4f9520a6a08c3dcf15622e3b887d8f3624fc42)
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