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
11static const int USE_MMAP = 0;
12
13typedef 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
22typedef 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
32pool *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   VALGRIND_MAKE_MEM_NOACCESS(p->where, SUPERBLOCK_SIZE);
50   return p;
51}
52
53void 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
70void pop(pool *p)
71{
72   level_list *l = p->levels;
73   p->levels = l->next;
74   VALGRIND_DESTROY_MEMPOOL(l->where);
75   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
83void 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
99char *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
113void 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
152int main(void)
153{
154   test();
155   return 0;
156}
157