// asm.c /* radare - LGPL - Copyright 2007-2012 - pancake */ #include #include #include #include #include #include "code.h" #define V if(verbose) static struct cp_item *cp_items = NULL; static struct cp_item cp_null_item = { .tag = -1, .name = "(NULL)", .value = "(NULL)" // must be strduped }; static RBinJavaClass cf; static struct cp_item * get_cp(int i) { if (i<0||i>cf.cp_count) return &cp_null_item; return &cp_items[i]; } static int java_resolve(int idx, char *str) { if (str == NULL) return 0; str[0]='\0'; if (idx<0||idx>cf.cp_count) return 1; if (cp_items) { if ((!strcmp (cp_items[idx].name, "MethodRef")) || (!strcmp (cp_items[idx].name, "FieldRef"))) { int class = USHORT (get_cp(idx)->bytes,0); //int namet = USHORT(get_cp(idx)->bytes,2); char *class_str = get_cp(USHORT(get_cp(class)->bytes,0)-1)->value; char *namet_str = get_cp(USHORT(get_cp(class)->bytes,2)-1)->value; //char *namet_str = get_cp(namet)->value; sprintf (str, "%s %s", class_str, namet_str); } else if (!strcmp (cp_items[idx].name, "String")) { sprintf(str, "\"%s\"", get_cp(USHORT(get_cp(idx)->bytes,0)-1)->value); } else if (!strcmp(cp_items[idx].name, "Utf8")) { sprintf (str, "\"%s\"", get_cp(idx)->value); } else sprintf (str, "0x%04x", USHORT(get_cp(idx)->bytes,0)); } else strcpy (str, "(null)"); return 0; } int java_print_opcode(int idx, const ut8 *bytes, char *output) { char arg[1024]; switch (java_ops[idx].byte) { case 0x12: case 0x13: case 0x14: java_resolve (bytes[1]-1, arg); sprintf (output, "%s %s", java_ops[idx].name, arg); return java_ops[idx].size; case 0xb2: // getstatic case 0xb6: // invokevirtual case 0xb7: // invokespecial case 0xb8: // invokestatic case 0xb9: // invokeinterface java_resolve ((int)USHORT (bytes,1)-1, arg); sprintf (output, "%s %s", java_ops[idx].name, arg); return java_ops[idx].size; } /* process arguments */ switch (java_ops[idx].size) { case 1: sprintf (output, "%s", java_ops[idx].name); break; case 2: sprintf (output, "%s %d", java_ops[idx].name, bytes[1]); break; case 3: sprintf (output, "%s 0x%x 0x%x", java_ops[idx].name, bytes[0], bytes[1]); break; case 5: sprintf (output, "%s %d", java_ops[idx].name, bytes[1]); break; } return java_ops[idx].size; } R_API int r_java_disasm(const ut8 *bytes, char *output, int len) { int i; for(i = 0;java_ops[i].name != NULL;i++) if (bytes[0] == java_ops[i].byte) return java_print_opcode (i, bytes, output); return -1; } static void check_eof(FILE *fd) { if (feof (fd)) { fprintf(stderr, "Unexpected eof\n"); exit(0); } } R_API int r_java_assemble(ut8 *bytes, const char *string) { char name[128]; int a,b,c,d; int i; sscanf (string, "%s %d %d %d %d", name, &a, &b, &c, &d); for (i = 0;java_ops[i].name != NULL;i++) if (!strcmp (name, java_ops[i].name)) { bytes[0] = java_ops[i].byte; switch (java_ops[i].size) { case 2: bytes[1] = a; break; case 3: bytes[1] = a; bytes[2] = b; break; case 5: bytes[1] = a; bytes[2] = b; bytes[3] = c; bytes[4] = d; break; } return java_ops[i].size; } return 0; } #define resolve(dst,from,field,value) {\ int i;\ for(i=0;from[i].field;i++) {\ if (from[i].field == value) \ dst = &from[i];\ break;\ }\ } unsigned short read_short(FILE *fd) { unsigned short sh = 0; fread (&sh, 2, 1, fd); return r_num_ntohs (sh); } static int attributes_walk(FILE *fd, int sz2, int fields, int verbose) { char *name, buf[99999]; int sz, k, j=0; for (j=0;jvalue; V printf(" %2d: Name Index: %d (%s)\n", j, USHORT(buf,0), name); // TODO add comment with constant pool index if (fields) { V printf("FIELD\n"); } else { V printf (" Length: %d\n", UINT (buf, 2)); if (!name) { printf ("**ERROR ** Cannot identify attribute name into constant pool\n"); continue; } if (!strcmp (name, "Code")) { fread(buf, 8, 1, fd); V printf(" Max Stack: %d\n", USHORT(buf, 0)); V printf(" Max Locals: %d\n", USHORT(buf, 2)); V printf(" Code Length: %d\n", UINT(buf, 4)); V printf(" Code At Offset: 0x%08"PFMT64x"\n", (ut64)ftell(fd)); fread(buf, UINT(buf, 4), 1, fd); // READ CODE sz = read_short(fd); V printf(" Exception table length: %d\n", sz); for (k=0;k0) attributes_walk(fd, sz, fields, verbose); } else if (!strcmp(name, "LineNumberTable")) { sz = (int)read_short(fd); V printf(" Table Length: %d\n", sz); for(k=0;kname); /* store constant pool item */ strcpy( cp_items[i].name, c->name); cp_items[i].tag = c->tag; cp_items[i].value = NULL; // no string by default cp_items[i].off = ftell(fd)-1; /* read bytes */ switch (c->tag) { case 1: // utf 8 string fread (buf, 2, 1, fd); sz = USHORT (buf,0); //cp_items[i].len = sz; fread(buf, sz, 1, fd); buf[sz] = '\0'; break; default: fread(buf, c->len, 1, fd); } memcpy (cp_items[i].bytes, buf, 5); /* parse value */ switch(c->tag) { case 1: V printf ("%s\n", buf); cp_items[i].value = strdup(buf); break; case 7: V printf ("%d\n", USHORT(buf,0)); break; case 8: V printf ("string ptr %d\n", USHORT(buf, 0)); break; case 9: case 11: case 10: // METHOD REF V printf("class = %d, ", USHORT(buf,0)); V printf("name_type = %d\n", USHORT(buf,2)); break; case 12: V printf("name = %d, ", USHORT(buf,0)); V printf("descriptor = %d\n", USHORT(buf,2)); break; default: V printf("%d\n", UINT(buf, 40)); } } fread (&cf2, sizeof (RBinJavaClass2), 1, fd); check_eof(fd); V printf("Access flags: 0x%04x\n", cf2.access_flags); this_class = r_num_ntohs (cf2.this_class); V printf ("This class: %d\n", this_class); check_eof (fd); //printf("This class: %d (%s)\n", ntohs(cf2.this_class), cp_items[ntohs(cf2.this_class)-1].value); // XXX this is a double pointer !!1 //printf("Super class: %d (%s)\n", ntohs(cf2.super_class), cp_items[ntohs(cf2.super_class)-1].value); sz = read_short (fd); V printf ("Interfaces count: %d\n", sz); if (sz>0) { fread (buf, sz*2, 1, fd); sz = read_short (fd); for (i=0; i0) { for (i=0;ivalue); V printf(" Descriptor Index: %d\n", USHORT(buf, 4)); //, cp_items[USHORT(buf, 4)-1].value); sz2 = USHORT(buf, 6); V printf(" field Attributes Count: %d\n", sz2); attributes_walk(fd, sz2, 1, verbose); } } sz = read_short(fd); V printf("Methods count: %d\n", sz); if (sz>0) { for (i=0;ivalue); V printf(" Descriptor Index: %d (%s)\n", USHORT(buf, 4), get_cp(USHORT(buf, 4)-1)->value); sz2 = USHORT(buf, 6); V printf(" method Attributes Count: %d\n", sz2); attributes_walk(fd, sz2, 0, verbose); } } fclose(fd); return 0; } #endif