MemoryTest.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. //===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator 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. #include "llvm/Support/Memory.h"
  9. #include "llvm/Support/Process.h"
  10. #include "gtest/gtest.h"
  11. #include <cassert>
  12. #include <cstdlib>
  13. #if defined(__NetBSD__)
  14. // clang-format off
  15. #include <sys/param.h>
  16. #include <sys/types.h>
  17. #include <sys/sysctl.h>
  18. #include <err.h>
  19. #include <unistd.h>
  20. // clang-format on
  21. #endif
  22. using namespace llvm;
  23. using namespace sys;
  24. namespace {
  25. bool IsMPROTECT() {
  26. #if defined(__NetBSD__)
  27. int mib[3];
  28. int paxflags;
  29. size_t len = sizeof(paxflags);
  30. mib[0] = CTL_PROC;
  31. mib[1] = getpid();
  32. mib[2] = PROC_PID_PAXFLAGS;
  33. if (sysctl(mib, 3, &paxflags, &len, NULL, 0) != 0)
  34. err(EXIT_FAILURE, "sysctl");
  35. return !!(paxflags & CTL_PROC_PAXFLAGS_MPROTECT);
  36. #else
  37. return false;
  38. #endif
  39. }
  40. class MappedMemoryTest : public ::testing::TestWithParam<unsigned> {
  41. public:
  42. MappedMemoryTest() {
  43. Flags = GetParam();
  44. PageSize = sys::Process::getPageSizeEstimate();
  45. }
  46. protected:
  47. // Adds RW flags to permit testing of the resulting memory
  48. unsigned getTestableEquivalent(unsigned RequestedFlags) {
  49. switch (RequestedFlags) {
  50. case Memory::MF_READ:
  51. case Memory::MF_WRITE:
  52. case Memory::MF_READ|Memory::MF_WRITE:
  53. return Memory::MF_READ|Memory::MF_WRITE;
  54. case Memory::MF_READ|Memory::MF_EXEC:
  55. case Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC:
  56. case Memory::MF_EXEC:
  57. return Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC;
  58. }
  59. // Default in case values are added to the enum, as required by some compilers
  60. return Memory::MF_READ|Memory::MF_WRITE;
  61. }
  62. // Returns true if the memory blocks overlap
  63. bool doesOverlap(MemoryBlock M1, MemoryBlock M2) {
  64. if (M1.base() == M2.base())
  65. return true;
  66. if (M1.base() > M2.base())
  67. return (unsigned char *)M2.base() + M2.allocatedSize() > M1.base();
  68. return (unsigned char *)M1.base() + M1.allocatedSize() > M2.base();
  69. }
  70. unsigned Flags;
  71. size_t PageSize;
  72. };
  73. // MPROTECT prevents W+X mmaps
  74. #define CHECK_UNSUPPORTED() \
  75. do { \
  76. if ((Flags & Memory::MF_WRITE) && (Flags & Memory::MF_EXEC) && \
  77. IsMPROTECT()) \
  78. return; \
  79. } while (0)
  80. TEST_P(MappedMemoryTest, AllocAndRelease) {
  81. CHECK_UNSUPPORTED();
  82. std::error_code EC;
  83. MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC);
  84. EXPECT_EQ(std::error_code(), EC);
  85. EXPECT_NE((void*)nullptr, M1.base());
  86. EXPECT_LE(sizeof(int), M1.allocatedSize());
  87. EXPECT_FALSE(Memory::releaseMappedMemory(M1));
  88. }
  89. TEST_P(MappedMemoryTest, AllocAndReleaseHuge) {
  90. CHECK_UNSUPPORTED();
  91. std::error_code EC;
  92. MemoryBlock M1 = Memory::allocateMappedMemory(
  93. sizeof(int), nullptr, Flags | Memory::MF_HUGE_HINT, EC);
  94. EXPECT_EQ(std::error_code(), EC);
  95. // Test large/huge memory pages. In the worst case, 4kb pages should be
  96. // returned, if large pages aren't available.
  97. EXPECT_NE((void *)nullptr, M1.base());
  98. EXPECT_LE(sizeof(int), M1.allocatedSize());
  99. EXPECT_FALSE(Memory::releaseMappedMemory(M1));
  100. }
  101. TEST_P(MappedMemoryTest, MultipleAllocAndRelease) {
  102. CHECK_UNSUPPORTED();
  103. std::error_code EC;
  104. MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
  105. EXPECT_EQ(std::error_code(), EC);
  106. MemoryBlock M2 = Memory::allocateMappedMemory(64, nullptr, Flags, EC);
  107. EXPECT_EQ(std::error_code(), EC);
  108. MemoryBlock M3 = Memory::allocateMappedMemory(32, nullptr, Flags, EC);
  109. EXPECT_EQ(std::error_code(), EC);
  110. EXPECT_NE((void*)nullptr, M1.base());
  111. EXPECT_LE(16U, M1.allocatedSize());
  112. EXPECT_NE((void*)nullptr, M2.base());
  113. EXPECT_LE(64U, M2.allocatedSize());
  114. EXPECT_NE((void*)nullptr, M3.base());
  115. EXPECT_LE(32U, M3.allocatedSize());
  116. EXPECT_FALSE(doesOverlap(M1, M2));
  117. EXPECT_FALSE(doesOverlap(M2, M3));
  118. EXPECT_FALSE(doesOverlap(M1, M3));
  119. EXPECT_FALSE(Memory::releaseMappedMemory(M1));
  120. EXPECT_FALSE(Memory::releaseMappedMemory(M3));
  121. MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
  122. EXPECT_EQ(std::error_code(), EC);
  123. EXPECT_NE((void*)nullptr, M4.base());
  124. EXPECT_LE(16U, M4.allocatedSize());
  125. EXPECT_FALSE(Memory::releaseMappedMemory(M4));
  126. EXPECT_FALSE(Memory::releaseMappedMemory(M2));
  127. }
  128. TEST_P(MappedMemoryTest, BasicWrite) {
  129. // This test applies only to readable and writeable combinations
  130. if (Flags &&
  131. !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE)))
  132. return;
  133. CHECK_UNSUPPORTED();
  134. std::error_code EC;
  135. MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC);
  136. EXPECT_EQ(std::error_code(), EC);
  137. EXPECT_NE((void*)nullptr, M1.base());
  138. EXPECT_LE(sizeof(int), M1.allocatedSize());
  139. int *a = (int*)M1.base();
  140. *a = 1;
  141. EXPECT_EQ(1, *a);
  142. EXPECT_FALSE(Memory::releaseMappedMemory(M1));
  143. }
  144. TEST_P(MappedMemoryTest, MultipleWrite) {
  145. // This test applies only to readable and writeable combinations
  146. if (Flags &&
  147. !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE)))
  148. return;
  149. CHECK_UNSUPPORTED();
  150. std::error_code EC;
  151. MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,
  152. EC);
  153. EXPECT_EQ(std::error_code(), EC);
  154. MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags,
  155. EC);
  156. EXPECT_EQ(std::error_code(), EC);
  157. MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags,
  158. EC);
  159. EXPECT_EQ(std::error_code(), EC);
  160. EXPECT_FALSE(doesOverlap(M1, M2));
  161. EXPECT_FALSE(doesOverlap(M2, M3));
  162. EXPECT_FALSE(doesOverlap(M1, M3));
  163. EXPECT_NE((void*)nullptr, M1.base());
  164. EXPECT_LE(1U * sizeof(int), M1.allocatedSize());
  165. EXPECT_NE((void*)nullptr, M2.base());
  166. EXPECT_LE(8U * sizeof(int), M2.allocatedSize());
  167. EXPECT_NE((void*)nullptr, M3.base());
  168. EXPECT_LE(4U * sizeof(int), M3.allocatedSize());
  169. int *x = (int*)M1.base();
  170. *x = 1;
  171. int *y = (int*)M2.base();
  172. for (int i = 0; i < 8; i++) {
  173. y[i] = i;
  174. }
  175. int *z = (int*)M3.base();
  176. *z = 42;
  177. EXPECT_EQ(1, *x);
  178. EXPECT_EQ(7, y[7]);
  179. EXPECT_EQ(42, *z);
  180. EXPECT_FALSE(Memory::releaseMappedMemory(M1));
  181. EXPECT_FALSE(Memory::releaseMappedMemory(M3));
  182. MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), nullptr,
  183. Flags, EC);
  184. EXPECT_EQ(std::error_code(), EC);
  185. EXPECT_NE((void*)nullptr, M4.base());
  186. EXPECT_LE(64U * sizeof(int), M4.allocatedSize());
  187. x = (int*)M4.base();
  188. *x = 4;
  189. EXPECT_EQ(4, *x);
  190. EXPECT_FALSE(Memory::releaseMappedMemory(M4));
  191. // Verify that M2 remains unaffected by other activity
  192. for (int i = 0; i < 8; i++) {
  193. EXPECT_EQ(i, y[i]);
  194. }
  195. EXPECT_FALSE(Memory::releaseMappedMemory(M2));
  196. }
  197. TEST_P(MappedMemoryTest, EnabledWrite) {
  198. // MPROTECT prevents W+X, and since this test always adds W we need
  199. // to block any variant with X.
  200. if ((Flags & Memory::MF_EXEC) && IsMPROTECT())
  201. return;
  202. std::error_code EC;
  203. MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), nullptr, Flags,
  204. EC);
  205. EXPECT_EQ(std::error_code(), EC);
  206. MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags,
  207. EC);
  208. EXPECT_EQ(std::error_code(), EC);
  209. MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags,
  210. EC);
  211. EXPECT_EQ(std::error_code(), EC);
  212. EXPECT_NE((void*)nullptr, M1.base());
  213. EXPECT_LE(2U * sizeof(int), M1.allocatedSize());
  214. EXPECT_NE((void*)nullptr, M2.base());
  215. EXPECT_LE(8U * sizeof(int), M2.allocatedSize());
  216. EXPECT_NE((void*)nullptr, M3.base());
  217. EXPECT_LE(4U * sizeof(int), M3.allocatedSize());
  218. EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags)));
  219. EXPECT_FALSE(Memory::protectMappedMemory(M2, getTestableEquivalent(Flags)));
  220. EXPECT_FALSE(Memory::protectMappedMemory(M3, getTestableEquivalent(Flags)));
  221. EXPECT_FALSE(doesOverlap(M1, M2));
  222. EXPECT_FALSE(doesOverlap(M2, M3));
  223. EXPECT_FALSE(doesOverlap(M1, M3));
  224. int *x = (int*)M1.base();
  225. *x = 1;
  226. int *y = (int*)M2.base();
  227. for (unsigned int i = 0; i < 8; i++) {
  228. y[i] = i;
  229. }
  230. int *z = (int*)M3.base();
  231. *z = 42;
  232. EXPECT_EQ(1, *x);
  233. EXPECT_EQ(7, y[7]);
  234. EXPECT_EQ(42, *z);
  235. EXPECT_FALSE(Memory::releaseMappedMemory(M1));
  236. EXPECT_FALSE(Memory::releaseMappedMemory(M3));
  237. EXPECT_EQ(6, y[6]);
  238. MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
  239. EXPECT_EQ(std::error_code(), EC);
  240. EXPECT_NE((void*)nullptr, M4.base());
  241. EXPECT_LE(16U, M4.allocatedSize());
  242. EXPECT_EQ(std::error_code(),
  243. Memory::protectMappedMemory(M4, getTestableEquivalent(Flags)));
  244. x = (int*)M4.base();
  245. *x = 4;
  246. EXPECT_EQ(4, *x);
  247. EXPECT_FALSE(Memory::releaseMappedMemory(M4));
  248. EXPECT_FALSE(Memory::releaseMappedMemory(M2));
  249. }
  250. TEST_P(MappedMemoryTest, SuccessiveNear) {
  251. CHECK_UNSUPPORTED();
  252. std::error_code EC;
  253. MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
  254. EXPECT_EQ(std::error_code(), EC);
  255. MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC);
  256. EXPECT_EQ(std::error_code(), EC);
  257. MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC);
  258. EXPECT_EQ(std::error_code(), EC);
  259. EXPECT_NE((void*)nullptr, M1.base());
  260. EXPECT_LE(16U, M1.allocatedSize());
  261. EXPECT_NE((void*)nullptr, M2.base());
  262. EXPECT_LE(64U, M2.allocatedSize());
  263. EXPECT_NE((void*)nullptr, M3.base());
  264. EXPECT_LE(32U, M3.allocatedSize());
  265. EXPECT_FALSE(doesOverlap(M1, M2));
  266. EXPECT_FALSE(doesOverlap(M2, M3));
  267. EXPECT_FALSE(doesOverlap(M1, M3));
  268. EXPECT_FALSE(Memory::releaseMappedMemory(M1));
  269. EXPECT_FALSE(Memory::releaseMappedMemory(M3));
  270. EXPECT_FALSE(Memory::releaseMappedMemory(M2));
  271. }
  272. TEST_P(MappedMemoryTest, DuplicateNear) {
  273. CHECK_UNSUPPORTED();
  274. std::error_code EC;
  275. MemoryBlock Near((void*)(3*PageSize), 16);
  276. MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
  277. EXPECT_EQ(std::error_code(), EC);
  278. MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
  279. EXPECT_EQ(std::error_code(), EC);
  280. MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
  281. EXPECT_EQ(std::error_code(), EC);
  282. EXPECT_NE((void*)nullptr, M1.base());
  283. EXPECT_LE(16U, M1.allocatedSize());
  284. EXPECT_NE((void*)nullptr, M2.base());
  285. EXPECT_LE(64U, M2.allocatedSize());
  286. EXPECT_NE((void*)nullptr, M3.base());
  287. EXPECT_LE(32U, M3.allocatedSize());
  288. EXPECT_FALSE(Memory::releaseMappedMemory(M1));
  289. EXPECT_FALSE(Memory::releaseMappedMemory(M3));
  290. EXPECT_FALSE(Memory::releaseMappedMemory(M2));
  291. }
  292. TEST_P(MappedMemoryTest, ZeroNear) {
  293. CHECK_UNSUPPORTED();
  294. std::error_code EC;
  295. MemoryBlock Near(nullptr, 0);
  296. MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
  297. EXPECT_EQ(std::error_code(), EC);
  298. MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
  299. EXPECT_EQ(std::error_code(), EC);
  300. MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
  301. EXPECT_EQ(std::error_code(), EC);
  302. EXPECT_NE((void*)nullptr, M1.base());
  303. EXPECT_LE(16U, M1.allocatedSize());
  304. EXPECT_NE((void*)nullptr, M2.base());
  305. EXPECT_LE(64U, M2.allocatedSize());
  306. EXPECT_NE((void*)nullptr, M3.base());
  307. EXPECT_LE(32U, M3.allocatedSize());
  308. EXPECT_FALSE(doesOverlap(M1, M2));
  309. EXPECT_FALSE(doesOverlap(M2, M3));
  310. EXPECT_FALSE(doesOverlap(M1, M3));
  311. EXPECT_FALSE(Memory::releaseMappedMemory(M1));
  312. EXPECT_FALSE(Memory::releaseMappedMemory(M3));
  313. EXPECT_FALSE(Memory::releaseMappedMemory(M2));
  314. }
  315. TEST_P(MappedMemoryTest, ZeroSizeNear) {
  316. CHECK_UNSUPPORTED();
  317. std::error_code EC;
  318. MemoryBlock Near((void*)(4*PageSize), 0);
  319. MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
  320. EXPECT_EQ(std::error_code(), EC);
  321. MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
  322. EXPECT_EQ(std::error_code(), EC);
  323. MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
  324. EXPECT_EQ(std::error_code(), EC);
  325. EXPECT_NE((void*)nullptr, M1.base());
  326. EXPECT_LE(16U, M1.allocatedSize());
  327. EXPECT_NE((void*)nullptr, M2.base());
  328. EXPECT_LE(64U, M2.allocatedSize());
  329. EXPECT_NE((void*)nullptr, M3.base());
  330. EXPECT_LE(32U, M3.allocatedSize());
  331. EXPECT_FALSE(doesOverlap(M1, M2));
  332. EXPECT_FALSE(doesOverlap(M2, M3));
  333. EXPECT_FALSE(doesOverlap(M1, M3));
  334. EXPECT_FALSE(Memory::releaseMappedMemory(M1));
  335. EXPECT_FALSE(Memory::releaseMappedMemory(M3));
  336. EXPECT_FALSE(Memory::releaseMappedMemory(M2));
  337. }
  338. TEST_P(MappedMemoryTest, UnalignedNear) {
  339. CHECK_UNSUPPORTED();
  340. std::error_code EC;
  341. MemoryBlock Near((void*)(2*PageSize+5), 0);
  342. MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC);
  343. EXPECT_EQ(std::error_code(), EC);
  344. EXPECT_NE((void*)nullptr, M1.base());
  345. EXPECT_LE(sizeof(int), M1.allocatedSize());
  346. EXPECT_FALSE(Memory::releaseMappedMemory(M1));
  347. }
  348. // Note that Memory::MF_WRITE is not supported exclusively across
  349. // operating systems and architectures and can imply MF_READ|MF_WRITE
  350. unsigned MemoryFlags[] = {
  351. Memory::MF_READ,
  352. Memory::MF_WRITE,
  353. Memory::MF_READ|Memory::MF_WRITE,
  354. Memory::MF_EXEC,
  355. Memory::MF_READ|Memory::MF_EXEC,
  356. Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC
  357. };
  358. INSTANTIATE_TEST_CASE_P(AllocationTests,
  359. MappedMemoryTest,
  360. ::testing::ValuesIn(MemoryFlags),);
  361. } // anonymous namespace