def new_jclass(self, class_file): Heap.new_jclass(self) self.access_flag = common_utils.get_int_from_bytes( class_file.access_flag) self.constant_pool = ConstantPool.new_constant_pool(class_file) self.fields = Field.new_fields(class_file.fields, self.constant_pool.constants) self.methods = Method.new_methods(self, class_file.methods, self.constant_pool.constants) super_class = self.constant_pool.constants[ common_utils.get_int_from_bytes(class_file.super_class)] if super_class is not None: self.super_class_name = super_class.class_name # 从方法区取 self.interfaces = None self.static_fields = {} for sf in self.__get_static_fields(): desc = sf.descriptor slot = Slot() if desc == 'B' or desc == 'I' or desc == 'J' or desc == 'S' or desc == 'Z': slot.num = 0 elif desc == 'C': slot.num = '0' elif desc == 'F': slot.num = 0.0 elif desc == 'D': slot.num = 0.0 self.static_fields[sf.name] = slot
def new_methods(jclass, cf_methods, constant_pool): methods = [] for m in cf_methods: nm = Method() nm.jclass = jclass nm.access_flag = common_utils.get_int_from_bytes(m.access_flags) nm.name = constant_pool[common_utils.get_int_from_bytes( m.name_index)] nm.descriptor = constant_pool[common_utils.get_int_from_bytes( m.descriptor_index)] attr = get_attribute(m.attributes, constant_pool, 'Code') nm.max_stack = common_utils.get_int_from_bytes(attr.max_stack) nm.max_locals = common_utils.get_int_from_bytes(attr.max_locals) nm.code = attr.code nm.exceptions = [] for ex in attr.exception_table: jex = JException() jex.start_pc = common_utils.get_int_from_bytes(ex.start_pc) jex.end_pc = common_utils.get_int_from_bytes(ex.end_pc) jex.handler_pc = common_utils.get_int_from_bytes(ex.handler_pc) jex.catch_type = common_utils.get_int_from_bytes(ex.catch_type) nm.exceptions.append(jex) nm.arg_desc = Method.get_arg_desc(nm.descriptor) methods.append(nm) return methods
def read_fields(self): tmp_class_file = self.class_file fields = [] for i in range( common_utils.get_int_from_bytes(tmp_class_file.fields_count)): field = FieldInfo() field.access_flags = self.reader.read_b2() field.name_index = self.reader.read_b2() field.descriptor_index = self.reader.read_b2() field.attributes_count = self.reader.read_b2() field.attributes = self.read_attributes_( common_utils.get_int_from_bytes(field.attributes_count)) fields.append(field) tmp_class_file.fields = fields
def read_methods(self): tmp_class = self.class_file methods = [] for i in range( common_utils.get_int_from_bytes( self.class_file.methods_count)): method = MethodInfo() method.access_flags = self.reader.read_b2() method.name_index = self.reader.read_b2() method.descriptor_index = self.reader.read_b2() method.attributes_count = self.reader.read_b2() method.attributes = self.read_attributes_( common_utils.get_int_from_bytes(method.attributes_count)) methods.append(method) tmp_class.methods = methods
def new_fields(cf_fields, constant_pool): fields = [] for f in cf_fields: nf = Field() nf.access_flag = common_utils.get_int_from_bytes(f.access_flags) nf.name = constant_pool[common_utils.get_int_from_bytes( f.name_index)] nf.descriptor_index = common_utils.get_int_from_bytes( f.descriptor_index) nf.descriptor = constant_pool[nf.descriptor_index] attr = get_attribute(f.attributes, constant_pool, 'ConstantValue') if attr is not None: nf.constant_value_index = common_utils.get_int_from_bytes( attr.constant_value_index) fields.append(nf) return fields
def new_constant_pool(class_file): r_cp = class_file.constant_pool constants = [] for cp in r_cp: if isinstance(cp, ClassInfo): constants.append(ClassRef.new_class_ref(r_cp, cp)) elif isinstance(cp, FieldRefInfo): constants.append(FieldRef.new_field_ref(r_cp, cp)) elif isinstance(cp, MethodRefInfo): constants.append(MethodRef.new_method_ref(r_cp, cp)) elif isinstance(cp, InterfaceMethodRefInfo): constants.append(None) elif isinstance(cp, StringInfo): st = r_cp[common_utils.get_int_from_bytes(cp.string_index)] st = common_utils.get_string_from_bytes(st.bytes) jstring = JString() jstring.data = st constants.append(jstring) elif isinstance(cp, IntegerInfo): jint = JInteger() jint.data = common_utils.get_int_from_bytes(cp.bytes) constants.append(jint) elif isinstance(cp, FloatInfo): jfloat = JFloat() jfloat.data = common_utils.get_float_from_bytes(cp.bytes) constants.append(jfloat) elif isinstance(cp, LongInfo): jlong = JLong() jlong.data = common_utils.get_long_from_bytes( cp.high_bytes, cp.low_bytes) constants.append(jlong) elif isinstance(cp, DoubleInfo): jdouble = JDouble() jdouble.data = common_utils.get_double_from_bytes( cp.high_bytes, cp.low_bytes) constants.append(jdouble) elif isinstance(cp, NameAndTypeInfo): constants.append(None) elif isinstance(cp, Utf8Info): constants.append(common_utils.get_string_from_bytes(cp.bytes)) elif isinstance(cp, MethodHandleInfo): constants.append(None) else: constants.append(None) constants_pool = ConstantPool() constants_pool.constants = constants return constants_pool
def get_attribute(attributes, constant_pool, name): for attr in attributes: index = common_utils.get_int_from_bytes(attr.attribute_name_index) aname = constant_pool[index] if aname == name: return attr return None
def read_interfaces(self): tmp_class_file = self.class_file interfaces = [] for i in range( common_utils.get_int_from_bytes( tmp_class_file.interface_count)): interfaces.append(self.reader.read_b2()) tmp_class_file.interfaces = interfaces
def new_method_ref(cp, method_ref_info): mr = MethodRef() cl = cp[common_utils.get_int_from_bytes(method_ref_info.class_index)] mr.class_name = MemberRef.get_string(cp, cl.name_index) mr.cp = cp name_and_type = MemberRef.get_obj(cp, method_ref_info.name_and_type_index) mr.name = MemberRef.get_string(cp, name_and_type.name_index) mr.descriptor = MemberRef.get_string(cp, name_and_type.descriptor_index) return mr
def new_field_ref(cp, field_ref_info): fr = FieldRef() cl = cp[common_utils.get_int_from_bytes(field_ref_info.class_index)] fr.class_name = MemberRef.get_string(cp, cl.name_index) fr.cp = cp name_and_type = MemberRef.get_obj(cp, field_ref_info.name_and_type_index) fr.name = MemberRef.get_string(cp, name_and_type.name_index) fr.descriptor = MemberRef.get_string(cp, name_and_type.descriptor_index) return fr
def read_attributes_(self, attributes_count): tmp_class = self.class_file attributes = [] for i in range(attributes_count): attribute_name_index = self.reader.read_b2() attribute_length = self.reader.read_b4() attr_name = tmp_class.constant_pool[ common_utils.get_int_from_bytes(attribute_name_index)] attr_name = common_utils.get_string_from_bytes(attr_name.bytes) # TODO: 重构一下这个地方,有点乱看着 if attr_name == BaseAttribute.ATTR_CONSTANT_VALUE: attr = ConstantValueAttribute() attr.attribute_name_index = attribute_name_index attr.attribute_length = attribute_length attr.constant_value_index = self.reader.read_b2() attributes.append(attr) elif attr_name == BaseAttribute.ATTR_CODE: attr = CodeAttribute() attr.attribute_name_index = attribute_name_index attr.attribute_length = attribute_length attr.max_stack = self.reader.read_b2() attr.max_locals = self.reader.read_b2() attr.code_length = self.reader.read_b4() attr.code = self.reader.read_bn( common_utils.get_int_from_bytes(attr.code_length)) attr.exception_table_length = self.reader.read_b2() attr.exception_table = self.read_exception_table( common_utils.get_int_from_bytes( attr.exception_table_length)) attr.attributes_count = self.reader.read_b2() attr.attributes = self.read_attributes_( common_utils.get_int_from_bytes(attr.attributes_count)) attributes.append(attr) elif attr_name == BaseAttribute.ATTR_SOURCE_FILE: attr = SourceFileAttribute() attr.attribute_name_index = attribute_name_index attr.attribute_length = attribute_length attr.sourcefile_index = self.reader.read_b2() attributes.append(attr) elif attr_name == BaseAttribute.ATTR_SIGNATURE: attr = SignatureAttribute() attr.attribute_name_index = attribute_name_index attr.attribute_length = attribute_length attr.signature_index = self.reader.read_b2() attributes.append(attr) # TODO: 这个 Exception 和 code 里的 exception 有什么区别? elif attr_name == BaseAttribute.ATTR_EXCEPTIONS: # attr = ExceptionsAttribute() # attr.attribute_name_index = attribute_name_index # attr.attribute_length = attribute_length # attr.number_of_exceptions = self.reader.read_b2() # attributes.append(attr) self.reader.read_bn( common_utils.get_int_from_bytes(attribute_length)) attributes.append(None) else: # 不认识的属性跳过 self.reader.read_bn( common_utils.get_int_from_bytes(attribute_length)) attributes.append(None) return attributes
self.read_attributes() def __str__(self): tmp_class = self.class_file return "magic: %s, minor_version: %s" % (tmp_class.magic, tmp_class.minor_version) if __name__ == '__main__': parser = ClassParser('../test/Hello.class') parser.parse() clf = parser.class_file print('========= magic =========') print(parser.class_file.magic) print('========= minor =========') print(common_utils.get_int_from_bytes(clf.minor_version)) print('========= major =========') print(common_utils.get_int_from_bytes(clf.major_version)) print('========= constant_pool =========') constant_pool_count = clf.constant_pool_count pools = clf.constant_pool for i in range(common_utils.get_int_from_bytes(constant_pool_count) - 1): pool = pools[i] print(pool) print('========= class =========') print(common_utils.get_int_from_bytes(clf.access_flag)) print(clf.this_class) print(clf.super_class) print('========= interface =========') print(clf.interface_count) for i in range(common_utils.get_int_from_bytes(clf.interface_count)):
def get_obj(cp, index_byte): return cp[common_utils.get_int_from_bytes(index_byte)]
def get_string(cp, index_byte): return common_utils.get_string_from_bytes( cp[common_utils.get_int_from_bytes(index_byte)].bytes)
def new_class_ref(cp, class_info): # ConstantPool ConstantClassInfo cr = ClassRef() cr.cp = cp tmp = cp[common_utils.get_int_from_bytes(class_info.name_index)] cr.class_name = common_utils.get_string_from_bytes(tmp.bytes) return cr
def read_attributes(self): self.class_file.attributes = self.read_attributes_( common_utils.get_int_from_bytes(self.class_file.attributes_count))
def read_constant_pool(self): constant_pool = [None] # constant_pool 第 0 个元素无用 skip = False for i in range( common_utils.get_int_from_bytes( self.class_file.constant_pool_count) - 1): if skip: # long double 占两个槽 constant_pool.append(None) skip = False continue info = None tag = self.reader.read_b1() if tag == ConstantPoolBaseInfo.CONSTANT_CLASS: info = ClassInfo() info.tag = tag info.name_index = self.reader.read_b2() elif tag == ConstantPoolBaseInfo.CONSTANT_FIELD_REF: info = FieldRefInfo() info.tag = tag info.class_index = self.reader.read_b2() info.name_and_type_index = self.reader.read_b2() elif tag == ConstantPoolBaseInfo.CONSTANT_METHOD_REF: info = MethodRefInfo() info.tag = tag info.class_index = self.reader.read_b2() info.name_and_type_index = self.reader.read_b2() elif tag == ConstantPoolBaseInfo.CONSTANT_INTERFACE_METHOD_REF: info = InterfaceMethodRefInfo() info.tag = tag info.class_index = self.reader.read_b2() info.name_and_type_index = self.reader.read_b2() elif tag == ConstantPoolBaseInfo.CONSTANT_STRING: info = StringInfo() info.tag = tag info.string_index = self.reader.read_b2() elif tag == ConstantPoolBaseInfo.CONSTANT_INTEGER: info = IntegerInfo() info.tag = tag info.bytes = self.reader.read_b4() elif tag == ConstantPoolBaseInfo.CONSTANT_FLOAT: info = FloatInfo() info.tag = tag info.bytes = self.reader.read_b4() elif tag == ConstantPoolBaseInfo.CONSTANT_LONG: info = LongInfo() info.tag = tag info.high_bytes = self.reader.read_b4() info.low_bytes = self.reader.read_b4() skip = True elif tag == ConstantPoolBaseInfo.CONSTANT_DOUBLE: info = DoubleInfo() info.tag = tag info.high_bytes = self.reader.read_b4() info.low_bytes = self.reader.read_b4() skip = True elif tag == ConstantPoolBaseInfo.CONSTANT_NAME_AND_TYPE: info = NameAndTypeInfo() info.tag = tag info.name_index = self.reader.read_b2() info.descriptor_index = self.reader.read_b2() elif tag == ConstantPoolBaseInfo.CONSTANT_UTF_8: info = Utf8Info() info.tag = tag info.length = self.reader.read_b2() info.bytes = self.reader.read_bn( common_utils.get_int_from_bytes(info.length)) elif tag == ConstantPoolBaseInfo.CONSTANT_METHOD_HANDLE: info = MethodHandleInfo() info.tag = tag info.reference_kind = self.reader.read_b1() info.reference_index = self.reader.read_b2() elif tag == ConstantPoolBaseInfo.CONSTANT_METHOD_TYPE: info = MethodTypeInfo() info.tag = tag info.descriptor_index = self.reader.read_b2() elif tag == ConstantPoolBaseInfo.CONSTANT_INVOKE_DYNAMIC: info = InvokeDynamicInfo() info.tag = tag info.bootstrap_method_attr_index = self.reader.read_b2() info.name_and_type_index = self.reader.read_b2() if info is not None: constant_pool.append(info) self.class_file.constant_pool = constant_pool