1 /*
2 * Stack-less Just-In-Time compiler
3 *
4 * Copyright Zoltan Herczeg ([email protected]). All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without modification, are
7 * permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice, this list of
10 * conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 * of conditions and the following disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
sljit_jump_has_label(struct sljit_jump * jump)27 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_label(struct sljit_jump *jump)
28 {
29 return !(jump->flags & JUMP_ADDR) && (jump->u.label != NULL);
30 }
31
sljit_jump_has_target(struct sljit_jump * jump)32 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_target(struct sljit_jump *jump)
33 {
34 return (jump->flags & JUMP_ADDR) != 0;
35 }
36
sljit_jump_is_mov_addr(struct sljit_jump * jump)37 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_is_mov_addr(struct sljit_jump *jump)
38 {
39 return (jump->flags & JUMP_MOV_ADDR) != 0;
40 }
41
42 #define SLJIT_SERIALIZE_DEBUG ((sljit_u16)0x1)
43
44 struct sljit_serialized_compiler {
45 sljit_u32 signature;
46 sljit_u16 version;
47 sljit_u16 cpu_type;
48
49 sljit_uw buf_segment_count;
50 sljit_uw label_count;
51 sljit_uw jump_count;
52 sljit_uw const_count;
53
54 sljit_s32 options;
55 sljit_s32 scratches;
56 sljit_s32 saveds;
57 sljit_s32 fscratches;
58 sljit_s32 fsaveds;
59 sljit_s32 local_size;
60 sljit_uw size;
61
62 #if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
63 sljit_s32 status_flags_state;
64 #endif /* SLJIT_HAS_STATUS_FLAGS_STATE */
65
66 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
67 sljit_s32 args_size;
68 #endif /* SLJIT_CONFIG_X86_32 */
69
70 #if ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \
71 || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
72 sljit_uw args_size;
73 #endif /* (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */
74
75 #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
76 sljit_uw cpool_diff;
77 sljit_uw cpool_fill;
78 sljit_uw patches;
79 #endif /* SLJIT_CONFIG_ARM_V6 */
80
81 #if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
82 sljit_s32 delay_slot;
83 #endif /* SLJIT_CONFIG_MIPS */
84
85 };
86
87 struct sljit_serialized_debug_info {
88 sljit_sw last_flags;
89 sljit_s32 last_return;
90 sljit_s32 logical_local_size;
91 };
92
93 struct sljit_serialized_label {
94 sljit_uw size;
95 };
96
97 struct sljit_serialized_jump {
98 sljit_uw addr;
99 sljit_uw flags;
100 sljit_uw value;
101 };
102
103 struct sljit_serialized_const {
104 sljit_uw addr;
105 };
106
107 #define SLJIT_SERIALIZE_ALIGN(v) (((v) + sizeof(sljit_uw) - 1) & ~(sljit_uw)(sizeof(sljit_uw) - 1))
108 #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
109 #define SLJIT_SERIALIZE_SIGNATURE 0x534c4a54
110 #else /* !SLJIT_LITTLE_ENDIAN */
111 #define SLJIT_SERIALIZE_SIGNATURE 0x544a4c53
112 #endif /* SLJIT_LITTLE_ENDIAN */
113 #define SLJIT_SERIALIZE_VERSION 1
114
sljit_serialize_compiler(struct sljit_compiler * compiler,sljit_s32 options,sljit_uw * size)115 SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compiler *compiler,
116 sljit_s32 options, sljit_uw *size)
117 {
118 sljit_uw serialized_size = sizeof(struct sljit_serialized_compiler);
119 struct sljit_memory_fragment *buf;
120 struct sljit_label *label;
121 struct sljit_jump *jump;
122 struct sljit_const *const_;
123 struct sljit_serialized_compiler *serialized_compiler;
124 struct sljit_serialized_label *serialized_label;
125 struct sljit_serialized_jump *serialized_jump;
126 struct sljit_serialized_const *serialized_const;
127 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
128 || (defined SLJIT_DEBUG && SLJIT_DEBUG)
129 struct sljit_serialized_debug_info *serialized_debug_info;
130 #endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
131 sljit_uw counter, used_size;
132 sljit_u8 *result;
133 sljit_u8 *ptr;
134 SLJIT_UNUSED_ARG(options);
135
136 if (size != NULL)
137 *size = 0;
138
139 PTR_FAIL_IF(compiler->error);
140
141 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
142 || (defined SLJIT_DEBUG && SLJIT_DEBUG)
143 if (!(options & SLJIT_SERIALIZE_IGNORE_DEBUG))
144 serialized_size += sizeof(struct sljit_serialized_debug_info);
145 #endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
146
147 #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
148 serialized_size += SLJIT_SERIALIZE_ALIGN(compiler->cpool_fill * (sizeof(sljit_uw) + 1));
149 #endif /* SLJIT_CONFIG_ARM_V6 */
150
151 /* Compute the size of the data. */
152 buf = compiler->buf;
153 while (buf != NULL) {
154 serialized_size += sizeof(sljit_uw) + SLJIT_SERIALIZE_ALIGN(buf->used_size);
155 buf = buf->next;
156 }
157
158 serialized_size += compiler->label_count * sizeof(struct sljit_serialized_label);
159
160 jump = compiler->jumps;
161 while (jump != NULL) {
162 serialized_size += sizeof(struct sljit_serialized_jump);
163 jump = jump->next;
164 }
165
166 const_ = compiler->consts;
167 while (const_ != NULL) {
168 serialized_size += sizeof(struct sljit_serialized_const);
169 const_ = const_->next;
170 }
171
172 result = (sljit_u8*)SLJIT_MALLOC(serialized_size, compiler->allocator_data);
173 PTR_FAIL_IF_NULL(result);
174
175 if (size != NULL)
176 *size = serialized_size;
177
178 ptr = result;
179 serialized_compiler = (struct sljit_serialized_compiler*)ptr;
180 ptr += sizeof(struct sljit_serialized_compiler);
181
182 serialized_compiler->signature = SLJIT_SERIALIZE_SIGNATURE;
183 serialized_compiler->version = SLJIT_SERIALIZE_VERSION;
184 serialized_compiler->cpu_type = 0;
185 serialized_compiler->label_count = compiler->label_count;
186 serialized_compiler->options = compiler->options;
187 serialized_compiler->scratches = compiler->scratches;
188 serialized_compiler->saveds = compiler->saveds;
189 serialized_compiler->fscratches = compiler->fscratches;
190 serialized_compiler->fsaveds = compiler->fsaveds;
191 serialized_compiler->local_size = compiler->local_size;
192 serialized_compiler->size = compiler->size;
193
194 #if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
195 serialized_compiler->status_flags_state = compiler->status_flags_state;
196 #endif /* SLJIT_HAS_STATUS_FLAGS_STATE */
197
198 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
199 || ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \
200 || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
201 serialized_compiler->args_size = compiler->args_size;
202 #endif /* SLJIT_CONFIG_X86_32 || (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */
203
204 #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
205 serialized_compiler->cpool_diff = compiler->cpool_diff;
206 serialized_compiler->cpool_fill = compiler->cpool_fill;
207 serialized_compiler->patches = compiler->patches;
208
209 SLJIT_MEMCPY(ptr, compiler->cpool, compiler->cpool_fill * sizeof(sljit_uw));
210 SLJIT_MEMCPY(ptr + compiler->cpool_fill * sizeof(sljit_uw), compiler->cpool_unique, compiler->cpool_fill);
211 ptr += SLJIT_SERIALIZE_ALIGN(compiler->cpool_fill * (sizeof(sljit_uw) + 1));
212 #endif /* SLJIT_CONFIG_ARM_V6 */
213
214 #if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
215 serialized_compiler->delay_slot = compiler->delay_slot;
216 #endif /* SLJIT_CONFIG_MIPS */
217
218 buf = compiler->buf;
219 counter = 0;
220 while (buf != NULL) {
221 used_size = buf->used_size;
222 *(sljit_uw*)ptr = used_size;
223 ptr += sizeof(sljit_uw);
224 SLJIT_MEMCPY(ptr, buf->memory, used_size);
225 ptr += SLJIT_SERIALIZE_ALIGN(used_size);
226 buf = buf->next;
227 counter++;
228 }
229 serialized_compiler->buf_segment_count = counter;
230
231 label = compiler->labels;
232 while (label != NULL) {
233 serialized_label = (struct sljit_serialized_label*)ptr;
234 serialized_label->size = label->size;
235 ptr += sizeof(struct sljit_serialized_label);
236 label = label->next;
237 }
238
239 jump = compiler->jumps;
240 counter = 0;
241 while (jump != NULL) {
242 serialized_jump = (struct sljit_serialized_jump*)ptr;
243 serialized_jump->addr = jump->addr;
244 serialized_jump->flags = jump->flags;
245
246 if (jump->flags & JUMP_ADDR)
247 serialized_jump->value = jump->u.target;
248 else if (jump->u.label != NULL)
249 serialized_jump->value = jump->u.label->u.index;
250 else
251 serialized_jump->value = SLJIT_MAX_ADDRESS;
252
253 ptr += sizeof(struct sljit_serialized_jump);
254 jump = jump->next;
255 counter++;
256 }
257 serialized_compiler->jump_count = counter;
258
259 const_ = compiler->consts;
260 counter = 0;
261 while (const_ != NULL) {
262 serialized_const = (struct sljit_serialized_const*)ptr;
263 serialized_const->addr = const_->addr;
264 ptr += sizeof(struct sljit_serialized_const);
265 const_ = const_->next;
266 counter++;
267 }
268 serialized_compiler->const_count = counter;
269
270 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
271 || (defined SLJIT_DEBUG && SLJIT_DEBUG)
272 if (!(options & SLJIT_SERIALIZE_IGNORE_DEBUG)) {
273 serialized_debug_info = (struct sljit_serialized_debug_info*)ptr;
274 serialized_debug_info->last_flags = compiler->last_flags;
275 serialized_debug_info->last_return = compiler->last_return;
276 serialized_debug_info->logical_local_size = compiler->logical_local_size;
277 serialized_compiler->cpu_type |= SLJIT_SERIALIZE_DEBUG;
278 #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
279 ptr += sizeof(struct sljit_serialized_debug_info);
280 #endif /* SLJIT_DEBUG */
281 }
282 #endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
283
284 SLJIT_ASSERT((sljit_uw)(ptr - result) == serialized_size);
285 return (sljit_uw*)result;
286 }
287
sljit_deserialize_compiler(sljit_uw * buffer,sljit_uw size,sljit_s32 options,void * allocator_data)288 SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit_uw* buffer, sljit_uw size,
289 sljit_s32 options, void *allocator_data)
290 {
291 struct sljit_compiler *compiler;
292 struct sljit_serialized_compiler *serialized_compiler;
293 struct sljit_serialized_label *serialized_label;
294 struct sljit_serialized_jump *serialized_jump;
295 struct sljit_serialized_const *serialized_const;
296 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
297 || (defined SLJIT_DEBUG && SLJIT_DEBUG)
298 struct sljit_serialized_debug_info *serialized_debug_info;
299 #endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
300 struct sljit_memory_fragment *buf;
301 struct sljit_memory_fragment *last_buf;
302 struct sljit_label *label;
303 struct sljit_label *last_label;
304 struct sljit_label **label_list = NULL;
305 struct sljit_jump *jump;
306 struct sljit_jump *last_jump;
307 struct sljit_const *const_;
308 struct sljit_const *last_const;
309 sljit_u8 *ptr = (sljit_u8*)buffer;
310 sljit_u8 *end = ptr + size;
311 sljit_uw i, used_size, aligned_size, label_count;
312 SLJIT_UNUSED_ARG(options);
313
314 if (size < sizeof(struct sljit_serialized_compiler) || (size & (sizeof(sljit_uw) - 1)) != 0)
315 return NULL;
316
317 serialized_compiler = (struct sljit_serialized_compiler*)ptr;
318
319 if (serialized_compiler->signature != SLJIT_SERIALIZE_SIGNATURE || serialized_compiler->version != SLJIT_SERIALIZE_VERSION)
320 return NULL;
321
322 compiler = sljit_create_compiler(allocator_data);
323 PTR_FAIL_IF(compiler == NULL);
324
325 compiler->label_count = serialized_compiler->label_count;
326 compiler->options = serialized_compiler->options;
327 compiler->scratches = serialized_compiler->scratches;
328 compiler->saveds = serialized_compiler->saveds;
329 compiler->fscratches = serialized_compiler->fscratches;
330 compiler->fsaveds = serialized_compiler->fsaveds;
331 compiler->local_size = serialized_compiler->local_size;
332 compiler->size = serialized_compiler->size;
333
334 #if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
335 compiler->status_flags_state = serialized_compiler->status_flags_state;
336 #endif /* SLJIT_HAS_STATUS_FLAGS_STATE */
337
338 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
339 || ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \
340 || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
341 compiler->args_size = serialized_compiler->args_size;
342 #endif /* SLJIT_CONFIG_X86_32 || (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */
343
344 #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
345 used_size = serialized_compiler->cpool_fill;
346 aligned_size = SLJIT_SERIALIZE_ALIGN(used_size * (sizeof(sljit_uw) + 1));
347 compiler->cpool_diff = serialized_compiler->cpool_diff;
348 compiler->cpool_fill = used_size;
349 compiler->patches = serialized_compiler->patches;
350
351 if ((sljit_uw)(end - ptr) < aligned_size)
352 goto error;
353
354 SLJIT_MEMCPY(compiler->cpool, ptr, used_size * sizeof(sljit_uw));
355 SLJIT_MEMCPY(compiler->cpool_unique, ptr + used_size * sizeof(sljit_uw), used_size);
356 ptr += aligned_size;
357 #endif /* SLJIT_CONFIG_ARM_V6 */
358
359 #if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
360 compiler->delay_slot = serialized_compiler->delay_slot;
361 #endif /* SLJIT_CONFIG_MIPS */
362
363 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
364 || (defined SLJIT_DEBUG && SLJIT_DEBUG)
365 if (!(serialized_compiler->cpu_type & SLJIT_SERIALIZE_DEBUG))
366 goto error;
367 #endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
368
369 ptr += sizeof(struct sljit_serialized_compiler);
370 i = serialized_compiler->buf_segment_count;
371 last_buf = NULL;
372 while (i > 0) {
373 if ((sljit_uw)(end - ptr) < sizeof(sljit_uw))
374 goto error;
375
376 used_size = *(sljit_uw*)ptr;
377 aligned_size = SLJIT_SERIALIZE_ALIGN(used_size);
378 ptr += sizeof(sljit_uw);
379
380 if ((sljit_uw)(end - ptr) < aligned_size)
381 goto error;
382
383 if (last_buf == NULL) {
384 SLJIT_ASSERT(compiler->buf != NULL && compiler->buf->next == NULL);
385 buf = compiler->buf;
386 } else {
387 buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data);
388 if (!buf)
389 goto error;
390 buf->next = NULL;
391 }
392
393 buf->used_size = used_size;
394 SLJIT_MEMCPY(buf->memory, ptr, used_size);
395
396 if (last_buf != NULL)
397 last_buf->next = buf;
398 last_buf = buf;
399
400 ptr += aligned_size;
401 i--;
402 }
403
404 last_label = NULL;
405 label_count = serialized_compiler->label_count;
406 if ((sljit_uw)(end - ptr) < label_count * sizeof(struct sljit_serialized_label))
407 goto error;
408
409 label_list = (struct sljit_label **)SLJIT_MALLOC(label_count * sizeof(struct sljit_label*), allocator_data);
410 if (label_list == NULL)
411 goto error;
412
413 for (i = 0; i < label_count; i++) {
414 label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
415 if (label == NULL)
416 goto error;
417
418 serialized_label = (struct sljit_serialized_label*)ptr;
419 label->next = NULL;
420 label->u.index = i;
421 label->size = serialized_label->size;
422
423 if (last_label != NULL)
424 last_label->next = label;
425 else
426 compiler->labels = label;
427 last_label = label;
428
429 label_list[i] = label;
430 ptr += sizeof(struct sljit_serialized_label);
431 }
432 compiler->last_label = last_label;
433
434 last_jump = NULL;
435 i = serialized_compiler->jump_count;
436 if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_jump))
437 goto error;
438
439 while (i > 0) {
440 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
441 if (jump == NULL)
442 goto error;
443
444 serialized_jump = (struct sljit_serialized_jump*)ptr;
445 jump->next = NULL;
446 jump->addr = serialized_jump->addr;
447 jump->flags = serialized_jump->flags;
448
449 if (!(serialized_jump->flags & JUMP_ADDR)) {
450 if (serialized_jump->value != SLJIT_MAX_ADDRESS) {
451 if (serialized_jump->value >= label_count)
452 goto error;
453 jump->u.label = label_list[serialized_jump->value];
454 } else
455 jump->u.label = NULL;
456 } else
457 jump->u.target = serialized_jump->value;
458
459 if (last_jump != NULL)
460 last_jump->next = jump;
461 else
462 compiler->jumps = jump;
463 last_jump = jump;
464
465 ptr += sizeof(struct sljit_serialized_jump);
466 i--;
467 }
468 compiler->last_jump = last_jump;
469
470 SLJIT_FREE(label_list, allocator_data);
471 label_list = NULL;
472
473 last_const = NULL;
474 i = serialized_compiler->const_count;
475 if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_const))
476 goto error;
477
478 while (i > 0) {
479 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
480 if (const_ == NULL)
481 goto error;
482
483 serialized_const = (struct sljit_serialized_const*)ptr;
484 const_->next = NULL;
485 const_->addr = serialized_const->addr;
486
487 if (last_const != NULL)
488 last_const->next = const_;
489 else
490 compiler->consts = const_;
491 last_const = const_;
492
493 ptr += sizeof(struct sljit_serialized_const);
494 i--;
495 }
496 compiler->last_const = last_const;
497
498 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
499 || (defined SLJIT_DEBUG && SLJIT_DEBUG)
500 if ((sljit_uw)(end - ptr) < sizeof(struct sljit_serialized_debug_info))
501 goto error;
502
503 serialized_debug_info = (struct sljit_serialized_debug_info*)ptr;
504 compiler->last_flags = (sljit_s32)serialized_debug_info->last_flags;
505 compiler->last_return = serialized_debug_info->last_return;
506 compiler->logical_local_size = serialized_debug_info->logical_local_size;
507 #endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
508
509 return compiler;
510
511 error:
512 sljit_free_compiler(compiler);
513 if (label_list != NULL)
514 SLJIT_FREE(label_list, allocator_data);
515 return NULL;
516 }
517