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(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 return NULL; 592 593 if (len > 0) { 594 code = xalloc(len); 595 596 if (!read_string(input->fp, code, len, "sourceinfo code buffer data", errp)) { 597 free(code); 598 free(path); 599 600 return NULL; 601 } 602 603 source = uc_source_new_buffer(path, code, len); 604 } 605 else { 606 source = uc_source_new_file(path); 607 608 if (!source) { 609 fprintf(stderr, "Unable to open source file %s: %s\n", path, strerror(errno)); 610 source = uc_source_new_buffer(path, xstrdup(""), 0); 611 } 612 } 613 614 if (!read_vector(input->fp, &source->lineinfo, "sourceinfo lineinfo", errp)) { 615 uc_source_put(source); 616 free(path); 617 618 return NULL; 619 } 620 621 uc_source_runpath_set(source, input->runpath); 622 uc_vector_push(&program->sources, source); 623 624 free(path); 625 626 count--; 627 } 628 } 629 else { 630 source = uc_source_new_buffer("[no source]", xstrdup(""), 0); 631 632 uc_source_runpath_set(source, input->runpath); 633 uc_vector_push(&program->sources, source); 634 } 635 636 return source; 637 } 638 639 static bool 640 read_chunk(FILE *file, uc_chunk_t *chunk, uint32_t flags, const char *subj, char **errp) 641 { 642 uc_varrange_t *varrange; 643 uc_ehrange_t *ehrange; 644 char subjbuf[192]; 645 size_t i; 646 647 /* read bytecode data */ 648 snprintf(subjbuf, sizeof(subjbuf), "%s byte code", subj); 649 650 if (!read_vector(file, chunk, subjbuf, errp)) 651 goto out; 652 653 /* read exception ranges */ 654 if (flags & UC_FUNCTION_F_HAS_EXCEPTIONS) { 655 snprintf(subjbuf, sizeof(subjbuf), "%s exception ranges count", subj); 656 657 if (!read_size_t(file, &chunk->ehranges.count, sizeof(uint32_t), subjbuf, errp)) 658 goto out; 659 660 chunk->ehranges.entries = xcalloc( 661 sizeof(chunk->ehranges.entries[0]), 662 chunk->ehranges.count); 663 664 for (i = 0; i < chunk->ehranges.count; i++) { 665 snprintf(subjbuf, sizeof(subjbuf), "%s exception range %zu of %zu offset", 666 subj, i, chunk->ehranges.count); 667 668 ehrange = &chunk->ehranges.entries[i]; 669 670 if (!read_size_t(file, &ehrange->from, sizeof(uint32_t), subjbuf, errp) || 671 !read_size_t(file, &ehrange->to, sizeof(uint32_t), subjbuf, errp) || 672 !read_size_t(file, &ehrange->target, sizeof(uint32_t), subjbuf, errp) || 673 !read_size_t(file, &ehrange->slot, sizeof(uint32_t), subjbuf, errp)) 674 goto out; 675 } 676 } 677 678 /* read variable info */ 679 if (flags & UC_FUNCTION_F_HAS_VARDBG) { 680 snprintf(subjbuf, sizeof(subjbuf), "%s variable scopes count", subj); 681 682 if (!read_size_t(file, &chunk->debuginfo.variables.count, sizeof(uint32_t), subjbuf, errp)) 683 goto out; 684 685 chunk->debuginfo.variables.entries = xcalloc( 686 sizeof(chunk->debuginfo.variables.entries[0]), 687 chunk->debuginfo.variables.count); 688 689 for (i = 0; i < chunk->debuginfo.variables.count; i++) { 690 snprintf(subjbuf, sizeof(subjbuf), "%s variable scope %zu of %zu offset", 691 subj, i, chunk->debuginfo.variables.count); 692 693 varrange = &chunk->debuginfo.variables.entries[i]; 694 695 if (!read_size_t(file, &varrange->from, sizeof(uint32_t), subjbuf, errp) || 696 !read_size_t(file, &varrange->to, sizeof(uint32_t), subjbuf, errp) || 697 !read_size_t(file, &varrange->slot, sizeof(uint32_t), subjbuf, errp) || 698 !read_size_t(file, &varrange->nameidx, sizeof(uint32_t), subjbuf, errp)) 699 goto out; 700 701 if (varrange->slot >= ((uint32_t)-1 / 2)) 702 varrange->slot = ((size_t)-1 / 2) + (varrange->slot - ((uint32_t)-1 / 2)); 703 } 704 705 snprintf(subjbuf, sizeof(subjbuf), "%s variable names", subj); 706 707 if (!read_vallist(file, &chunk->debuginfo.varnames, subjbuf, errp)) 708 goto out; 709 } 710 711 /* read offset info */ 712 if (flags & UC_FUNCTION_F_HAS_OFFSETDBG) { 713 snprintf(subjbuf, sizeof(subjbuf), "%s source offsets", subj); 714 715 if (!read_vector(file, &chunk->debuginfo.offsets, subjbuf, errp)) 716 goto out; 717 } 718 719 return true; 720 721 out: 722 uc_vallist_free(&chunk->debuginfo.varnames); 723 724 free(chunk->entries); 725 free(chunk->ehranges.entries); 726 free(chunk->debuginfo.variables.entries); 727 728 chunk->count = 0; 729 chunk->entries = NULL; 730 731 chunk->ehranges.count = 0; 732 chunk->ehranges.entries = NULL; 733 734 chunk->debuginfo.variables.count = 0; 735 chunk->debuginfo.variables.entries = NULL; 736 737 return false; 738 } 739 740 static bool 741 read_function(FILE *file, uc_program_t *program, size_t idx, char **errp) 742 { 743 size_t nargs, nupvals, srcidx, srcpos; 744 char subjbuf[64], *name = NULL; 745 uc_function_t *func = NULL; 746 uc_source_t *source; 747 uint32_t flags, u32; 748 749 snprintf(subjbuf, sizeof(subjbuf), "function #%zu flags", idx); 750 751 if (!read_u32(file, &flags, subjbuf, errp)) 752 goto out; 753 754 if (flags & UC_FUNCTION_F_HAS_NAME) { 755 snprintf(subjbuf, sizeof(subjbuf), "function #%zu name length", idx); 756 757 if (!read_u32(file, &u32, subjbuf, errp)) 758 goto out; 759 760 name = xalloc(u32); 761 762 snprintf(subjbuf, sizeof(subjbuf), "function #%zu name", idx); 763 764 if (!read_string(file, name, u32, subjbuf, errp)) 765 goto out; 766 } 767 768 snprintf(subjbuf, sizeof(subjbuf), "function #%zu (%s) arg count and offset", idx, name ? name : "-"); 769 770 if (!read_size_t(file, &nargs, sizeof(uint16_t), subjbuf, errp) || 771 !read_size_t(file, &nupvals, sizeof(uint16_t), subjbuf, errp) || 772 !read_size_t(file, &srcidx, sizeof(uint32_t), subjbuf, errp) || 773 !read_size_t(file, &srcpos, sizeof(uint32_t), subjbuf, errp)) { 774 goto out; 775 } 776 777 // FIXME 778 if (srcidx < program->sources.count) 779 source = program->sources.entries[srcidx]; 780 else 781 source = program->sources.entries[0]; 782 783 func = (uc_function_t *)uc_program_function_new(program, name, source, srcpos); 784 func->arrow = (flags & UC_FUNCTION_F_IS_ARROW); 785 func->vararg = (flags & UC_FUNCTION_F_IS_VARARG); 786 func->strict = (flags & UC_FUNCTION_F_IS_STRICT); 787 func->module = (flags & UC_FUNCTION_F_IS_MODULE); 788 func->nargs = nargs; 789 func->nupvals = nupvals; 790 791 snprintf(subjbuf, sizeof(subjbuf), "function #%zu (%s) body", idx, name ? name : "-"); 792 793 if (!read_chunk(file, &func->chunk, flags, subjbuf, errp)) 794 goto out; 795 796 free(name); 797 798 return true; 799 800 out: 801 free(name); 802 803 return false; 804 } 805 806 uc_program_t * 807 uc_program_load(uc_source_t *input, char **errp) 808 { 809 uc_program_t *program = NULL; 810 uint32_t flags, nfuncs, i; 811 812 if (!read_u32(input->fp, &i, "file magic", errp)) 813 goto out; 814 815 if (i != UC_PRECOMPILED_BYTECODE_MAGIC) { 816 xasprintf(errp, "Invalid file magic\n"); 817 goto out; 818 } 819 820 if (!read_u32(input->fp, &flags, "program flags", errp)) 821 goto out; 822 823 program = uc_program_new(); 824 825 if (!read_sourceinfo(input, flags, errp, program)) 826 goto out; 827 828 if (!read_vallist(input->fp, &program->constants, "constants", errp)) 829 goto out; 830 831 if (!read_u32(input->fp, &nfuncs, "function count", errp)) 832 goto out; 833 834 for (i = 0; i < nfuncs; i++) 835 if (!read_function(input->fp, program, i, errp)) 836 goto out; 837 838 return program; 839 840 out: 841 uc_program_put(program); 842 843 return NULL; 844 } 845 846 uc_function_t * 847 uc_program_entry(uc_program_t *program) 848 { 849 if (program->functions.prev == &program->functions) 850 return NULL; 851 852 return (uc_function_t *)program->functions.prev; 853 } 854
This page was automatically generated by LXR 0.3.1. • OpenWrt