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