def parse_exception_table(self, file_object): return { 'start_pc': convert_bytes_to_int(file_object.read(2)), 'end_pc': convert_bytes_to_int(file_object.read(2)), 'handler_pc': convert_bytes_to_int(file_object.read(2)), 'catch_type': convert_bytes_to_int(file_object.read(2)) }
def parse(self, filename): self.class_file = ClassFile() with open(filename, "rb") as f: self.class_file.magic = f.read(4) self.class_file.minor_version = convert_bytes_to_int(f.read(2)) self.class_file.major_versio = convert_bytes_to_int(f.read(2)) self.class_file.constant_pool_count = convert_bytes_to_int( f.read(2)) for _ in range(self.class_file.constant_pool_count - 1): self.class_file.add_constant_pool(self.parse_constant_pool(f)) self.class_file.access_flags = convert_bytes_to_int(f.read(2)) self.class_file.this_class = convert_bytes_to_int(f.read(2)) self.class_file.super_class = convert_bytes_to_int(f.read(2)) self.class_file.interfaces_count = convert_bytes_to_int(f.read(2)) for _ in range(self.class_file.interfaces_count): self.class_file.add_interfaces(int.from_bytes(f.read(2))) self.class_file.fields_count = convert_bytes_to_int(f.read(2)) for _ in range(self.class_file.fields_count): self.class_file.add_field(self.parse_field()) self.class_file.methods_count = convert_bytes_to_int(f.read(2)) for _ in range(self.class_file.methods_count): self.class_file.add_method(self.parse_methods(f)) self.class_file.attributes_count = convert_bytes_to_int(f.read(2)) for _ in range(self.class_file.attributes_count): self.class_file.add_attribute(self.parse_attributes(f)) return self.class_file
def parse_methods(self, file_object): return { 'access_flags': convert_bytes_to_int(file_object.read(2)), 'name_index': convert_bytes_to_int(file_object.read(2)), 'descriptor_index': convert_bytes_to_int(file_object.read(2)), 'attributes_count': convert_bytes_to_int(file_object.read(2)), 'attributes': self.parse_attributes(file_object) }
def parse_line_number_table(self, file_object): line_number_table_length = convert_bytes_to_int(file_object.read(2)) line_number_table = [{ 'start_pc': convert_bytes_to_int(file_object.read(2)), 'line_number': convert_bytes_to_int(file_object.read(2)) } for _ in range(line_number_table_length)] return { 'line_number_table_length': line_number_table_length, 'line_number_table': line_number_table }
def parse_attributes(self, file_object): attribute_name_index = convert_bytes_to_int(file_object.read(2)) attribute_length = convert_bytes_to_int(file_object.read(4)) attribute_name = self.class_file.constant_pool[attribute_name_index][ 'bytes'] attribute_name = ''.join( map(lambda x: x.decode('UTF-8'), attribute_name)) attributes = { 'attribute_name_index': attribute_name_index, 'attribute_length': attribute_length, } attributes.update(self.attribute_parser[attribute_name](file_object)) return attributes
def _getstatic(self): index_byte1 = convert_bytes_to_int(self.read_codes()) index_byte2 = convert_bytes_to_int(self.read_codes()) index = index_byte1 << 8 | index_byte2 field_ref = self.constant_pool[index] class_name = self.get_class_name(field_ref['class_index']) name_and_type_index = field_ref['name_and_type_index'] name_and_type = self.get_name_and_type(name_and_type_index) # convert to python module path class_name = class_name.replace('/', '.') target_class = importlib.import_module(class_name) target_field = getattr(target_class, name_and_type['name']) self.stack.append(target_field)
def parse_utf8(self, file_object): length = convert_bytes_to_int(file_object.read(2)) bytes_list = [file_object.read(1) for _ in range(length)] return { 'tag': self.constant_pool_tags['CONSTANT_Utf8'], 'length': length, 'bytes': bytes_list }
def _invokevirtual(self): index_byte1 = convert_bytes_to_int(self.read_codes()) index_byte2 = convert_bytes_to_int(self.read_codes()) index = index_byte1 << 8 | index_byte2 # get method name from constant_pool method_ref = self.constant_pool[index] name_and_type = self.get_name_and_type( method_ref['name_and_type_index']) method_name = name_and_type['name'] # get args from stack arg_types = name_and_type['type'] arg_num = len(arg_types.split(';')) - 1 args = [self.stack.pop() for _ in range(arg_num)] args.reverse() # call method target_method = getattr(self.stack.pop(), method_name) target_method(*args)
def parse_code(self, file_object): max_stack = convert_bytes_to_int(file_object.read(2)) max_locals = convert_bytes_to_int(file_object.read(2)) code_length = convert_bytes_to_int(file_object.read(4)) codes = [file_object.read(1) for _ in range(code_length)] exception_table_length = convert_bytes_to_int(file_object.read(2)) exception_table = [ file_object.read(1) for _ in range(exception_table_length) ] attributes_count = convert_bytes_to_int(file_object.read(2)) attributes = [ self.parse_attributes(file_object) for _ in range(attributes_count) ] return { 'max_stack': max_stack, 'max_locals': max_locals, 'code_length': code_length, 'codes': codes, 'exception_table_length': exception_table_length, 'exception_table': exception_table, 'attributes_count': attributes_count, 'attributes': attributes }
def parse_method_ref(self, file_object): return { 'tag': self.constant_pool_tags['CONSTANT_Methodref'], 'class_index': convert_bytes_to_int(file_object.read(2)), 'name_and_type_index': convert_bytes_to_int(file_object.read(2)) }
def parse_string(self, file_object): return { 'tag': self.constant_pool_tags['CONSTANT_String'], 'string_index': convert_bytes_to_int(file_object.read(2)) }
def parse_class(self, file_object): return { 'tag': self.constant_pool_tags['CONSTANT_Class'], 'name_index': convert_bytes_to_int(file_object.read(2)) }
def parse_constant_pool(self, file_object): tag = convert_bytes_to_int(file_object.read(1)) return self.constant_parser[tag](file_object)
def parse_source_file(self, file_object): return {'sourcefile_index': convert_bytes_to_int(file_object.read(2))}
def parse_name_and_type(self, file_object): return { 'tag': self.constant_pool_tags['CONSTANT_NameAndType'], 'name_index': convert_bytes_to_int(file_object.read(2)), 'descriptor_index': convert_bytes_to_int(file_object.read(2)) }
def _ldc(self): index = convert_bytes_to_int(self.read_codes()) # TODO: implement other than string string = convert_bytes_to_string(self.constant_pool[ self.constant_pool[index]['string_index']]['bytes']) self.stack.append(string)