• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ucode/program.c

  1 /*
  2  * Copyright (C) 2022 Jo-Philipp Wich <jo@mein.io>
  3  *
  4  * Permission to use, copy, modify, and/or distribute this software for any
  5  * purpose with or without fee is hereby granted, provided that the above
  6  * copyright notice and this permission notice appear in all copies.
  7  *
  8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 15  */
 16 
 17 #include <assert.h>
 18 #include <errno.h>
 19 #include <endian.h>
 20 
 21 #include "ucode/program.h"
 22 #include "ucode/source.h"
 23 #include "ucode/vallist.h"
 24 #include "ucode/chunk.h"
 25 
 26 
 27 uc_program_t *
 28 uc_program_new(uc_source_t *source)
 29 {
 30         uc_program_t *prog;
 31 
 32         prog = xalloc(sizeof(*prog));
 33 
 34         prog->header.type = UC_PROGRAM;
 35         prog->header.refcount = 1;
 36 
 37         prog->functions.next = &prog->functions;
 38         prog->functions.prev = &prog->functions;
 39 
 40         prog->source = uc_source_get(source);
 41 
 42         uc_vallist_init(&prog->constants);
 43 
 44         return prog;
 45 }
 46 
 47 uc_function_t *
 48 uc_program_function_new(uc_program_t *prog, const char *name, size_t srcpos)
 49 {
 50         uc_function_t *func;
 51         size_t namelen = 0;
 52 
 53         if (name)
 54                 namelen = strlen(name);
 55 
 56         func = xalloc(sizeof(*func) + namelen + 1);
 57 
 58         if (name)
 59                 strcpy(func->name, name);
 60 
 61         func->nargs = 0;
 62         func->nupvals = 0;
 63         func->srcpos = srcpos;
 64         func->program = prog;
 65         func->vararg = false;
 66 
 67         uc_chunk_init(&func->chunk);
 68         ucv_ref(&prog->functions, &func->progref);
 69 
 70         return func;
 71 }
 72 
 73 size_t
 74 uc_program_function_id(uc_program_t *prog, uc_function_t *func)
 75 {
 76         size_t i = 1;
 77 
 78         uc_program_function_foreach(prog, fn) {
 79                 if (fn == func)
 80                         return i;
 81 
 82                 i++;
 83         }
 84 
 85         return 0;
 86 }
 87 
 88 uc_function_t *
 89 uc_program_function_load(uc_program_t *prog, size_t id)
 90 {
 91         size_t i = 1;
 92 
 93         uc_program_function_foreach(prog, fn)
 94                 if (i++ == id)
 95                         return fn;
 96 
 97         return NULL;
 98 }
 99 
100 size_t
101 uc_program_function_srcpos(uc_function_t *fn, size_t off)
102 {
103         size_t pos;
104 
105         if (!fn)
106                 return 0;
107 
108         pos = uc_chunk_debug_get_srcpos(&fn->chunk, off);
109 
110         return pos ? fn->srcpos + pos : 0;
111 }
112 
113 void
114 uc_program_function_free(uc_function_t *func)
115 {
116         if (!func)
117                 return;
118 
119         ucv_unref(&func->progref);
120         uc_chunk_free(&func->chunk);
121         free(func);
122 }
123 
124 uc_value_t *
125 uc_program_get_constant(uc_program_t *prog, size_t idx)
126 {
127         return uc_vallist_get(&prog->constants, idx);
128 }
129 
130 ssize_t
131 uc_program_add_constant(uc_program_t *prog, uc_value_t *val)
132 {
133         return uc_vallist_add(&prog->constants, val);
134 }
135 
136 static void
137 write_u16(size_t value, FILE *file)
138 {
139         uint16_t n;
140 
141         if (sizeof(value) > sizeof(n))
142                 assert(value <= UINT16_MAX);
143 
144         n = htobe16((uint16_t)value);
145 
146         fwrite(&n, 1, sizeof(n), file);
147 }
148 
149 static void
150 write_u32(size_t value, FILE *file)
151 {
152         uint32_t n;
153 
154         if (sizeof(value) > sizeof(n))
155                 assert(value <= UINT32_MAX);
156 
157         n = htobe32((uint32_t)value);
158 
159         fwrite(&n, 1, sizeof(n), file);
160 }
161 
162 static void
163 write_u64(uint64_t value, FILE *file)
164 {
165         uint64_t n;
166 
167         if (sizeof(value) > sizeof(n))
168                 assert(value <= UINT64_MAX);
169 
170         n = htobe64((uint64_t)value);
171 
172         fwrite(&n, 1, sizeof(n), file);
173 }
174 
175 static void
176 _write_vector(size_t count, size_t itemsize, void *data, FILE *file)
177 {
178         size_t pad = (~(count * itemsize) + 1) & (sizeof(uint32_t) - 1);
179         char z[sizeof(uint32_t) - 1] = { 0 };
180 
181         write_u32(count, file);
182         fwrite(data, itemsize, count, file);
183         fwrite(z, 1, pad, file);
184 }
185 
186 #define write_vector(vec, file) \
187         _write_vector((vec)->count, sizeof((vec)->entries[0]), (vec)->entries, file)
188 
189 #define write_string(str, file) \
190         _write_vector(strlen(str) + 1, 1, str, file)
191 
192 static void
193 write_vallist(uc_value_list_t *vallist, FILE *file)
194 {
195         size_t i;
196 
197         /* write index */
198         write_u32(vallist->isize, file);
199 
200         for (i = 0; i < vallist->isize; i++)
201                 write_u64(vallist->index[i], file);
202 
203         /* write data */
204         write_u32(vallist->dsize, file);
205         fwrite(vallist->data, 1, vallist->dsize, file);
206 }
207 
208 enum {
209         UC_PROGRAM_F_DEBUG      = (1 << 0),
210         UC_PROGRAM_F_SOURCEINFO = (1 << 1),
211         UC_PROGRAM_F_SOURCEBUF  = (1 << 2),
212 };
213 
214 enum {
215         UC_FUNCTION_F_IS_ARROW       = (1 << 0),
216         UC_FUNCTION_F_IS_VARARG      = (1 << 1),
217         UC_FUNCTION_F_IS_STRICT      = (1 << 2),
218         UC_FUNCTION_F_HAS_EXCEPTIONS = (1 << 3),
219         UC_FUNCTION_F_HAS_NAME       = (1 << 4),
220         UC_FUNCTION_F_HAS_VARDBG     = (1 << 5),
221         UC_FUNCTION_F_HAS_OFFSETDBG  = (1 << 6),
222 };
223 
224 static void
225 write_chunk(uc_chunk_t *chunk, FILE *file, uint32_t flags)
226 {
227         size_t i;
228 
229         /* write bytecode data */
230         write_vector(chunk, file);
231 
232         /* write exception ranges */
233         if (flags & UC_FUNCTION_F_HAS_EXCEPTIONS) {
234                 write_u32(chunk->ehranges.count, file);
235 
236                 for (i = 0; i < chunk->ehranges.count; i++) {
237                         write_u32(chunk->ehranges.entries[i].from,   file);
238                         write_u32(chunk->ehranges.entries[i].to,     file);
239                         write_u32(chunk->ehranges.entries[i].target, file);
240                         write_u32(chunk->ehranges.entries[i].slot,   file);
241                 }
242         }
243 
244         /* write variable info */
245         if (flags & UC_FUNCTION_F_HAS_VARDBG) {
246                 write_u32(chunk->debuginfo.variables.count, file);
247 
248                 for (i = 0; i < chunk->debuginfo.variables.count; i++) {
249                         write_u32(chunk->debuginfo.variables.entries[i].from,    file);
250                         write_u32(chunk->debuginfo.variables.entries[i].to,      file);
251                         write_u32(chunk->debuginfo.variables.entries[i].slot,    file);
252                         write_u32(chunk->debuginfo.variables.entries[i].nameidx, file);
253                 }
254 
255                 write_vallist(&chunk->debuginfo.varnames, file);
256         }
257 
258         /* write offset info */
259         if (flags & UC_FUNCTION_F_HAS_OFFSETDBG)
260                 write_vector(&chunk->debuginfo.offsets, file);
261 }
262 
263 static void
264 write_function(uc_function_t *func, FILE *file, bool debug)
265 {
266         uint32_t flags = 0;
267 
268         if (func->arrow)
269                 flags |= UC_FUNCTION_F_IS_ARROW;
270 
271         if (func->vararg)
272                 flags |= UC_FUNCTION_F_IS_VARARG;
273 
274         if (func->strict)
275                 flags |= UC_FUNCTION_F_IS_STRICT;
276 
277         if (func->chunk.ehranges.count)
278                 flags |= UC_FUNCTION_F_HAS_EXCEPTIONS;
279 
280         if (debug && func->name[0])
281                 flags |= UC_FUNCTION_F_HAS_NAME;
282 
283         if (debug && func->chunk.debuginfo.variables.count)
284                 flags |= UC_FUNCTION_F_HAS_VARDBG;
285 
286         if (debug && func->chunk.debuginfo.offsets.count)
287                 flags |= UC_FUNCTION_F_HAS_OFFSETDBG;
288 
289         write_u32(flags, file);
290 
291         if (flags & UC_FUNCTION_F_HAS_NAME)
292                 write_string(func->name, file);
293 
294         write_u16(func->nargs, file);
295         write_u16(func->nupvals, file);
296         write_u32(func->srcpos, file);
297 
298         write_chunk(&func->chunk, file, flags);
299 }
300 
301 void
302 uc_program_write(uc_program_t *prog, FILE *file, bool debug)
303 {
304         uint32_t flags = 0;
305         size_t i = 0;
306 
307         if (debug)
308                 flags |= UC_PROGRAM_F_DEBUG;
309 
310         if (debug && prog->source) {
311                 flags |= UC_PROGRAM_F_SOURCEINFO;
312 
313                 if (prog->source->buffer)
314                         flags |= UC_PROGRAM_F_SOURCEBUF;
315         }
316 
317         /* magic word + flags */
318         write_u32(UC_PRECOMPILED_BYTECODE_MAGIC, file);
319         write_u32(flags, file);
320 
321         if (flags & UC_PROGRAM_F_SOURCEINFO) {
322                 /* write source file name */
323                 write_string(prog->source->filename, file);
324 
325                 /* include source buffer if program was compiled from stdin */
326                 if (flags & UC_PROGRAM_F_SOURCEBUF)
327                         write_string(prog->source->buffer, file);
328 
329                 /* write lineinfo data */
330                 write_vector(&prog->source->lineinfo, file);
331         }
332 
333         /* write constants */
334         write_vallist(&prog->constants, file);
335 
336         /* write program sections */
337         uc_program_function_foreach(prog, fn1) {
338                 (void)fn1;
339                 i++;
340         }
341 
342         write_u32(i, file);
343 
344         uc_program_function_foreach(prog, fn2)
345                 write_function(fn2, file, debug);
346 }
347 
348 static bool
349 read_error(FILE *file, char **errp, const char *subject, size_t rlen, size_t len)
350 {
351         const char *reason;
352 
353         if (feof(file))
354                 reason = "Premature EOF";
355         else
356                 reason = strerror(errno);
357 
358         if (errp)
359                 xasprintf(errp,
360                           "%s while reading %s at offset %ld, got %zu of %zu bytes\n",
361                           reason, subject, ftell(file) - rlen, rlen, len);
362 
363         return false;
364 }
365 
366 static bool
367 skip_padding(FILE *file, size_t len, char **errp)
368 {
369         size_t pad = (~len + 1) & (sizeof(uint32_t) - 1), rlen;
370         char buf[sizeof(uint32_t) - 1];
371 
372         if (pad != 0) {
373                 rlen = fread(buf, 1, pad, file);
374 
375                 if (rlen != pad)
376                         return read_error(file, errp, "padding", rlen, pad);
377         }
378 
379         return true;
380 }
381 
382 static bool
383 read_u32(FILE *file, uint32_t *n, const char *subj, char **errp)
384 {
385         size_t rlen = fread(n, 1, sizeof(*n), file);
386 
387         if (rlen != sizeof(*n)) {
388                 *n = 0;
389 
390                 return read_error(file, errp, subj ? subj : "uint32_t", rlen, sizeof(*n));
391         }
392 
393         *n = be32toh(*n);
394 
395         return true;
396 }
397 
398 static bool
399 read_u64(FILE *file, uint64_t *n, const char *subj, char **errp)
400 {
401         size_t rlen = fread(n, 1, sizeof(*n), file);
402 
403         if (rlen != sizeof(*n)) {
404                 *n = 0;
405 
406                 return read_error(file, errp, subj ? subj : "uint64_t", rlen, sizeof(*n));
407         }
408 
409         *n = be64toh(*n);
410 
411         return true;
412 }
413 
414 static bool
415 read_size_t(FILE *file, size_t *n, size_t size, const char *subj, char **errp)
416 {
417         union { uint8_t u8; uint16_t u16; uint32_t u32; uint64_t u64; } nval;
418         size_t rlen;
419 
420         rlen = fread(&nval.u64, 1, size, file);
421 
422         if (rlen != size) {
423                 *n = 0;
424 
425                 if (!subj) {
426                         switch (size) {
427                         case 1: subj = "uint8_t";  break;
428                         case 2: subj = "uint16_t"; break;
429                         case 4: subj = "uint32_t"; break;
430                         case 8: subj = "uint64_t"; break;
431                         }
432                 }
433 
434                 return read_error(file, errp, subj, rlen, sizeof(nval));
435         }
436 
437         switch (size) {
438         case 1: *n = (size_t)        nval.u8;   break;
439         case 2: *n = (size_t)be16toh(nval.u16); break;
440         case 4: *n = (size_t)be32toh(nval.u32); break;
441         case 8: *n = (size_t)be64toh(nval.u64); break;
442         }
443 
444         return true;
445 }
446 
447 static bool
448 _read_vector(FILE *file, void *ptr, size_t itemsize, const char *subj, char **errp)
449 {
450         struct { size_t count; void *data; } *vec = ptr;
451         size_t rlen, len;
452         char subjbuf[64];
453 
454         snprintf(subjbuf, sizeof(subjbuf), "%s vector size", subj);
455 
456         if (!read_size_t(file, &vec->count, sizeof(uint32_t), subjbuf, errp))
457                 return false;
458 
459         vec->data = xcalloc(vec->count, itemsize);
460 
461         len = vec->count;
462         rlen = fread(vec->data, itemsize, len, file);
463 
464         if (rlen != len) {
465                 free(vec->data);
466 
467                 vec->count = 0;
468                 vec->data = NULL;
469 
470                 snprintf(subjbuf, sizeof(subjbuf), "%s vector data", subj);
471 
472                 return read_error(file, errp, subjbuf, rlen * itemsize, len * itemsize);
473         }
474 
475         return skip_padding(file, vec->count * itemsize, errp);
476 }
477 
478 #define read_vector(file, vec, subj, errp) \
479         _read_vector(file, vec, sizeof((vec)->entries[0]), subj, errp)
480 
481 static bool
482 read_string(FILE *file, char *dst, size_t len, const char *subj, char **errp)
483 {
484         size_t rlen;
485 
486         rlen = fread(dst, 1, len, file);
487 
488         if (rlen != len)
489                 return read_error(file, errp, subj, rlen, len);
490 
491         return skip_padding(file, len, errp);
492 }
493 
494 static bool
495 read_vallist(FILE *file, uc_value_list_t *vallist, const char *subj, char **errp)
496 {
497         char subjbuf[64];
498         size_t i;
499 
500         /* read index */
501         snprintf(subjbuf, sizeof(subjbuf), "%s index size", subj);
502 
503         if (!read_size_t(file, &vallist->isize, sizeof(uint32_t), subjbuf, errp))
504                 goto out;
505 
506         vallist->index = xcalloc(sizeof(vallist->index[0]), vallist->isize);
507 
508         for (i = 0; i < vallist->isize; i++) {
509                 snprintf(subjbuf, sizeof(subjbuf), "%s index entry %zu of %zu", subj, i, vallist->isize);
510 
511                 if (!read_u64(file, &vallist->index[i], subjbuf, errp))
512                         goto out;
513         }
514 
515         /* read data */
516         snprintf(subjbuf, sizeof(subjbuf), "%s data size", subj);
517 
518         if (!read_size_t(file, &vallist->dsize, sizeof(uint32_t), subjbuf, errp))
519                 goto out;
520 
521         vallist->data = xalloc(vallist->dsize);
522 
523         snprintf(subjbuf, sizeof(subjbuf), "%s data", subj);
524 
525         if (!read_string(file, vallist->data, vallist->dsize, subj, errp))
526                 goto out;
527 
528         return true;
529 
530 out:
531         free(vallist->index);
532         free(vallist->data);
533 
534         vallist->isize = 0;
535         vallist->index = NULL;
536 
537         vallist->dsize = 0;
538         vallist->data = NULL;
539 
540         return false;
541 }
542 
543 static uc_source_t *
544 read_sourceinfo(uc_source_t *input, uint32_t flags, char **errp)
545 {
546         char *path = NULL, *code = NULL;
547         uc_source_t *source = NULL;
548         size_t len;
549 
550         if (flags & UC_PROGRAM_F_SOURCEINFO) {
551                 if (!read_size_t(input->fp, &len, sizeof(uint32_t), "sourceinfo filename length", errp))
552                         goto out;
553 
554                 path = xalloc(len);
555 
556                 if (!read_string(input->fp, path, len, "sourceinfo filename", errp))
557                         goto out;
558 
559                 if (flags & UC_PROGRAM_F_SOURCEBUF) {
560                         if (!read_size_t(input->fp, &len, sizeof(uint32_t), "sourceinfo code buffer length", errp))
561                                 goto out;
562 
563                         code = xalloc(len);
564 
565                         if (!read_string(input->fp, code, len, "sourceinfo code buffer data", errp)) {
566                                 free(code);
567                                 goto out;
568                         }
569 
570                         source = uc_source_new_buffer(path, code, len);
571                 }
572                 else {
573                         source = uc_source_new_file(path);
574 
575                         if (!source) {
576                                 fprintf(stderr, "Unable to open source file %s: %s\n", path, strerror(errno));
577                                 source = uc_source_new_buffer(path, xstrdup(""), 0);
578                         }
579                 }
580 
581                 if (!read_vector(input->fp, &source->lineinfo, "sourceinfo lineinfo", errp)) {
582                         uc_source_put(source);
583                         source = NULL;
584                         goto out;
585                 }
586         }
587         else {
588                 source = uc_source_new_buffer("[no source]", xstrdup(""), 0);
589         }
590 
591         uc_source_runpath_set(source, input->runpath);
592 
593 out:
594         free(path);
595 
596         return source;
597 }
598 
599 static bool
600 read_chunk(FILE *file, uc_chunk_t *chunk, uint32_t flags, const char *subj, char **errp)
601 {
602         uc_varrange_t *varrange;
603         uc_ehrange_t *ehrange;
604         char subjbuf[192];
605         size_t i;
606 
607         /* read bytecode data */
608         snprintf(subjbuf, sizeof(subjbuf), "%s byte code", subj);
609 
610         if (!read_vector(file, chunk, subjbuf, errp))
611                 goto out;
612 
613         /* read exception ranges */
614         if (flags & UC_FUNCTION_F_HAS_EXCEPTIONS) {
615                 snprintf(subjbuf, sizeof(subjbuf), "%s exception ranges count", subj);
616 
617                 if (!read_size_t(file, &chunk->ehranges.count, sizeof(uint32_t), subjbuf, errp))
618                         goto out;
619 
620                 chunk->ehranges.entries = xcalloc(
621                         sizeof(chunk->ehranges.entries[0]),
622                         chunk->ehranges.count);
623 
624                 for (i = 0; i < chunk->ehranges.count; i++) {
625                         snprintf(subjbuf, sizeof(subjbuf), "%s exception range %zu of %zu offset",
626                                 subj, i, chunk->ehranges.count);
627 
628                         ehrange = &chunk->ehranges.entries[i];
629 
630                         if (!read_size_t(file, &ehrange->from,   sizeof(uint32_t), subjbuf, errp) ||
631                             !read_size_t(file, &ehrange->to,     sizeof(uint32_t), subjbuf, errp) ||
632                             !read_size_t(file, &ehrange->target, sizeof(uint32_t), subjbuf, errp) ||
633                             !read_size_t(file, &ehrange->slot,   sizeof(uint32_t), subjbuf, errp))
634                                 goto out;
635                 }
636         }
637 
638         /* read variable info */
639         if (flags & UC_FUNCTION_F_HAS_VARDBG) {
640                 snprintf(subjbuf, sizeof(subjbuf), "%s variable scopes count", subj);
641 
642                 if (!read_size_t(file, &chunk->debuginfo.variables.count, sizeof(uint32_t), subjbuf, errp))
643                         goto out;
644 
645                 chunk->debuginfo.variables.entries = xcalloc(
646                         sizeof(chunk->debuginfo.variables.entries[0]),
647                         chunk->debuginfo.variables.count);
648 
649                 for (i = 0; i < chunk->debuginfo.variables.count; i++) {
650                         snprintf(subjbuf, sizeof(subjbuf), "%s variable scope %zu of %zu offset",
651                                 subj, i, chunk->debuginfo.variables.count);
652 
653                         varrange = &chunk->debuginfo.variables.entries[i];
654 
655                         if (!read_size_t(file, &varrange->from,    sizeof(uint32_t), subjbuf, errp) ||
656                             !read_size_t(file, &varrange->to,      sizeof(uint32_t), subjbuf, errp) ||
657                             !read_size_t(file, &varrange->slot,    sizeof(uint32_t), subjbuf, errp) ||
658                             !read_size_t(file, &varrange->nameidx, sizeof(uint32_t), subjbuf, errp))
659                             goto out;
660                 }
661 
662                 snprintf(subjbuf, sizeof(subjbuf), "%s variable names", subj);
663 
664                 if (!read_vallist(file, &chunk->debuginfo.varnames, subjbuf, errp))
665                         goto out;
666         }
667 
668         /* read offset info */
669         if (flags & UC_FUNCTION_F_HAS_OFFSETDBG) {
670                 snprintf(subjbuf, sizeof(subjbuf), "%s source offsets", subj);
671 
672                 if (!read_vector(file, &chunk->debuginfo.offsets, subjbuf, errp))
673                         goto out;
674         }
675 
676         return true;
677 
678 out:
679         uc_vallist_free(&chunk->debuginfo.varnames);
680 
681         free(chunk->entries);
682         free(chunk->ehranges.entries);
683         free(chunk->debuginfo.variables.entries);
684 
685         chunk->count = 0;
686         chunk->entries = NULL;
687 
688         chunk->ehranges.count = 0;
689         chunk->ehranges.entries = NULL;
690 
691         chunk->debuginfo.variables.count = 0;
692         chunk->debuginfo.variables.entries = NULL;
693 
694         return false;
695 }
696 
697 static bool
698 read_function(FILE *file, uc_program_t *program, size_t idx, char **errp)
699 {
700         char subjbuf[64], *name = NULL;
701         uc_function_t *func = NULL;
702         uint32_t flags, u32;
703 
704         snprintf(subjbuf, sizeof(subjbuf), "function #%zu flags", idx);
705 
706         if (!read_u32(file, &flags, subjbuf, errp))
707                 goto out;
708 
709         if (flags & UC_FUNCTION_F_HAS_NAME) {
710                 snprintf(subjbuf, sizeof(subjbuf), "function #%zu name length", idx);
711 
712                 if (!read_u32(file, &u32, subjbuf, errp))
713                         goto out;
714 
715                 name = xalloc(u32);
716 
717                 snprintf(subjbuf, sizeof(subjbuf), "function #%zu name", idx);
718 
719                 if (!read_string(file, name, u32, subjbuf, errp))
720                         goto out;
721         }
722 
723         snprintf(subjbuf, sizeof(subjbuf), "function #%zu (%s) arg count and offset", idx, name ? name : "-");
724 
725         func = (uc_function_t *)uc_program_function_new(program, name, 0);
726         func->arrow   = (flags & UC_FUNCTION_F_IS_ARROW);
727         func->vararg  = (flags & UC_FUNCTION_F_IS_VARARG);
728         func->strict  = (flags & UC_FUNCTION_F_IS_STRICT);
729 
730         if (!read_size_t(file, &func->nargs,   sizeof(uint16_t), subjbuf, errp) ||
731             !read_size_t(file, &func->nupvals, sizeof(uint16_t), subjbuf, errp) ||
732             !read_size_t(file, &func->srcpos,  sizeof(uint32_t), subjbuf, errp))
733                 goto out;
734 
735         snprintf(subjbuf, sizeof(subjbuf), "function #%zu (%s) body", idx, name ? name : "-");
736 
737         if (!read_chunk(file, &func->chunk, flags, subjbuf, errp))
738                 goto out;
739 
740         free(name);
741 
742         return true;
743 
744 out:
745         free(name);
746 
747         return false;
748 }
749 
750 uc_program_t *
751 uc_program_load(uc_source_t *input, char **errp)
752 {
753         uc_program_t *program = NULL;
754         uc_source_t *source = NULL;
755         uint32_t flags, nfuncs, i;
756 
757         if (!read_u32(input->fp, &i, "file magic", errp))
758                 goto out;
759 
760         if (i != UC_PRECOMPILED_BYTECODE_MAGIC) {
761                 xasprintf(errp, "Invalid file magic\n");
762                 goto out;
763         }
764 
765         if (!read_u32(input->fp, &flags, "program flags", errp))
766                 goto out;
767 
768         source = read_sourceinfo(input, flags, errp);
769 
770         if (!source)
771                 goto out;
772 
773         program = uc_program_new(source);
774 
775         uc_source_put(source);
776 
777         if (!read_vallist(input->fp, &program->constants, "constants", errp))
778                 goto out;
779 
780         if (!read_u32(input->fp, &nfuncs, "function count", errp))
781                 goto out;
782 
783         for (i = 0; i < nfuncs; i++)
784                 if (!read_function(input->fp, program, i, errp))
785                         goto out;
786 
787         return program;
788 
789 out:
790         uc_program_put(program);
791 
792         return NULL;
793 }
794 
795 uc_function_t *
796 uc_program_entry(uc_program_t *program)
797 {
798         if (program->functions.prev == &program->functions)
799                 return NULL;
800 
801         return (uc_function_t *)program->functions.prev;
802 }
803 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt