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