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
make_pool()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
push(pool * p)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
pop(pool * p)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
destroy_pool(pool * p)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
allocate(pool * p,int size)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
test(void)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
main(void)152 int main(void)
153 {
154 test();
155 return 0;
156 }
157