X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fas3%2Fcode.c;h=541ebf55ba714d532b7a0697a0efe58a0016549a;hp=5e196def59a9428bd6673223775a742b8ae35fe7;hb=2391d7ae5d8a145a250a8b80ab8c93ba74eba030;hpb=a52ce1beaa285529abb33715b5cce9810502c508 diff --git a/lib/as3/code.c b/lib/as3/code.c index 5e196de..541ebf5 100644 --- a/lib/as3/code.c +++ b/lib/as3/code.c @@ -45,6 +45,7 @@ i = u30 index into method info b = byte c = u30 index into class + N = u30 index into namespaces s = string (u30 index into strings) S = switch u = u30 @@ -166,7 +167,7 @@ opcode_t opcodes[]={ {0x2f, "pushdouble", "f", 0, 1, 0, 0}, //index into floats {0x27, "pushfalse", "", 0, 1, 0, 0}, {0x2d, "pushint", "I", 0, 1, 0, 0}, //index into ints -{0x31, "pushnamespace", "u", 0, 1, 0, 0}, //index into namespace TODO +{0x31, "pushnamespace", "N", 0, 1, 0, 0}, //index into namespace {0x28, "pushnan", "", 0, 1, 0, 0}, {0x20, "pushnull", "", 0, 1, 0, 0}, {0x30, "pushscope", "", -1, 0, 1, 0}, @@ -197,8 +198,7 @@ opcode_t opcodes[]={ {0xa7, "urshift", "", -2, 1, 0, 0}, /* opcodes not documented, but seen in the wild */ -//0x53: seen in builtin.abc -{0x53, "applytype", "n", -1, 1, 0, OP_STACK_ARGS}, +{0x53, "applytype", "n", -1, 1, 0, OP_STACK_ARGS}, //seen in builtin.abc /* dummy instructions. Warning: these are not actually supported by flash */ {0xfb, "__pushpackage__", "s", 0, 1, 0, OP_INTERNAL}, @@ -255,10 +255,10 @@ code_t* code_atposition(codelookup_t*l, int pos) void lookupswitch_print(lookupswitch_t*l) { - printf("default: %08x\n", l->def); + printf("default: %08x\n", (int)l->def); code_list_t*t = l->targets; while(t) { - printf("target: %08x\n", t->code); + printf("target: %08x\n", (int)t->code); t = t->next; } } @@ -305,6 +305,8 @@ code_t*code_parse(TAG*tag, int len, abc_file_t*file, pool_t*pool, codelookup_t** data = (void*)(ptroff_t)swf_GetU30(tag); } else if(*p == '2') { //multiname data = multiname_clone(pool_lookup_multiname(pool, swf_GetU30(tag))); + } else if(*p == 'N') { //namespace + data = namespace_clone(pool_lookup_namespace(pool, swf_GetU30(tag))); } else if(*p == 'U') { //uint data = (void*)(ptroff_t)pool_lookup_uint(pool, swf_GetU30(tag)); } else if(*p == 'I') { //int @@ -369,15 +371,15 @@ code_t*code_parse(TAG*tag, int len, abc_file_t*file, pool_t*pool, codelookup_t** if(c) { opcode_t*op = opcode_get(c->opcode); if(op->flags & (OP_JUMP|OP_BRANCH)) { - printf("%5d) %02x %s %d\n", t, tag->data[start+t], op->name, c->data[0]); + printf("%50d) %02x %s %d\n", t, tag->data[start+t], op->name, c->data[0]); } else { - printf("%5d) %02x %s\n", t, tag->data[start+t], op->name); + printf("%50d) %02x %s\n", t, tag->data[start+t], op->name); } } else { - printf("%5d) %02x\n", t, tag->data[start+t]); + printf("%50d) %02x\n", t, tag->data[start+t]); } } - //printf("%5d) %02x\n", t, tag->data[start+t]); + //printf("%05d) %02x\n", t, tag->data[start+t]); #endif code_t*c = head; @@ -428,6 +430,8 @@ void code_free(code_t*c) 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)) { @@ -467,69 +471,105 @@ static int opcode_write(TAG*tag, code_t*c, pool_t*pool, abc_file_t*file, int len while(*p) { void*data = c->data[pos++]; assert(pos<=2); - if(*p == 'n') { // number - len += swf_SetU30(tag, (ptroff_t)data); - } else if(*p == '2') { //multiname - multiname_t*m = (multiname_t*)data; - len += swf_SetU30(tag, pool_register_multiname(pool, m)); - } else if(*p == 'm') { //method - abc_method_t*m = (abc_method_t*)data; - len += swf_SetU30(tag, m->index); - } else if(*p == 'c') { //classinfo - abc_class_t*cls = (abc_class_t*)data; - len += swf_SetU30(tag, cls->index); - } else if(*p == 'i') { //methodbody - abc_method_body_t*m = (abc_method_body_t*)data; - len += swf_SetU30(tag, m->index); - } else if(*p == 'I') { // int - len += swf_SetU30(tag, pool_register_int(pool, (ptroff_t)data)); - } else if(*p == 'U') { // uint - len += swf_SetU30(tag, pool_register_uint(pool, (ptroff_t)data)); - } else if(*p == 'f') { // float - len += swf_SetU30(tag, pool_register_float(pool, *(double*)data)); - } else if(*p == 'u') { // integer - len += swf_SetU30(tag, (ptroff_t)data); - } else if(*p == 'r') { // integer - len += swf_SetU30(tag, (ptroff_t)data); - } else if(*p == 'b') { // byte - if(tag) - swf_SetU8(tag, (ptroff_t)data); - len++; - } else if(*p == 'j') { // jump - int skip = length-c->pos-4; - if(c->branch) - skip = (c->branch->pos) - c->pos - 4; - len += swf_SetS24(tag, skip); - } else if(*p == 's') { // string - int index = pool_register_string2(pool, (string_t*)data); - len += swf_SetU30(tag, index); - } else if(*p == 'D') { // debug statement - if(tag) - swf_SetU8(tag, 1); - len++; - len+=swf_SetU30(tag, pool_register_string(pool,c->data[0])); - if(tag) - swf_SetU8(tag, (ptroff_t)c->data[1]); - len++; - len+=swf_SetU30(tag, 0); - } else if(*p == 'S') { // switch statement - lookupswitch_t*l = (lookupswitch_t*)data; - int offset = 0; - len+=swf_SetS24(tag, l->def->pos-c->pos+offset); //default - code_list_t*t = l->targets; - if(list_length(t)) { - len+=swf_SetU30(tag, list_length(t)-1); //nr-1 + switch(*p) { + case 'n': { // number + len += swf_SetU30(tag, (ptroff_t)data); + break; + } + case '2': { //multiname + multiname_t*m = (multiname_t*)data; + len += swf_SetU30(tag, pool_register_multiname(pool, m)); + break; + } + case 'N': { //namespace + namespace_t*ns = (namespace_t*)data; + len += swf_SetU30(tag, pool_register_namespace(pool, ns)); + break; + } + case 'm': { //method + abc_method_t*m = (abc_method_t*)data; + len += swf_SetU30(tag, m->index); + break; + } + case 'c': { //classinfo + abc_class_t*cls = (abc_class_t*)data; + len += swf_SetU30(tag, cls->index); + break; + } + case 'i': { //methodbody + abc_method_body_t*m = (abc_method_body_t*)data; + len += swf_SetU30(tag, m->index); + break; + } + case 'I': { // int + len += swf_SetU30(tag, pool_register_int(pool, (ptroff_t)data)); + break; + } + case 'U': { // uint + len += swf_SetU30(tag, pool_register_uint(pool, (ptroff_t)data)); + break; + } + case 'f': { // float + len += swf_SetU30(tag, pool_register_float(pool, *(double*)data)); + break; + } + case 'u': { // integer + len += swf_SetU30(tag, (ptroff_t)data); + break; + } + case 'r': { // integer + len += swf_SetU30(tag, (ptroff_t)data); + break; + } + case 'b': { // byte + if(tag) + swf_SetU8(tag, (ptroff_t)data); + len++; + break; + } + case 'j': { // jump + int skip = length-c->pos-4; + if(c->branch) + skip = (c->branch->pos) - c->pos - 4; + len += swf_SetS24(tag, skip); + break; + } + case 's': { // string + int index = pool_register_string2(pool, (string_t*)data); + len += swf_SetU30(tag, index); + break; + } + case 'D': { // debug statement + if(tag) + swf_SetU8(tag, 1); + len++; + len+=swf_SetU30(tag, pool_register_string(pool,c->data[0])); + if(tag) + swf_SetU8(tag, (ptroff_t)c->data[1]); + len++; + len+=swf_SetU30(tag, 0); + break; + } + case 'S': { // switch statement + lookupswitch_t*l = (lookupswitch_t*)data; + int offset = 0; + len+=swf_SetS24(tag, l->def->pos-c->pos+offset); //default code_list_t*t = l->targets; - while(t) { - len+=swf_SetS24(tag, t->code->pos - c->pos+offset); - t = t->next; + if(list_length(t)) { + len+=swf_SetU30(tag, list_length(t)-1); //nr-1 + code_list_t*t = l->targets; + while(t) { + len+=swf_SetS24(tag, t->code->pos - c->pos+offset); + t = t->next; + } + } else { + len+=swf_SetU30(tag, 0); //nr-1 + len+=swf_SetS24(tag, l->def->pos-c->pos+offset); } - } else { - len+=swf_SetU30(tag, 0); //nr-1 - len+=swf_SetS24(tag, l->def->pos-c->pos+offset); + break; } - } else { - printf("Can't parse opcode param type \"%c\"\n", *p); + default: + printf("Can't parse opcode param type \"%c\"\n", *p); } p++; } @@ -618,7 +658,7 @@ static void dumpstack(currentstats_t*stats) for(t=0;tnum;t++) { code_t*c = stats->stack[t].code; opcode_t*op = opcode_get(c->opcode); - printf("%5d) %c %d:%d %s", t, (stats->stack[t].flags&FLAG_SEEN)?'x':'|', + printf("%05d) %c %d:%d %s", t, (stats->stack[t].flags&FLAG_SEEN)?'x':'|', stats->stack[t].stackpos, stats->stack[t].scopepos, op->name); @@ -631,6 +671,8 @@ static void dumpstack(currentstats_t*stats) } if(op->params[0]=='2') { printf(" %s", multiname_tostring(c->data[0])); + } else if(op->params[0]=='N') { + printf(" %s", namespace_tostring(c->data[0])); } printf("\n"); } @@ -803,15 +845,17 @@ static currentstats_t* code_get_stats(code_t*code, abc_exception_list_t*exceptio for(t=0;topcode); if(op->flags & (OP_JUMP|OP_BRANCH)) { - printf("%5d) %s %08x\n", t, op->name, c->branch); + printf("%05d) %s %08x\n", t, op->name, c->branch); } else if(op->params[0]=='2') { - printf("%5d) %s %s\n", t, op->name, multiname_tostring(c->data[0])); + 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("%5d) %s\n", t, op->name); + printf("%05d) %s\n", t, op->name); } c = c->next; } - //printf("%5d) %02x\n", t, tag->data[start+t]); + //printf("%05d) %02x\n", t, tag->data[start+t]); #endif num = 0; @@ -892,13 +936,13 @@ int code_dump2(code_t*c, abc_exception_list_t*exceptions, abc_file_t*file, char* if(stats) { int f = stats->stack[c->pos].flags; - fprintf(fo, "%s%5d) %c %d:%d %s ", prefix, c->pos, + 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%5d) ? ?:? %s ", prefix, c->pos, op->name); + fprintf(fo, "%s%05d) ? ?:? %s ", prefix, c->pos, op->name); } while(*p) { @@ -914,6 +958,11 @@ int code_dump2(code_t*c, abc_exception_list_t*exceptions, abc_file_t*file, char* 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); @@ -941,7 +990,7 @@ int code_dump2(code_t*c, abc_exception_list_t*exceptions, abc_file_t*file, char* if(c->branch) fprintf(fo, "->%d", c->branch->pos); else - fprintf(fo, "%08x", c->branch); + fprintf(fo, "%08x", (unsigned int)c->branch); } else if(*p == 's') { char*s = string_escape((string_t*)data); fprintf(fo, "\"%s\"", s); @@ -1086,23 +1135,34 @@ code_t*code_dup(code_t*c) { if(!c) return 0; - while(c->prev) c = c->prev; + 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; - opcode_t*op = opcode_get(c->opcode); - if(c->branch || c->opcode == OPCODE_LABEL) { - fprintf(stderr, "Error: Can't duplicate branching code\n"); - return 0; + 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') { @@ -1124,6 +1184,22 @@ code_t*code_dup(code_t*c) 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; } @@ -1149,6 +1225,19 @@ code_t*code_cutlast(code_t*c) return code_cut(c); } +char is_getlocal(code_t*c) +{ + if(!c) return 0; + if(c->opcode == OPCODE_GETLOCAL || + c->opcode == OPCODE_GETLOCAL_0 || + c->opcode == OPCODE_GETLOCAL_1 || + c->opcode == OPCODE_GETLOCAL_2 || + c->opcode == OPCODE_GETLOCAL_3) { + return 1; + } + return 0; +} + code_t* cut_last_push(code_t*c) { assert(!c->next);