1/* 2 * This file was generated by the mknodes program. 3 */ 4 5/*- 6 * Copyright (c) 1991, 1993 7 * The Regents of the University of California. All rights reserved. 8 * Copyright (c) 1997-2005 9 * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved. 10 * 11 * This code is derived from software contributed to Berkeley by 12 * Kenneth Almquist. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95 39 */ 40 41#include <zircon/syscalls.h> 42#include <stdlib.h> 43 44/* 45 * Routine for dealing with parsed shell commands. 46 */ 47 48#include "shell.h" 49#include "nodes.h" 50#include "memalloc.h" 51#include "machdep.h" 52#include "mystring.h" 53#include "system.h" 54#include "error.h" 55#include "var.h" 56 57 58int funcblocksize; /* size of structures in function */ 59int funcstringsize; /* size of strings in node */ 60pointer funcblock; /* block to allocate function from */ 61char *funcstring; /* block to allocate strings from */ 62 63static const short nodesize[26] = { 64 SHELL_ALIGN(sizeof (struct ncmd)), 65 SHELL_ALIGN(sizeof (struct npipe)), 66 SHELL_ALIGN(sizeof (struct nredir)), 67 SHELL_ALIGN(sizeof (struct nredir)), 68 SHELL_ALIGN(sizeof (struct nredir)), 69 SHELL_ALIGN(sizeof (struct nbinary)), 70 SHELL_ALIGN(sizeof (struct nbinary)), 71 SHELL_ALIGN(sizeof (struct nbinary)), 72 SHELL_ALIGN(sizeof (struct nif)), 73 SHELL_ALIGN(sizeof (struct nbinary)), 74 SHELL_ALIGN(sizeof (struct nbinary)), 75 SHELL_ALIGN(sizeof (struct nfor)), 76 SHELL_ALIGN(sizeof (struct ncase)), 77 SHELL_ALIGN(sizeof (struct nclist)), 78 SHELL_ALIGN(sizeof (struct ndefun)), 79 SHELL_ALIGN(sizeof (struct narg)), 80 SHELL_ALIGN(sizeof (struct nfile)), 81 SHELL_ALIGN(sizeof (struct nfile)), 82 SHELL_ALIGN(sizeof (struct nfile)), 83 SHELL_ALIGN(sizeof (struct nfile)), 84 SHELL_ALIGN(sizeof (struct nfile)), 85 SHELL_ALIGN(sizeof (struct ndup)), 86 SHELL_ALIGN(sizeof (struct ndup)), 87 SHELL_ALIGN(sizeof (struct nhere)), 88 SHELL_ALIGN(sizeof (struct nhere)), 89 SHELL_ALIGN(sizeof (struct nnot)), 90}; 91 92 93STATIC void calcsize(union node *); 94STATIC void sizenodelist(struct nodelist *); 95STATIC union node *copynode(union node *); 96STATIC struct nodelist *copynodelist(struct nodelist *); 97STATIC char *nodesavestr(char *); 98 99STATIC void writenode(union node *n, size_t node_size, size_t block_size); 100STATIC void encodenode(union node *); 101STATIC void encodenodelist(struct nodelist *); 102STATIC void encodestring(const char *); 103 104STATIC void decodenode(union node **); 105STATIC void decodenodelist(struct nodelist **); 106STATIC char *decodestring(); 107 108/* 109 * Make a copy of a parse tree. 110 */ 111 112struct funcnode * 113copyfunc(union node *n) 114{ 115 struct funcnode *f; 116 size_t blocksize; 117 118 funcblocksize = offsetof(struct funcnode, n); 119 funcstringsize = 0; 120 calcsize(n); 121 blocksize = funcblocksize; 122 f = ckmalloc(blocksize + funcstringsize); 123 funcblock = (char *) f + offsetof(struct funcnode, n); 124 funcstring = (char *) f + blocksize; 125 copynode(n); 126 f->count = 0; 127 return f; 128} 129 130 131 132STATIC void 133calcsize(n) 134 union node *n; 135{ 136 if (n == NULL) 137 return; 138 funcblocksize += nodesize[n->type]; 139 switch (n->type) { 140 case NCMD: 141 calcsize(n->ncmd.redirect); 142 calcsize(n->ncmd.args); 143 calcsize(n->ncmd.assign); 144 break; 145 case NPIPE: 146 sizenodelist(n->npipe.cmdlist); 147 break; 148 case NREDIR: 149 case NBACKGND: 150 case NSUBSHELL: 151 calcsize(n->nredir.redirect); 152 calcsize(n->nredir.n); 153 break; 154 case NAND: 155 case NOR: 156 case NSEMI: 157 case NWHILE: 158 case NUNTIL: 159 calcsize(n->nbinary.ch2); 160 calcsize(n->nbinary.ch1); 161 break; 162 case NIF: 163 calcsize(n->nif.elsepart); 164 calcsize(n->nif.ifpart); 165 calcsize(n->nif.test); 166 break; 167 case NFOR: 168 funcstringsize += strlen(n->nfor.var) + 1; 169 calcsize(n->nfor.body); 170 calcsize(n->nfor.args); 171 break; 172 case NCASE: 173 calcsize(n->ncase.cases); 174 calcsize(n->ncase.expr); 175 break; 176 case NCLIST: 177 calcsize(n->nclist.body); 178 calcsize(n->nclist.pattern); 179 calcsize(n->nclist.next); 180 break; 181 case NDEFUN: 182 calcsize(n->ndefun.body); 183 funcstringsize += strlen(n->ndefun.text) + 1; 184 break; 185 case NARG: 186 sizenodelist(n->narg.backquote); 187 funcstringsize += strlen(n->narg.text) + 1; 188 calcsize(n->narg.next); 189 break; 190 case NTO: 191 case NCLOBBER: 192 case NFROM: 193 case NFROMTO: 194 case NAPPEND: 195 calcsize(n->nfile.fname); 196 calcsize(n->nfile.next); 197 break; 198 case NTOFD: 199 case NFROMFD: 200 calcsize(n->ndup.vname); 201 calcsize(n->ndup.next); 202 break; 203 case NHERE: 204 case NXHERE: 205 calcsize(n->nhere.doc); 206 calcsize(n->nhere.next); 207 break; 208 case NNOT: 209 calcsize(n->nnot.com); 210 break; 211 }; 212} 213 214 215 216STATIC void 217sizenodelist(lp) 218 struct nodelist *lp; 219{ 220 while (lp) { 221 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist)); 222 calcsize(lp->n); 223 lp = lp->next; 224 } 225} 226 227 228 229STATIC union node * 230copynode(n) 231 union node *n; 232{ 233 union node *new; 234 235 if (n == NULL) 236 return NULL; 237 new = funcblock; 238 funcblock = (char *) funcblock + nodesize[n->type]; 239 switch (n->type) { 240 case NCMD: 241 new->ncmd.redirect = copynode(n->ncmd.redirect); 242 new->ncmd.args = copynode(n->ncmd.args); 243 new->ncmd.assign = copynode(n->ncmd.assign); 244 new->ncmd.linno = n->ncmd.linno; 245 break; 246 case NPIPE: 247 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); 248 new->npipe.backgnd = n->npipe.backgnd; 249 break; 250 case NREDIR: 251 case NBACKGND: 252 case NSUBSHELL: 253 new->nredir.redirect = copynode(n->nredir.redirect); 254 new->nredir.n = copynode(n->nredir.n); 255 new->nredir.linno = n->nredir.linno; 256 break; 257 case NAND: 258 case NOR: 259 case NSEMI: 260 case NWHILE: 261 case NUNTIL: 262 new->nbinary.ch2 = copynode(n->nbinary.ch2); 263 new->nbinary.ch1 = copynode(n->nbinary.ch1); 264 break; 265 case NIF: 266 new->nif.elsepart = copynode(n->nif.elsepart); 267 new->nif.ifpart = copynode(n->nif.ifpart); 268 new->nif.test = copynode(n->nif.test); 269 break; 270 case NFOR: 271 new->nfor.var = nodesavestr(n->nfor.var); 272 new->nfor.body = copynode(n->nfor.body); 273 new->nfor.args = copynode(n->nfor.args); 274 new->nfor.linno = n->nfor.linno; 275 break; 276 case NCASE: 277 new->ncase.cases = copynode(n->ncase.cases); 278 new->ncase.expr = copynode(n->ncase.expr); 279 new->ncase.linno = n->ncase.linno; 280 break; 281 case NCLIST: 282 new->nclist.body = copynode(n->nclist.body); 283 new->nclist.pattern = copynode(n->nclist.pattern); 284 new->nclist.next = copynode(n->nclist.next); 285 break; 286 case NDEFUN: 287 new->ndefun.body = copynode(n->ndefun.body); 288 new->ndefun.text = nodesavestr(n->ndefun.text); 289 new->ndefun.linno = n->ndefun.linno; 290 break; 291 case NARG: 292 new->narg.backquote = copynodelist(n->narg.backquote); 293 new->narg.text = nodesavestr(n->narg.text); 294 new->narg.next = copynode(n->narg.next); 295 break; 296 case NTO: 297 case NCLOBBER: 298 case NFROM: 299 case NFROMTO: 300 case NAPPEND: 301 new->nfile.fname = copynode(n->nfile.fname); 302 new->nfile.fd = n->nfile.fd; 303 new->nfile.next = copynode(n->nfile.next); 304 break; 305 case NTOFD: 306 case NFROMFD: 307 new->ndup.vname = copynode(n->ndup.vname); 308 new->ndup.dupfd = n->ndup.dupfd; 309 new->ndup.fd = n->ndup.fd; 310 new->ndup.next = copynode(n->ndup.next); 311 break; 312 case NHERE: 313 case NXHERE: 314 new->nhere.doc = copynode(n->nhere.doc); 315 new->nhere.fd = n->nhere.fd; 316 new->nhere.next = copynode(n->nhere.next); 317 break; 318 case NNOT: 319 new->nnot.com = copynode(n->nnot.com); 320 break; 321 }; 322 new->type = n->type; 323 return new; 324} 325 326 327STATIC struct nodelist * 328copynodelist(lp) 329 struct nodelist *lp; 330{ 331 struct nodelist *start; 332 struct nodelist **lpp; 333 334 lpp = &start; 335 while (lp) { 336 *lpp = funcblock; 337 funcblock = (char *) funcblock + 338 SHELL_ALIGN(sizeof(struct nodelist)); 339 (*lpp)->n = copynode(lp->n); 340 lp = lp->next; 341 lpp = &(*lpp)->next; 342 } 343 *lpp = NULL; 344 return start; 345} 346 347 348 349STATIC char * 350nodesavestr(s) 351 char *s; 352{ 353 char *rtn = funcstring; 354 355 funcstring = stpcpy(funcstring, s) + 1; 356 return rtn; 357} 358 359STATIC void writenode(union node *n, size_t node_size, size_t block_size) 360{ 361 if (block_size > funcblocksize) { 362 sh_error("Unable to encode AST"); 363 exraise(-1); 364 } 365 memcpy(funcblock, n, node_size); 366 funcblock = (char *) funcblock + block_size; 367 funcblocksize -= block_size; 368} 369 370STATIC void 371encodenode(union node *n) 372{ 373 if (n == NULL) 374 return; 375 switch (n->type) { 376 case NCMD: 377 writenode(n, sizeof(struct ncmd), nodesize[n->type]); 378 encodenode(n->ncmd.redirect); 379 encodenode(n->ncmd.args); 380 encodenode(n->ncmd.assign); 381 break; 382 case NPIPE: 383 writenode(n, sizeof(struct npipe), nodesize[n->type]); 384 encodenodelist(n->npipe.cmdlist); 385 break; 386 case NREDIR: 387 case NBACKGND: 388 case NSUBSHELL: 389 writenode(n, sizeof(struct nredir), nodesize[n->type]); 390 encodenode(n->nredir.redirect); 391 encodenode(n->nredir.n); 392 break; 393 case NAND: 394 case NOR: 395 case NSEMI: 396 case NWHILE: 397 case NUNTIL: 398 writenode(n, sizeof(struct nbinary), nodesize[n->type]); 399 encodenode(n->nbinary.ch2); 400 encodenode(n->nbinary.ch1); 401 break; 402 case NIF: 403 writenode(n, sizeof(struct nif), nodesize[n->type]); 404 encodenode(n->nif.elsepart); 405 encodenode(n->nif.ifpart); 406 encodenode(n->nif.test); 407 break; 408 case NFOR: 409 writenode(n, sizeof(struct nfor), nodesize[n->type]); 410 encodestring(n->nfor.var); 411 encodenode(n->nfor.body); 412 encodenode(n->nfor.args); 413 break; 414 case NCASE: 415 writenode(n, sizeof(struct ncase), nodesize[n->type]); 416 encodenode(n->ncase.cases); 417 encodenode(n->ncase.expr); 418 break; 419 case NCLIST: 420 writenode(n, sizeof(struct nclist), nodesize[n->type]); 421 encodenode(n->nclist.body); 422 encodenode(n->nclist.pattern); 423 encodenode(n->nclist.next); 424 break; 425 case NDEFUN: 426 writenode(n, sizeof(struct ndefun), nodesize[n->type]); 427 encodenode(n->ndefun.body); 428 encodestring(n->ndefun.text); 429 break; 430 case NARG: 431 writenode(n, sizeof(struct narg), nodesize[n->type]); 432 encodenodelist(n->narg.backquote); 433 encodestring(n->narg.text); 434 encodenode(n->narg.next); 435 break; 436 case NTO: 437 case NCLOBBER: 438 case NFROM: 439 case NFROMTO: 440 case NAPPEND: 441 writenode(n, sizeof(struct nfile), nodesize[n->type]); 442 encodenode(n->nfile.fname); 443 encodenode(n->nfile.next); 444 break; 445 case NTOFD: 446 case NFROMFD: 447 writenode(n, sizeof(struct ndup), nodesize[n->type]); 448 encodenode(n->ndup.vname); 449 encodenode(n->ndup.next); 450 break; 451 case NHERE: 452 case NXHERE: 453 writenode(n, sizeof(struct nhere), nodesize[n->type]); 454 encodenode(n->nhere.doc); 455 encodenode(n->nhere.next); 456 break; 457 case NNOT: 458 writenode(n, sizeof(struct nnot), nodesize[n->type]); 459 encodenode(n->nnot.com); 460 break; 461 }; 462} 463 464STATIC void 465encodenodelist(struct nodelist *lp) 466{ 467 while (lp) { 468 memcpy(funcblock, lp, sizeof(struct nodelist)); 469 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist)); 470 encodenode(lp->n); 471 lp = lp->next; 472 } 473} 474 475STATIC void 476encodestring(const char *s) 477{ 478 funcstring = stpcpy(funcstring, s) + 1; 479} 480 481 482STATIC void 483decodenode(union node **npp) 484{ 485 if (*npp == NULL) 486 return; 487 *npp = funcblock; 488 union node *n = *npp; 489 funcblock = (char *) funcblock + nodesize[n->type]; 490 switch (n->type) { 491 case NCMD: 492 decodenode(&n->ncmd.redirect); 493 decodenode(&n->ncmd.args); 494 decodenode(&n->ncmd.assign); 495 break; 496 case NPIPE: 497 decodenodelist(&n->npipe.cmdlist); 498 break; 499 case NREDIR: 500 case NBACKGND: 501 case NSUBSHELL: 502 decodenode(&n->nredir.redirect); 503 decodenode(&n->nredir.n); 504 break; 505 case NAND: 506 case NOR: 507 case NSEMI: 508 case NWHILE: 509 case NUNTIL: 510 decodenode(&n->nbinary.ch2); 511 decodenode(&n->nbinary.ch1); 512 break; 513 case NIF: 514 decodenode(&n->nif.elsepart); 515 decodenode(&n->nif.ifpart); 516 decodenode(&n->nif.test); 517 break; 518 case NFOR: 519 n->nfor.var = decodestring(); 520 decodenode(&n->nfor.body); 521 decodenode(&n->nfor.args); 522 break; 523 case NCASE: 524 decodenode(&n->ncase.cases); 525 decodenode(&n->ncase.expr); 526 break; 527 case NCLIST: 528 decodenode(&n->nclist.body); 529 decodenode(&n->nclist.pattern); 530 decodenode(&n->nclist.next); 531 break; 532 case NDEFUN: 533 decodenode(&n->ndefun.body); 534 n->ndefun.text = decodestring(); 535 break; 536 case NARG: 537 decodenodelist(&n->narg.backquote); 538 n->narg.text = decodestring(); 539 decodenode(&n->narg.next); 540 break; 541 case NTO: 542 case NCLOBBER: 543 case NFROM: 544 case NFROMTO: 545 case NAPPEND: 546 decodenode(&n->nfile.fname); 547 decodenode(&n->nfile.next); 548 break; 549 case NTOFD: 550 case NFROMFD: 551 decodenode(&n->ndup.vname); 552 decodenode(&n->ndup.next); 553 break; 554 case NHERE: 555 case NXHERE: 556 decodenode(&n->nhere.doc); 557 decodenode(&n->nhere.next); 558 break; 559 case NNOT: 560 decodenode(&n->nnot.com); 561 break; 562 }; 563} 564 565STATIC void 566decodenodelist(struct nodelist **lpp) 567{ 568 while (*lpp) { 569 *lpp = funcblock; 570 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist)); 571 struct nodelist *lp = *lpp; 572 decodenode(&lp->n); 573 lpp = &lp->next; 574 } 575} 576 577STATIC char * 578decodestring() 579{ 580 char *result = funcstring; 581 funcstring += strlen(result) + 1; 582 return result; 583} 584 585/* 586 * Free a parse tree. 587 */ 588 589void 590freefunc(struct funcnode *f) 591{ 592 if (f && --f->count < 0) 593 ckfree(f); 594} 595 596// Fuchsia-specific: 597// This is the definition of the header of the VMO used for transferring initialization 598// information to a subshell. This information would be automatically inherited if we 599// were able to invoke the subshell using a fork(). 600// For now, we pass symbol table information (non-exported symbols, those are passed in 601// the environment) and a list of operations to be performed by the subshell. 602struct state_header 603{ 604 size_t total_size; 605 size_t num_symbols; 606 size_t symtab_offset; 607 size_t cmd_offset; 608 size_t string_offset; 609}; 610static const size_t kHeaderSize = SHELL_ALIGN(sizeof(struct state_header)); 611 612static char *ignored_syms[] = { "_", "PPID", "PWD" }; 613 614static bool 615ignore_sym(char *name) 616{ 617 for (size_t sym_ndx = 0; 618 sym_ndx < sizeof(ignored_syms) / sizeof(char *); 619 sym_ndx++) { 620 if (!strcmp(ignored_syms[sym_ndx], name)) { 621 return true; 622 } 623 } 624 return false; 625} 626 627// Determine the space needed to represent the NULL-terminated symbol table 628// 'vars'. Also sets 'num_vars' to the number of symbol table entries. 629static size_t 630calc_symtab_size(char **vars, size_t *num_vars) 631{ 632 size_t total_len = 0; 633 *num_vars = 0; 634 while (*vars) { 635 if (! ignore_sym(*vars)) { 636 // + 2 for NULL symbol flags 637 total_len += strlen(*vars) + 2; 638 (*num_vars)++; 639 } 640 vars++; 641 } 642 return total_len; 643} 644 645// Write symbols into 'buffer'. If 'is_readonly' is set, all variables are 646// marked as such. 647static size_t 648output_symtab(char *buffer, char **vars, bool is_readonly) 649{ 650 char *orig_buffer = buffer; 651 while (*vars) { 652 if (! ignore_sym(*vars)) { 653 *buffer++ = is_readonly ? 1 : 0; 654 size_t len = strlen(*vars); 655 buffer = mempcpy(buffer, *vars, len + 1); 656 } 657 vars++; 658 } 659 return buffer - orig_buffer; 660} 661 662// Read in symbols from the encoded table 'buffer'. We currently only support 663// two variants of variables: readonly (flags == 1) and writable (flags == 0). 664static void 665restore_symtab(char *buffer, size_t num_syms) 666{ 667 while(num_syms--) { 668 bool is_readonly = (*buffer++ == 1); 669 setvareq(buffer, is_readonly ? VREADONLY : 0); 670 buffer += (strlen(buffer) + 1); 671 } 672} 673 674// The encoded format contains four segments: 675// 676// * A header that specifies the number of symbols, and offsets of each of 677// the three segments (see "struct state_header"). 678// * A symbol table. Each entry in the symbol table is a single-byte of flags 679// (1 = read-only, 0 = writable) followed by a NULL-terminted NAME=VALUE 680// string. 681// * A sequence of nodes in a pre-order traversal of the node tree. 682// - The encoded size of each node is determined by its type. 683// - Pointer fields in each node contain zero if that pointer should decode 684// a NULL. Otherwise, if the pointer should decode as non-NULL, the field 685// contains an arbitrary non-zero value. (These values are the address of 686// the node or the string in the encoding process, which isn't meaningful to 687// the decoding progress). 688// * A sequence of null-terminated strings, in the order the strings are 689// encountered in a pre-order traversal of the node tree. 690 691zx_status_t 692codec_encode(struct nodelist *nlist, zx_handle_t *vmo) 693{ 694 funcblocksize = 0; 695 funcstringsize = 0; 696 char **writable_vars = listvars(0, VEXPORT | VREADONLY, 0); 697 char **readonly_vars = listvars(VREADONLY, VEXPORT, 0); 698 699 // Calculate the size of the components 700 size_t num_writable_vars; 701 size_t num_readonly_vars; 702 size_t total_symtab_size = calc_symtab_size(writable_vars, &num_writable_vars) + 703 calc_symtab_size(readonly_vars, &num_readonly_vars); 704 total_symtab_size = SHELL_ALIGN(total_symtab_size); 705 sizenodelist(nlist); 706 struct state_header header; 707 708 // Fill in the header 709 header.num_symbols = num_writable_vars + num_readonly_vars; 710 header.symtab_offset = kHeaderSize; 711 header.cmd_offset = header.symtab_offset + total_symtab_size; 712 header.string_offset = header.cmd_offset + funcblocksize; 713 714 char buffer[header.string_offset + funcstringsize]; 715 header.total_size = sizeof(buffer); 716 717 // Output the symbol tables 718 memcpy(buffer, &header, sizeof(header)); 719 size_t symtab_offset = header.symtab_offset; 720 char* symtab = &buffer[symtab_offset]; 721 symtab_offset += output_symtab(symtab, writable_vars, 0); 722 output_symtab(symtab, readonly_vars, 1); 723 724 // Output the command nodes 725 funcblock = buffer + header.cmd_offset; 726 funcstring = buffer + header.string_offset; 727 encodenodelist(nlist); 728 729 // And VMO-ify the whole thing 730 zx_status_t status = zx_vmo_create(sizeof(buffer), 0, vmo); 731 if (status != ZX_OK) 732 return status; 733 return zx_vmo_write(*vmo, buffer, 0, sizeof(buffer)); 734} 735 736struct nodelist *codec_decode(char *buffer, size_t length) 737{ 738 struct state_header header; 739 if (length < sizeof(header)) { 740 return NULL; 741 } 742 memcpy(&header, buffer, sizeof(header)); 743 if (length < header.total_size) { 744 return NULL; 745 } 746 747 restore_symtab(buffer + header.symtab_offset, header.num_symbols); 748 funcblock = buffer + header.cmd_offset; 749 funcstring = buffer + header.string_offset; 750 struct nodelist dummy; 751 // The decodenodelist API is very... unique. It needs the 752 // argument to point to something non-NULL, even though the 753 // argument is otherwise ignored and used as an output parameter. 754 struct nodelist *nlist = &dummy; 755 decodenodelist(&nlist); 756 return nlist; 757} 758 759