1 //===-- SubprocessMemoryTest.cpp --------------------------------*- C++ -*-===// 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 "SubprocessMemory.h" 10 11 #include "X86/TestBase.h" 12 #include "gtest/gtest.h" 13 #include <string> 14 #include <unordered_map> 15 16 #ifdef __linux__ 17 #include <endian.h> 18 #include <fcntl.h> 19 #include <sys/mman.h> 20 #include <sys/syscall.h> 21 #include <unistd.h> 22 #endif // __linux__ 23 24 namespace llvm { 25 namespace exegesis { 26 27 #if defined(__linux__) && !defined(__ANDROID__) && \ 28 !(defined(__powerpc__) || defined(__s390x__) || defined(__sparc__)) 29 30 // This needs to be updated anytime a test is added or removed from the test 31 // suite. 32 static constexpr const size_t TestCount = 4; 33 34 class SubprocessMemoryTest : public X86TestBase { 35 protected: 36 int getSharedMemoryNumber(const unsigned TestNumber) { 37 // Do a process similar to 2D array indexing so that each process gets it's 38 // own shared memory space to avoid collisions. This will not overflow as 39 // the maximum value a PID can take on is 10^22. 40 return getpid() * TestCount + TestNumber; 41 } 42 43 void 44 testCommon(std::unordered_map<std::string, MemoryValue> MemoryDefinitions, 45 const unsigned TestNumber) { 46 EXPECT_FALSE( 47 SM.initializeSubprocessMemory(getSharedMemoryNumber(TestNumber))); 48 EXPECT_FALSE(SM.addMemoryDefinition(MemoryDefinitions, 49 getSharedMemoryNumber(TestNumber))); 50 } 51 52 std::string getSharedMemoryName(const unsigned TestNumber, 53 const unsigned DefinitionNumber) { 54 long CurrentTID = syscall(SYS_gettid); 55 return "/" + std::to_string(getSharedMemoryNumber(TestNumber)) + "t" + 56 std::to_string(CurrentTID) + "memdef" + 57 std::to_string(DefinitionNumber); 58 } 59 60 void checkSharedMemoryDefinition(const std::string &DefinitionName, 61 size_t DefinitionSize, 62 std::vector<uint8_t> ExpectedValue) { 63 int SharedMemoryFD = 64 shm_open(DefinitionName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 65 uint8_t *SharedMemoryMapping = (uint8_t *)mmap( 66 NULL, DefinitionSize, PROT_READ, MAP_SHARED, SharedMemoryFD, 0); 67 EXPECT_NE(reinterpret_cast<intptr_t>(SharedMemoryMapping), -1); 68 for (size_t I = 0; I < ExpectedValue.size(); ++I) { 69 EXPECT_EQ(SharedMemoryMapping[I], ExpectedValue[I]); 70 } 71 munmap(SharedMemoryMapping, DefinitionSize); 72 } 73 74 SubprocessMemory SM; 75 }; 76 77 // Some of the tests below are failing on s390x and PPC due to the shared 78 // memory calls not working in some cases, so they have been disabled. 79 // TODO(boomanaiden154): Investigate and fix this issue on PPC. 80 81 TEST_F(SubprocessMemoryTest, OneDefinition) { 82 testCommon({{"test1", {APInt(8, 0xff), 4096, 0}}}, 0); 83 checkSharedMemoryDefinition(getSharedMemoryName(0, 0), 4096, {0xff}); 84 } 85 86 TEST_F(SubprocessMemoryTest, MultipleDefinitions) { 87 testCommon({{"test1", {APInt(8, 0xaa), 4096, 0}}, 88 {"test2", {APInt(8, 0xbb), 4096, 1}}, 89 {"test3", {APInt(8, 0xcc), 4096, 2}}}, 90 1); 91 checkSharedMemoryDefinition(getSharedMemoryName(1, 0), 4096, {0xaa}); 92 checkSharedMemoryDefinition(getSharedMemoryName(1, 1), 4096, {0xbb}); 93 checkSharedMemoryDefinition(getSharedMemoryName(1, 2), 4096, {0xcc}); 94 } 95 96 TEST_F(SubprocessMemoryTest, DefinitionFillsCompletely) { 97 testCommon({{"test1", {APInt(8, 0xaa), 4096, 0}}, 98 {"test2", {APInt(16, 0xbbbb), 4096, 1}}, 99 {"test3", {APInt(24, 0xcccccc), 4096, 2}}}, 100 2); 101 std::vector<uint8_t> Test1Expected(512, 0xaa); 102 std::vector<uint8_t> Test2Expected(512, 0xbb); 103 std::vector<uint8_t> Test3Expected(512, 0xcc); 104 checkSharedMemoryDefinition(getSharedMemoryName(2, 0), 4096, Test1Expected); 105 checkSharedMemoryDefinition(getSharedMemoryName(2, 1), 4096, Test2Expected); 106 checkSharedMemoryDefinition(getSharedMemoryName(2, 2), 4096, Test3Expected); 107 } 108 109 // The following test is only supported on little endian systems. 110 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 111 TEST_F(SubprocessMemoryTest, DISABLED_DefinitionEndTruncation) { 112 #else 113 TEST_F(SubprocessMemoryTest, DefinitionEndTruncation) { 114 #endif 115 testCommon({{"test1", {APInt(48, 0xaabbccddeeff), 4096, 0}}}, 3); 116 std::vector<uint8_t> Test1Expected(512, 0); 117 // order is reversed since we're assuming a little endian system. 118 for (size_t I = 0; I < Test1Expected.size(); ++I) { 119 switch (I % 6) { 120 case 0: 121 Test1Expected[I] = 0xff; 122 break; 123 case 1: 124 Test1Expected[I] = 0xee; 125 break; 126 case 2: 127 Test1Expected[I] = 0xdd; 128 break; 129 case 3: 130 Test1Expected[I] = 0xcc; 131 break; 132 case 4: 133 Test1Expected[I] = 0xbb; 134 break; 135 case 5: 136 Test1Expected[I] = 0xaa; 137 } 138 } 139 checkSharedMemoryDefinition(getSharedMemoryName(3, 0), 4096, Test1Expected); 140 } 141 142 #endif // __linux__ && !__ANDROID__ && !(__powerpc__ || __s390x__ || __sparc__) 143 144 } // namespace exegesis 145 } // namespace llvm 146