blob: eb9aeb23c61f717da130291b93c0bbc6f4cff55b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __TPOOL_H_
#define __TPOOL_H_
#include "open/vm_class_manipulation.h"
#include "verifier.h"
#include "stackmap.h"
#include "memory.h"
#include "ver_utils.h"
/**
* Verification type constraint structure.
*/
struct vf_TypeConstraint {
const char *source; // constraint source class name
const char *target; // constraint target class name
vf_TypeConstraint *next; // next constraint
};
typedef vf_TypeConstraint* vf_TypeConstraint_p;
//verifier's data stored in classloader
typedef struct {
Memory *pool; // constraint memory pool
vf_Hash *hash; // constraint hash table
vf_Hash *string; // string pool hash table
} vf_ClassLoaderData_t;
struct vf_ValidType {
Class_Handle cls; //class handler
const char* name; //name of the class
};
#define CLASS_NOT_LOADED ((Class_Handle)-1)
class SharedClasswideData;
/**
* Utility class for dealing with Java types, converting object references to SmConstant,
* parsing constantpool, etc.
* TODO: remove constant pool parse and verification from the bytecode verifier.
*/
class vf_TypePool {
public:
vf_TypePool(SharedClasswideData *_classwide, Class_Handle _klass, unsigned table_incr);
~vf_TypePool() {
if( validTypes ) tc_free(validTypes);
}
SmConstant cpool_get_ldcarg(unsigned short cp_idx);
SmConstant cpool_get_ldc2arg(unsigned short cp_idx);
int cpool_is_reftype(unsigned short cp_idx);
int cpool_get_class(unsigned short cp_idx, SmConstant *ref, int expected_dim = 0);
int cpool_get_array(unsigned short cp_idx, SmConstant *ref);
int cpool_get_field(unsigned short cp_idx, SmConstant *ref, SmConstant *value);
int cpool_method_start(unsigned short cp_idx, const char **state, SmConstant *objectref,
unsigned short *name_idx, int opcode);
int cpool_method_get_rettype(const char **state, SmConstant *rettype, int *args_sz);
int cpool_method_next_arg(const char **state, SmConstant *argument);
int cpool_method_is_constructor_call(unsigned short name_idx);
SmConstant get_type(const char *type_name, int name_len);
SmConstant get_ref_type(const char *type_name, int name_len);
SmConstant get_primitive_type(const char type_char);
SmConstant get_ref_from_array(SmConstant element);
SmConstant get_type(const char *type_name) {
return get_type(type_name, (int)strlen(type_name) );
}
SmConstant get_ref_type(const char *type_name) {
return get_ref_type(type_name, (int)strlen(type_name) );
}
int mustbe_assignable(SmConstant from, SmConstant to);
int ref_mustbe_assignable(SmConstant from, SmConstant to);
vf_ValidType *getVaildType(unsigned index) {
assert(index && validTypes && index < validTypesTableSz);
return validTypes + index;
}
Class_Handle sm_get_handler(SmConstant type) {
unsigned index = type.getReferenceIdx();
return getVaildType(index)->cls;
}
const char* sm_get_refname(SmConstant type) {
unsigned index = type.getReferenceIdx();
return getVaildType(index)->name;
}
//return SmConstant (known verification type) corresponding to 'type_name' and cache result in the 'cache'
SmConstant sm_get_const_existing(const char* type_name, SmConstant* cache) {
if( (*cache) == SM_NONE ) {
//TODO: check asm code for strlen
(*cache) = get_ref_type(type_name, (int)strlen(type_name));
}
return (*cache);
}
//return SmConstant (known verification type) corresponding to the super class of the class being verified
//returned value is cached
SmConstant sm_get_const_super() {
const char* _super = class_get_name( class_get_super_class( k_class ));
return get_ref_type(_super, (int)strlen(_super) );
}
//return SmConstant (known verification type) corresponding to the class being verified
//returned value is cached
SmConstant sm_get_const_this() {
return sm_get_const_existing(class_get_name(k_class), &const_this);
}
//return SmConstant (known verification type) corresponding to java/lang/Object
//returned value is cached
SmConstant sm_get_const_object() {
return sm_get_const_existing("java/lang/Object", &const_object);
}
//return SmConstant (known verification type) corresponding to java/lang/Class
//returned value is cached
SmConstant sm_get_const_class() {
return sm_get_const_existing("java/lang/Class", &const_class);
}
//return SmConstant (known verification type) corresponding to java/lang/String
//returned value is cached
SmConstant sm_get_const_string() {
return sm_get_const_existing("java/lang/String", &const_string);
}
//return SmConstant (known verification type) corresponding to java/lang/Throwable
//returned value is cached
SmConstant sm_get_const_throwable() {
return sm_get_const_existing("java/lang/Throwable", &const_throwable);
}
//return SmConstant (known verification type) corresponding to U_8[]
//returned value is cached
SmConstant sm_get_const_arrayref_of_bb() {
return sm_get_const_existing("[B", &const_arrayref_of_bb);
}
//return SmConstant (known verification type) corresponding to char[]
//returned value is cached
SmConstant sm_get_const_arrayref_of_char() {
return sm_get_const_existing("[C", &const_arrayref_of_char);
}
//return SmConstant (known verification type) corresponding to double[]
//returned value is cached
SmConstant sm_get_const_arrayref_of_double() {
return sm_get_const_existing("[D", &const_arrayref_of_double);
}
//return SmConstant (known verification type) corresponding to float[]
//returned value is cached
SmConstant sm_get_const_arrayref_of_float() {
return sm_get_const_existing("[F", &const_arrayref_of_float);
}
//return SmConstant (known verification type) corresponding to int[]
//returned value is cached
SmConstant sm_get_const_arrayref_of_integer() {
return sm_get_const_existing("[I", &const_arrayref_of_integer);
}
//return SmConstant (known verification type) corresponding to long[]
//returned value is cached
SmConstant sm_get_const_arrayref_of_long() {
return sm_get_const_existing("[J", &const_arrayref_of_long);
}
//return SmConstant (known verification type) corresponding to short[]
//returned value is cached
SmConstant sm_get_const_arrayref_of_short() {
return sm_get_const_existing("[S", &const_arrayref_of_short);
}
//return SmConstant (known verification type) corresponding to Object[]
//returned value is cached
SmConstant sm_get_const_arrayref_of_object() {
return sm_get_const_existing("[Ljava/lang/Object;", &const_arrayref_of_object);
}
//return SmConstant represented array of specified type
//the type is specified in the OP_NEWARRAY instruction. See the spec for possible types
SmConstant sm_get_const_arrayref(U_8 see_spec) {
switch ( see_spec ) {
case 4: //T_BOOLEAN
case 8: //T_BYTE
return sm_get_const_arrayref_of_bb();
case 5: //T_CHAR
return sm_get_const_arrayref_of_char();
case 6: //T_FLOAT
return sm_get_const_arrayref_of_float();
case 7: //T_DOUBLE
return sm_get_const_arrayref_of_double();
case 9: //T_SHORT
return sm_get_const_arrayref_of_short();
case 10: //T_INT
return sm_get_const_arrayref_of_integer();
case 11: //T_LONG
return sm_get_const_arrayref_of_long();
}
assert(0);
return SM_BOGUS;
}
//check if expected_ref is a super class of 'this', its package differs, and it's protected
enum FieldAndMethodCheck {_FALSE, _CLONE, _TRUE};
int checkFieldAccess(SmConstant expected_ref, unsigned short method_idx);
int checkVirtualAccess(SmConstant expected_ref, unsigned short method_idx);
int checkSuperAndPackage(SmConstant expected_ref);
private:
//ref to the main class of the verifier
SharedClasswideData *classwide;
//class handler of the class being verified
Class_Handle k_class;
//constantpool length
unsigned k_cp_length;
//hash table storing class names
vf_Hash hash;
vf_ValidType *validTypes;
unsigned tableIncr;
unsigned validTypesTableMax;
unsigned validTypesTableSz;
/*****************/
//cache for SmConstant constants;
SmConstant const_object, const_class, const_string, const_throwable, const_arrayref_of_bb,
const_arrayref_of_char, const_arrayref_of_double, const_arrayref_of_float,
const_arrayref_of_integer, const_arrayref_of_long, const_arrayref_of_short,
const_arrayref_of_object, const_this;
void NewConstraint(const char *available, const char *required);
//Get next free table entry index.
//Reallocate table if out of free entries.
unsigned check_table() {
if( validTypesTableSz + 1 >= validTypesTableMax ) {
validTypesTableMax += tableIncr;
validTypes = (vf_ValidType*)tc_realloc(validTypes, sizeof(vf_ValidType) * validTypesTableMax);
}
return validTypesTableSz++;
}
int is_bool_array_conv_needed(const char *type_name, int length);
};
Class_Handle vf_resolve_class(Class_Handle k_class, const char* name, bool need_load);
int vf_is_extending(Class_Handle from, Class_Handle to);
#endif