Refactor of {bin|asm}/java into shlr/java

This commit is contained in:
pancake 2012-11-16 02:29:30 +01:00
parent 8ea25c4a46
commit 8f6459977d
16 changed files with 210 additions and 239 deletions

View File

@ -1,5 +1,4 @@
/* radare - LGPL - Copyright 2010 */
/* pancake<nopcode.org> */
/* radare - LGPL - Copyright 2010-2012 - pancake */
#include <string.h>
@ -8,7 +7,7 @@
#include <r_asm.h>
#include <r_anal.h>
#include "../../asm/arch/java/javasm/javasm.h"
#include "../../../shlr/java/code.h"
/* code analysis functions */

View File

@ -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}

View File

@ -1,41 +0,0 @@
#include <r_types.h>
#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);

View File

@ -1,26 +1,30 @@
/* radare - LGPL - Copyright 2009-2012 - nibble */
/* radare - LGPL - Copyright 2009-2012 - nibble, pancake */
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_asm.h>
#include <java/javasm/javasm.h>
#include "../../shlr/java/code.h"
#include <r_core.h>
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 = {

View File

@ -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}

View File

@ -5,7 +5,7 @@
#include <r_util.h>
#include <r_lib.h>
#include <r_bin.h>
#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)))

View File

@ -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}

View File

@ -1,5 +1,7 @@
all:
cd udis86 ; ${MAKE}
cd java ; ${MAKE}
clean mrproper:
cd udis86 ; ${MAKE} clean
cd java ; ${MAKE} clean

10
shlr/java/Makefile Normal file
View File

@ -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

1
shlr/java/README Normal file
View File

@ -0,0 +1 @@
Export constant pool as key-value database

View File

@ -1,25 +1,15 @@
// XXX this is dupped in r_asm and r_bin :O
/*
* Copyright (C) 2007-2012
* pancake <youterm.com>, nibble <develsec.org>
*/
/* radare - LGPL - Copyright 2007-2012 - pancake */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//#include <getopt.h>
#include <stdarg.h>
#include <unistd.h>
#include "java.h"
#include "class.h"
#include <r_types.h>
#include <r_util.h>
//#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;i<bin->cf.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; i<bin->cf.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 (sz<sizeof (buf)) {
r_buf_read_at (bin->b, 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;i<sz;i++) {
fprintf (stderr, "Interfaces: TODO\n");
}
}
} else buf = malloc (128);
sz = read_short (bin);
bin->fields_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; i<sz; i++) {
r_buf_read_at(bin->b, 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; i<sz; i++) {
r_buf_read_at(bin->b, 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, "<init>()V"))
if (!strcmp (bin->methods[i].name, "<init>()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;i<bin->cf.cp_count;i++)
for (i=0; i<bin->cf.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;

View File

@ -1,7 +1,9 @@
#include <r_types.h>
#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);

View File

@ -1,74 +1,23 @@
// XXX: dupped in rasm, rbin.. rasm must use rbin callback to do it
/*
* Copyright (C) 2007-2011
* pancake <youterm.com>
*
* 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 <r_types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//#include <getopt.h>
#include <stdarg.h>
#include "javasm.h"
#if __UNIX__
#include <netinet/in.h>
#include <arpa/inet.h>
#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;i<cf.cp_count;i++) {
struct constant_t *c;
fread (buf, 1, 1, fd);
if (!buf[0])break;
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) {
eprintf ("--- Invalid tag '%d'\n", buf[0]);
eprintf ("Invalid tag '%d'\n", buf[0]);
return 0;
}
V printf(" %3d %s: ", i+1, c->name);
/* 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

32
shlr/java/code.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef _INCLUDE_R_JAVA_H_
#define _INCLUDE_R_JAVA_H_
#include <r_types.h>
#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

7
shlr/java/main.c Normal file
View File

@ -0,0 +1,7 @@
#include <stdio.h>
#include "code.h"
int main() {
RBinJavaObj *o = r_bin_java_new ("/tmp/CON.class");
printf ("Hello World %p\n", o);
}

View File

@ -1,5 +1,7 @@
/* radare - LGPL - Copyright 2007-2012 - pancake */
#include <stdio.h>
#include "javasm.h"
#include "code.h"
struct java_op java_ops[] = {
{ "aconst_null" , 0x01 , 1 } ,