diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt index 5402ae030b345c..c60377eb2cc1f7 100644 --- a/libc/test/src/sys/mman/linux/CMakeLists.txt +++ b/libc/test/src/sys/mman/linux/CMakeLists.txt @@ -76,5 +76,6 @@ add_libc_unittest( libc.src.sys.mman.munmap libc.src.sys.mman.madvise libc.src.sys.mman.mincore + libc.src.unistd.sysconf libc.test.UnitTest.ErrnoSetterMatcher ) diff --git a/libc/test/src/sys/mman/linux/mincore_test.cpp b/libc/test/src/sys/mman/linux/mincore_test.cpp index 7c8ca3b4ffa4cc..655fd8631af89a 100644 --- a/libc/test/src/sys/mman/linux/mincore_test.cpp +++ b/libc/test/src/sys/mman/linux/mincore_test.cpp @@ -11,12 +11,13 @@ #include "src/sys/mman/mincore.h" #include "src/sys/mman/mmap.h" #include "src/sys/mman/munmap.h" +#include "src/unistd/sysconf.h" #include "test/UnitTest/ErrnoSetterMatcher.h" #include "test/UnitTest/LibcTest.h" #include "test/UnitTest/Test.h" -#include // For EXEC_PAGESIZE #include +#include // For sysconf. using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; @@ -28,73 +29,90 @@ TEST(LlvmLibcMincoreTest, UnMappedMemory) { EXPECT_THAT(res, Fails(ENOMEM, -1)); } +// It is always possible to find an aligned boundary if we allocate page sized +// memory. +static char *aligned_addr(void *addr, size_t alignment) { + char *byte_addr = static_cast(addr); + uintptr_t addr_val = reinterpret_cast(addr); + uintptr_t offset = + addr_val % alignment == 0 ? 0 : alignment - (addr_val % alignment); + return byte_addr + offset; +} + TEST(LlvmLibcMincoreTest, InvalidVec) { - void *addr = LIBC_NAMESPACE::mmap(nullptr, 4 * EXEC_PAGESIZE, PROT_READ, + size_t page_size = static_cast(LIBC_NAMESPACE::sysconf(_SC_PAGESIZE)); + void *addr = LIBC_NAMESPACE::mmap(nullptr, 5 * page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); EXPECT_NE(addr, MAP_FAILED); - EXPECT_EQ(reinterpret_cast(addr) % EXEC_PAGESIZE, 0ul); + // Since we allocated 5 pages, we can find an aligned boundary after which + // there are at least 4 pages + char *aligned = aligned_addr(addr, page_size); libc_errno = 0; - int res = LIBC_NAMESPACE::mincore(addr, 1, nullptr); + int res = LIBC_NAMESPACE::mincore(aligned, 1, nullptr); EXPECT_THAT(res, Fails(EFAULT, -1)); - void *area = - LIBC_NAMESPACE::mmap(nullptr, EXEC_PAGESIZE, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + void *area = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); EXPECT_NE(area, MAP_FAILED); - unsigned char *ptr = static_cast(area) + EXEC_PAGESIZE - 3; - res = LIBC_NAMESPACE::mincore(addr, 4 * EXEC_PAGESIZE, ptr); + unsigned char *ptr = static_cast(area) + page_size - 3; + res = LIBC_NAMESPACE::mincore(aligned, 4 * page_size, ptr); EXPECT_THAT(res, Fails(EFAULT, -1)); - EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, EXEC_PAGESIZE), Succeeds()); - EXPECT_THAT(LIBC_NAMESPACE::munmap(area, 2), Succeeds()); + EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, 5 * page_size), Succeeds()); + EXPECT_THAT(LIBC_NAMESPACE::munmap(area, page_size), Succeeds()); } TEST(LlvmLibcMincoreTest, UnalignedAddr) { - void *addr = LIBC_NAMESPACE::mmap(nullptr, EXEC_PAGESIZE, PROT_READ, + size_t page_size = static_cast(LIBC_NAMESPACE::sysconf(_SC_PAGESIZE)); + void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); EXPECT_NE(addr, MAP_FAILED); - EXPECT_EQ(reinterpret_cast(addr) % EXEC_PAGESIZE, 0ul); + char *aligned = aligned_addr(addr, page_size); libc_errno = 0; - int res = LIBC_NAMESPACE::mincore(static_cast(addr) + 1, 1, nullptr); + int res = LIBC_NAMESPACE::mincore(aligned + 1, 1, nullptr); EXPECT_THAT(res, Fails(EINVAL, -1)); - EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, EXEC_PAGESIZE), Succeeds()); + EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds()); } TEST(LlvmLibcMincoreTest, NoError) { - void *addr = LIBC_NAMESPACE::mmap(nullptr, EXEC_PAGESIZE, PROT_READ, + size_t page_size = static_cast(LIBC_NAMESPACE::sysconf(_SC_PAGESIZE)); + void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); EXPECT_NE(addr, MAP_FAILED); - EXPECT_EQ(reinterpret_cast(addr) % EXEC_PAGESIZE, 0ul); + char *aligned = aligned_addr(addr, page_size); unsigned char vec; libc_errno = 0; - int res = LIBC_NAMESPACE::mincore(addr, 1, &vec); + int res = LIBC_NAMESPACE::mincore(aligned, 1, &vec); EXPECT_THAT(res, Succeeds()); - EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, EXEC_PAGESIZE), Succeeds()); + EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds()); } TEST(LlvmLibcMincoreTest, NegativeLength) { - void *addr = LIBC_NAMESPACE::mmap(nullptr, EXEC_PAGESIZE, PROT_READ, + size_t page_size = static_cast(LIBC_NAMESPACE::sysconf(_SC_PAGESIZE)); + void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); EXPECT_NE(addr, MAP_FAILED); - EXPECT_EQ(reinterpret_cast(addr) % EXEC_PAGESIZE, 0ul); + char *aligned = aligned_addr(addr, page_size); unsigned char vec; libc_errno = 0; - int res = LIBC_NAMESPACE::mincore(addr, -1, &vec); + int res = LIBC_NAMESPACE::mincore(aligned, -1, &vec); EXPECT_THAT(res, Fails(ENOMEM, -1)); - EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, EXEC_PAGESIZE), Succeeds()); + EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds()); } TEST(LlvmLibcMincoreTest, PageOut) { unsigned char vec; + size_t page_size = static_cast(LIBC_NAMESPACE::sysconf(_SC_PAGESIZE)); + // allocate 2 pages since we need to page out page_size bytes void *addr = - LIBC_NAMESPACE::mmap(nullptr, EXEC_PAGESIZE, PROT_READ | PROT_WRITE, + LIBC_NAMESPACE::mmap(nullptr, 2 * page_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); EXPECT_NE(addr, MAP_FAILED); - EXPECT_EQ(reinterpret_cast(addr) % EXEC_PAGESIZE, 0ul); + char *aligned = aligned_addr(addr, page_size); // touch the page { - static_cast(addr)[0] = 0; + aligned[0] = 0; libc_errno = 0; - int res = LIBC_NAMESPACE::mincore(addr, 1, &vec); + int res = LIBC_NAMESPACE::mincore(aligned, 1, &vec); EXPECT_EQ(vec & 1u, 1u); EXPECT_THAT(res, Succeeds()); } @@ -102,14 +120,14 @@ TEST(LlvmLibcMincoreTest, PageOut) { // page out the memory { libc_errno = 0; - EXPECT_THAT(LIBC_NAMESPACE::madvise(addr, EXEC_PAGESIZE, MADV_DONTNEED), + EXPECT_THAT(LIBC_NAMESPACE::madvise(aligned, page_size, MADV_DONTNEED), Succeeds()); libc_errno = 0; - int res = LIBC_NAMESPACE::mincore(addr, EXEC_PAGESIZE, &vec); + int res = LIBC_NAMESPACE::mincore(aligned, 1, &vec); EXPECT_EQ(vec & 1u, 0u); EXPECT_THAT(res, Succeeds()); } - EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, EXEC_PAGESIZE), Succeeds()); + EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, 2 * page_size), Succeeds()); }