1 #include <unistd.h> 2 #include "tests/sys_mman.h" 3 #include <assert.h> 4 #include <stdlib.h> 5 6 #include "../memcheck.h" 7 8 #define SUPERBLOCK_SIZE 100000 9 #define REDZONE_SIZE 8 10 11 static const int USE_MMAP = 0; 12 13 typedef struct _level_list 14 { 15 struct _level_list *next; 16 char *where; 17 // Padding ensures the struct is the same size on 32-bit and 64-bit 18 // machines. 19 char padding[16 - 2*sizeof(char*)]; 20 } level_list; 21 22 typedef struct _pool { 23 char *mem; 24 char *where; 25 level_list *levels; 26 int size, left; 27 // Padding ensures the struct is the same size on 32-bit and 64-bit 28 // machines. 29 char padding[24 - 3*sizeof(char*)]; 30 } pool; 31 32 pool *make_pool() 33 { 34 pool *p; 35 36 if(USE_MMAP) { 37 p = (pool *)mmap(0, sizeof(pool), PROT_READ|PROT_WRITE|PROT_EXEC, 38 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 39 p->where = p->mem = (char *)mmap(NULL, SUPERBLOCK_SIZE, 40 PROT_READ|PROT_WRITE|PROT_EXEC, 41 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 42 } else { 43 p = (pool *)malloc(sizeof(pool)); 44 p->where = p->mem = (char *)malloc(SUPERBLOCK_SIZE); 45 } 46 47 p->size = p->left = SUPERBLOCK_SIZE; 48 p->levels = NULL; 49 (void) VALGRIND_MAKE_MEM_NOACCESS(p->where, SUPERBLOCK_SIZE); 50 return p; 51 } 52 53 void push(pool *p) 54 { 55 level_list *l; 56 57 if(USE_MMAP) 58 l = (level_list *)mmap(0, sizeof(level_list), 59 PROT_READ|PROT_WRITE|PROT_EXEC, 60 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 61 else 62 l = (level_list *)malloc(sizeof(level_list)); 63 64 l->next = p->levels; 65 l->where = p->where; 66 VALGRIND_CREATE_MEMPOOL(l->where, REDZONE_SIZE, 0); 67 p->levels = l; 68 } 69 70 void pop(pool *p) 71 { 72 level_list *l = p->levels; 73 p->levels = l->next; 74 VALGRIND_DESTROY_MEMPOOL(l->where); 75 (void) VALGRIND_MAKE_MEM_NOACCESS(l->where, p->where-l->where); 76 p->where = l->where; 77 if(USE_MMAP) 78 munmap(l, sizeof(level_list)); 79 else 80 free(l); 81 } 82 83 void destroy_pool(pool *p) 84 { 85 level_list *l = p->levels; 86 87 while(l) { 88 pop(p); 89 } 90 if(USE_MMAP) { 91 munmap(p->mem, SUPERBLOCK_SIZE); 92 munmap(p, sizeof(pool)); 93 } else { 94 free(p->mem); 95 free(p); 96 } 97 } 98 99 char *allocate(pool *p, int size) 100 { 101 char *where; 102 p->left -= size + (REDZONE_SIZE*2); 103 where = p->where + REDZONE_SIZE; 104 p->where += size + (REDZONE_SIZE*2); 105 VALGRIND_MEMPOOL_ALLOC(p->levels->where, where, size); 106 return where; 107 } 108 109 //------------------------------------------------------------------------- 110 // Rest 111 //------------------------------------------------------------------------- 112 113 void test(void) 114 { 115 char *x1, *x2, *x3, *x4, *x5; 116 117 pool *p = make_pool(); 118 119 push(p); 120 121 x1 = allocate(p, 10); 122 x2 = allocate(p, 20); 123 push(p); 124 x3 = allocate(p, 10); 125 x4 = allocate(p, 20); 126 127 *x1 = 'a'; // valid 128 *x2 = 'b'; // valid 129 130 x1[-1] = 'h'; // invalid 131 x1[10] = 'i'; // invalid 132 133 pop(p); 134 135 *x3 = 'c'; // invalid 136 *x4 = 'd'; // invalid 137 138 *x1 = 'e'; // valid 139 *x2 = 'f'; // valid 140 141 x5 = allocate(p, 10); 142 143 *x5 = 'g'; // valid 144 145 // pop(p); 146 147 // *x5 = 'g'; // invalid 148 149 // destroy_pool(p); 150 } 151 152 int main(void) 153 { 154 test(); 155 return 0; 156 } 157