673 lines · 14.8 KB · C
RawDownload
#include "java.h" /* * Class loader. */ Class	*class;		/* class under translation */PCode	*pcode;		/* pointers to byte code of defined methods */char	*THISCLASS;char	*SUPERCLASS; char*CLASSNAME(int i){	return class->cps[class->cps[i].ci.name_index].utf8.utf8;} char*STRING(int i){	return class->cps[i].utf8.utf8;} typedef	union Fc	Fc; union Fc{	float	f;	uint	ival;}; static doublecanontod(uint v[]){	union { double d; uint ui[2]; } a; 	a.d = 1.;	if(a.ui[0]) {		a.ui[0] = v[0];		a.ui[1] = v[1];	} else {		a.ui[0] = v[1];		a.ui[1] = v[0];	}	return a.d;} /* * Bytecode verification. */ static voidverifyutf8index(int index){	verifycpindex(nil, index, 1 << CON_Utf8);	if(STRING(index) == nil)		verifyerrormess("nil name or descriptor");} static voidverifyclassindex(int index){	verifycpindex(nil, index, 1 << CON_Class);	verifyutf8index(class->cps[index].ci.name_index);} static voidverifyfielddesc(int name_index, int sig_index){	char *sig;	char ftype; 	verifyutf8index(name_index);	verifyutf8index(sig_index);	sig = STRING(sig_index);	ftype = sig[0];	sig = nextjavatype(sig);	if(ftype == 'V' || sig[0] != '\0')		verifyerrormess("field descriptor");} static voidverifymethoddesc(int name_index, int sig_index){	char *name, *sig;	char rtype;	int wargs; 	verifyutf8index(name_index);	name = STRING(name_index);	verifyutf8index(sig_index);	sig = STRING(sig_index); 	/* check special <method> names */	if(name[0] == '<') {		if(strcmp(name, "<init>") == 0)			;		else if(strcmp(name, "<clinit>") == 0) {			if(strcmp(sig, "()V") != 0)				verifyerrormess("<clinit> signature");			return;		} else			verifyerrormess("<method> name");	} 	/* check signature */	if(sig[0] != '(')		goto bad;	sig++;	wargs = 0;	while(sig[0] != ')') {		wargs++;		if(sig[0] == 'J' || sig[0] == 'D')			wargs++;		sig = nextjavatype(sig);	}	sig++;	rtype = sig[0];	sig = nextjavatype(sig);	if(wargs > 255 || sig[0] != '\0' || (name[0] == '<' && rtype != 'V'))bad:		verifyerrormess("method descriptor");} static voidverifycpindexes(void){	int i;	Const *cp;	int nameindex, sigindex, natindex; 	for(i = 1; i < class->cp_count; i++) {		cp = &class->cps[i];		switch(class->cts[i]) {		case CON_Class:			verifyutf8index(cp->ci.name_index);			break;		case CON_Fieldref:		case CON_Methodref:		case CON_InterfaceMref:			verifyclassindex(cp->fmiref.class_index);			natindex = cp->fmiref.name_type_index;			verifycpindex(nil, natindex, 1 << CON_NameAndType);			nameindex = class->cps[natindex].nat.name_index;			sigindex = class->cps[natindex].nat.sig_index;			if(class->cts[i] == CON_Fieldref)				verifyfielddesc(nameindex, sigindex);			else				verifymethoddesc(nameindex, sigindex);			break;		case CON_String:			verifycpindex(nil, cp->string_index, 1 << CON_Utf8);			break;		case CON_Integer:		case CON_Float:		case CON_NameAndType:			/*			 * CON_NameAndType is verified through			 * CON_Fieldref, CON_Methodref, CON_InterfaceMref			 */		case CON_Utf8:			break;		case CON_Long:		case CON_Double:			i++;			break;		}	}} #define CLASSMUTEX	(ACC_FINAL|ACC_ABSTRACT) static voidverifyclassflags(void){	int bad; 	if(class->access_flags & ACC_INTERFACE) {		if(strcmp(SUPERCLASS, "java/lang/Object") != 0)			verifyerrormess("superclass");		/* java bug: ACC_ABSTRACT should be set ???		bad = (class->access_flags & ACC_ABSTRACT) != ACC_ABSTRACT;		*/		bad = 0;		bad += (class->access_flags & ACC_FINAL) != 0;	} else {		bad = (class->access_flags & CLASSMUTEX) == CLASSMUTEX;	}	if(bad)		verifyerrormess("access_flags");} static intmultippp(int flag){	int ret; 	switch(flag & (ACC_PUBLIC|ACC_PRIVATE|ACC_PROTECTED)) {	case 0:	case ACC_PUBLIC:	case ACC_PRIVATE:	case ACC_PROTECTED:		ret = 0;		break;	default:		ret = 1;		break;	}	return ret;} #define IFACEFIELD	(ACC_PUBLIC|ACC_STATIC|ACC_FINAL)#define _IFACEFIELD	(ACC_PRIVATE|ACC_PROTECTED|ACC_VOLATILE|ACC_TRANSIENT)#define FIELDMUTEX	(ACC_FINAL|ACC_VOLATILE)#define CVATTRTAGS	((1<<CON_Integer)|(1<<CON_Long)|(1<<CON_Float)|(1<<CON_Double)|(1<<CON_String)) static voidverifyfield(Field *fp){	int bad, n;	char c; 	verifyfielddesc(fp->name_index, fp->sig_index);	if(class->access_flags & ACC_INTERFACE) {		bad = (fp->access_flags & _IFACEFIELD) != 0;		bad += (fp->access_flags & IFACEFIELD) != IFACEFIELD;	} else {		bad = multippp(fp->access_flags);		bad += (fp->access_flags & FIELDMUTEX) == FIELDMUTEX;	}	if(bad)		verifyerrormess("access_flags"); 	/* verify ConstantValue attribute */	n = CVattrindex(fp);	if(n == 0)		return;	verifycpindex(nil, n, CVATTRTAGS);	c = STRING(fp->sig_index)[0];	switch(class->cts[n]) {	case CON_Integer:		switch(c) {		case 'Z':		case 'B':		case 'C':		case 'S':		case 'I':			bad = 0;			break;		default:			bad = 1;			break;		}		break;	case CON_Long:		bad = (c != 'J');		break;	case CON_Float:		bad = (c != 'F');		break;	case CON_Double:		bad = (c != 'D');		break;	case CON_String:		bad = (c != 'L');		break;	}	if(bad)		verifyerrormess("ConstantValue attribute");} #define IFACEMETHOD	(ACC_PUBLIC|ACC_ABSTRACT)#define _IFACEMETHOD	(ACC_PRIVATE|ACC_PROTECTED|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE)#define _INITFLAGS	(ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE|ACC_ABSTRACT)/* java bug: ACC_SYNCHRONIZED wrongly allowed with ACC_ABSTRACT ???#define METHODMUTEX	(ACC_PRIVATE|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE)*/#define METHODMUTEX	(ACC_PRIVATE|ACC_STATIC|ACC_FINAL|ACC_NATIVE) static voidverifymethod(Method *mp){	int bad;	char *name; 	verifymethoddesc(mp->name_index, mp->sig_index);	name = STRING(mp->name_index);	if(strcmp(name, "<clinit>") == 0)		return;	if(class->access_flags & ACC_INTERFACE) {		bad = (mp->access_flags & _IFACEMETHOD) != 0;		bad += (mp->access_flags & IFACEMETHOD) != IFACEMETHOD;	} else {		bad = multippp(mp->access_flags);		if(strcmp(name, "<init>") == 0)			bad += (mp->access_flags & _INITFLAGS) != 0;		if(mp->access_flags & ACC_ABSTRACT)			bad += (mp->access_flags & METHODMUTEX) != 0;	}	if(bad)		verifyerrormess("access_flags");	/*	 * Code attribute verified during disassembly	 * ignore Exceptions attribute for now	 */} /* * Parse a byte stream into a Class stucture. */ static voidbyte2Class(uchar *text){	Fc fc;	uint v[2];	int i, j;	Field *fp;	Method *mp;	Const *cp;	Attr a; 	uSet(text);	class = Malloc(sizeof(Class)); 	if(u4() != 0xCAFEBABE)		verifyerrormess("magic"); 	class->min = u2();	class->maj = u2(); 	class->cp_count = u2();	class->cps = Mallocz(class->cp_count*sizeof(Const));	class->cts = Mallocz(class->cp_count); 	for(i = 1; i < class->cp_count; i++) {		cp = &class->cps[i];		class->cts[i] = u1();		switch(class->cts[i]) {		case CON_Class:			cp->ci.name_index = u2();			break;		case CON_Fieldref:		case CON_Methodref:		case CON_InterfaceMref:			cp->fmiref.class_index = u2();			cp->fmiref.name_type_index = u2();			break;		case CON_String:			cp->string_index = u2();			break;		case CON_Integer:			cp->tint = u4();			break;		case CON_Float:			fc.ival = (uint)u4();			cp->tdouble = fc.f;			break;		case CON_Long:			cp->tvlong = ((vlong)u4()<<32) | (vlong)u4();			i++;			break;		case CON_Double:			v[0] = (uint)u4();			v[1] = (uint)u4();			cp->tdouble = canontod(v);			i++;			break;		case CON_NameAndType:			cp->nat.name_index = u2();			cp->nat.sig_index = u2();			break;		case CON_Utf8:			cp->utf8.ln = u2();			cp->utf8.utf8 = Malloc(cp->utf8.ln+1);			memmove(cp->utf8.utf8, uPtr(), cp->utf8.ln);			cp->utf8.utf8[cp->utf8.ln] = '\0';			uN(cp->utf8.ln);			break;		default:			verifyerrormess("constant pool tag");		}	} 	verifycpindexes();		/* verify after all are established */ 	class->access_flags = u2();	/* verify after [THIS|SUPER]CLASS set */ 	class->this_class = u2();	verifyclassindex(class->this_class);	THISCLASS = CLASSNAME(class->this_class); 	class->super_class = u2();	if(class->super_class != 0) {		verifyclassindex(class->super_class);		SUPERCLASS = CLASSNAME(class->super_class);	} else if(strcmp(THISCLASS, "java/lang/Object") != 0)		verifyerrormess("superclass"); 	verifyclassflags(); 	/* for compatibility with JavaSoft VM */	if(strncmp(THISCLASS, "inferno/vm/", sizeof("inferno/vm/")-1) == 0) {		/*		 * ACC_ABSTRACT & ACC_FINAL are both set in JVM,		 * but a class can't be declared that way		 */		class->access_flags |= ACC_ABSTRACT;		/*		 * ACC_SUPER not set in JVM, but javac sets it		 * for inferno/vm/Array		 */		class->access_flags &= ~ACC_SUPER;	} else if(class->access_flags & ACC_INTERFACE) {		/* interfaces are implicitly abstract */		class->access_flags |= ACC_ABSTRACT;	} 	class->interfaces_count = u2();	if(class->interfaces_count > 0)		class->interfaces = Malloc(class->interfaces_count*sizeof(ushort));	for(i = 0; i < class->interfaces_count; i++) {		class->interfaces[i] = u2();		verifyclassindex(class->interfaces[i]);	} 	class->fields_count = u2();	if(class->fields_count > 0)		class->fields = Malloc(class->fields_count*sizeof(Field));	for(i = 0, fp = class->fields; i < class->fields_count; i++, fp++) {		fp->access_flags = u2();		fp->name_index = u2();		fp->sig_index = u2();		fp->attr_count = u2();		if(fp->attr_count > 0)			fp->attr_info = Malloc(fp->attr_count*sizeof(Attr));		for(j = 0; j < fp->attr_count; j++)			getattr(&fp->attr_info[j]);		verifyfield(fp);	} 	class->methods_count = u2();	if(class->methods_count > 0) {		class->methods = Malloc(class->methods_count*sizeof(Method));		pcode = Mallocz(class->methods_count*sizeof(PCode));	}	for(i = 0, mp = class->methods; i < class->methods_count; i++, mp++) {		mp->access_flags = u2();		mp->name_index = u2();		mp->sig_index = u2();		mp->attr_count = u2();		if(mp->attr_count > 0)			mp->attr_info = Malloc(mp->attr_count*sizeof(Attr));		for(j = 0; j < mp->attr_count; j++)			getattr(&mp->attr_info[j]);		verifymethod(mp);	} 	/* get SourceFile attribute */	class->source_file = 0;	i = u2();	for(j = 0; j < i; j++) {		getattr(&a);		if(strcmp(STRING(a.name), "SourceFile") == 0) {			class->source_file = (a.info[0] << 8) | a.info[1];			verifyutf8index(class->source_file);			free(a.info);			break;		}		free(a.info);	}} /* * Return Class structure for named class. */ voidClassLoader(char *name){	int fd;	Dir dir;	uchar *bytecode; 	fd = open(name, OREAD);	if(fd < 0)		fatal("ClassLoader: can't open %s: %r\n", name); 	if(dirfstat(fd, &dir) < 0)		fatal("ClassLoader: can't stat %s: %r\n", name); 	bytecode = Malloc(dir.length);	if(read(fd, bytecode, dir.length) != dir.length)		fatal("ClassLoader: read %s: %r\n", name); 	byte2Class(bytecode); 	close(fd);	free(bytecode);} 

Lines 1–500 of 673.