Files
Nico Weber 532fa5afbe [ld64.lld, llvm-otool] Minimal arm64e.x1 support (#222721)
Just enough for `llvm-otool -hv` to dump the cpusubtype, and for
ld64.lld to not reject .tbd files that have an arm64e.x1 slice.

This is needed to link mac binaries against the macOS 27 SDK.

(cherry picked from commit b8007a8e4020b8bca2b12e941660e10bf5bf6716)
2026-09-29 11:47:27 +02:00

142 lines
4.7 KiB
C++

//===-- 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;
case ARM::ArchKind::ARMV8MBaseline:
return MachO::CPU_SUBTYPE_ARM_V8M_BASE;
case ARM::ArchKind::ARMV8MMainline:
return MachO::CPU_SUBTYPE_ARM_V8M_MAIN;
case ARM::ArchKind::ARMV8_1MMainline:
return MachO::CPU_SUBTYPE_ARM_V8_1M_MAIN;
}
}
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;
if (T.isArm64e_x1())
return MachO::CPU_SUBTYPE_ARM64E_X1;
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());
}
static MachO::CPUSubTypeRISCV getRISCVSubType(const Triple &T) {
return MachO::CPU_SUBTYPE_RISCV_ALL;
}
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;
if (T.getArch() == Triple::riscv32)
return MachO::CPU_TYPE_RISCV;
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);
if (T.getArch() == Triple::riscv32)
return getRISCVSubType(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);
}