f8c4b341d5224a99faff8a42d977b3dc4c6d11e9
[lazyeval.git] / withMulklib.c
1 #include <stdio.h>
2 #include <signal.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <udis86.h>
7 #include <sys/mman.h>
8 #include <errno.h>
9 #include "bitmapped_patricia_tree.h"
10 #define __USE_GNU
11 #include <ucontext.h>
12
13 /* This code is only for x86_64 gcc linux. It is NOT threadsafe. */
14
15 void* slice_alloc (size_t length) {
16   static intptr_t *nextslice = NULL + 1;
17   static intptr_t *lastslice = NULL;
18
19   int num = length / sizeof(intptr_t) + 1;
20
21   if (lastslice < nextslice + num) {
22     nextslice = (intptr_t *)malloc(1024*sizeof(intptr_t));
23     lastslice = nextslice + 1023;
24   }
25
26   void* ret = (void*) nextslice;
27   nextslice += num;
28   return ret;
29 }
30
31 /* w00t, I am a three-star-programmer! */
32 void ***dereferencedPointer;
33 void ***lastDereferencedPointer;
34 void **lockedPointer;
35 void **lastLockedPointer;
36
37 typedef struct {
38   void* (*function) (void*);
39   void* argument;
40   void*** dereferencedPointer;
41 } tree_entry;
42
43 bpt_t pointer_tree;
44
45 bpt_t bpt_assoc_and_release(bpt_t bpt, bpt_key_t key, void *value) {
46   bpt_t new_bpt = bpt_assoc(bpt, key, value);
47   bpt_release(bpt);
48   return new_bpt;
49 }
50
51 void maybeAllocateMorePointers () {
52   if (lastDereferencedPointer > dereferencedPointer) {
53     lockedPointer = (void**) mmap(NULL, 
54                                   sysconf(_SC_PAGE_SIZE)*sizeof(void*),
55                                   PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE,
56                                   -1, 0);
57     dereferencedPointer = (void***) mmap(NULL,
58                                          sysconf(_SC_PAGE_SIZE)*sizeof(void**),
59                                          PROT_READ | PROT_WRITE,
60                                          MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
61
62     if ((dereferencedPointer == MAP_FAILED)) {
63       printf("Mmap failed 2!\n");
64       if ((lockedPointer == MAP_FAILED)) {
65         printf("Mmap failed 1!\n");
66         exit(-1);
67       }
68       exit(-1);
69     }
70
71     lastLockedPointer = lockedPointer + sysconf(_SC_PAGE_SIZE);
72     lastDereferencedPointer = dereferencedPointer + sysconf(_SC_PAGE_SIZE);
73
74     void** lp = lockedPointer;
75     void*** dp = dereferencedPointer;
76     while (lp < lastLockedPointer) {
77       *dp = lp;
78       lp++; dp++;
79     }
80   }
81 }
82
83 inline void initializePointerTree () {
84   pointer_tree = NULL;
85   dereferencedPointer = NULL + 2;
86   lastDereferencedPointer = 1 + dereferencedPointer;
87   maybeAllocateMorePointers ();
88 }
89
90 void*** lazy_alloc (void* (*calculate) (void*), void* opt) {
91   maybeAllocateMorePointers ();
92   void*** ret = dereferencedPointer;
93
94   lockedPointer++;
95   dereferencedPointer++;
96
97   tree_entry *en = (tree_entry*) slice_alloc (sizeof(tree_entry));
98   en->function = calculate;
99   en->argument = opt;
100   en->dereferencedPointer = ret;
101
102
103   pointer_tree = bpt_assoc_and_release(pointer_tree, (intptr_t) *ret,
104                                        (void*) en);
105   return ret;
106 }
107
108 void handle_segv(int segv, siginfo_t* siginfo, void* ucontext) {
109   ucontext_t* uc = (ucontext_t*) ucontext;
110
111   /* do disassembly at from IP */
112   ud_t ud_obj;
113   ud_init(&ud_obj);
114   ud_set_mode(&ud_obj, 64);
115   ud_set_syntax(&ud_obj, UD_SYN_ATT);
116   ud_set_input_buffer(&ud_obj, (unsigned char*) uc->uc_mcontext.gregs[REG_RIP],
117                       10);
118
119   /* was disassembly successful? */
120   if (!ud_disassemble(&ud_obj)) {
121     printf("Disassembly fail!\n");
122     exit(-1);
123   }
124
125   /* is disassembly a memory-operation? */
126   struct ud_operand op0 = ud_obj.operand[0];
127   struct ud_operand op1 = ud_obj.operand[1];
128   struct ud_operand op;
129
130   if (op0.type == UD_OP_MEM) {
131     op = op0;
132   } else if (op1.type == UD_OP_MEM) {
133     op = op1;
134   } else {
135     printf("Instruction unknown\n");
136     exit(-1);
137   }
138
139   /* find out the register - this part is clumsy as we have two sets
140      of constants */
141
142   int setreg;
143   switch (op.base) {
144   case UD_R_RAX:
145   case UD_R_EAX:
146     setreg = REG_RAX;
147     break;
148   case UD_R_RCX:
149   case UD_R_ECX:
150     setreg = REG_RCX;
151     break;
152   case UD_R_RDX:
153   case UD_R_EDX:
154     setreg = REG_RDX;
155     break;
156   case UD_R_RBX:
157   case UD_R_EBX:
158     setreg = REG_RBX;
159     break;
160   case UD_R_RSP:
161   case UD_R_ESP:
162     setreg = REG_RSP;
163     break;
164   case UD_R_RBP:
165   case UD_R_EBP:
166     setreg = REG_RBP;
167     break;
168   case UD_R_RSI:
169   case UD_R_ESI:
170     setreg = REG_RSI;
171     break;
172   case UD_R_RDI:
173   case UD_R_EDI:
174     setreg = REG_RDI;
175     break;
176   case UD_R_R8:
177   case UD_R_R8D:
178     setreg = REG_R8;
179     break;
180   case UD_R_R9:
181   case UD_R_R9D:
182     setreg = REG_R9;
183     break;
184   case UD_R_R10:
185   case UD_R_R10D:
186     setreg = REG_R10;
187     break;
188   case UD_R_R11:
189   case UD_R_R11D:
190     setreg = REG_R11;
191     break;
192   case UD_R_R12:
193   case UD_R_R12D:
194     setreg = REG_R12;
195     break;
196   case UD_R_R13:
197   case UD_R_R13D:
198     setreg = REG_R13;
199     break;
200   case UD_R_R14:
201   case UD_R_R14D:
202     setreg = REG_R14;
203     break;
204   case UD_R_R15:
205   case UD_R_R15D:
206     setreg = REG_R15;
207     break;
208   default:
209     printf("Register not supported!\n");
210     exit(-1);
211   }
212
213   intptr_t address = uc->uc_mcontext.gregs[setreg];
214
215   if (!bpt_has_key(pointer_tree, address)) {
216     printf("Address not found in Patricia tree.\n");
217     exit(-1);
218   }
219
220   tree_entry *te = (tree_entry*) bpt_get(pointer_tree, address);
221   void* newAddress = (te->function)(te->argument);
222   *(te->dereferencedPointer) = newAddress;
223
224   /* set the register - as before */
225   uc->uc_mcontext.gregs[setreg] = (greg_t) newAddress;
226 }
227
228 inline void initializeSignalHandler () {
229   struct sigaction q;
230   bzero(&q, sizeof(q));
231   q.sa_sigaction = handle_segv;
232   q.sa_flags = SA_SIGINFO;
233   sigaction(11, &q, NULL);
234 }
235
236 void *calculateLazy24 (void* bla) {
237   int* ret = (int*) slice_alloc (sizeof(int));
238   *ret = 42;
239   return (void*) ret;
240 }
241
242 int main (void) {
243   initializePointerTree ();
244   initializeSignalHandler ();
245   void *** lazy42 = lazy_alloc(calculateLazy24, NULL);
246   printf("%d\n", **((int**)lazy42));
247
248 }