100d8c1abSChris Bieneman //===- unittest/BinaryFormat/MachOTest.cpp - MachO support tests ----------===// 200d8c1abSChris Bieneman // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 600d8c1abSChris Bieneman // 700d8c1abSChris Bieneman //===----------------------------------------------------------------------===// 800d8c1abSChris Bieneman 93a226dbeSRainer Orth #include "llvm/ADT/bit.h" 1000d8c1abSChris Bieneman #include "llvm/BinaryFormat/MachO.h" 1162c7f035SArchibald Elliott #include "llvm/TargetParser/Triple.h" 1200d8c1abSChris Bieneman #include "gtest/gtest.h" 1300d8c1abSChris Bieneman 1400d8c1abSChris Bieneman using namespace llvm; 1500d8c1abSChris Bieneman using namespace llvm::MachO; 1600d8c1abSChris Bieneman 173a226dbeSRainer Orth #if BYTE_ORDER == BIG_ENDIAN 183a226dbeSRainer Orth // As discussed in Issue #86793, this test cannot work on a strict-alignment 193a226dbeSRainer Orth // targets like SPARC. Besides, it's undefined behaviour on big-endian hosts. 203a226dbeSRainer Orth #define MAYBE_UnalignedLC DISABLED_UnalignedLC 213a226dbeSRainer Orth #else 223a226dbeSRainer Orth #define MAYBE_UnalignedLC UnalignedLC 233a226dbeSRainer Orth #endif 243a226dbeSRainer Orth 253a226dbeSRainer Orth TEST(MachOTest, MAYBE_UnalignedLC) { 2600d8c1abSChris Bieneman unsigned char Valid32BitMachO[] = { 2700d8c1abSChris Bieneman 0xCE, 0xFA, 0xED, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 2800d8c1abSChris Bieneman 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 2900d8c1abSChris Bieneman 0x85, 0x80, 0x21, 0x01, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 3000d8c1abSChris Bieneman 0x5F, 0x5F, 0x50, 0x41, 0x47, 0x45, 0x5A, 0x45, 0x52, 0x4F, 0x00, 0x00, 3100d8c1abSChris Bieneman 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 3200d8c1abSChris Bieneman 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3300d8c1abSChris Bieneman 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3400d8c1abSChris Bieneman 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x4C, 0x49, 3500d8c1abSChris Bieneman 0x4E, 0x4B, 0x45, 0x44, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3600d8c1abSChris Bieneman 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 3700d8c1abSChris Bieneman 0x8C, 0x0B, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 3800d8c1abSChris Bieneman 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 3900d8c1abSChris Bieneman 4000d8c1abSChris Bieneman mach_header *Header = 4100d8c1abSChris Bieneman reinterpret_cast<mach_header *>(Valid32BitMachO); 4200d8c1abSChris Bieneman if (!sys::IsLittleEndianHost) 4300d8c1abSChris Bieneman swapStruct(*Header); 4400d8c1abSChris Bieneman ASSERT_EQ(Header->magic, MH_MAGIC); 4500d8c1abSChris Bieneman unsigned char *Current = Valid32BitMachO + sizeof(mach_header); 4600d8c1abSChris Bieneman unsigned char *BufferEnd = 4700d8c1abSChris Bieneman Valid32BitMachO + sizeof(mach_header) + Header->sizeofcmds; 4800d8c1abSChris Bieneman while (Current < BufferEnd) { 4900d8c1abSChris Bieneman macho_load_command *LC = 5000d8c1abSChris Bieneman reinterpret_cast<macho_load_command *>(Current); 5100d8c1abSChris Bieneman if (!sys::IsLittleEndianHost) 5200d8c1abSChris Bieneman swapStruct(LC->load_command_data); 5300d8c1abSChris Bieneman ASSERT_EQ(LC->load_command_data.cmd, LC_SEGMENT); 5400d8c1abSChris Bieneman Current += LC->load_command_data.cmdsize; 5500d8c1abSChris Bieneman } 5600d8c1abSChris Bieneman } 577b0a5683SFrancis Visoiu Mistrih 587b0a5683SFrancis Visoiu Mistrih TEST(MachOTest, CPUType) { 597b0a5683SFrancis Visoiu Mistrih #define CHECK_CPUTYPE(StrTriple, ExpectedCPUType) \ 607b0a5683SFrancis Visoiu Mistrih ASSERT_EQ((MachO::CPUType)cantFail(MachO::getCPUType(Triple(StrTriple))), \ 617b0a5683SFrancis Visoiu Mistrih (ExpectedCPUType)) 627b0a5683SFrancis Visoiu Mistrih CHECK_CPUTYPE("x86_64-apple-darwin", MachO::CPU_TYPE_X86_64); 637b0a5683SFrancis Visoiu Mistrih CHECK_CPUTYPE("x86_64h-apple-darwin", MachO::CPU_TYPE_X86_64); 647b0a5683SFrancis Visoiu Mistrih CHECK_CPUTYPE("i386-apple-darwin", MachO::CPU_TYPE_X86); 657b0a5683SFrancis Visoiu Mistrih CHECK_CPUTYPE("armv7-apple-darwin", MachO::CPU_TYPE_ARM); 667b0a5683SFrancis Visoiu Mistrih CHECK_CPUTYPE("thumbv7-apple-darwin", MachO::CPU_TYPE_ARM); 677b0a5683SFrancis Visoiu Mistrih CHECK_CPUTYPE("arm64-apple-darwin", MachO::CPU_TYPE_ARM64); 687b0a5683SFrancis Visoiu Mistrih CHECK_CPUTYPE("arm64e-apple-darwin", MachO::CPU_TYPE_ARM64); 697b0a5683SFrancis Visoiu Mistrih CHECK_CPUTYPE("arm64_32-apple-darwin", MachO::CPU_TYPE_ARM64_32); 707b0a5683SFrancis Visoiu Mistrih 717b0a5683SFrancis Visoiu Mistrih { 727b0a5683SFrancis Visoiu Mistrih // Not a mach-o. 737b0a5683SFrancis Visoiu Mistrih Expected<uint32_t> Type = MachO::getCPUType(Triple("x86_64-linux-unknown")); 747b0a5683SFrancis Visoiu Mistrih ASSERT_EQ(toString(Type.takeError()), 757b0a5683SFrancis Visoiu Mistrih "Unsupported triple for mach-o cpu type: x86_64-linux-unknown"); 767b0a5683SFrancis Visoiu Mistrih } 777b0a5683SFrancis Visoiu Mistrih { 787b0a5683SFrancis Visoiu Mistrih // Not a valid mach-o architecture. 797b0a5683SFrancis Visoiu Mistrih Expected<uint32_t> Type = MachO::getCPUType(Triple("mips-apple-darwin")); 807b0a5683SFrancis Visoiu Mistrih ASSERT_EQ(toString(Type.takeError()), 817b0a5683SFrancis Visoiu Mistrih "Unsupported triple for mach-o cpu type: mips-apple-darwin"); 827b0a5683SFrancis Visoiu Mistrih } 837b0a5683SFrancis Visoiu Mistrih #undef CHECK_CPUTYPE 847b0a5683SFrancis Visoiu Mistrih } 857b0a5683SFrancis Visoiu Mistrih 867b0a5683SFrancis Visoiu Mistrih TEST(MachOTest, CPUSubType) { 877b0a5683SFrancis Visoiu Mistrih #define CHECK_CPUSUBTYPE(StrTriple, ExpectedCPUSubType) \ 887b0a5683SFrancis Visoiu Mistrih ASSERT_EQ(cantFail(MachO::getCPUSubType(Triple(StrTriple))), \ 897b0a5683SFrancis Visoiu Mistrih ((uint32_t)ExpectedCPUSubType)) 907b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("x86_64-apple-darwin", MachO::CPU_SUBTYPE_X86_64_ALL); 917b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("x86_64h-apple-darwin", MachO::CPU_SUBTYPE_X86_64_H); 927b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("i386-apple-darwin", MachO::CPU_SUBTYPE_I386_ALL); 937b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("arm-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7); // Default 947b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("armv4t-apple-darwin", MachO::CPU_SUBTYPE_ARM_V4T); 957b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("armv5t-apple-darwin", MachO::CPU_SUBTYPE_ARM_V5); 967b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("armv5te-apple-darwin", MachO::CPU_SUBTYPE_ARM_V5); 977b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("armv5tej-apple-darwin", MachO::CPU_SUBTYPE_ARM_V5); 987b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("armv6-apple-darwin", MachO::CPU_SUBTYPE_ARM_V6); 997b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("armv6k-apple-darwin", MachO::CPU_SUBTYPE_ARM_V6); 1007b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("armv7a-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7); 1017b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("armv7s-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7S); 1027b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("armv7k-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7K); 1037b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("armv6m-apple-darwin", MachO::CPU_SUBTYPE_ARM_V6M); 1047b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("armv7m-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7M); 1057b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("armv7em-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7EM); 1067b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("thumbv7-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7); 1077b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("thumbv6-apple-darwin", MachO::CPU_SUBTYPE_ARM_V6); 1087b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("arm64-apple-darwin", MachO::CPU_SUBTYPE_ARM64_ALL); 1097b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("arm64e-apple-darwin", MachO::CPU_SUBTYPE_ARM64E); 1107b0a5683SFrancis Visoiu Mistrih CHECK_CPUSUBTYPE("arm64_32-apple-darwin", MachO::CPU_SUBTYPE_ARM64_32_V8); 1117b0a5683SFrancis Visoiu Mistrih 1127b0a5683SFrancis Visoiu Mistrih { 1137b0a5683SFrancis Visoiu Mistrih // Not a mach-o. 1147b0a5683SFrancis Visoiu Mistrih Expected<uint32_t> Type = 1157b0a5683SFrancis Visoiu Mistrih MachO::getCPUSubType(Triple("x86_64-linux-unknown")); 1167b0a5683SFrancis Visoiu Mistrih ASSERT_EQ( 1177b0a5683SFrancis Visoiu Mistrih toString(Type.takeError()), 1187b0a5683SFrancis Visoiu Mistrih "Unsupported triple for mach-o cpu subtype: x86_64-linux-unknown"); 1197b0a5683SFrancis Visoiu Mistrih } 1207b0a5683SFrancis Visoiu Mistrih { 1217b0a5683SFrancis Visoiu Mistrih // Not a valid mach-o architecture. 1227b0a5683SFrancis Visoiu Mistrih Expected<uint32_t> Type = MachO::getCPUSubType(Triple("mips-apple-darwin")); 1237b0a5683SFrancis Visoiu Mistrih ASSERT_EQ(toString(Type.takeError()), 1247b0a5683SFrancis Visoiu Mistrih "Unsupported triple for mach-o cpu subtype: mips-apple-darwin"); 1257b0a5683SFrancis Visoiu Mistrih } 1267b0a5683SFrancis Visoiu Mistrih #undef CHECK_CPUSUBTYPE 1277b0a5683SFrancis Visoiu Mistrih } 128*fd4f9520SAhmed Bougacha 129*fd4f9520SAhmed Bougacha TEST(MachOTest, CPUSubTypePtrAuthABI) { 130*fd4f9520SAhmed Bougacha { 131*fd4f9520SAhmed Bougacha Expected<uint32_t> Type = MachO::getCPUSubType( 132*fd4f9520SAhmed Bougacha Triple("x86_64-apple-darwin"), /*PtrAuthABIVersion=*/5, 133*fd4f9520SAhmed Bougacha /*PtrAuthKernelABIVersion=*/false); 134*fd4f9520SAhmed Bougacha ASSERT_EQ(toString(Type.takeError()), 135*fd4f9520SAhmed Bougacha "ptrauth ABI version is only supported on arm64e."); 136*fd4f9520SAhmed Bougacha } 137*fd4f9520SAhmed Bougacha { 138*fd4f9520SAhmed Bougacha Expected<uint32_t> Type = MachO::getCPUSubType( 139*fd4f9520SAhmed Bougacha Triple("arm64e-apple-darwin"), /*PtrAuthABIVersion=*/0x10, 140*fd4f9520SAhmed Bougacha /*PtrAuthKernelABIVersion=*/false); 141*fd4f9520SAhmed Bougacha ASSERT_EQ(toString(Type.takeError()), 142*fd4f9520SAhmed Bougacha "The ptrauth ABI version needs to fit within 4 bits."); 143*fd4f9520SAhmed Bougacha } 144*fd4f9520SAhmed Bougacha { 145*fd4f9520SAhmed Bougacha uint32_t Type = cantFail(MachO::getCPUSubType( 146*fd4f9520SAhmed Bougacha Triple("arm64e-apple-darwin"), 147*fd4f9520SAhmed Bougacha /*PtrAuthABIVersion=*/5, /*PtrAuthKernelABIVersion=*/false)); 148*fd4f9520SAhmed Bougacha ASSERT_EQ(Type, 0x85000002U); 149*fd4f9520SAhmed Bougacha } 150*fd4f9520SAhmed Bougacha { 151*fd4f9520SAhmed Bougacha uint32_t Type = cantFail(MachO::getCPUSubType( 152*fd4f9520SAhmed Bougacha Triple("arm64e-apple-darwin"), 153*fd4f9520SAhmed Bougacha /*PtrAuthABIVersion=*/5, /*PtrAuthKernelABIVersion=*/true)); 154*fd4f9520SAhmed Bougacha ASSERT_EQ(Type, 0xC5000002U); 155*fd4f9520SAhmed Bougacha } 156*fd4f9520SAhmed Bougacha { 157*fd4f9520SAhmed Bougacha uint32_t Type = cantFail(MachO::getCPUSubType( 158*fd4f9520SAhmed Bougacha Triple("arm64e-apple-darwin"), 159*fd4f9520SAhmed Bougacha /*PtrAuthABIVersion=*/0xF, /*PtrAuthKernelABIVersion=*/false)); 160*fd4f9520SAhmed Bougacha ASSERT_EQ(Type, 0x8F000002U); 161*fd4f9520SAhmed Bougacha } 162*fd4f9520SAhmed Bougacha { 163*fd4f9520SAhmed Bougacha uint32_t Type = cantFail(MachO::getCPUSubType( 164*fd4f9520SAhmed Bougacha Triple("arm64e-apple-darwin"), 165*fd4f9520SAhmed Bougacha /*PtrAuthABIVersion=*/0xF, /*PtrAuthKernelABIVersion=*/true)); 166*fd4f9520SAhmed Bougacha ASSERT_EQ(Type, 0xCF000002U); 167*fd4f9520SAhmed Bougacha } 168*fd4f9520SAhmed Bougacha { 169*fd4f9520SAhmed Bougacha uint32_t Type = cantFail(MachO::getCPUSubType( 170*fd4f9520SAhmed Bougacha Triple("arm64e-apple-darwin"), 171*fd4f9520SAhmed Bougacha /*PtrAuthABIVersion=*/0, /*PtrAuthKernelABIVersion=*/false)); 172*fd4f9520SAhmed Bougacha ASSERT_EQ(Type, 0x80000002U); 173*fd4f9520SAhmed Bougacha } 174*fd4f9520SAhmed Bougacha { 175*fd4f9520SAhmed Bougacha uint32_t Type = cantFail(MachO::getCPUSubType( 176*fd4f9520SAhmed Bougacha Triple("arm64e-apple-darwin"), 177*fd4f9520SAhmed Bougacha /*PtrAuthABIVersion=*/0, /*PtrAuthKernelABIVersion=*/true)); 178*fd4f9520SAhmed Bougacha ASSERT_EQ(Type, 0xC0000002U); 179*fd4f9520SAhmed Bougacha } 180*fd4f9520SAhmed Bougacha } 181