-
Notifications
You must be signed in to change notification settings - Fork 601
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Copy just used pages from huge ANONYMOUS mappings.
ASan creates a "shadow" of the used memory. This is done in a mapping of around 20 TB address space, but most of it is not yet used. This patch helps an ASan-enabled rr build in following tests: nested_detach nested_detach_kill nested_detach_kill_stuck nested_detach_wait nested_release Avoids error message: ERROR: AddressSanitizer: requested allocation size 0x20000000000 (0x20000001000 after adjustments for alignment, red zones etc.) exceeds maximum supported size of 0x10000000000 (thread T0) Changes in V4: - Rename variable offset to page_offset to know the stored units. - Rename read_count to page_read_count. - Remove unneded check if inside the mapping. - Fixed parentheses in condition. - Use type size_t instead of ssize_t to avoid different signedness comparision warning.
- Loading branch information
Showing
3 changed files
with
145 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ | ||
|
||
#include "util_internal.h" | ||
|
||
static const int magic = 0xab; | ||
static uint64_t size = 0x400000; /* 4 MB, at least the value in Task::dup_from */ | ||
static size_t page_size; | ||
static void* pages[10]; | ||
static unsigned int idx; /*next index of pages*/ | ||
|
||
void test_alloc(char* mem, unsigned int count, off_t offset) { | ||
|
||
test_assert(0 == munmap(mem + size, page_size)); | ||
|
||
/* one page near the start */ | ||
test_assert(idx < sizeof(pages)/sizeof(pages[0])); | ||
pages[idx] = mem + page_size; | ||
memset(pages[idx], magic, page_size); | ||
idx++; | ||
|
||
/* one or more pages near or at the end */ | ||
for (unsigned int i = 0; i < count; i++) { | ||
test_assert(idx < sizeof(pages)/sizeof(pages[0])); | ||
pages[idx] = mem + offset + i * page_size; | ||
memset(pages[idx], magic, page_size); | ||
idx++; | ||
} | ||
} | ||
|
||
int main(void) { | ||
page_size = sysconf(_SC_PAGESIZE); | ||
|
||
/* Create one big mapping, then break it up by munmap | ||
* into smaller ones, to better test the handling in | ||
* the end of mappings. */ | ||
|
||
void* mem1 = mmap(NULL, 4 * (size + page_size), PROT_READ | PROT_WRITE, | ||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); | ||
test_assert(mem1 != MAP_FAILED); | ||
|
||
void* mem2 = mem1 + size + page_size; | ||
void* mem3 = mem2 + size + page_size; | ||
void* mem4 = mem3 + size + page_size; | ||
|
||
test_alloc(mem1, 1, size - page_size); /* one page used at last page */ | ||
test_alloc(mem2, 1, size - page_size * 2); /* one page used before last page */ | ||
test_alloc(mem3, 2, size - page_size * 2); /* two consecutive pages at last two pages */ | ||
test_alloc(mem4, 2, size - page_size * 3); /* two consecutive pages before last page */ | ||
|
||
pid_t pid = fork(); | ||
if (pid == 0) { | ||
if (running_under_rr()) { | ||
rr_detach_teleport(); | ||
} | ||
|
||
/* create one page for easier comparison */ | ||
char* cmp = malloc(page_size * 3); | ||
test_assert(cmp != NULL); | ||
memset(cmp, magic, page_size * 3); | ||
|
||
/* check if the saved pages have the expected value */ | ||
for (unsigned int i = 0; i < idx; i++) { | ||
test_assert(memcmp(pages[i], cmp, page_size) == 0); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int status; | ||
wait(&status); | ||
test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0); | ||
atomic_puts("EXIT-SUCCESS"); | ||
return 0; | ||
} |