static currentstats_t* code_get_stats(code_t*code, abc_exception_list_t*exceptions) { code = code_start(code); int num = 0; code_t*c = code; while(c) { num++; c = c->next; } currentstats_t* current = malloc(sizeof(currentstats_t)); current->stack = rfx_calloc(sizeof(stackpos_t)*num); current->maxlocal = 0; current->maxstack = 0; current->maxscope = 0; current->num = num; current->flags = 0; //#define DEBUG_BYTES #ifdef DEBUG_BYTES int t; c = code; for(t=0;t<num;t++) { opcode_t*op = opcode_get(c->opcode); if(op->flags & (OP_JUMP|OP_BRANCH)) { printf("%05d) %s %08x\n", t, op->name, c->branch); } else if(op->params[0]=='2') { printf("%05d) %s %s\n", t, op->name, multiname_tostring(c->data[0])); } else if(op->params[0]=='N') { printf("%05d) %s %s\n", t, op->name, namespace_tostring(c->data[0])); } else { printf("%05d) %s\n", t, op->name); } c = c->next; } //printf("%05d) %02x\n", t, tag->data[start+t]); #endif num = 0; c = code; while(c) { //crosslink current->stack[num].code = c; c->pos = num; num++; c = c->next; } if(!callcode(current, 0, 0, 0)) { free(current); return 0; } abc_exception_list_t*e = exceptions; while(e) { if(e->abc_exception->target) callcode(current, e->abc_exception->target->pos, 1, 0); e = e->next; } return current; }
static void code_image( Telem* elem ) { int i, d = elem->data.image.d, w = elem->data.image.w, h = elem->data.image.h; fprintf( outfile, "static void image_" ); code_c_name( elem->name ); fprintf( outfile, " (void)\n" "{\n" " %sunsigned char map[] = {", static_image? "static ": "" ); for (i=0; i<w*h*d; i++) { if (i%(w*d) == 0) fprintf( outfile, "\n " ); fprintf( outfile, "%2d,", atoi(elem->params[i+2]->data.name) ); } fprintf( outfile, "\n" " 0 };\n\n" ); indent(); code_start( elem ); fprintf( outfile, "( %d, %d, map )", elem->data.image.w, elem->data.image.h ); code_attrs( elem ); fprintf( outfile, ";\n}\n\n" ); unindent(); }
void code_write(TAG*tag, code_t*code, pool_t*pool, abc_file_t*file) { code = code_start(code); int pos = 0; int length = 0; code_t*c = code; while(c) { c->pos = pos; pos += opcode_write(0, c, pool, file, 0); c = c->next; } length = pos; swf_SetU30(tag, pos); int start = tag->len; c = code; pos = 0; while(c) { opcode_t*op = opcode_get(code->opcode); if(op->flags&(OP_BRANCH|OP_JUMP)) { int skip = 0; } pos += opcode_write(tag, c, pool, file, length); c = c->next; } assert(tag->len - start == pos); }
void code_free(code_t*c) { c = code_start(c); while(c) { code_t*next = c->next; opcode_t*op = opcode_get(c->opcode); char*p = op?op->params:""; int pos=0; while(*p) { void*data = c->data[pos]; if(*p == '2') { //multiname multiname_destroy(data); } else if(*p == 'N') { //namespace namespace_destroy(data); } else if(strchr("sDf", *p)) { free(data); } else if(strchr("S", *p)) { lookupswitch_t*l = (lookupswitch_t*)data; list_free(l->targets);l->targets=0; free(l); } c->data[pos]=0; p++;pos++; } memset(c, 0, sizeof(c)); free(c); c = next; } }
int code_dump(code_t*c) { code_t*cc = code_start(c); while(cc) { assert(!cc->next || cc->next->prev == cc); cc = cc->next; } return code_dump2(c, 0, 0, "", stdout); }
static void code_decl( Telem *e ) { if (e->name || e->attrs) { code_start( e ); elems[e->elemidx].code( e ); code_attrs( e ); } else { codeindent(); if (e->name && e->elemidx != IMAGE && e->elemidx != COLOR) generatename( e ); if ( codename( e ) ) fprintf( outfile, " = " ); codeelemname( e ); elems[e->elemidx].code( e ); } }
code_t* var_block(code_t*body, dict_t*vars) { code_t*c = 0; code_t*k = 0; int t; DICT_ITERATE_DATA(vars, variable_t*, v) { if(v->type && v->init) { c = defaultvalue(c, v->type); c = abc_setlocal(c, v->index); } if(v->type && v->kill) { k = abc_kill(k, v->index); } } if(k) { code_t*x = body; while(x) { if(x->opcode== OPCODE___BREAK__ || x->opcode== OPCODE___CONTINUE__) { /* link kill code before break/continue */ code_t*e = code_dup(k); code_t*s = code_start(e); s->prev = x->prev; if(x->prev) { x->prev->next = s; } e->next = x; x->prev = e; } x = x->prev; } } c = code_append(c, body); c = code_append(c, k); return c; }
int code_dump2(code_t*c, abc_exception_list_t*exceptions, abc_file_t*file, char*prefix, FILE*fo) { abc_exception_list_t*e = exceptions; c = code_start(c); currentstats_t*stats = code_get_stats(c, exceptions); int pos = 0; while(c) { U8 opcode = c->opcode; char found = 0; opcode_t*op = opcode_get(opcode); e = exceptions; while(e) { if(c==e->abc_exception->from) fprintf(fo, "%s TRY {\n", prefix); if(c==e->abc_exception->target) { char*s1 = multiname_tostring(e->abc_exception->exc_type); char*s2 = multiname_tostring(e->abc_exception->var_name); fprintf(fo, "%s CATCH(%s %s)\n", prefix, s1, s2); free(s1); free(s2); } e = e->next; } if(!op) { fprintf(stderr, "Can't parse opcode %02x.\n", opcode); return 0; } else { char*p = op->params; char first = 1; int i=0; if(stats) { int f = stats->stack[c->pos].flags; fprintf(fo, "%s%05d) %c %d:%d %s ", prefix, c->pos, (f&FLAG_ERROR)?'E':((f&FLAG_SEEN)?'+':'|'), stats->stack[c->pos].stackpos, stats->stack[c->pos].scopepos, op->name); } else { fprintf(fo, "%s%05d) ? ?:? %s ", prefix, c->pos, op->name); } while(*p) { void*data = c->data[i]; if(i>0) printf(", "); if(*p == 'n') { int n = (ptroff_t)data; fprintf(fo, "%d params", n); } else if(*p == '2') { multiname_t*n = (multiname_t*)data; char* m = multiname_tostring(n); fprintf(fo, "%s", m); free(m); } else if(*p == 'N') { namespace_t*ns = (namespace_t*)data; char* m = namespace_tostring(ns); fprintf(fo, "%s", m); free(m); } else if(*p == 'm') { abc_method_t*m = (abc_method_t*)data; fprintf(fo, "[method %08x %s]", m->index, m->name); } else if(*p == 'c') { abc_class_t*cls = (abc_class_t*)data; char*classname = multiname_tostring(cls->classname); fprintf(fo, "[classinfo %08x %s]", cls->index, classname); free(classname); } else if(*p == 'i') { abc_method_body_t*b = (abc_method_body_t*)data; fprintf(fo, "[methodbody]"); } else if(*p == 'u' || *p == 'I' || *p == 'U') { int n = (ptroff_t)data; fprintf(fo, "%d", n); } else if(*p == 'f') { double f = *(double*)data; fprintf(fo, "%f", f); } else if(*p == 'r') { int n = (ptroff_t)data; fprintf(fo, "r%d", n); } else if(*p == 'b') { int b = (signed char)(ptroff_t)data; fprintf(fo, "%d", b); } else if(*p == 'j') { if(c->branch) fprintf(fo, "->%d", c->branch->pos); else fprintf(fo, "%08x", (unsigned int)c->branch); } else if(*p == 's') { char*s = string_escape((string_t*)data); fprintf(fo, "\"%s\"", s); free(s); } else if(*p == 'D') { fprintf(fo, "[register %02x=%s]", (ptroff_t)c->data[1], (char*)c->data[0]); } else if(*p == 'S') { lookupswitch_t*l = c->data[0]; fprintf(fo, "["); if(l->def) fprintf(fo, "default->%d", l->def->pos); else fprintf(fo, "default->00000000"); code_list_t*t = l->targets; while(t) { if(t->code) fprintf(fo, ",->%d", t->code->pos); else fprintf(fo, ",->00000000"); t = t->next; } fprintf(fo, "]"); } else { fprintf(stderr, "Can't parse opcode param type \"%c\"\n", *p); return 0; } p++; i++; first = 0; } fprintf(fo, "\n"); } e = exceptions; while(e) { if(c==e->abc_exception->to) { if(e->abc_exception->target) fprintf(fo, "%s } // END TRY (HANDLER: %d)\n", prefix, e->abc_exception->target->pos); else fprintf(fo, "%s } // END TRY (HANDLER: 00000000)\n", prefix); } e = e->next; } pos++; c = c->next; } stats_free(stats); return 1; }
code_t*code_dup(code_t*c) { if(!c) return 0; dict_t*pos2pos = dict_new2(&ptr_type); code_t*last = 0; c = code_start(c); code_t*start = 0; char does_branch = 0; while(c) { NEW(code_t, n); memcpy(n, c, sizeof(code_t)); if(!start) start=n; if(c->opcode == OPCODE_LABEL || c->opcode == OPCODE_NOP) { dict_put(pos2pos, c, n); } if(c->branch) { does_branch = 1; } opcode_t*op = opcode_get(c->opcode); char*p = op?op->params:""; int pos=0; while(*p) { if(*p == '2') { //multiname c->data[pos] = multiname_clone(c->data[pos]); } else if(*p == 'N') { //multiname c->data[pos] = namespace_clone(c->data[pos]); } else if(*p == 's') { c->data[pos] = string_dup3(c->data[pos]); } else if(*p == 'D') { c->data[pos] = strdup(c->data[pos]); } else if(*p == 'f') { double old = *(double*)c->data[pos]; c->data[pos] = malloc(sizeof(double)); *(double*)c->data[pos] = old; } else if(strchr("S", *p)) { c->data[pos] = lookupswitch_dup(c->data[pos]); } p++;pos++; } n->prev = last; if(last) { last->next = n; } last = n; c = c->next; } if(does_branch) { c = start; while(c) { if(c->branch) { code_t*target = dict_lookup(pos2pos, c->branch); if(!target) { fprintf(stderr, "Error: Can't find branch target in code_dup\n"); return 0; } c->branch = target; } c = c->next; } } dict_destroy(pos2pos); return last; }