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