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

source code of lldb/test/API/functionalities/memory/holes/main.cpp