xref: /llvm-project/lldb/test/API/functionalities/memory/holes/main.cpp (revision 181cc75ea8be70e3fa7145456e1bf2331e0bc5e4)
1*181cc75eSPavel Labath #include <algorithm>
2*181cc75eSPavel Labath #include <cstdint>
3*181cc75eSPavel Labath #include <cstdio>
4*181cc75eSPavel Labath #include <cstdlib>
5*181cc75eSPavel Labath #include <cstring>
6*181cc75eSPavel Labath #include <iostream>
7*181cc75eSPavel Labath 
8*181cc75eSPavel Labath constexpr size_t num_pages = 7;
9*181cc75eSPavel Labath constexpr size_t accessible_pages[] = {0, 2, 4, 6};
10*181cc75eSPavel Labath 
11*181cc75eSPavel Labath bool is_accessible(size_t page) {
12*181cc75eSPavel Labath   return std::find(std::begin(accessible_pages), std::end(accessible_pages),
13*181cc75eSPavel Labath                    page) != std::end(accessible_pages);
14*181cc75eSPavel Labath }
15*181cc75eSPavel Labath 
16*181cc75eSPavel Labath // allocate_memory_with_holes returns a pointer to `num_pages` pages of memory,
17*181cc75eSPavel Labath // where some of the pages are inaccessible (even to debugging APIs). We use
18*181cc75eSPavel Labath // this to test lldb's ability to skip over inaccessible blocks.
19*181cc75eSPavel Labath #ifdef _WIN32
20*181cc75eSPavel Labath #include "Windows.h"
21*181cc75eSPavel Labath 
22*181cc75eSPavel Labath int getpagesize() {
23*181cc75eSPavel Labath   SYSTEM_INFO system_info;
24*181cc75eSPavel Labath   GetSystemInfo(&system_info);
25*181cc75eSPavel Labath   return system_info.dwPageSize;
26*181cc75eSPavel Labath }
27*181cc75eSPavel Labath 
28*181cc75eSPavel Labath char *allocate_memory_with_holes() {
29*181cc75eSPavel Labath   int pagesize = getpagesize();
30*181cc75eSPavel Labath   void *mem =
31*181cc75eSPavel Labath       VirtualAlloc(nullptr, num_pages * pagesize, MEM_RESERVE, PAGE_NOACCESS);
32*181cc75eSPavel Labath   if (!mem) {
33*181cc75eSPavel Labath     std::cerr << std::system_category().message(GetLastError()) << std::endl;
34*181cc75eSPavel Labath     exit(1);
35*181cc75eSPavel Labath   }
36*181cc75eSPavel Labath   char *bytes = static_cast<char *>(mem);
37*181cc75eSPavel Labath   for (size_t page = 0; page < num_pages; ++page) {
38*181cc75eSPavel Labath     if (!is_accessible(page))
39*181cc75eSPavel Labath       continue;
40*181cc75eSPavel Labath     if (!VirtualAlloc(bytes + page * pagesize, pagesize, MEM_COMMIT,
41*181cc75eSPavel Labath                       PAGE_READWRITE)) {
42*181cc75eSPavel Labath       std::cerr << std::system_category().message(GetLastError()) << std::endl;
43*181cc75eSPavel Labath       exit(1);
44*181cc75eSPavel Labath     }
45*181cc75eSPavel Labath   }
46*181cc75eSPavel Labath   return bytes;
47*181cc75eSPavel Labath }
48*181cc75eSPavel Labath #else
49*181cc75eSPavel Labath #include "sys/mman.h"
50*181cc75eSPavel Labath #include "unistd.h"
51*181cc75eSPavel Labath 
52*181cc75eSPavel Labath char *allocate_memory_with_holes() {
53*181cc75eSPavel Labath   int pagesize = getpagesize();
54*181cc75eSPavel Labath   void *mem = mmap(nullptr, num_pages * pagesize, PROT_READ | PROT_WRITE,
55*181cc75eSPavel Labath                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
56*181cc75eSPavel Labath   if (mem == MAP_FAILED) {
57*181cc75eSPavel Labath     perror("mmap");
58*181cc75eSPavel Labath     exit(1);
59*181cc75eSPavel Labath   }
60*181cc75eSPavel Labath   char *bytes = static_cast<char *>(mem);
61*181cc75eSPavel Labath   for (size_t page = 0; page < num_pages; ++page) {
62*181cc75eSPavel Labath     if (is_accessible(page))
63*181cc75eSPavel Labath       continue;
64*181cc75eSPavel Labath     if (munmap(bytes + page * pagesize, pagesize) != 0) {
65*181cc75eSPavel Labath       perror("munmap");
66*181cc75eSPavel Labath       exit(1);
67*181cc75eSPavel Labath     }
68*181cc75eSPavel Labath   }
69*181cc75eSPavel Labath   return bytes;
70*181cc75eSPavel Labath }
71*181cc75eSPavel Labath #endif
72*181cc75eSPavel Labath 
73*181cc75eSPavel Labath int main(int argc, char const *argv[]) {
74*181cc75eSPavel Labath   char *mem_with_holes = allocate_memory_with_holes();
75*181cc75eSPavel Labath   int pagesize = getpagesize();
76*181cc75eSPavel Labath   char *positions[] = {
77*181cc75eSPavel Labath       mem_with_holes,                // Beginning of memory
78*181cc75eSPavel Labath       mem_with_holes + 2 * pagesize, // After a hole
79*181cc75eSPavel Labath       mem_with_holes + 2 * pagesize +
80*181cc75eSPavel Labath           pagesize / 2, // Middle of a block, after an existing match.
81*181cc75eSPavel Labath       mem_with_holes + 5 * pagesize - 7, // End of a block
82*181cc75eSPavel Labath       mem_with_holes + 7 * pagesize - 7, // End of memory
83*181cc75eSPavel Labath   };
84*181cc75eSPavel Labath   for (char *p : positions)
85*181cc75eSPavel Labath     strcpy(p, "needle");
86*181cc75eSPavel Labath 
87*181cc75eSPavel Labath   return 0; // break here
88*181cc75eSPavel Labath }
89