| #include <algorithm> |
| #include <cstdint> |
| #include <cstdio> |
| #include <cstdlib> |
| #include <cstring> |
| #include <iostream> |
| |
| constexpr size_t num_pages = 7; |
| constexpr size_t accessible_pages[] = {0, 2, 4, 6}; |
| |
| bool is_accessible(size_t page) { |
| return std::find(std::begin(accessible_pages), std::end(accessible_pages), |
| page) != std::end(accessible_pages); |
| } |
| |
| // allocate_memory_with_holes returns a pointer to `num_pages` pages of memory, |
| // where some of the pages are inaccessible (even to debugging APIs). We use |
| // this to test lldb's ability to skip over inaccessible blocks. |
| #ifdef _WIN32 |
| #include "Windows.h" |
| |
| int getpagesize() { |
| SYSTEM_INFO system_info; |
| GetSystemInfo(&system_info); |
| return system_info.dwPageSize; |
| } |
| |
| char *allocate_memory_with_holes() { |
| int pagesize = getpagesize(); |
| void *mem = |
| VirtualAlloc(nullptr, num_pages * pagesize, MEM_RESERVE, PAGE_NOACCESS); |
| if (!mem) { |
| std::cerr << std::system_category().message(GetLastError()) << std::endl; |
| exit(1); |
| } |
| char *bytes = static_cast<char *>(mem); |
| for (size_t page = 0; page < num_pages; ++page) { |
| if (!is_accessible(page)) |
| continue; |
| if (!VirtualAlloc(bytes + page * pagesize, pagesize, MEM_COMMIT, |
| PAGE_READWRITE)) { |
| std::cerr << std::system_category().message(GetLastError()) << std::endl; |
| exit(1); |
| } |
| } |
| return bytes; |
| } |
| #else |
| #include "sys/mman.h" |
| #include "unistd.h" |
| |
| char *allocate_memory_with_holes() { |
| int pagesize = getpagesize(); |
| void *mem = mmap(nullptr, num_pages * pagesize, PROT_READ | PROT_WRITE, |
| MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
| if (mem == MAP_FAILED) { |
| perror("mmap"); |
| exit(1); |
| } |
| char *bytes = static_cast<char *>(mem); |
| for (size_t page = 0; page < num_pages; ++page) { |
| if (is_accessible(page)) |
| continue; |
| if (munmap(bytes + page * pagesize, pagesize) != 0) { |
| perror("munmap"); |
| exit(1); |
| } |
| } |
| return bytes; |
| } |
| #endif |
| |
| int main(int argc, char const *argv[]) { |
| char *mem_with_holes = allocate_memory_with_holes(); |
| int pagesize = getpagesize(); |
| char *positions[] = { |
| mem_with_holes, // Beginning of memory |
| mem_with_holes + 2 * pagesize, // After a hole |
| mem_with_holes + 2 * pagesize + |
| pagesize / 2, // Middle of a block, after an existing match. |
| mem_with_holes + 5 * pagesize - 7, // End of a block |
| mem_with_holes + 7 * pagesize - 7, // End of memory |
| }; |
| for (char *p : positions) |
| strcpy(p, "needle"); |
| |
| return 0; // break here |
| } |