1 //===- unittest/BinaryFormat/MachOTest.cpp - MachO support tests ----------===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ADT/bit.h" 10 #include "llvm/BinaryFormat/MachO.h" 11 #include "llvm/TargetParser/Triple.h" 12 #include "gtest/gtest.h" 13 14 using namespace llvm; 15 using namespace llvm::MachO; 16 17 #if BYTE_ORDER == BIG_ENDIAN 18 // As discussed in Issue #86793, this test cannot work on a strict-alignment 19 // targets like SPARC. Besides, it's undefined behaviour on big-endian hosts. 20 #define MAYBE_UnalignedLC DISABLED_UnalignedLC 21 #else 22 #define MAYBE_UnalignedLC UnalignedLC 23 #endif 24 25 TEST(MachOTest, MAYBE_UnalignedLC) { 26 unsigned char Valid32BitMachO[] = { 27 0xCE, 0xFA, 0xED, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 28 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 29 0x85, 0x80, 0x21, 0x01, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 30 0x5F, 0x5F, 0x50, 0x41, 0x47, 0x45, 0x5A, 0x45, 0x52, 0x4F, 0x00, 0x00, 31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 34 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x4C, 0x49, 35 0x4E, 0x4B, 0x45, 0x44, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 36 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 37 0x8C, 0x0B, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 39 40 mach_header *Header = 41 reinterpret_cast<mach_header *>(Valid32BitMachO); 42 if (!sys::IsLittleEndianHost) 43 swapStruct(*Header); 44 ASSERT_EQ(Header->magic, MH_MAGIC); 45 unsigned char *Current = Valid32BitMachO + sizeof(mach_header); 46 unsigned char *BufferEnd = 47 Valid32BitMachO + sizeof(mach_header) + Header->sizeofcmds; 48 while (Current < BufferEnd) { 49 macho_load_command *LC = 50 reinterpret_cast<macho_load_command *>(Current); 51 if (!sys::IsLittleEndianHost) 52 swapStruct(LC->load_command_data); 53 ASSERT_EQ(LC->load_command_data.cmd, LC_SEGMENT); 54 Current += LC->load_command_data.cmdsize; 55 } 56 } 57 58 TEST(MachOTest, CPUType) { 59 #define CHECK_CPUTYPE(StrTriple, ExpectedCPUType) \ 60 ASSERT_EQ((MachO::CPUType)cantFail(MachO::getCPUType(Triple(StrTriple))), \ 61 (ExpectedCPUType)) 62 CHECK_CPUTYPE("x86_64-apple-darwin", MachO::CPU_TYPE_X86_64); 63 CHECK_CPUTYPE("x86_64h-apple-darwin", MachO::CPU_TYPE_X86_64); 64 CHECK_CPUTYPE("i386-apple-darwin", MachO::CPU_TYPE_X86); 65 CHECK_CPUTYPE("armv7-apple-darwin", MachO::CPU_TYPE_ARM); 66 CHECK_CPUTYPE("thumbv7-apple-darwin", MachO::CPU_TYPE_ARM); 67 CHECK_CPUTYPE("arm64-apple-darwin", MachO::CPU_TYPE_ARM64); 68 CHECK_CPUTYPE("arm64e-apple-darwin", MachO::CPU_TYPE_ARM64); 69 CHECK_CPUTYPE("arm64_32-apple-darwin", MachO::CPU_TYPE_ARM64_32); 70 71 { 72 // Not a mach-o. 73 Expected<uint32_t> Type = MachO::getCPUType(Triple("x86_64-linux-unknown")); 74 ASSERT_EQ(toString(Type.takeError()), 75 "Unsupported triple for mach-o cpu type: x86_64-linux-unknown"); 76 } 77 { 78 // Not a valid mach-o architecture. 79 Expected<uint32_t> Type = MachO::getCPUType(Triple("mips-apple-darwin")); 80 ASSERT_EQ(toString(Type.takeError()), 81 "Unsupported triple for mach-o cpu type: mips-apple-darwin"); 82 } 83 #undef CHECK_CPUTYPE 84 } 85 86 TEST(MachOTest, CPUSubType) { 87 #define CHECK_CPUSUBTYPE(StrTriple, ExpectedCPUSubType) \ 88 ASSERT_EQ(cantFail(MachO::getCPUSubType(Triple(StrTriple))), \ 89 ((uint32_t)ExpectedCPUSubType)) 90 CHECK_CPUSUBTYPE("x86_64-apple-darwin", MachO::CPU_SUBTYPE_X86_64_ALL); 91 CHECK_CPUSUBTYPE("x86_64h-apple-darwin", MachO::CPU_SUBTYPE_X86_64_H); 92 CHECK_CPUSUBTYPE("i386-apple-darwin", MachO::CPU_SUBTYPE_I386_ALL); 93 CHECK_CPUSUBTYPE("arm-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7); // Default 94 CHECK_CPUSUBTYPE("armv4t-apple-darwin", MachO::CPU_SUBTYPE_ARM_V4T); 95 CHECK_CPUSUBTYPE("armv5t-apple-darwin", MachO::CPU_SUBTYPE_ARM_V5); 96 CHECK_CPUSUBTYPE("armv5te-apple-darwin", MachO::CPU_SUBTYPE_ARM_V5); 97 CHECK_CPUSUBTYPE("armv5tej-apple-darwin", MachO::CPU_SUBTYPE_ARM_V5); 98 CHECK_CPUSUBTYPE("armv6-apple-darwin", MachO::CPU_SUBTYPE_ARM_V6); 99 CHECK_CPUSUBTYPE("armv6k-apple-darwin", MachO::CPU_SUBTYPE_ARM_V6); 100 CHECK_CPUSUBTYPE("armv7a-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7); 101 CHECK_CPUSUBTYPE("armv7s-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7S); 102 CHECK_CPUSUBTYPE("armv7k-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7K); 103 CHECK_CPUSUBTYPE("armv6m-apple-darwin", MachO::CPU_SUBTYPE_ARM_V6M); 104 CHECK_CPUSUBTYPE("armv7m-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7M); 105 CHECK_CPUSUBTYPE("armv7em-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7EM); 106 CHECK_CPUSUBTYPE("thumbv7-apple-darwin", MachO::CPU_SUBTYPE_ARM_V7); 107 CHECK_CPUSUBTYPE("thumbv6-apple-darwin", MachO::CPU_SUBTYPE_ARM_V6); 108 CHECK_CPUSUBTYPE("arm64-apple-darwin", MachO::CPU_SUBTYPE_ARM64_ALL); 109 CHECK_CPUSUBTYPE("arm64e-apple-darwin", MachO::CPU_SUBTYPE_ARM64E); 110 CHECK_CPUSUBTYPE("arm64_32-apple-darwin", MachO::CPU_SUBTYPE_ARM64_32_V8); 111 112 { 113 // Not a mach-o. 114 Expected<uint32_t> Type = 115 MachO::getCPUSubType(Triple("x86_64-linux-unknown")); 116 ASSERT_EQ( 117 toString(Type.takeError()), 118 "Unsupported triple for mach-o cpu subtype: x86_64-linux-unknown"); 119 } 120 { 121 // Not a valid mach-o architecture. 122 Expected<uint32_t> Type = MachO::getCPUSubType(Triple("mips-apple-darwin")); 123 ASSERT_EQ(toString(Type.takeError()), 124 "Unsupported triple for mach-o cpu subtype: mips-apple-darwin"); 125 } 126 #undef CHECK_CPUSUBTYPE 127 } 128 129 TEST(MachOTest, CPUSubTypePtrAuthABI) { 130 { 131 Expected<uint32_t> Type = MachO::getCPUSubType( 132 Triple("x86_64-apple-darwin"), /*PtrAuthABIVersion=*/5, 133 /*PtrAuthKernelABIVersion=*/false); 134 ASSERT_EQ(toString(Type.takeError()), 135 "ptrauth ABI version is only supported on arm64e."); 136 } 137 { 138 Expected<uint32_t> Type = MachO::getCPUSubType( 139 Triple("arm64e-apple-darwin"), /*PtrAuthABIVersion=*/0x10, 140 /*PtrAuthKernelABIVersion=*/false); 141 ASSERT_EQ(toString(Type.takeError()), 142 "The ptrauth ABI version needs to fit within 4 bits."); 143 } 144 { 145 uint32_t Type = cantFail(MachO::getCPUSubType( 146 Triple("arm64e-apple-darwin"), 147 /*PtrAuthABIVersion=*/5, /*PtrAuthKernelABIVersion=*/false)); 148 ASSERT_EQ(Type, 0x85000002U); 149 } 150 { 151 uint32_t Type = cantFail(MachO::getCPUSubType( 152 Triple("arm64e-apple-darwin"), 153 /*PtrAuthABIVersion=*/5, /*PtrAuthKernelABIVersion=*/true)); 154 ASSERT_EQ(Type, 0xC5000002U); 155 } 156 { 157 uint32_t Type = cantFail(MachO::getCPUSubType( 158 Triple("arm64e-apple-darwin"), 159 /*PtrAuthABIVersion=*/0xF, /*PtrAuthKernelABIVersion=*/false)); 160 ASSERT_EQ(Type, 0x8F000002U); 161 } 162 { 163 uint32_t Type = cantFail(MachO::getCPUSubType( 164 Triple("arm64e-apple-darwin"), 165 /*PtrAuthABIVersion=*/0xF, /*PtrAuthKernelABIVersion=*/true)); 166 ASSERT_EQ(Type, 0xCF000002U); 167 } 168 { 169 uint32_t Type = cantFail(MachO::getCPUSubType( 170 Triple("arm64e-apple-darwin"), 171 /*PtrAuthABIVersion=*/0, /*PtrAuthKernelABIVersion=*/false)); 172 ASSERT_EQ(Type, 0x80000002U); 173 } 174 { 175 uint32_t Type = cantFail(MachO::getCPUSubType( 176 Triple("arm64e-apple-darwin"), 177 /*PtrAuthABIVersion=*/0, /*PtrAuthKernelABIVersion=*/true)); 178 ASSERT_EQ(Type, 0xC0000002U); 179 } 180 } 181