?? classread.cc
字號:
/* * HT Editor * classread.cc * * Copyright (C) 2001 Stanley Gambarin <stanleyg76@yahoo.com> * Copyright (C) 2002 Sebastian Biallas (sb@biallas.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdlib.h>#include <string.h>#include "analy.h"#include "class.h"#include "strtools.h"#include "snprintf.h"#include "stream.h"static u1 inp[4];static u4 offset;#define cls_read(a, b, c, d) (((b) != ((d)->read((a), (b)*(c)))) \ ? (0) : (offset+=(b), (b)))#define READ1() \ (((inp[0]=inp[1]=inp[2]=inp[3]=0), \ (1 == cls_read (inp, 1, 1, htio))) \ ? (u1)(inp[0]) : 0)#define READ2() \ (((inp[0]=inp[1]=inp[2]=inp[3]=0), \ (2 == cls_read (inp, 2, 1, htio))) \ ? ((((u2)inp[0])<<8)|inp[1]) : 0)#define READ4() \ (((inp[0]=inp[1]=inp[2]=inp[3]=0), \ (4 == cls_read (inp, 4, 1, htio))) \ ? (((((((u4)inp[0]<<8)|inp[1])<<8)|inp[2])<<8)|inp[3]) : 0)#define READN(inb, n) cls_read (inb, n, 1, htio)#define SKIPN(n) {u1 b; for (u4 i=0; i<n; i++) {cls_read(&b, 1, 1, htio);}}ClassMethod::ClassMethod(char *n, char *d, ClassAddress s, uint l, int f, int e_len, exception_info *e){ name = n; start = s; type = d; length = l; flags = f; exctbl_len = e_len; exctbl = e;}int ClassMethod::compareTo(const Object *obj) const{ ClassMethod *cm = (ClassMethod*)obj; if ((start + length - 1) < cm->start) return -1; if (start > (cm->start + cm->length - 1)) return 1; return 0;}ClassField::ClassField(char *n, char *d, int f){ name = n; type = d; flags = f;}/* extract name from a utf8 constant pool entry */static char *get_string(Stream *htio, classfile *clazz, uint index){ return (index < clazz->cpool_count) ? clazz->cpool[index]->value.string : (char*)"?";}/* extract name from a utf8 constant pool class entry */static char *get_class_name(Stream *htio, classfile *clazz, uint index){ return (index < clazz->cpool_count) ? get_string(htio, clazz, clazz->cpool[index]->value.llval[0]): (char*)"?";}/* extract name from a utf8 constant pool class entry */static void get_name_and_type(Stream *htio, classfile *clazz, uint index, char *name, char *type){ strcpy(name, (index < clazz->cpool_count) ? get_string(htio, clazz, clazz->cpool[index]->value.llval[0]) : "?"); strcpy(type, (index < clazz->cpool_count) ? get_string(htio, clazz, clazz->cpool[index]->value.llval[1]) : "?");}/* read and return constant pool entry */static cp_info *read_cpool_entry(Stream *htio, classfile *clazz){ cp_info *cp; u2 idx; cp = ht_malloc(sizeof (*cp)); cp->offset = offset; cp->tag = READ1(); switch (cp->tag) { case CONSTANT_Utf8: idx = READ2(); cp->value.string = ht_malloc(idx+1); cls_read(cp->value.string, idx, 1, htio); cp->value.string[idx] = 0; break; case CONSTANT_Integer: case CONSTANT_Float: cp->value.ival = READ4(); break; case CONSTANT_Long: case CONSTANT_Double: cp->value.llval[0] = READ4(); cp->value.llval[1] = READ4(); break; case CONSTANT_Class: case CONSTANT_String: cp->value.llval[0] = READ2(); break; case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: case CONSTANT_NameAndType: cp->value.llval[0] = READ2(); cp->value.llval[1] = READ2(); break; default: return NULL; } return (cp);}/* read and return an attribute read */attrib_info *attribute_read(Stream *htio, classfile *clazz){ attrib_info *a; u4 len; char *aname; a = ht_malloc(sizeof (*a)); if (!a) { return NULL; } a->offset = offset; a->name = READ2(); a->len = len = READ4(); aname = get_string(htio, clazz, a->name); if (!strcmp (aname, "ConstantValue")) { a->tag = ATTRIB_ConstantValue; } else if (!strcmp(aname, "Code")) { a->tag = ATTRIB_Code; a->code.max_stack = READ2(); a->code.max_locals = READ2(); a->code.len = READ4(); a->code.start = offset; len -= 2+2+4+a->code.len; SKIPN(a->code.len); a->code.exctbl_len = READ2(); if (a->code.exctbl_len) { a->code.exctbl = ht_malloc(a->code.exctbl_len * sizeof(exception_info)); for (uint i=0; i < a->code.exctbl_len; i++) { a->code.exctbl[i].start_pc = READ2(); a->code.exctbl[i].end_pc = READ2(); a->code.exctbl[i].handler_pc = READ2(); a->code.exctbl[i].catch_type = READ2(); } } len -= 2 + 8*a->code.exctbl_len; } else if (!strcmp(aname, "Signature")) { a->tag = ATTRIB_Signature; a->signature = READ2(); len -= 2; } else if (!strcmp(aname, "Exceptions")) { a->tag = ATTRIB_Exceptions; } else if (!strcmp(aname, "InnerClasses")) { a->tag = ATTRIB_InnerClasses; } else if (!strcmp(aname, "Synthetic")) { a->tag = ATTRIB_Synthetic; } else if (!strcmp(aname, "SourceFile")) { a->tag = ATTRIB_SourceFile; } else if (!strcmp(aname, "LineNumberTable")) { a->tag = ATTRIB_LineNumberTable; } else if (!strcmp(aname, "LocalVariableTable")) { a->tag = ATTRIB_LocalVariableTable; } else if (!strcmp(aname, "Deprecated")) { a->tag = ATTRIB_Deprecated; } SKIPN(len); return (a);}/* read and return method info */static mf_info *read_fieldmethod(Stream *htio, ht_class_shared_data *shared){ mf_info *m; u2 idx; classfile *clazz = shared->file; m = (mf_info *)calloc(1, sizeof (*m)); if (!m) { return NULL; } m->offset = offset; m->flags = READ2(); m->name = get_string(htio, clazz, READ2()); m->desc = get_string(htio, clazz, READ2()); m->attribs_count = idx = READ2(); if (idx) { m->attribs = ht_malloc(idx * sizeof (*(m->attribs))); if (!m->attribs) { return NULL; } for (int i=0; i < (int)idx; i++) { m->attribs[i] = attribute_read(htio, clazz); } } return m;}/* read and return classfile */ht_class_shared_data *class_read(File *htio){ ht_class_shared_data *shared; classfile *clazz; u2 count; u2 cpcount, index; clazz = ht_malloc(sizeof (*clazz)); if (!clazz) { return NULL; } shared = ht_malloc(sizeof (ht_class_shared_data)); shared->file = clazz; shared->methods = new AVLTree(true); shared->fields = new Array(true); shared->valid = new Area(); shared->valid->init(); shared->initialized = new Area(); shared->initialized->init(); clazz->offset = offset = 0; clazz->magic = READ4(); if (clazz->magic != 0xCAFEBABE) { return NULL; } clazz->minor_version = READ2(); clazz->major_version = READ2(); count = clazz->cpool_count = READ2(); clazz->cpool = ht_malloc((count+1) * sizeof (*(clazz->cpool))); if (!clazz->cpool) { return NULL; } cpcount = clazz->cpool_count; for (int i=1; i<(int)count; i++) { clazz->cpool[i] = read_cpool_entry(htio, clazz); if ((clazz->cpool[i]->tag == CONSTANT_Long) || (clazz->cpool[i]->tag == CONSTANT_Double)) { i++; } } clazz->coffset = offset; clazz->access_flags = READ2(); shared->flags = clazz->access_flags; index = READ2(); clazz->this_class = index; index = READ2(); clazz->super_class = index; count = clazz->interfaces_count = READ2(); shared->classinfo.interfaces = NULL; shared->classinfo.thisclass = get_class_name(htio, clazz, clazz->this_class); if (strcmp(shared->classinfo.thisclass, "?") == 0) return NULL; shared->classinfo.superclass = get_class_name(htio, clazz, clazz->super_class); if (strcmp(shared->classinfo.superclass, "?") == 0) return NULL; if (count) { clazz->interfaces = ht_malloc(count * sizeof (*(clazz->interfaces))); if (!clazz->interfaces) return NULL; shared->classinfo.interfaces = new Array(true); for (int i=0; i < (int)count; i++) { index = READ2(); clazz->interfaces[i] = index; shared->classinfo.interfaces->insert(new String(get_class_name(htio, clazz, index))); } } else { clazz->interfaces = 0; } clazz->foffset = offset; count = clazz->fields_count = READ2(); if (count) { clazz->fields = ht_malloc(count * sizeof (*(clazz->fields))); if (!clazz->fields) { return NULL; } for (int i=0; i < (int)count; i++) { mf_info *m = read_fieldmethod(htio, shared); clazz->fields[i] = m; ClassField *cf = new ClassField(m->name, m->desc, m->flags); int acount = m->attribs_count; for (int j=0; j < acount; j++) { attrib_info *ai = m->attribs[j]; if (ai->tag == ATTRIB_Signature) { cf->addsig(get_string(htio, shared->file, ai->signature)); } } shared->fields->insert(cf); } } else { clazz->fields = 0; } clazz->moffset = offset; count = clazz->methods_count = READ2(); if (count) { clazz->methods = ht_malloc(count * sizeof (*(clazz->methods))); if (!clazz->methods) { return NULL; } for (int i=0; i < (int)count; i++) { mf_info *m = read_fieldmethod(htio, shared); clazz->methods[i] = m; int acount = m->attribs_count; bool ok = false; ClassMethod *cm = NULL; for (int j=0; j < acount; j++) { attrib_info *ai = m->attribs[j]; if (ai->tag == ATTRIB_Code) { cm = new ClassMethod(m->name, m->desc, ai->code.start, ai->code.len, m->flags, ai->code.exctbl_len, ai->code.exctbl); shared->methods->insert(cm); AddressFlat32 a1(ai->code.start); AddressFlat32 a2(ai->code.start+ai->code.len); shared->initialized->add(&a1, &a2); shared->valid->add(&a1, &a2); ok = true; } else if (ai->tag == ATTRIB_Signature && cm) { cm->addsig(get_string(htio, shared->file, ai->signature)); } } if (!ok) { // fake abstract method ClassMethod *cm = new ClassMethod(m->name, m->desc, offset, 1, m->flags, 0, NULL); shared->methods->insert(cm); Address *a1 = new AddressFlat32(offset); Address *a2 = new AddressFlat32(offset+1); shared->valid->add(a1, a2); delete a1; delete a2; } } } else { clazz->methods = 0; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -