#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
}