From 8f6459977d54d9333c1e8b4af22fefdd764210e2 Mon Sep 17 00:00:00 2001 From: pancake Date: Fri, 16 Nov 2012 02:29:30 +0100 Subject: [PATCH] Refactor of {bin|asm}/java into shlr/java --- libr/anal/p/anal_java.c | 5 +- libr/anal/p/java.mk | 7 +- libr/asm/arch/java/javasm/javasm.h | 41 ----- libr/asm/p/asm_java.c | 12 +- libr/asm/p/java.mk | 11 +- libr/bin/p/bin_java.c | 2 +- libr/bin/p/java.mk | 10 +- shlr/Makefile | 2 + shlr/java/Makefile | 10 ++ shlr/java/README | 1 + .../format/java/java.c => shlr/java/class.c | 123 +++++++------- .../format/java/java.h => shlr/java/class.h | 29 ++-- .../java/javasm/javasm.c => shlr/java/code.c | 153 ++++++------------ shlr/java/code.h | 32 ++++ shlr/java/main.c | 7 + .../java/javasm/java_ops.c => shlr/java/ops.c | 4 +- 16 files changed, 210 insertions(+), 239 deletions(-) delete mode 100644 libr/asm/arch/java/javasm/javasm.h create mode 100644 shlr/java/Makefile create mode 100644 shlr/java/README rename libr/bin/format/java/java.c => shlr/java/class.c (87%) rename libr/bin/format/java/java.h => shlr/java/class.h (84%) rename libr/asm/arch/java/javasm/javasm.c => shlr/java/code.c (68%) create mode 100644 shlr/java/code.h create mode 100644 shlr/java/main.c rename libr/asm/arch/java/javasm/java_ops.c => shlr/java/ops.c (99%) diff --git a/libr/anal/p/anal_java.c b/libr/anal/p/anal_java.c index a33941576d..e917e798c9 100644 --- a/libr/anal/p/anal_java.c +++ b/libr/anal/p/anal_java.c @@ -1,5 +1,4 @@ -/* radare - LGPL - Copyright 2010 */ -/* pancake */ +/* radare - LGPL - Copyright 2010-2012 - pancake */ #include @@ -8,7 +7,7 @@ #include #include -#include "../../asm/arch/java/javasm/javasm.h" +#include "../../../shlr/java/code.h" /* code analysis functions */ diff --git a/libr/anal/p/java.mk b/libr/anal/p/java.mk index f31e3b626a..e86ae72d0e 100644 --- a/libr/anal/p/java.mk +++ b/libr/anal/p/java.mk @@ -1,6 +1,7 @@ OBJ_JAVA=anal_java.o -#OBJ_JAVA+=$(realpath $(LTOP)/asm/arch/java/javasm/java_ops.o) -OBJ_JAVA+=../../asm/arch/java/javasm/java_ops.o +SHARED_JAVA+=../../shlr/java/ops.o +SHARED2_JAVA=$(addprefix ../,${SHARED_JAVA}) +OBJ_JAVA+=${SHARED2_JAVA} STATIC_OBJ+=${OBJ_JAVA} TARGET_JAVA=anal_java.${EXT_SO} @@ -8,4 +9,4 @@ TARGET_JAVA=anal_java.${EXT_SO} ALL_TARGETS+=${TARGET_JAVA} ${TARGET_JAVA}: ${OBJ_JAVA} - ${CC} $(call libname,anal_java) ${CFLAGS} -o anal_java.${EXT_SO} ${OBJ_JAVA} + ${CC} $(call libname,anal_java) ${CFLAGS} -o anal_java.${EXT_SO} ${OBJ_JAVA} ${SHARED2_JAVA} diff --git a/libr/asm/arch/java/javasm/javasm.h b/libr/asm/arch/java/javasm/javasm.h deleted file mode 100644 index 3b292bc97d..0000000000 --- a/libr/asm/arch/java/javasm/javasm.h +++ /dev/null @@ -1,41 +0,0 @@ -#include - -#define USHORT(x,y) (unsigned short)((0xff&x[y+1]|((x[y]&0xff)<<8)) & 0xffff) -#define UINT(x,y) (unsigned int)(((x[y]&0xff)<<24)|((x[y+1]&0xff)<<16)|((x[y+2]&0xff)<<8)|(x[y+3]&0xff)) - -struct classfile { - unsigned char cafebabe[4]; - unsigned char minor[2]; - unsigned char major[2]; - unsigned short cp_count; -}; - -struct classfile2 { - unsigned short access_flags; - unsigned short this_class; - unsigned short super_class; -}; - -struct cp_item { - int tag; - char name[255]; - char *value; - unsigned char bytes[5]; - ut64 off; -}; - -struct java_op { - char *name; - unsigned char byte; - int size; -}; -extern struct java_op java_ops[]; -//extern struct cp_item *cp_items; -//extern struct cp_item cp_null_item; // NOTE: must be initialized for safe use - -int java_print_opcode(int idx, const ut8 *bytes, char *output, int len); -int java_disasm(const ut8 *bytes, char *output, int len); -int java_assemble(unsigned char *bytes, const char *string); -unsigned short read_short(FILE *fd); -void javasm_init(); -int java_classdump(const char *file, int verbose); diff --git a/libr/asm/p/asm_java.c b/libr/asm/p/asm_java.c index 14c0448227..36ca338a86 100644 --- a/libr/asm/p/asm_java.c +++ b/libr/asm/p/asm_java.c @@ -1,26 +1,30 @@ -/* radare - LGPL - Copyright 2009-2012 - nibble */ +/* radare - LGPL - Copyright 2009-2012 - nibble, pancake */ #include #include #include #include -#include +#include "../../shlr/java/code.h" #include static const char *lastfile = NULL; static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, ut64 len) { // XXX: crossmodule dependency RCore *core = (RCore*)a->user; +// TODO: get class info from rbin if loaded +#if 0 if (core && core->file && lastfile != core->file->filename) { lastfile = core->file->filename; java_classdump (lastfile, 0); } else javasm_init (); - return op->inst_len = java_disasm (buf, op->buf_asm, sizeof (op->buf_asm)); +#endif + return op->inst_len = r_java_disasm (buf, op->buf_asm, sizeof (op->buf_asm)); } static int assemble(RAsm *a, RAsmOp *op, const char *buf) { - return op->inst_len = java_assemble (op->buf, buf); + // TODO: get class info from bin if possible + return op->inst_len = r_java_assemble (op->buf, buf); } RAsmPlugin r_asm_plugin_java = { diff --git a/libr/asm/p/java.mk b/libr/asm/p/java.mk index bbee48f779..588c610ef5 100644 --- a/libr/asm/p/java.mk +++ b/libr/asm/p/java.mk @@ -1,11 +1,16 @@ OBJ_JAVA=asm_java.o -OBJ_JAVA+=../arch/java/javasm/javasm.o -OBJ_JAVA+=../arch/java/javasm/java_ops.o + +SHARED_JAVA+=../../shlr/java/class.o +SHARED_JAVA+=../../shlr/java/code.o +SHARED_JAVA+=../../shlr/java/ops.o +SHARED2_JAVA=$(addprefix ../,${SHARED_JAVA}) STATIC_OBJ+=${OBJ_JAVA} +SHARED_OBJ+=${SHARED_JAVA} TARGET_JAVA=asm_java.${EXT_SO} ALL_TARGETS+=${TARGET_JAVA} ${TARGET_JAVA}: ${OBJ_JAVA} - ${CC} $(call libname,asm_java) ${LDFLAGS} ${CFLAGS} -o asm_java.${EXT_SO} ${OBJ_JAVA} + ${CC} $(call libname,asm_java) ${LDFLAGS} ${CFLAGS} \ + -o asm_java.${EXT_SO} ${OBJ_JAVA} ${SHARED2_JAVA} diff --git a/libr/bin/p/bin_java.c b/libr/bin/p/bin_java.c index a6092347f8..af5008eb7a 100644 --- a/libr/bin/p/bin_java.c +++ b/libr/bin/p/bin_java.c @@ -5,7 +5,7 @@ #include #include #include -#include "java/java.h" +#include "../../shlr/java/class.h" static int load(RBinArch *arch) { if (!(arch->bin_obj = r_bin_java_new_buf (arch->buf))) diff --git a/libr/bin/p/java.mk b/libr/bin/p/java.mk index 08eb353dbf..e2e12490ec 100644 --- a/libr/bin/p/java.mk +++ b/libr/bin/p/java.mk @@ -1,9 +1,15 @@ -OBJ_JAVA=bin_java.o ../format/java/java.o +OBJ_JAVA=bin_java.o +#../format/java/java.o +SHARED_JAVA=../../shlr/java/class.o +SHARED_JAVA+=../../shlr/java/code.o +SHARED_JAVA+=../../shlr/java/ops.o +SHARED2_JAVA=$(addprefix ../,${SHARED_JAVA}) STATIC_OBJ+=${OBJ_JAVA} +SHARED_OBJ+=${SHARED_JAVA} TARGET_JAVA=bin_java.${EXT_SO} ALL_TARGETS+=${TARGET_JAVA} ${TARGET_JAVA}: ${OBJ_JAVA} - ${CC} $(call libname,bin_java) ${CFLAGS} ${OBJ_JAVA} $(LDFLAGS) + ${CC} $(call libname,bin_java) ${CFLAGS} ${OBJ_JAVA} $(LDFLAGS) ${SHARED2_JAVA} diff --git a/shlr/Makefile b/shlr/Makefile index 6c9f2c60d3..77831a8ffb 100644 --- a/shlr/Makefile +++ b/shlr/Makefile @@ -1,5 +1,7 @@ all: cd udis86 ; ${MAKE} + cd java ; ${MAKE} clean mrproper: cd udis86 ; ${MAKE} clean + cd java ; ${MAKE} clean diff --git a/shlr/java/Makefile b/shlr/java/Makefile new file mode 100644 index 0000000000..a563399510 --- /dev/null +++ b/shlr/java/Makefile @@ -0,0 +1,10 @@ +CFLAGS+=-I../../libr/include +OBJS=code.o class.o ops.o + +all: out + +out: ${OBJS} + ${CC} -g ${CFLAGS} -I. ${OBJS} main.c -lr_util -o out + +clean: + rm -f ${OBJS} a.out diff --git a/shlr/java/README b/shlr/java/README new file mode 100644 index 0000000000..100737733f --- /dev/null +++ b/shlr/java/README @@ -0,0 +1 @@ +Export constant pool as key-value database diff --git a/libr/bin/format/java/java.c b/shlr/java/class.c similarity index 87% rename from libr/bin/format/java/java.c rename to shlr/java/class.c index 01b4e75e47..b85174b2f9 100644 --- a/libr/bin/format/java/java.c +++ b/shlr/java/class.c @@ -1,25 +1,15 @@ -// XXX this is dupped in r_asm and r_bin :O -/* - * Copyright (C) 2007-2012 - * pancake , nibble - */ +/* radare - LGPL - Copyright 2007-2012 - pancake */ #include #include #include -//#include #include #include -#include "java.h" +#include "class.h" #include #include -//#define IFDBG if(1) -static struct constant_t { - char *name; - int tag; - int len; -} constants[] = { +static RBinJavaConstant r_bin_java_constants[] = { { "Class", 7, 2 }, // 2 name_idx { "FieldRef", 9, 4 }, // 2 class idx, 2 name/type_idx { "MethodRef", 10, 4 }, // 2 class idx, 2 name/type_idx @@ -34,9 +24,10 @@ static struct constant_t { { NULL, 0, 0 } }; -static struct r_bin_java_cp_item_t cp_null_item = {0}; // NOTE: must be initialized for safe use +// NOTE: must be initialized for safe use +static struct r_bin_java_cp_item_t cp_null_item = {0}; -static unsigned short read_short(RBinJavaObj *bin) { +static ut16 read_short(RBinJavaObj *bin) { ut16 sh = 0; r_buf_read_at (bin->b, R_BUF_CUR, (ut8*)&sh, 2); return R_BIN_JAVA_SWAPUSHORT (sh); @@ -197,15 +188,15 @@ eprintf ("local.%d.%d.name=%s\n", bin->midx, i, name); } static int javasm_init(RBinJavaObj *bin) { - unsigned short sz, sz2; - char buf[0x4096]; - int i, j; + RBinJavaConstant *c; + int i, j, bufsz; + ut16 sz, sz2; + char *buf; /* Initialize structs */ - bin->cp_items = NULL; bin->fields = NULL; bin->methods = NULL; - + bin->cp_items = NULL; bin->lines.count = 0; /* Initialize cp_null_item */ @@ -214,7 +205,7 @@ static int javasm_init(RBinJavaObj *bin) { cp_null_item.value = strdup ("(null)"); /* start parsing */ - r_buf_read_at (bin->b, R_BUF_CUR, (ut8*)&bin->cf, 10); //sizeof(struct r_bin_java_classfile_t), 1, bin->fd); + r_buf_read_at (bin->b, R_BUF_CUR, (ut8*)&bin->cf, 10); if (memcmp (bin->cf.cafebabe, "\xCA\xFE\xBA\xBE", 4)) { eprintf ("javasm_init: Invalid header (%02x %02x %02x %02x)\n", bin->cf.cafebabe[0], bin->cf.cafebabe[1], @@ -224,27 +215,26 @@ static int javasm_init(RBinJavaObj *bin) { bin->cf.cp_count = R_BIN_JAVA_SWAPUSHORT (bin->cf.cp_count); if (bin->cf.major[0]==bin->cf.major[1] && bin->cf.major[0]==0) { - fprintf (stderr, "This is not a Java CLASS. It looks like a MACH0 header\n"); + eprintf ("Java CLASS with MACH0 header?\n"); return R_FALSE; } bin->cf.cp_count--; IFDBG printf ("ConstantPoolCount %d\n", bin->cf.cp_count); - bin->cp_items = malloc (sizeof (struct r_bin_java_cp_item_t)*(bin->cf.cp_count+1)); - for (i=0;icf.cp_count;i++) { - struct constant_t *c; - + bin->cp_items = malloc (sizeof (RBinJavaCpItem)*(bin->cf.cp_count+1)); + bufsz = 1024; + buf = malloc (bufsz); + for (i=0; icf.cp_count; i++) { r_buf_read_at (bin->b, R_BUF_CUR, (ut8*)buf, 1); - c = NULL; - for (j=0; constants[j].name; j++) { - if (constants[j].tag == buf[0]) { - c = &constants[j]; + for (j=0; r_bin_java_constants[j].name; j++) { + if (r_bin_java_constants[j].tag == buf[0]) { + c = &r_bin_java_constants[j]; break; } } if (c == NULL) { - fprintf (stderr, "Invalid tag '%d' at offset 0x%08"PFMT64x"\n", + eprintf ("Invalid tag '%d' at offset 0x%08"PFMT64x"\n", *buf, (ut64)bin->b->cur); return R_FALSE; } @@ -264,13 +254,16 @@ static int javasm_init(RBinJavaObj *bin) { sz = R_BIN_JAVA_USHORT (buf, 0); bin->cp_items[i].length = sz; bin->cp_items[i].off += 3; - if (szb, R_BUF_CUR, (ut8*)buf, sz); - buf[sz] = '\0'; - } else { - eprintf ("Invalid utf8 length %d\n", sz); - buf[0] = 0; + if (sz>=bufsz) { + free (buf); + buf = malloc (sz); + if (!buf) { + eprintf ("ETOOBIGSTR\n"); + break; + } } + r_buf_read_at (bin->b, R_BUF_CUR, (ut8*)buf, sz); + buf[sz] = '\0'; break; default: r_buf_read_at (bin->b, R_BUF_CUR, (ut8*)buf, c->len); @@ -308,6 +301,8 @@ static int javasm_init(RBinJavaObj *bin) { printf ("%d\n", R_BIN_JAVA_UINT (buf, 40)); } } + free (buf); + buf = NULL; r_buf_read_at (bin->b, R_BUF_CUR, (ut8*)&bin->cf2, sizeof(struct r_bin_java_classfile2_t)); IFDBG printf ("Access flags: 0x%04x\n", bin->cf2.access_flags); @@ -320,12 +315,14 @@ static int javasm_init(RBinJavaObj *bin) { /* TODO: intefaces*/ IFDBG printf("Interfaces count: %d\n", sz); if (sz>0) { - r_buf_read_at(bin->b, R_BUF_CUR, (ut8*)buf, sz*2); - sz = read_short(bin); + bufsz = sz*2; + buf = malloc (bufsz+8); + r_buf_read_at(bin->b, R_BUF_CUR, (ut8*)buf, bufsz); + sz = read_short (bin); for (i=0;ifields_count = sz; @@ -333,8 +330,8 @@ static int javasm_init(RBinJavaObj *bin) { if (sz>0) { bin->fields = malloc (1+sz * sizeof(struct r_bin_java_fm_t)); for (i=0; ib, R_BUF_CUR, (ut8*)buf, 8); - bin->fields[i].flags = R_BIN_JAVA_USHORT(buf, 0); + r_buf_read_at (bin->b, R_BUF_CUR, (ut8*)buf, 8); + bin->fields[i].flags = R_BIN_JAVA_USHORT (buf, 0); IFDBG printf("%2d: Access Flags: %d\n", i, bin->fields[i].flags); bin->fields[i].name_idx = R_BIN_JAVA_USHORT(buf, 2); bin->fields[i].name = r_str_dup (NULL, (get_cp (bin, R_BIN_JAVA_USHORT(buf,2)-1))->value); @@ -353,13 +350,13 @@ static int javasm_init(RBinJavaObj *bin) { } } - sz = read_short(bin); + sz = read_short (bin); bin->methods_count = sz; - IFDBG printf("Methods count: %d\n", sz); + IFDBG eprintf ("Methods count: %d\n", sz); if (sz>0) { bin->methods = malloc(sz * sizeof(struct r_bin_java_fm_t)); for (i=0; ib, R_BUF_CUR, (ut8*)buf, 8); + r_buf_read_at (bin->b, R_BUF_CUR, (ut8*)buf, 8); bin->methods[i].flags = R_BIN_JAVA_USHORT(buf, 0); IFDBG printf("%2d: Access Flags: %d\n", i, bin->methods[i].flags); @@ -391,32 +388,31 @@ bin->midx = i; } } } - + free (buf); return R_TRUE; } -char* r_bin_java_get_version(RBinJavaObj* bin) { - return r_str_dup_printf("0x%02x%02x 0x%02x%02x", +R_API char* r_bin_java_get_version(RBinJavaObj* bin) { + return r_str_dup_printf ("0x%02x%02x 0x%02x%02x", bin->cf.major[1],bin->cf.major[0], bin->cf.minor[1],bin->cf.minor[0]); } -ut64 r_bin_java_get_main(RBinJavaObj* bin) { +R_API ut64 r_bin_java_get_main(RBinJavaObj* bin) { int i, j; for (i=0; i < bin->methods_count; i++) { if (!strcmp(bin->methods[i].name, "main([Ljava/lang/String;)V")) for (j=0; j < bin->methods[i].attr_count; j++) if (bin->methods[i].attributes[j].type == R_BIN_JAVA_TYPE_CODE) return (ut64)bin->methods[i].attributes->info.code.code_offset; -//eprintf ("METH : %s\n", bin->methods[i].name); -} + } return 0; } -ut64 r_bin_java_get_entrypoint(RBinJavaObj* bin) { +R_API ut64 r_bin_java_get_entrypoint(RBinJavaObj* bin) { int i, j; for (i=0; i < bin->methods_count; i++) - if (!strcmp(bin->methods[i].name, "()V")) + if (!strcmp (bin->methods[i].name, "()V")) for (j=0; j < bin->methods[i].attr_count; j++) if (bin->methods[i].attributes[j].type == R_BIN_JAVA_TYPE_CODE) return (ut64)bin->methods[i].attributes->info.code.code_offset; @@ -427,7 +423,8 @@ struct r_bin_java_sym_t* r_bin_java_get_symbols(RBinJavaObj* bin) { struct r_bin_java_sym_t *symbols; int ns, i, j, ctr = 0; - if ((symbols = malloc ((bin->methods_count + 1) * sizeof(struct r_bin_java_sym_t))) == NULL) + if (!(symbols = malloc ((bin->methods_count + 1) * \ + sizeof (struct r_bin_java_sym_t)))) return NULL; bin->fsym = 0; bin->fsymsz = 0; @@ -456,9 +453,10 @@ struct r_bin_java_str_t* r_bin_java_get_strings(RBinJavaObj* bin) { struct r_bin_java_str_t *strings = NULL; int i, ctr = 0; - for(i=0;icf.cp_count;i++) + for (i=0; icf.cp_count; i++) { if (bin->cp_items[i].tag == 1) { - if ((strings = realloc(strings, (ctr + 1) * sizeof(struct r_bin_java_str_t))) == NULL) + if ((strings = realloc(strings, (ctr + 1) * \ + sizeof (RBinJavaString))) == NULL) return NULL; strings[ctr].offset = (ut64)bin->cp_items[i].off; strings[ctr].ordinal = (ut64)bin->cp_items[i].ord; @@ -467,15 +465,17 @@ struct r_bin_java_str_t* r_bin_java_get_strings(RBinJavaObj* bin) { strings[ctr].last = 0; ctr++; } + } if (ctr) { - if ((strings = realloc(strings, (ctr + 1) * sizeof(struct r_bin_java_str_t))) == NULL) + if (!(strings = realloc (strings, (ctr + 1) * + sizeof (RBinJavaString)))) return NULL; strings[ctr].last = 1; } return strings; } -void* r_bin_java_free(RBinJavaObj* bin) { +R_API void* r_bin_java_free(RBinJavaObj* bin) { if (!bin) return NULL; if (bin->cp_items) free (bin->cp_items); if (bin->fields) free (bin->fields); @@ -485,7 +485,7 @@ void* r_bin_java_free(RBinJavaObj* bin) { return NULL; } -RBinJavaObj* r_bin_java_new(const char* file) { +R_API RBinJavaObj* r_bin_java_new(const char* file) { ut8 *buf; RBinJavaObj *bin = R_NEW0 (RBinJavaObj); bin->file = file; @@ -500,13 +500,12 @@ RBinJavaObj* r_bin_java_new(const char* file) { return bin; } -RBinJavaObj* r_bin_java_new_buf(RBuffer *buf) { +R_API RBinJavaObj* r_bin_java_new_buf(RBuffer *buf) { RBinJavaObj *bin = R_NEW0 (RBinJavaObj); if (!bin) return NULL; bin->b = buf; bin->size = buf->length; - // seek backward - buf->cur = 0; + buf->cur = 0; // rewind if (!javasm_init (bin)) return r_bin_java_free (bin); return bin; diff --git a/libr/bin/format/java/java.h b/shlr/java/class.h similarity index 84% rename from libr/bin/format/java/java.h rename to shlr/java/class.h index 8ba2387649..772e2adddc 100644 --- a/libr/bin/format/java/java.h +++ b/shlr/java/class.h @@ -1,7 +1,9 @@ #include -#define R_BIN_JAVA_MAXSTR 256 +#define USHORT(x,y) (unsigned short)(x[y+1]|(x[y]<<8)) +#define UINT(x,y) (unsigned int) ((x[y]<<24)|(x[y+1]<<16)|(x[y+2]<<8)|x[y+3]) +#define R_BIN_JAVA_MAXSTR 256 #define R_BIN_JAVA_USHORT(x,y) (unsigned short)((0xff&x[y+1]|((x[y]&0xff)<<8)) & 0xffff) #define R_BIN_JAVA_UINT(x,y) (unsigned int)(((x[y]&0xff)<<24)|((x[y+1]&0xff)<<16)|((x[y+2]&0xff)<<8)|(x[y+3]&0xff)) @@ -14,20 +16,20 @@ enum { R_BIN_JAVA_TYPE_CONST }; -struct r_bin_java_classfile_t { +typedef struct r_bin_java_classfile_t { ut8 cafebabe[4]; ut8 minor[2]; ut8 major[2]; unsigned short cp_count; -}; +} RBinJavaClass; -struct r_bin_java_classfile2_t { +typedef struct r_bin_java_classfile2_t { unsigned short access_flags; unsigned short this_class; unsigned short super_class; -}; +} RBinJavaClass2; -struct r_bin_java_cp_item_t { +typedef struct r_bin_java_cp_item_t { int tag; char name[32]; char *value; @@ -35,8 +37,13 @@ struct r_bin_java_cp_item_t { unsigned short length; unsigned short ord; unsigned short off; -}; +} RBinJavaCpItem; +typedef struct r_bin_java_constant_t { + char *name; + int tag; + int len; +} RBinJavaConstant; struct r_bin_java_attr_code_t { unsigned short max_stack; unsigned short max_locals; @@ -101,20 +108,20 @@ typedef struct r_bin_java_obj_t { int fsymsz; } RBinJavaObj; -struct r_bin_java_sym_t { +typedef struct r_bin_java_sym_t { char name[R_BIN_JAVA_MAXSTR]; ut64 offset; // XXX: ut64 is too much ut64 size; int last; -}; +} RBinJavaSymbol; -struct r_bin_java_str_t { +typedef struct r_bin_java_str_t { char str[R_BIN_JAVA_MAXSTR]; ut64 offset; ut64 ordinal; ut64 size; int last; -}; +} RBinJavaString; char* r_bin_java_get_version(struct r_bin_java_obj_t* bin); ut64 r_bin_java_get_entrypoint(struct r_bin_java_obj_t* bin); diff --git a/libr/asm/arch/java/javasm/javasm.c b/shlr/java/code.c similarity index 68% rename from libr/asm/arch/java/javasm/javasm.c rename to shlr/java/code.c index 831df361c1..81ca9b0676 100644 --- a/libr/asm/arch/java/javasm/javasm.c +++ b/shlr/java/code.c @@ -1,74 +1,23 @@ -// XXX: dupped in rasm, rbin.. rasm must use rbin callback to do it -/* - * Copyright (C) 2007-2011 - * pancake - * - * radare is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * radare is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with radare; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -// TODO: add radare related commands to stdout with -r (R printf..) +// asm.c +/* radare - LGPL - Copyright 2007-2012 - pancake */ #include #include #include #include -//#include #include -#include "javasm.h" -#if __UNIX__ -#include -#include -#endif +#include "code.h" #define V if(verbose) static struct cp_item *cp_items = NULL; -static struct cp_item cp_null_item; // NOTE: must be initialized for safe use - -static struct constant_t { - char *name; - int tag; - int len; -} constants[] = { - { "Class", 7, 2 }, // 2 name_idx - { "FieldRef", 9, 4 }, // 2 class idx, 2 name/type_idx - { "MethodRef", 10, 4 }, // 2 class idx, 2 name/type_idx - { "InterfaceMethodRef", 11, 4 }, // 2 class idx, 2 name/type_idx - { "String", 8, 2 }, // 2 string_idx - { "Integer", 3, 4 }, // 4 bytes - { "Float", 4, 4 }, // 4 bytes - { "Long", 5, 8 }, // 4 high 4 low - { "Double", 6, 8 }, // 4 high 4 low - { "NameAndType", 12, 4 }, // 4 high 4 low - { "Utf8", 1, 2 }, // 2 bytes = length, N bytes string - { NULL, 0, 0 } +static struct cp_item cp_null_item = { + .tag = -1, + .name = "(NULL)", + .value = "(NULL)" // must be strduped }; -static struct classfile cf; - -static ut16 r_ntohs (ut16 foo) { -/* XXX BIGENDIAN NOT DEFINED HERE !!!1 */ -#if BIGENDIAN - /* do nothing */ -#else - ut8 *p = (ut8 *)&foo; - foo = p[1] | p[0]<<8; -#endif - return foo; -} +static RBinJavaClass cf; static struct cp_item * get_cp(int i) { if (i<0||i>cf.cp_count) @@ -76,7 +25,7 @@ static struct cp_item * get_cp(int i) { return &cp_items[i]; } -static int java_resolve(int idx, char *str, int len) { +static int java_resolve(int idx, char *str) { if (str == NULL) return 0; @@ -91,80 +40,77 @@ static int java_resolve(int idx, char *str, int len) { 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; - // TODO forever progress // - snprintf (str, len, "%s %s", class_str, namet_str); + sprintf (str, "%s %s", class_str, namet_str); } else if (!strcmp (cp_items[idx].name, "String")) { - snprintf (str, len, "\"%s\"", - get_cp(USHORT(get_cp(idx)->bytes,0)-1)->value); + sprintf(str, "\"%s\"", get_cp(USHORT(get_cp(idx)->bytes,0)-1)->value); } else if (!strcmp(cp_items[idx].name, "Utf8")) { - snprintf (str, len, "\"%s\"", get_cp(idx)->value); - } else snprintf (str, len, "0x%04x", USHORT(get_cp(idx)->bytes,0)); + 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, int len) { +int java_print_opcode(int idx, const ut8 *bytes, char *output) { char arg[1024]; - switch(java_ops[idx].byte) { + switch (java_ops[idx].byte) { case 0x12: case 0x13: case 0x14: - java_resolve(bytes[1]-1, arg, sizeof (arg)); - snprintf(output, len, "%s %s", java_ops[idx].name, arg); + 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, sizeof (arg)); - snprintf(output, len, "%s %s", java_ops[idx].name, arg); + 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: snprintf(output, len, "%s", java_ops[idx].name); + case 1: sprintf (output, "%s", java_ops[idx].name); break; - case 2: snprintf(output, len, "%s %d", java_ops[idx].name, bytes[1]); + case 2: sprintf (output, "%s %d", java_ops[idx].name, bytes[1]); break; - case 3: snprintf(output, len, "%s 0x%x 0x%x", java_ops[idx].name, bytes[0], bytes[1]); + case 3: sprintf (output, "%s 0x%x 0x%x", java_ops[idx].name, bytes[0], bytes[1]); break; - case 5: snprintf(output, len, "%s %d", java_ops[idx].name, bytes[1]); + case 5: sprintf (output, "%s %d", java_ops[idx].name, bytes[1]); break; } - return java_ops[idx].size; } -int java_disasm(const ut8 *bytes, char *output, int len) { +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, len); + return java_print_opcode (i, bytes, output); return -1; } static void check_eof(FILE *fd) { - if (feof(fd)) { + if (feof (fd)) { fprintf(stderr, "Unexpected eof\n"); exit(0); } } -int java_assemble(unsigned char *bytes, const char *string) { - int i; +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)) { + 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) { + 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; @@ -190,7 +136,7 @@ int java_assemble(unsigned char *bytes, const char *string) { unsigned short read_short(FILE *fd) { unsigned short sh = 0; fread (&sh, 2, 1, fd); - return r_ntohs (sh); + return r_num_ntohs (sh); } static int attributes_walk(FILE *fd, int sz2, int fields, int verbose) { @@ -274,17 +220,12 @@ static int attributes_walk(FILE *fd, int sz2, int fields, int verbose) { return 0; } -void javasm_init() { - cp_null_item.tag = -1; - strcpy (cp_null_item.name, "(null)"); - cp_null_item.value = strdup ("(null)"); -} - +#if 0 int java_classdump(const char *file, int verbose) { - struct classfile2 cf2; + RBinJavaClass2 cf2; unsigned short sz, sz2; int this_class; - char *buf = NULL; + char buf[0x9999]; int i,j; FILE *fd = fopen(file, "rb"); @@ -301,10 +242,10 @@ int java_classdump(const char *file, int verbose) { } /* show class version information */ - V printf("Version: 0x%02x%02x 0x%02x%02x\n", + V printf ("Version: 0x%02x%02x 0x%02x%02x\n", cf.major[1],cf.major[0], cf.minor[1],cf.minor[0]); - cf.cp_count = r_ntohs(cf.cp_count); + cf.cp_count = r_num_ntohs(cf.cp_count); if (cf.major[0]==cf.major[1] && cf.major[0]==0) { fprintf(stderr, "Oops. this is a Mach-O\n"); return 0; @@ -312,27 +253,25 @@ int java_classdump(const char *file, int verbose) { cf.cp_count--; V printf ("ConstantPoolCount %d\n", cf.cp_count); -buf = malloc (0x20000); cp_items = malloc (sizeof (struct cp_item)*(cf.cp_count+1)); for (i=0;iname); /* store constant pool item */ - strcpy (cp_items[i].name, c->name); + 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; @@ -342,7 +281,6 @@ if (!buf[0])break; case 1: // utf 8 string fread (buf, 2, 1, fd); sz = USHORT (buf,0); -printf ("SZ =%d\n", sz); //cp_items[i].len = sz; fread(buf, sz, 1, fd); buf[sz] = '\0'; @@ -380,10 +318,10 @@ printf ("SZ =%d\n", sz); } } - fread (&cf2, sizeof (struct classfile2), 1, fd); + fread (&cf2, sizeof (RBinJavaClass2), 1, fd); check_eof(fd); V printf("Access flags: 0x%04x\n", cf2.access_flags); - this_class = r_ntohs(cf2.this_class); + 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 @@ -431,8 +369,7 @@ printf ("SZ =%d\n", sz); } } -free (buf); fclose(fd); - return 0; } +#endif diff --git a/shlr/java/code.h b/shlr/java/code.h new file mode 100644 index 0000000000..31817c9c22 --- /dev/null +++ b/shlr/java/code.h @@ -0,0 +1,32 @@ +#ifndef _INCLUDE_R_JAVA_H_ +#define _INCLUDE_R_JAVA_H_ + +#include +#include "class.h" + +struct cp_item { + int tag; + char name[255]; + char *value; + unsigned char bytes[5]; + ut64 off; +}; + +struct java_op { + char *name; + unsigned char byte; + int size; +}; + +extern struct java_op java_ops[]; + +int java_print_opcode(int idx, const ut8 *bytes, char *output); +//int r_java_disasm(const ut8 *bytes, char *output, int len); +unsigned short read_short(FILE *fd); +void javasm_init (); +int java_classdump(const char *file, int verbose); + +R_API int r_java_disasm(const ut8 *bytes, char *output, int len); +R_API int r_java_assemble(ut8 *bytes, const char *string); + +#endif diff --git a/shlr/java/main.c b/shlr/java/main.c new file mode 100644 index 0000000000..ea2f8830fa --- /dev/null +++ b/shlr/java/main.c @@ -0,0 +1,7 @@ +#include +#include "code.h" + +int main() { + RBinJavaObj *o = r_bin_java_new ("/tmp/CON.class"); + printf ("Hello World %p\n", o); +} diff --git a/libr/asm/arch/java/javasm/java_ops.c b/shlr/java/ops.c similarity index 99% rename from libr/asm/arch/java/javasm/java_ops.c rename to shlr/java/ops.c index 324fa96e7a..b4e953dccf 100644 --- a/libr/asm/arch/java/javasm/java_ops.c +++ b/shlr/java/ops.c @@ -1,5 +1,7 @@ +/* radare - LGPL - Copyright 2007-2012 - pancake */ + #include -#include "javasm.h" +#include "code.h" struct java_op java_ops[] = { { "aconst_null" , 0x01 , 1 } ,