Best Python code snippet using Airtest
jvm.py
Source:jvm.py
...494 def get_length(self) :495 return self.__extra + calcsize( CONSTANT_INFO[ self.__tag.get_value() ][1] )496 def get_raw(self) :497 if self.__bytes != None :498 return self.format.get_value_buff() + self.__bytes.get_value_buff()499 return self.format.get_value_buff()500 def show(self) :501 if self.__bytes != None :502 print self.format.get_value(), self.__bytes.get_value()503 else :504 print self.format.get_value()505class MethodRef(CpInfo) :506 def __init__(self, class_manager, buff) :507 super(MethodRef, self).__init__( buff )508 def get_class_index(self) :509 return self.format.get_value().class_index510 def get_name_and_type_index(self) :511 return self.format.get_value().name_and_type_index512class InterfaceMethodRef(CpInfo) :513 def __init__(self, class_manager, buff) :514 super(InterfaceMethodRef, self).__init__( buff )515 def get_class_index(self) :516 return self.format.get_value().class_index517 def get_name_and_type_index(self) :518 return self.format.get_value().name_and_type_index519class FieldRef(CpInfo) :520 def __init__(self, class_manager, buff) :521 super(FieldRef, self).__init__( buff )522 def get_class_index(self) :523 return self.format.get_value().class_index524 def get_name_and_type_index(self) :525 return self.format.get_value().name_and_type_index526class Class(CpInfo) :527 def __init__(self, class_manager, buff) :528 super(Class, self).__init__( buff )529 def get_name_index(self) :530 return self.format.get_value().name_index531class Utf8(CpInfo) :532 def __init__(self, class_manager, buff) :533 super(Utf8, self).__init__( buff )534class String(CpInfo) :535 def __init__(self, class_manager, buff) :536 super(String, self).__init__( buff )537class Integer(CpInfo) :538 def __init__(self, class_manager, buff) :539 super(Integer, self).__init__( buff )540class Float(CpInfo) :541 def __init__(self, class_manager, buff) :542 super(Float, self).__init__( buff )543class Long(CpInfo) :544 def __init__(self, class_manager, buff) :545 super(Long, self).__init__( buff )546class Double(CpInfo) :547 def __init__(self, class_manager, buff) :548 super(Double, self).__init__( buff )549class NameAndType(CpInfo) :550 def __init__(self, class_manager, buff) :551 super(NameAndType, self).__init__( buff )552 def get_get_name_index(self) :553 return self.format.get_value().get_name_index554 def get_name_index(self) :555 return self.format.get_value().name_index556 def get_descriptor_index(self) :557 return self.format.get_value().descriptor_index558class EmptyConstant :559 def __init__(self) :560 pass561 def get_name(self) :562 return ""563 def get_raw(self) :564 return ""565 def get_length(self) :566 return 0567 def show(self) :568 pass569CONSTANT_INFO = {570 7 : [ "CONSTANT_Class", '>BH', namedtuple( "CONSTANT_Class_info", "tag name_index" ), Class ],571 9 : [ "CONSTANT_Fieldref", '>BHH', namedtuple( "CONSTANT_Fieldref_info", "tag class_index name_and_type_index" ), FieldRef ],572 10 : [ "CONSTANT_Methodref", '>BHH', namedtuple( "CONSTANT_Methodref_info", "tag class_index name_and_type_index" ), MethodRef ],573 11 : [ "CONSTANT_InterfaceMethodref", '>BHH', namedtuple( "CONSTANT_InterfaceMethodref_info", "tag class_index name_and_type_index" ), InterfaceMethodRef ],574 8 : [ "CONSTANT_String", '>BH', namedtuple( "CONSTANT_String_info", "tag string_index" ), String ],575 3 : [ "CONSTANT_Integer", '>BL', namedtuple( "CONSTANT_Integer_info", "tag bytes" ), Integer ],576 4 : [ "CONSTANT_Float", '>BL', namedtuple( "CONSTANT_Float_info", "tag bytes" ), Float ],577 5 : [ "CONSTANT_Long", '>BLL', namedtuple( "CONSTANT_Long_info", "tag high_bytes low_bytes" ), Long ],578 6 : [ "CONSTANT_Double", '>BLL', namedtuple( "CONSTANT_Long_info", "tag high_bytes low_bytes" ), Double ],579 12 : [ "CONSTANT_NameAndType", '>BHH', namedtuple( "CONSTANT_NameAndType_info", "tag name_index descriptor_index" ), NameAndType ],580 1 : [ "CONSTANT_Utf8", '>BH', namedtuple( "CONSTANT_Utf8_info", "tag length" ), Utf8 ]581 }582INVERT_CONSTANT_INFO = dict([( CONSTANT_INFO[k][0], k ) for k in CONSTANT_INFO])583ITEM_Top = 0584ITEM_Integer = 1585ITEM_Float = 2586ITEM_Long = 4587ITEM_Double = 3588ITEM_Null = 5589ITEM_UninitializedThis = 6590ITEM_Object = 7591ITEM_Uninitialized = 8592VERIFICATION_TYPE_INFO = {593 ITEM_Top : [ "Top_variable_info", '>B', namedtuple( "Top_variable_info", "tag" ) ],594 ITEM_Integer : [ "Integer_variable_info", '>B', namedtuple( "Integer_variable_info", "tag" ) ],595 ITEM_Float : [ "Float_variable_info", '>B', namedtuple( "Float_variable_info", "tag" ) ],596 ITEM_Long : [ "Long_variable_info", '>B', namedtuple( "Long_variable_info", "tag" ) ],597 ITEM_Double : [ "Double_variable_info", '>B', namedtuple( "Double_variable_info", "tag" ) ],598 ITEM_Null : [ "Null_variable_info", '>B', namedtuple( "Null_variable_info", "tag" ) ],599 ITEM_UninitializedThis : [ "UninitializedThis_variable_info", '>B', namedtuple( "UninitializedThis_variable_info", "tag" ) ],600 ITEM_Object : [ "Object_variable_info", '>BH', namedtuple( "Object_variable_info", "tag cpool_index" ), [ ("cpool_index", "get_class") ] ],601 ITEM_Uninitialized : [ "Uninitialized_variable_info", '>BH', namedtuple( "Uninitialized_variable_info", "tag offset" ) ],602 }603class FieldInfo :604 """An object which represents a Field"""605 def __init__(self, class_manager, buff) :606 self.__raw_buff = buff.read( calcsize( FIELD_INFO[0] ) )607 self.format = SVs( FIELD_INFO[0], FIELD_INFO[1], self.__raw_buff )608 self.__CM = class_manager609 self.__attributes = []610 for i in range(0, self.format.get_value().attributes_count) :611 ai = AttributeInfo( self.__CM, buff )612 self.__attributes.append( ai )613 def get_raw(self) :614 return self.__raw_buff + ''.join(x.get_raw() for x in self.__attributes)615 def get_length(self) :616 val = 0617 for i in self.__attributes :618 val += i.length619 return val + calcsize( FIELD_INFO[0] )620 def get_access(self) :621 try :622 return ACC_FIELD_FLAGS[ self.format.get_value().access_flags ][0]623 except KeyError :624 ok = True625 access = ""626 for i in ACC_FIELD_FLAGS :627 if (i & self.format.get_value().access_flags) == i :628 access += ACC_FIELD_FLAGS[ i ][0] + " "629 ok = False630 if ok == False :631 return access[:-1]632 return "ACC_PRIVATE"633 def set_access(self, value) :634 self.format.set_value( { "access_flags" : value } )635 def get_class_name(self) :636 return self.__CM.get_this_class_name()637 def get_name(self) :638 return self.__CM.get_string( self.format.get_value().name_index )639 def set_name(self, name) :640 return self.__CM.set_string( self.format.get_value().name_index, name )641 def get_descriptor(self) :642 return self.__CM.get_string( self.format.get_value().descriptor_index )643 def set_descriptor(self, name) :644 return self.__CM.set_string( self.format.get_value().descriptor_index, name )645 def get_attributes(self) :646 return self.__attributes647 def get_name_index(self) :648 return self.format.get_value().name_index649 def get_descriptor_index(self) :650 return self.format.get_value().descriptor_index651 def show(self) :652 print self.format.get_value(), self.get_name(), self.get_descriptor()653 for i in self.__attributes :654 i.show()655class MethodInfo :656 """An object which represents a Method"""657 def __init__(self, class_manager, buff) :658 self.format = SVs( METHOD_INFO[0], METHOD_INFO[1], buff.read( calcsize( METHOD_INFO[0] ) ) )659 self.__CM = class_manager660 self.__code = None661 self.__attributes = []662 for i in range(0, self.format.get_value().attributes_count) :663 ai = AttributeInfo( self.__CM, buff )664 self.__attributes.append( ai )665 if ai.get_name() == "Code" :666 self.__code = ai667 def get_raw(self) :668 return self.format.get_value_buff() + ''.join(x.get_raw() for x in self.__attributes)669 def get_length(self) :670 val = 0671 for i in self.__attributes :672 val += i.length673 return val + calcsize( METHOD_INFO[0] )674 def get_attributes(self) :675 return self.__attributes676 def get_access(self) :677 return ACC_METHOD_FLAGS[ self.format.get_value().access_flags ][0]678 def set_access(self, value) :679 self.format.set_value( { "access_flags" : value } )680 def get_name(self) :681 return self.__CM.get_string( self.format.get_value().name_index )682 def set_name(self, name) :683 return self.__CM.set_string( self.format.get_value().name_index, name )684 def get_descriptor(self) :685 return self.__CM.get_string( self.format.get_value().descriptor_index )686 def set_descriptor(self, name) :687 return self.__CM.set_string( self.format.get_value().name_descriptor, name )688 def get_name_index(self) :689 return self.format.get_value().name_index690 def get_descriptor_index(self) :691 return self.format.get_value().descriptor_index692 def get_local_variables(self) :693 return self.get_code().get_local_variables()694 def get_code(self) :695 if self.__code == None :696 return None697 return self.__code.get_item()698 def set_name_index(self, name_index) :699 self.format.set_value( { "name_index" : name_index } )700 def set_descriptor_index(self, descriptor_index) :701 self.format.set_value( { "descriptor_index" : descriptor_index } )702 def get_class_name(self) :703 return self.__CM.get_this_class_name()704 def set_cm(self, cm) :705 self.__CM = cm706 for i in self.__attributes :707 i.set_cm( cm )708 def with_descriptor(self, descriptor) :709 return descriptor == self.__CM.get_string( self.format.get_value().descriptor_index )710 def _patch_bytecodes(self) :711 return self.get_code()._patch_bytecodes()712 def show(self) :713 print "*" * 80714 print self.format.get_value(), self.get_class_name(), self.get_name(), self.get_descriptor()715 for i in self.__attributes :716 i.show()717 print "*" * 80718 def pretty_show(self, vm_a) :719 print "*" * 80720 print self.format.get_value(), self.get_class_name(), self.get_name(), self.get_descriptor()721 for i in self.__attributes :722 i.pretty_show(vm_a.hmethods[ self ])723 print "*" * 80724class CreateString :725 """Create a specific String constant by given the name index"""726 def __init__(self, class_manager, bytes) :727 self.__string_index = class_manager.add_string( bytes )728 def get_raw(self) :729 tag_value = INVERT_CONSTANT_INFO[ "CONSTANT_String" ]730 buff = pack( CONSTANT_INFO[ tag_value ][1], tag_value, self.__string_index )731 return buff732class CreateInteger :733 """Create a specific Integer constant by given the name index"""734 def __init__(self, byte) :735 self.__byte = byte736 def get_raw(self) :737 tag_value = INVERT_CONSTANT_INFO[ "CONSTANT_Integer" ]738 buff = pack( CONSTANT_INFO[ tag_value ][1], tag_value, self.__byte )739 return buff740class CreateClass :741 """Create a specific Class constant by given the name index"""742 def __init__(self, class_manager, name_index) :743 self.__CM = class_manager744 self.__name_index = name_index745 def get_raw(self) :746 tag_value = INVERT_CONSTANT_INFO[ "CONSTANT_Class" ]747 buff = pack( CONSTANT_INFO[ tag_value ][1], tag_value, self.__name_index )748 return buff749class CreateNameAndType :750 """Create a specific NameAndType constant by given the name and the descriptor index"""751 def __init__(self, class_manager, name_index, descriptor_index) :752 self.__CM = class_manager753 self.__name_index = name_index754 self.__descriptor_index = descriptor_index755 def get_raw(self) :756 tag_value = INVERT_CONSTANT_INFO[ "CONSTANT_NameAndType" ]757 buff = pack( CONSTANT_INFO[ tag_value ][1], tag_value, self.__name_index, self.__descriptor_index )758 return buff759class CreateFieldRef :760 """Create a specific FieldRef constant by given the class and the NameAndType index"""761 def __init__(self, class_manager, class_index, name_and_type_index) :762 self.__CM = class_manager763 self.__class_index = class_index764 self.__name_and_type_index = name_and_type_index765 def get_raw(self) :766 tag_value = INVERT_CONSTANT_INFO[ "CONSTANT_Fieldref" ]767 buff = pack( CONSTANT_INFO[ tag_value ][1], tag_value, self.__class_index, self.__name_and_type_index )768 return buff769class CreateMethodRef :770 """Create a specific MethodRef constant by given the class and the NameAndType index"""771 def __init__(self, class_manager, class_index, name_and_type_index) :772 self.__CM = class_manager773 self.__class_index = class_index774 self.__name_and_type_index = name_and_type_index775 def get_raw(self) :776 tag_value = INVERT_CONSTANT_INFO[ "CONSTANT_Methodref" ]777 buff = pack( CONSTANT_INFO[ tag_value ][1], tag_value, self.__class_index, self.__name_and_type_index )778 return buff779class CreateCodeAttributeInfo :780 """Create a specific CodeAttributeInfo by given bytecodes (into an human readable format)"""781 def __init__(self, class_manager, codes) :782 self.__CM = class_manager783#ATTRIBUTE_INFO = [ '>HL', namedtuple("AttributeInfo", "attribute_name_index attribute_length") ]784 self.__attribute_name_index = self.__CM.get_string_index( "Code" )785 self.__attribute_length = 0786########787# CODE_LOW_STRUCT = [ '>HHL', namedtuple( "LOW", "max_stack max_locals code_length" ) ]788 self.__max_stack = 1789 self.__max_locals = 2790 self.__code_length = 0791########792# CODE793 raw_buff = ""794 for i in codes :795 op_name = i[0]796 op_value = INVERT_JAVA_OPCODES[ op_name ]797 raw_buff += pack( '>B', op_value )798 if len( JAVA_OPCODES[ op_value ] ) > 1 :799 r_function, v_function, r_buff, r_format, f_function = EXTRACT_INFORMATION_SIMPLE( op_value )800 raw_buff += pack(r_format, *v_function( *i[1:] ) )801 self.__code = JavaCode( self.__CM, raw_buff )802 self.__code_length = len( raw_buff )803########804# EXCEPTION805 # u2 exception_table_length;806 self.__exception_table_length = 0807 # { u2 start_pc;808 # u2 end_pc;809 # u2 handler_pc;810 # u2 catch_type;811 # } exception_table[exception_table_length];812 self.__exception_table = []813########814# ATTRIBUTES815 # u2 attributes_count;816 self.__attributes_count = 0817 # attribute_info attributes[attributes_count];818 self.__attributes = []819########820 # FIXME : remove calcsize821 self.__attribute_length = calcsize( ATTRIBUTE_INFO[0] ) + \822 calcsize( CODE_LOW_STRUCT[0] ) + \823 self.__code_length + \824 calcsize('>H') + \825 calcsize('>H')826 def get_raw(self) :827 return pack( ATTRIBUTE_INFO[0], self.__attribute_name_index, self.__attribute_length ) + \828 pack( CODE_LOW_STRUCT[0], self.__max_stack, self.__max_locals, self.__code_length ) + \829 self.__code.get_raw() + \830 pack( '>H', self.__exception_table_length ) + \831 ''.join( i.get_raw() for i in self.__exception_table ) + \832 pack( '>H', self.__attributes_count ) + \833 ''.join( i.get_raw() for i in self.__attributes )834# FIELD_INFO = [ '>HHHH', namedtuple("FieldInfo", "access_flags name_index descriptor_index attributes_count") ]835class CreateFieldInfo :836 """Create a specific FieldInfo by given the name, the prototype of the "new" field"""837 def __init__(self, class_manager, name, proto) :838 self.__CM = class_manager839 access_flags_value = proto[0]840 type_value = proto[1]841 self.__access_flags = INVERT_ACC_FIELD_FLAGS[ access_flags_value ]842 self.__name_index = self.__CM.get_string_index( name )843 if self.__name_index == -1 :844 self.__name_index = self.__CM.add_string( name )845 else :846 bytecode.Exit("field %s is already present ...." % name)847 self.__descriptor_index = self.__CM.add_string( type_value )848 self.__attributes = []849 def get_raw(self) :850 buff = pack( FIELD_INFO[0], self.__access_flags, self.__name_index, self.__descriptor_index, len(self.__attributes) )851 for i in self.__attributes :852 buff += i.get_raw()853 return buff854# METHOD_INFO = [ '>HHHH', namedtuple("MethodInfo", "access_flags name_index descriptor_index attributes_count") ]855class CreateMethodInfo :856 """Create a specific MethodInfo by given the name, the prototype and the code (into an human readable format) of the "new" method"""857 def __init__(self, class_manager, name, proto, codes) :858 self.__CM = class_manager859 access_flags_value = proto[0]860 return_value = proto[1]861 arguments_value = proto[2]862 self.__access_flags = INVERT_ACC_METHOD_FLAGS[ access_flags_value ]863 self.__name_index = self.__CM.get_string_index( name )864 if self.__name_index == -1 :865 self.__name_index = self.__CM.add_string( name )866 proto_final = "(" + arguments_value + ")" + return_value867 self.__descriptor_index = self.__CM.add_string( proto_final )868 self.__attributes = []869 self.__attributes.append( CreateCodeAttributeInfo( self.__CM, codes ) )870 def get_raw(self) :871 buff = pack( METHOD_INFO[0], self.__access_flags, self.__name_index, self.__descriptor_index, len(self.__attributes) )872 for i in self.__attributes :873 buff += i.get_raw()874 return buff875class JBC :876 """JBC manages each bytecode with the value, name, raw buffer and special functions"""877 # special --> ( r_function, v_function, r_buff, r_format, f_function )878 def __init__(self, class_manager, op_name, raw_buff, special=None) :879 self.__CM = class_manager880 self.__op_name = op_name881 self.__raw_buff = raw_buff882 self.__special = special883 self.__special_value = None884 self._load()885 def _load(self) :886 if self.__special != None :887 ntuple = namedtuple( self.__op_name, self.__special[2] )888 x = ntuple._make( unpack( self.__special[3], self.__raw_buff[1:] ) )889 if self.__special[4] == None :890 self.__special_value = self.__special[0]( x )891 else :892 self.__special_value = getattr(self.__CM, self.__special[4])( self.__special[0]( x ) )893 def reload(self, raw_buff) :894 """Reload the bytecode with a new raw buffer"""895 self.__raw_buff = raw_buff896 self._load()897 def set_cm(self, cm) :898 self.__CM = cm899 def get_length(self) :900 """Return the length of the bytecode"""901 return len( self.__raw_buff )902 def get_raw(self) :903 """Return the current raw buffer of the bytecode"""904 return self.__raw_buff905 def get_name(self) :906 """Return the name of the bytecode"""907 return self.__op_name908 def get_operands(self) :909 """Return the operands of the bytecode"""910 if isinstance( self.__special_value, list ):911 if len(self.__special_value) == 1 :912 return self.__special_value[0]913 return self.__special_value914 def get_formatted_operands(self) :915 return []916 def adjust_r(self, pos, pos_modif, len_modif) :917 """Adjust the bytecode (if necessary (in this cas the bytecode is a branch bytecode)) when a bytecode has been removed"""918# print self.__op_name, pos, pos_modif, len_modif, self.__special_value, type(pos), type(pos_modif), type(len_modif), type(self.__special_value)919 if pos > pos_modif :920 if (self.__special_value + pos) < (pos_modif) :921# print "MODIF +", self.__special_value, len_modif,922 self.__special_value += len_modif923# print self.__special_value924 self.__raw_buff = pack( '>B', INVERT_JAVA_OPCODES[ self.__op_name ] ) + pack(self.__special[3], *self.__special[1]( self.__special_value ) )925 elif pos < pos_modif :926 if (self.__special_value + pos) > (pos_modif) :927# print "MODIF -", self.__special_value, len_modif,928 self.__special_value -= len_modif929# print self.__special_value930 self.__raw_buff = pack( '>B', INVERT_JAVA_OPCODES[ self.__op_name ] ) + pack(self.__special[3], *self.__special[1]( self.__special_value ) )931 def adjust_i(self, pos, pos_modif, len_modif) :932 """Adjust the bytecode (if necessary (in this cas the bytecode is a branch bytecode)) when a bytecode has been inserted"""933 #print self.__op_name, pos, pos_modif, len_modif, self.__special_value, type(pos), type(pos_modif), type(len_modif), type(self.__special_value)934 if pos > pos_modif :935 if (self.__special_value + pos) < (pos_modif) :936# print "MODIF +", self.__special_value, len_modif,937 self.__special_value -= len_modif938# print self.__special_value939 self.__raw_buff = pack( '>B', INVERT_JAVA_OPCODES[ self.__op_name ] ) + pack(self.__special[3], *self.__special[1]( self.__special_value ) )940 elif pos < pos_modif :941 if (self.__special_value + pos) > (pos_modif) :942# print "MODIF -", self.__special_value, len_modif,943 self.__special_value += len_modif944# print self.__special_value945 self.__raw_buff = pack( '>B', INVERT_JAVA_OPCODES[ self.__op_name ] ) + pack(self.__special[3], *self.__special[1]( self.__special_value ) )946 def show_buff(self, pos) :947 buff = ""948 if self.__special_value == None :949 buff += self.__op_name950 else :951 if self.__op_name in BRANCH_JVM_OPCODES :952 buff += "%s %s %s" % (self.__op_name, self.__special_value, self.__special_value + pos)953 else :954 buff += "%s %s" % (self.__op_name, self.__special_value)955 return buff956 def show(self, pos) :957 """Show the bytecode at a specific position958 pos - the position into the bytecodes (integer)959 """960 print self.show_buff( pos ),961class JavaCode :962 """JavaCode manages a list of bytecode to a specific method, by decoding a raw buffer and transform each bytecode into a JBC object"""963 def __init__(self, class_manager, buff) :964 self.__CM = class_manager965 self.__raw_buff = buff966 self.__bytecodes = []967 self.__maps = []968 self.__branches = []969 i = 0970 while i < len(self.__raw_buff) :971 op_value = unpack( '>B', self.__raw_buff[i])[0]972 if op_value in JAVA_OPCODES :973 if len( JAVA_OPCODES[ op_value ] ) >= 2 :974 # it's a fixed length opcode975 if isinstance(JAVA_OPCODES[ op_value ][1], str) == True :976 r_function, v_function, r_buff, r_format, f_function = EXTRACT_INFORMATION_SIMPLE( op_value )977 # it's a variable length opcode978 else :979 r_function, v_function, r_buff, r_format, f_function = EXTRACT_INFORMATION_VARIABLE( i, op_value, self.__raw_buff[ i : ] )980 len_format = calcsize(r_format)981 raw_buff = self.__raw_buff[ i : i + 1 + len_format ]982 jbc = JBC( class_manager, JAVA_OPCODES[ op_value ][0], raw_buff, ( r_function, v_function, r_buff, r_format, f_function ) )983 self.__bytecodes.append( jbc )984 i += len_format985 else :986 self.__bytecodes.append( JBC( class_manager, JAVA_OPCODES[ op_value ][0], self.__raw_buff[ i ] ) )987 else :988 bytecode.Exit( "op_value 0x%x is unknown" % op_value )989 i += 1990 # Create branch bytecodes list991 idx = 0992 nb = 0993 for i in self.__bytecodes :994 self.__maps.append( idx )995 if i.get_name() in BRANCH_JVM_OPCODES :996 self.__branches.append( nb )997 idx += i.get_length()998 nb += 1999 def _patch_bytecodes(self) :1000 methods = []1001 for i in self.__bytecodes :1002 if "invoke" in i.get_name() :1003 operands = i.get_operands()1004 methods.append( operands )1005 op_value = INVERT_JAVA_OPCODES[ i.get_name() ]1006 raw_buff = pack( '>B', op_value )1007 r_function, v_function, r_buff, r_format, f_function = EXTRACT_INFORMATION_SIMPLE( op_value )1008 new_class_index = self.__CM.create_class( operands[0] )1009 new_name_and_type_index = self.__CM.create_name_and_type( operands[1], operands[2] )1010 self.__CM.create_method_ref( new_class_index, new_name_and_type_index )1011 value = getattr( self.__CM, JAVA_OPCODES[ op_value ][5] )( *operands[0:] )1012 if value == -1 :1013 bytecode.Exit( "Unable to found method " + str(operands) )1014 raw_buff += pack(r_format, *v_function( value ) )1015 i.reload( raw_buff )1016 elif "anewarray" in i.get_name() :1017 operands = i.get_operands()1018 op_value = INVERT_JAVA_OPCODES[ i.get_name() ]1019 raw_buff = pack( '>B', op_value )1020 r_function, v_function, r_buff, r_format, f_function = EXTRACT_INFORMATION_SIMPLE( op_value )1021 new_class_index = self.__CM.create_class( operands )1022 raw_buff += pack(r_format, *v_function( new_class_index ) )1023 i.reload( raw_buff )1024 elif "getstatic" == i.get_name() :1025 operands = i.get_operands()1026 op_value = INVERT_JAVA_OPCODES[ i.get_name() ]1027 raw_buff = pack( '>B', op_value )1028 r_function, v_function, r_buff, r_format, f_function = EXTRACT_INFORMATION_SIMPLE( op_value )1029 new_class_index = self.__CM.create_class( operands[0] )1030 new_name_and_type_index = self.__CM.create_name_and_type( operands[1], operands[2] )1031 self.__CM.create_field_ref( new_class_index, new_name_and_type_index )1032 value = getattr( self.__CM, JAVA_OPCODES[ op_value ][5] )( *operands[1:] )1033 if value == -1 :1034 bytecode.Exit( "Unable to found method " + str(operands) )1035 raw_buff += pack(r_format, *v_function( value ) )1036 i.reload( raw_buff )1037 elif "ldc" == i.get_name() :1038 operands = i.get_operands()1039 op_value = INVERT_JAVA_OPCODES[ i.get_name() ]1040 raw_buff = pack( '>B', op_value )1041 r_function, v_function, r_buff, r_format, f_function = EXTRACT_INFORMATION_SIMPLE( op_value )1042 if operands[0] != "CONSTANT_Integer" and operands[0] != "CONSTANT_String" :1043 bytecode.Exit( "...." )1044 if operands[0] == "CONSTANT_Integer" :1045 new_int_index = self.__CM.create_integer( operands[1] )1046 raw_buff += pack(r_format, *v_function( new_int_index ) )1047 elif operands[0] == "CONSTANT_String" :1048 new_string_index = self.__CM.create_string( operands[1] )1049 raw_buff += pack(r_format, *v_function( new_string_index ) )1050 i.reload( raw_buff )1051 elif "new" == i.get_name() :1052 operands = i.get_operands()1053 op_value = INVERT_JAVA_OPCODES[ i.get_name() ]1054 raw_buff = pack( '>B', op_value )1055 r_function, v_function, r_buff, r_format, f_function = EXTRACT_INFORMATION_SIMPLE( op_value )1056 new_class_index = self.__CM.create_class( operands )1057 raw_buff += pack(r_format, *v_function( new_class_index ) )1058 i.reload( raw_buff )1059 return methods1060 def get(self) :1061 """1062 Return all bytecodes1063 @rtype : L{list}1064 """1065 return self.__bytecodes1066 def get_raw(self) :1067 return ''.join(x.get_raw() for x in self.__bytecodes)1068 def show(self) :1069 """1070 Display the code like a disassembler1071 """1072 nb = 01073 for i in self.__bytecodes :1074 print nb, self.__maps[nb],1075 i.show( self.__maps[nb] )1076 print1077 nb += 11078 def pretty_show(self, m_a) :1079 """1080 Display the code like a disassembler but with instructions' links1081 """1082 bytecode.PrettyShow( m_a.basic_blocks.gets() )1083 bytecode.PrettyShowEx( m_a.exceptions.gets() )1084 1085 def get_relative_idx(self, idx) :1086 """1087 Return the relative idx by given an offset in the code1088 @param idx : an offset in the code1089 @rtype : the relative index in the code, it's the position in the list of a bytecode1090 """1091 n = 01092 x = 01093 for i in self.__bytecodes :1094 #print n, idx1095 if n == idx :1096 return x1097 n += i.get_length()1098 x += 11099 return -11100 def get_at(self, idx) :1101 """1102 Return a specific bytecode at an index1103 @param : the index of a bytecode1104 @rtype : L{JBC}1105 """1106 return self.__bytecodes[ idx ]1107 def remove_at(self, idx) :1108 """1109 Remove bytecode at a specific index1110 @param idx : the index to remove the bytecode1111 @rtype : the length of the removed bytecode1112 """1113 val = self.__bytecodes[idx]1114 val_m = self.__maps[idx]1115 # Remove the index if it's in our branch list1116 if idx in self.__branches :1117 self.__branches.remove( idx )1118 # Adjust each branch1119 for i in self.__branches :1120 self.__bytecodes[i].adjust_r( self.__maps[i], val_m, val.get_length() )1121 # Remove it !1122 self.__maps.pop(idx)1123 self.__bytecodes.pop(idx)1124 # Adjust branch and map list1125 self._adjust_maps( val_m, val.get_length() * -1 )1126 self._adjust_branches( idx, -1 )1127 return val.get_length()1128 def _adjust_maps(self, val, size) :1129 nb = 01130 for i in self.__maps :1131 if i > val :1132 self.__maps[ nb ] = i + size1133 nb = nb + 11134 def _adjust_maps_i(self, val, size) :1135 nb = 01136 x = 01137 for i in self.__maps :1138 if i == val :1139 x+=11140 if x == 2 :1141 self.__maps[ nb ] = i + size1142 if i > val :1143 self.__maps[ nb ] = i + size1144 nb = nb + 11145 def _adjust_branches(self, val, size) :1146 nb = 01147 for i in self.__branches :1148 if i > val :1149 self.__branches[ nb ] = i + size1150 nb += 11151 def insert_at(self, idx, byte_code) :1152 """1153 Insert bytecode at a specific index1154 @param idx : the index to insert the bytecode1155 @param bytecode : a list which represent the bytecode1156 @rtype : the length of the inserted bytecode1157 """1158 # Get the op_value and add it to the raw_buff1159 op_name = byte_code[0]1160 op_value = INVERT_JAVA_OPCODES[ op_name ]1161 raw_buff = pack( '>B', op_value )1162 new_jbc = None1163 # If it's an op_value with args, we must handle that !1164 if len( JAVA_OPCODES[ op_value ] ) > 1 :1165 # Find information about the op_value1166 r_function, v_function, r_buff, r_format, f_function = EXTRACT_INFORMATION_SIMPLE( op_value )1167 # Special values for this op_value (advanced bytecode)1168 if len( JAVA_OPCODES[ op_value ] ) == 6 :1169 value = getattr( self.__CM, JAVA_OPCODES[ op_value ][5] )( *byte_code[1:] )1170 if value == -1 :1171 bytecode.Exit( "Unable to found " + str(byte_code[1:]) )1172 raw_buff += pack(r_format, *v_function( value ) )1173 else :1174 raw_buff += pack(r_format, *v_function( *byte_code[1:] ) )1175 new_jbc = JBC(self.__CM, op_name, raw_buff, ( r_function, v_function, r_buff, r_format, f_function ) )1176 else :1177 new_jbc = JBC(self.__CM, op_name, raw_buff)1178 # Adjust each branch with the new insertion1179 val_m = self.__maps[ idx ]1180 for i in self.__branches :1181 self.__bytecodes[i].adjust_i( self.__maps[i], val_m, new_jbc.get_length() )1182 # Insert the new bytecode at the correct index1183 # Adjust maps + branches1184 self.__bytecodes.insert( idx, new_jbc )1185 self.__maps.insert( idx, val_m )1186 self._adjust_maps_i( val_m, new_jbc.get_length() )1187 self._adjust_branches( idx, 1 )1188 # Add it to the branches if it's a correct op_value1189 if new_jbc.get_name() in BRANCH_JVM_OPCODES :1190 self.__branches.append( idx )1191 # FIXME1192 # modify the exception table1193 # modify tableswitch and lookupswitch instructions1194 # return the length of the raw_buff1195 return len(raw_buff)1196 def remplace_at(self, idx, bytecode) :1197 """1198 Remplace bytecode at a specific index by another bytecode (remplace = remove + insert)1199 @param idx : the index to insert the bytecode1200 @param bytecode : a list which represent the bytecode1201 @rtype : the length of the inserted bytecode1202 """1203 self.remove_at(idx) * (-1)1204 size = self.insert_at(idx, bytecode)1205 return size1206 def set_cm(self, cm) :1207 self.__CM = cm1208 for i in self.__bytecodes :1209 i.set_cm( cm )1210class BasicAttribute(object) :1211 def __init__(self) :1212 self.__attributes = []1213 def get_attributes(self) :1214 return self.__attributes1215 def set_cm(self, cm) :1216 self.__CM = cm1217class CodeAttribute(BasicAttribute) :1218 def __init__(self, class_manager, buff) :1219 self.__CM = class_manager1220 super(CodeAttribute, self).__init__()1221 # u2 attribute_name_index;1222 # u4 attribute_length;1223 # u2 max_stack;1224 # u2 max_locals;1225 # u4 code_length;1226 # u1 code[code_length];1227 self.low_struct = SVs( CODE_LOW_STRUCT[0], CODE_LOW_STRUCT[1], buff.read( calcsize(CODE_LOW_STRUCT[0]) ) )1228 self.__code = JavaCode( class_manager, buff.read( self.low_struct.get_value().code_length ) )1229 # u2 exception_table_length;1230 self.exception_table_length = SV( '>H', buff.read(2) )1231 # { u2 start_pc;1232 # u2 end_pc;1233 # u2 handler_pc;1234 # u2 catch_type;1235 # } exception_table[exception_table_length];1236 self.__exception_table = []1237 for i in range(0, self.exception_table_length.get_value()) :1238 et = SVs( EXCEPTION_TABLE[0], EXCEPTION_TABLE[1], buff.read( calcsize(EXCEPTION_TABLE[0]) ) )1239 self.__exception_table.append( et )1240 # u2 attributes_count;1241 self.attributes_count = SV( '>H', buff.read(2) )1242 # attribute_info attributes[attributes_count];1243 self.__attributes = []1244 for i in range(0, self.attributes_count.get_value()) :1245 ai = AttributeInfo( self.__CM, buff )1246 self.__attributes.append( ai )1247 def get_attributes(self) :1248 return self.__attributes1249 def get_exceptions(self) :1250 return self.__exception_table1251 def get_raw(self) :1252 return self.low_struct.get_value_buff() + \1253 self.__code.get_raw() + \1254 self.exception_table_length.get_value_buff() + \1255 ''.join(x.get_value_buff() for x in self.__exception_table) + \1256 self.attributes_count.get_value_buff() + \1257 ''.join(x.get_raw() for x in self.__attributes)1258 def get_length(self) :1259 return self.low_struct.get_value().code_length1260 def get_max_stack(self) :1261 return self.low_struct.get_value().max_stack1262 def get_max_locals(self) :1263 return self.low_struct.get_value().max_locals1264 def get_local_variables(self) :1265 for i in self.__attributes :1266 if i.get_name() == "StackMapTable" :1267 return i.get_item().get_local_variables()1268 return []1269 def get_bc(self) :1270 return self.__code1271 # FIXME : show* --> add exceptions1272 def show_info(self) :1273 print "!" * 701274 print self.low_struct.get_value()1275 bytecode._Print( "ATTRIBUTES_COUNT", self.attributes_count.get_value() )1276 for i in self.__attributes :1277 i.show()1278 print "!" * 701279 def _begin_show(self) :1280 print "!" * 701281 print self.low_struct.get_value()1282 def _end_show(self) :1283 bytecode._Print( "ATTRIBUTES_COUNT", self.attributes_count.get_value() )1284 for i in self.__attributes :1285 i.show()1286 print "!" * 701287 def show(self) :1288 self._begin_show()1289 self.__code.show()1290 self._end_show()1291 def pretty_show(self, m_a) :1292 self._begin_show()1293 self.__code.pretty_show(m_a)1294 self._end_show()1295 def _patch_bytecodes(self) :1296 return self.__code._patch_bytecodes()1297 def remplace_at(self, idx, bytecode) :1298 size = self.__code.remplace_at(idx, bytecode)1299 # Adjust the length of our bytecode1300 self.low_struct.set_value( { "code_length" : self.low_struct.get_value().code_length + size } )1301 def remove_at(self, idx) :1302 size = self.__code.remove_at(idx)1303 # Adjust the length of our bytecode1304 self.low_struct.set_value( { "code_length" : self.low_struct.get_value().code_length - size } )1305 def removes_at(self, l_idx) :1306 i = 01307 while i < len(l_idx) :1308 self.remove_at( l_idx[i] )1309 j = i + 11310 while j < len(l_idx) :1311 if l_idx[j] > l_idx[i] :1312 l_idx[j] -= 11313 j += 11314 i += 11315 def inserts_at(self, idx, l_bc) :1316# self.low_struct.set_value( { "max_stack" : self.low_struct.get_value().max_stack + 2 } )1317# print self.low_struct.get_value()1318 total_size = 01319 for i in l_bc :1320 size = self.insert_at( idx, i )1321 idx += 11322 total_size += size1323 return total_size1324 def insert_at(self, idx, bytecode) :1325 size = self.__code.insert_at(idx, bytecode)1326 # Adjust the length of our bytecode1327 self.low_struct.set_value( { "code_length" : self.low_struct.get_value().code_length + size } )1328 return size1329 def get_relative_idx(self, idx) :1330 return self.__code.get_relative_idx(idx)1331 def get_at(self, idx) :1332 return self.__code.get_at(idx)1333 def gets_at(self, l_idx) :1334 return [ self.__code.get_at(i) for i in l_idx ]1335 def set_cm(self, cm) :1336 self.__CM = cm1337 for i in self.__attributes :1338 i.set_cm( cm )1339 self.__code.set_cm( cm )1340 def _fix_attributes(self, new_cm) :1341 for i in self.__attributes :1342 i._fix_attributes( new_cm )1343class SourceFileAttribute(BasicAttribute) :1344 def __init__(self, cm, buff) :1345 super(SourceFileAttribute, self).__init__()1346 # u2 attribute_name_index;1347 # u4 attribute_length;1348 # u2 sourcefile_index;1349 self.sourcefile_index = SV( '>H', buff.read(2) )1350 def get_raw(self) :1351 return self.sourcefile_index.get_value_buff()1352 def show(self) :1353 print self.sourcefile_index1354class LineNumberTableAttribute(BasicAttribute) :1355 def __init__(self, cm, buff) :1356 super(LineNumberTableAttribute, self).__init__()1357 # u2 attribute_name_index;1358 # u4 attribute_length;1359 # u2 line_number_table_length;1360 # { u2 start_pc;1361 # u2 line_number;1362 # } line_number_table[line_number_table_length];1363 self.line_number_table_length = SV( '>H', buff.read( 2 ) )1364 self.__line_number_table = []1365 for i in range(0, self.line_number_table_length.get_value()) :1366 lnt = SVs( LINE_NUMBER_TABLE[0], LINE_NUMBER_TABLE[1], buff.read( 4 ) )1367 self.__line_number_table.append( lnt )1368 def get_raw(self) :1369 return self.line_number_table_length.get_value_buff() + \1370 ''.join(x.get_value_buff() for x in self.__line_number_table)1371 def get_line_number_table(self) :1372 return self.__line_number_table1373 def show(self) :1374 bytecode._Print("LINE_NUMBER_TABLE_LENGTH", self.line_number_table_length.get_value())1375 for x in self.__line_number_table :1376 print "\t", x.get_value()1377 def _fix_attributes(self, new_cm) :1378 pass1379class LocalVariableTableAttribute(BasicAttribute) :1380 def __init__(self, cm, buff) :1381 super(LocalVariableTableAttribute, self).__init__()1382 # u2 attribute_name_index;1383 # u4 attribute_length;1384 # u2 local_variable_table_length;1385 # { u2 start_pc;1386 # u2 length;1387 # u2 name_index;1388 # u2 descriptor_index;1389 # u2 index;1390 # } local_variable_table[local_variable_table_length];1391 self.local_variable_table_length = SV( '>H', buff.read(2) )1392 self.local_variable_table = []1393 for i in range(0, self.local_variable_table_length.get_value()) :1394 lvt = SVs( LOCAL_VARIABLE_TABLE[0], LOCAL_VARIABLE_TABLE[1], buff.read( calcsize(LOCAL_VARIABLE_TABLE[0]) ) )1395 self.local_variable_table.append( lvt )1396 def get_raw(self) :1397 return self.local_variable_table_length.get_value_buff() + \1398 ''.join(x.get_value_buff() for x in self.local_variable_table)1399 def show(self) :1400 print "LocalVariableTable", self.local_variable_table_length.get_value()1401 for x in self.local_variable_table :1402 print x.get_value()1403class LocalVariableTypeTableAttribute(BasicAttribute) :1404 def __init__(self, cm, buff) :1405 super(LocalVariableTypeTableAttribute, self).__init__()1406 # u2 attribute_name_index;1407 # u4 attribute_length;1408 # u2 local_variable_type_table_length;1409 # { u2 start_pc;1410 # u2 length;1411 # u2 name_index;1412 # u2 signature_index;1413 # u2 index;1414 # } local_variable_type_table[local_variable_type_table_length];1415 self.local_variable_type_table_length = SV( '>H', buff.read(2) )1416 self.local_variable_type_table = []1417 for i in range(0, self.local_variable_type_table_length.get_value()) :1418 lvtt = SVs( LOCAL_VARIABLE_TYPE_TABLE[0], LOCAL_VARIABLE_TYPE_TABLE[1], buff.read( calcsize(LOCAL_VARIABLE_TYPE_TABLE[0]) ) )1419 self.local_variable_type_table.append( lvtt )1420 def get_raw(self) :1421 return self.local_variable_type_table_length.get_value_buff() + \1422 ''.join(x.get_value_buff() for x in self.local_variable_type_table)1423 def show(self) :1424 print "LocalVariableTypeTable", self.local_variable_type_table_length.get_value()1425 for x in self.local_variable_type_table :1426 print x.get_value()1427class SourceDebugExtensionAttribute(BasicAttribute) :1428 def __init__(self, cm, buff) :1429 super(SourceDebugExtensionAttribute, self).__init__()1430 # u2 attribute_name_index;1431 # u4 attribute_length;1432 # u1 debug_extension[attribute_length];1433 self.debug_extension = buff.read( self.attribute_length )1434 def get_raw(self) :1435 return self.debug_extension1436 def show(self) :1437 print "SourceDebugExtension", self.debug_extension.get_value()1438class DeprecatedAttribute(BasicAttribute) :1439 def __init__(self, cm, buff) :1440 super(DeprecatedAttribute, self).__init__()1441 # u2 attribute_name_index;1442 # u4 attribute_length;1443 def get_raw(self) :1444 return ''1445 def show(self) :1446 print "Deprecated"1447class SyntheticAttribute(BasicAttribute) :1448 def __init__(self, cm, buff) :1449 super(SyntheticAttribute, self).__init__()1450 # u2 attribute_name_index;1451 # u4 attribute_length;1452 def get_raw(self) :1453 return ''1454 def show(self) :1455 print "Synthetic"1456class SignatureAttribute(BasicAttribute) :1457 def __init__(self, cm, buff) :1458 super(SignatureAttribute, self).__init__()1459 # u2 attribute_name_index;1460 # u4 attribute_length;1461 # u2 signature_index;1462 self.signature_index = SV( '>H', buff.read(2) )1463 def get_raw(self) :1464 return self.signature_index.get_value_buff()1465 def show(self) :1466 print "Signature", self.signature_index.get_value()1467class RuntimeVisibleAnnotationsAttribute(BasicAttribute) :1468 def __init__(self, cm, buff) :1469 super(RuntimeVisibleAnnotationsAttribute, self).__init__()1470 # u2 attribute_name_index;1471 # u4 attribute_length;1472 # u2 num_annotations;1473 # annotation annotations[num_annotations];1474 self.num_annotations = SV( '>H', buff.read(2) )1475 self.annotations = []1476 for i in range(0, self.num_annotations.get_value()) :1477 self.annotations.append( Annotation(cm, buff) )1478 def get_raw(self) :1479 return self.num_annotations.get_value_buff() + \1480 ''.join(x.get_raw() for x in self.annotations)1481 def show(self) :1482 print "RuntimeVisibleAnnotations", self.num_annotations.get_value()1483 for i in self.annotations :1484 i.show()1485class RuntimeInvisibleAnnotationsAttribute(RuntimeVisibleAnnotationsAttribute) :1486 def show(self) :1487 print "RuntimeInvisibleAnnotations", self.num_annotations.get_value()1488 for i in self.annotations :1489 i.show()1490class RuntimeVisibleParameterAnnotationsAttribute(BasicAttribute) :1491 def __init__(self, cm, buff) :1492 super(RuntimeVisibleParameterAnnotationsAttribute, self).__init__()1493 # u2 attribute_name_index;1494 # u4 attribute_length;1495 # u1 num_parameters;1496 #{1497 # u2 num_annotations;1498 # annotation annotations[num_annotations];1499 #} parameter_annotations[num_parameters];1500 self.num_parameters = SV( '>H', buff.read(2) )1501 self.parameter_annotations = []1502 for i in range(0, self.num_parameters.get_value()) :1503 self.parameter_annotations.append( ParameterAnnotation( cm, buff ) )1504 def get_raw(self) :1505 return self.num_parameters.get_value_buff() + \1506 ''.join(x.get_raw() for x in self.parameter_annotations)1507 def show(self) :1508 print "RuntimeVisibleParameterAnnotations", self.num_parameters.get_value()1509 for i in self.parameter_annotations :1510 i.show()1511class RuntimeInvisibleParameterAnnotationsAttribute(RuntimeVisibleParameterAnnotationsAttribute) :1512 def show(self) :1513 print "RuntimeVisibleParameterAnnotations", self.num_annotations.get_value()1514 for i in self.parameter_annotations :1515 i.show()1516class ParameterAnnotation :1517 def __init__(self, cm, buff) :1518 # u2 num_annotations;1519 # annotation annotations[num_annotations];1520 self.num_annotations = SV( '>H', buff.read(2) )1521 self.annotations = []1522 for i in range(0, self.num_annotations.get_value()) :1523 self.annotations = Annotation( cm, buff )1524 def get_raw(self) :1525 return self.num_annotations.get_value_buff() + \1526 ''.join(x.get_raw() for x in self.annotations)1527 def show(self) :1528 print "ParameterAnnotation", self.num_annotations.get_value()1529 for i in self.annotations :1530 i.show()1531class AnnotationDefaultAttribute(BasicAttribute) :1532 def __init__(self, cm, buff) :1533 super(AnnotationDefaultAttribute, self).__init__()1534 # u2 attribute_name_index;1535 # u4 attribute_length;1536 # element_value default_value;1537 self.default_value = ElementValue( cm, buff )1538 def get_raw(self) :1539 return self.default_value.get_raw()1540 def show(self) :1541 print "AnnotationDefault"1542 self.default_value.show()1543class Annotation :1544 def __init__(self, cm, buff) :1545 # u2 type_index;1546 # u2 num_element_value_pairs;1547 # { u2 element_name_index;1548 # element_value value;1549 # } element_value_pairs[num_element_value_pairs]1550 self.type_index = SV( '>H', buff.read(2) )1551 self.num_element_value_pairs = SV( '>H', buff.read(2) )1552 self.element_value_pairs = []1553 for i in range(0, self.num_element_value_pairs.get_value()) :1554 self.element_value_pairs.append( ElementValuePair(cm, buff) )1555 def get_raw(self) :1556 return self.type_index.get_value_buff() + self.num_element_value_pairs.get_value_buff() + \1557 ''.join(x.get_raw() for x in self.element_value_pairs)1558 def show(self) :1559 print "Annotation", self.type_index.get_value(), self.num_element_value_pairs.get_value()1560 for i in self.element_value_pairs :1561 i.show()1562class ElementValuePair :1563 def __init__(self, cm, buff) :1564 # u2 element_name_index;1565 # element_value value;1566 self.element_name_index = SV( '>H', buff.read(2) )1567 self.value = ElementValue(cm, buff)1568 def get_raw(self) :1569 return self.element_name_index.get_value_buff() + \1570 self.value.get_raw()1571 def show(self) :1572 print "ElementValuePair", self.element_name_index.get_value()1573 self.value.show()1574ENUM_CONST_VALUE = [ '>HH', namedtuple("EnumConstValue", "type_name_index const_name_index") ]1575class ElementValue :1576 def __init__(self, cm, buff) :1577 # u1 tag;1578 # union {1579 # u2 const_value_index;1580 # {1581 # u2 type_name_index;1582 # u2 const_name_index;1583 # } enum_const_value;1584 # u2 class_info_index;1585 # annotation annotation_value;1586 # {1587 # u2 num_values;1588 # element_value values[num_values];1589 # } array_value;1590 # } value;1591 self.tag = SV( '>B', buff.read(1) )1592 tag = chr( self.tag.get_value() )1593 if tag == 'B' or tag == 'C' or tag == 'D' or tag == 'F' or tag == 'I' or tag == 'J' or tag == 'S' or tag == 'Z' or tag == 's' :1594 self.value = SV( '>H', buff.read(2) )1595 elif tag == 'e' :1596 self.value = SVs( ENUM_CONST_VALUE[0], ENUM_CONST_VALUE[1], buff.read( calcsize(ENUM_CONST_VALUE[0]) ) )1597 elif tag == 'c' :1598 self.value = SV( '>H', buff.read(2) )1599 elif tag == '@' :1600 self.value = Annotation( cm, buff )1601 elif tag == '[' :1602 self.value = ArrayValue( cm, buff )1603 else :1604 bytecode.Exit( "tag %c not in VERIFICATION_TYPE_INFO" % self.tag.get_value() )1605 def get_raw(self) :1606 if isinstance(self.value, SV) or isinstance(self.value, SVs) :1607 return self.tag.get_value_buff() + self.value.get_value_buff()1608 return self.tag.get_value_buff() + self.value.get_raw()1609 def show(self) :1610 print "ElementValue", self.tag.get_value()1611 if isinstance(self.value, SV) or isinstance(self.value, SVs) :1612 print self.value.get_value()1613 else :1614 self.value.show()1615class ArrayValue :1616 def __init__(self, cm, buff) :1617 # u2 num_values;1618 # element_value values[num_values];1619 self.num_values = SV( '>H', buff.read(2) )1620 self.values = []1621 for i in range(0, self.num_values.get_value()) :1622 self.values.append( ElementValue(cm, buff) )1623 def get_raw(self) :1624 return self.num_values.get_value_buff() + \1625 ''.join(x.get_raw() for x in self.values)1626 def show(self) :1627 print "ArrayValue", self.num_values.get_value()1628 for i in self.values :1629 i.show()1630class ExceptionsAttribute(BasicAttribute) :1631 def __init__(self, cm, buff) :1632 super(ExceptionsAttribute, self).__init__()1633 # u2 attribute_name_index;1634 # u4 attribute_length;1635 # u2 number_of_exceptions;1636 # u2 exception_index_table[number_of_exceptions];1637 self.number_of_exceptions = SV( '>H', buff.read(2) )1638 self.__exception_index_table = []1639 for i in range(0, self.number_of_exceptions.get_value()) :1640 self.__exception_index_table.append( SV( '>H', buff.read(2) ) )1641 def get_raw(self) :1642 return self.number_of_exceptions.get_value_buff() + ''.join(x.get_value_buff() for x in self.__exception_index_table)1643 def get_exception_index_table(self) :1644 return self.__exception_index_table1645 def show(self) :1646 print "Exceptions", self.number_of_exceptions.get_value()1647 for i in self.__exception_index_table :1648 print "\t", i1649class VerificationTypeInfo :1650 def __init__(self, class_manager, buff) :1651 self.__CM = class_manager1652 tag = SV( '>B', buff.read_b(1) ).get_value()1653 if tag not in VERIFICATION_TYPE_INFO :1654 bytecode.Exit( "tag not in VERIFICATION_TYPE_INFO" )1655 format = VERIFICATION_TYPE_INFO[ tag ][1]1656 self.format = SVs( format, VERIFICATION_TYPE_INFO[ tag ][2], buff.read( calcsize( format ) ) )1657 def get_raw(self) :1658 return self.format.get_value_buff()1659 def show(self) :1660 general_format = self.format.get_value()1661 if len( VERIFICATION_TYPE_INFO[ general_format.tag ] ) > 3 :1662 print general_format,1663 for (i,j) in VERIFICATION_TYPE_INFO[ general_format.tag ][3] :1664 print getattr(self.__CM, j)( getattr(general_format, i) )1665 else :1666 print general_format1667 def _fix_attributes(self, new_cm) :1668 general_format = self.format.get_value()1669 if len( VERIFICATION_TYPE_INFO[ general_format.tag ] ) > 3 :1670 for (i,j) in VERIFICATION_TYPE_INFO[ general_format.tag ][3] :1671 # Fix the first object which is the current class1672 if getattr(self.__CM, j)( getattr(general_format, i) )[0] == self.__CM.get_this_class_name() :1673 self.format.set_value( { "cpool_index" : new_cm.get_this_class() } )1674 # Fix other objects1675 else :1676 new_class_index = new_cm.create_class( getattr(self.__CM, j)( getattr(general_format, i) )[0] )1677 self.format.set_value( { "cpool_index" : new_class_index } )1678 def set_cm(self, cm) :1679 self.__CM = cm1680class FullFrame :1681 def __init__(self, class_manager, buff) :1682 self.__CM = class_manager1683 # u1 frame_type = FULL_FRAME; /* 255 */1684 # u2 offset_delta;1685 # u2 number_of_locals;1686 self.frame_type = SV( '>B', buff.read(1) )1687 self.offset_delta = SV( '>H', buff.read(2) )1688 self.number_of_locals = SV( '>H', buff.read(2) )1689 # verification_type_info locals[number_of_locals];1690 self.__locals = []1691 for i in range(0, self.number_of_locals.get_value()) :1692 self.__locals.append( VerificationTypeInfo( self.__CM, buff ) )1693 # u2 number_of_stack_items;1694 self.number_of_stack_items = SV( '>H', buff.read(2) )1695 # verification_type_info stack[number_of_stack_items];1696 self.__stack = []1697 for i in range(0, self.number_of_stack_items.get_value()) :1698 self.__stack.append( VerificationTypeInfo( self.__CM, buff ) )1699 def get_locals(self) :1700 return self.__locals1701 def get_raw(self) :1702 return self.frame_type.get_value_buff() + \1703 self.offset_delta.get_value_buff() + \1704 self.number_of_locals.get_value_buff() + \1705 ''.join(x.get_raw() for x in self.__locals) + \1706 self.number_of_stack_items.get_value_buff() + \1707 ''.join(x.get_raw() for x in self.__stack)1708 def show(self) :1709 print "#" * 601710 bytecode._Print("\tFULL_FRAME", self.frame_type.get_value())1711 bytecode._Print("\tOFFSET_DELTA", self.offset_delta.get_value())1712 bytecode._Print("\tNUMBER_OF_LOCALS", self.number_of_locals.get_value())1713 for i in self.__locals :1714 i.show()1715 bytecode._Print("\tNUMBER_OF_STACK_ITEMS", self.number_of_stack_items.get_value())1716 for i in self.__stack :1717 i.show()1718 print "#" * 601719 def _fix_attributes(self, new_cm) :1720 for i in self.__locals :1721 i._fix_attributes( new_cm )1722 def set_cm(self, cm) :1723 self.__CM = cm1724 for i in self.__locals :1725 i.set_cm( cm )1726class ChopFrame :1727 def __init__(self, buff) :1728 # u1 frame_type=CHOP; /* 248-250 */1729 # u2 offset_delta;1730 self.frame_type = SV( '>B', buff.read(1) )1731 self.offset_delta = SV( '>H', buff.read(2) )1732 def get_raw(self) :1733 return self.frame_type.get_value_buff() + self.offset_delta.get_value_buff()1734 def show(self) :1735 print "#" * 601736 bytecode._Print("\tCHOP_FRAME", self.frame_type.get_value())1737 bytecode._Print("\tOFFSET_DELTA", self.offset_delta.get_value())1738 print "#" * 601739 def _fix_attributes(self, cm) :1740 pass1741 def set_cm(self, cm) :1742 pass1743class SameFrame :1744 def __init__(self, buff) :1745 # u1 frame_type = SAME;/* 0-63 */1746 self.frame_type = SV( '>B', buff.read(1) )1747 def get_raw(self) :1748 return self.frame_type.get_value_buff()1749 def show(self) :1750 print "#" * 601751 bytecode._Print("\tSAME_FRAME", self.frame_type.get_value())1752 print "#" * 601753 def _fix_attributes(self, new_cm) :1754 pass1755 def set_cm(self, cm) :1756 pass1757class SameLocals1StackItemFrame :1758 def __init__(self, class_manager, buff) :1759 self.__CM = class_manager1760 # u1 frame_type = SAME_LOCALS_1_STACK_ITEM;/* 64-127 */1761 # verification_type_info stack[1];1762 self.frame_type = SV( '>B', buff.read(1) )1763 self.stack = VerificationTypeInfo( self.__CM, buff )1764 def show(self) :1765 print "#" * 601766 bytecode._Print("\tSAME_LOCALS_1_STACK_ITEM_FRAME", self.frame_type.get_value())1767 self.stack.show()1768 print "#" * 601769 def get_raw(self) :1770 return self.frame_type.get_value_buff() + self.stack.get_raw()1771 def _fix_attributes(self, new_cm) :1772 pass1773 def set_cm(self, cm) :1774 self.__CM = cm1775class SameLocals1StackItemFrameExtended :1776 def __init__(self, class_manager, buff) :1777 self.__CM = class_manager1778 # u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; /* 247 */1779 # u2 offset_delta;1780 # verification_type_info stack[1];1781 self.frame_type = SV( '>B', buff.read(1) )1782 self.offset_delta = SV( '>H', buff.read(2) )1783 self.stack = VerificationTypeInfo( self.__CM, buff )1784 def get_raw(self) :1785 return self.frame_type.get_value_buff() + self.offset_delta.get_value_buff() + self.stack.get_value_buff()1786 def _fix_attributes(self, new_cm) :1787 pass1788 def set_cm(self, cm) :1789 self.__CM = cm1790 def show(self) :1791 print "#" * 601792 bytecode._Print("\tSAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED", self.frame_type.get_value())1793 bytecode._Print("\tOFFSET_DELTA", self.offset_delta.get_value())1794 self.stack.show()1795 print "#" * 601796class SameFrameExtended :1797 def __init__(self, buff) :1798 # u1 frame_type = SAME_FRAME_EXTENDED;/* 251*/1799 # u2 offset_delta;1800 self.frame_type = SV( '>B', buff.read(1) )1801 self.offset_delta = SV( '>H', buff.read(2) )1802 def get_raw(self) :1803 return self.frame_type.get_value_buff() + self.offset_delta.get_value_buff()1804 def _fix_attributes(self, cm) :1805 pass1806 def set_cm(self, cm) :1807 pass1808 def show(self) :1809 print "#" * 601810 bytecode._Print("\tSAME_FRAME_EXTENDED", self.frame_type.get_value())1811 bytecode._Print("\tOFFSET_DELTA", self.offset_delta.get_value())1812 print "#" * 601813class AppendFrame :1814 def __init__(self, class_manager, buff) :1815 self.__CM = class_manager1816 # u1 frame_type = APPEND; /* 252-254 */1817 # u2 offset_delta;1818 self.frame_type = SV( '>B', buff.read(1) )1819 self.offset_delta = SV( '>H', buff.read(2) )1820 # verification_type_info locals[frame_type -251];1821 self.__locals = []1822 k = self.frame_type.get_value() - 2511823 for i in range(0, k) :1824 self.__locals.append( VerificationTypeInfo( self.__CM, buff ) )1825 def get_locals(self) :1826 return self.__locals1827 def show(self) :1828 print "#" * 601829 bytecode._Print("\tAPPEND_FRAME", self.frame_type.get_value())1830 bytecode._Print("\tOFFSET_DELTA", self.offset_delta.get_value())1831 for i in self.__locals :1832 i.show()1833 print "#" * 601834 def get_raw(self) :1835 return self.frame_type.get_value_buff() + \1836 self.offset_delta.get_value_buff() + \1837 ''.join(x.get_raw() for x in self.__locals)1838 def _fix_attributes(self, new_cm) :1839 for i in self.__locals :1840 i._fix_attributes( new_cm )1841 def set_cm(self, cm) :1842 self.__CM = cm1843 for i in self.__locals :1844 i.set_cm( cm )1845class StackMapTableAttribute(BasicAttribute) :1846 def __init__(self, class_manager, buff) :1847 self.__CM = class_manager1848 super(StackMapTableAttribute, self).__init__()1849 # u2 attribute_name_index;1850 # u4 attribute_length1851 # u2 number_of_entries;1852 self.number_of_entries = SV( '>H', buff.read(2) )1853 # stack_map_frame entries[number_of_entries];1854 self.__entries = []1855 for i in range(0, self.number_of_entries.get_value()) :1856 frame_type = SV( '>B', buff.read_b(1) ).get_value()1857 if frame_type >= 0 and frame_type <= 63 :1858 self.__entries.append( SameFrame( buff ) )1859 elif frame_type >= 64 and frame_type <= 127 :1860 self.__entries.append( SameLocals1StackItemFrame( self.__CM, buff ) )1861 elif frame_type == 247 :1862 self.__entries.append( SameLocals1StackItemFrameExtended( self.__CM, buff ) )1863 elif frame_type >= 248 and frame_type <= 250 :1864 self.__entries.append( ChopFrame( buff ) )1865 elif frame_type == 251 :1866 self.__entries.append( SameFrameExtended( buff ) )1867 elif frame_type >= 252 and frame_type <= 254 :1868 self.__entries.append( AppendFrame( self.__CM, buff ) )1869 elif frame_type == 255 :1870 self.__entries.append( FullFrame( self.__CM, buff ) )1871 else :1872 bytecode.Exit( "Frame type %d is unknown" % frame_type )1873 def get_entries(self) :1874 return self.__entries1875 def get_local_variables(self) :1876 for i in self.__entries :1877 if isinstance(i, FullFrame) :1878 return i.get_local_variables()1879 return []1880 def get_raw(self) :1881 return self.number_of_entries.get_value_buff() + \1882 ''.join(x.get_raw() for x in self.__entries )1883 def show(self) :1884 bytecode._Print("NUMBER_OF_ENTRIES", self.number_of_entries.get_value())1885 for i in self.__entries :1886 i.show()1887 def _fix_attributes(self, new_cm) :1888 for i in self.__entries :1889 i._fix_attributes( new_cm )1890 def set_cm(self, cm) :1891 self.__CM = cm1892 for i in self.__entries :1893 i.set_cm( cm )1894class InnerClassesDesc :1895 def __init__(self, class_manager, buff) :1896 INNER_CLASSES_FORMAT = [ ">HHHH", "inner_class_info_index outer_class_info_index inner_name_index inner_class_access_flags" ]1897 self.__CM = class_manager1898 self.__raw_buff = buff.read( calcsize( INNER_CLASSES_FORMAT[0] ) )1899 self.format = SVs( INNER_CLASSES_FORMAT[0], namedtuple( "InnerClassesFormat", INNER_CLASSES_FORMAT[1] ), self.__raw_buff )1900 def show(self) :1901 print self.format1902 def get_raw(self) :1903 return self.format.get_value_buff()1904 def set_cm(self, cm) :1905 self.__CM = cm1906class InnerClassesAttribute(BasicAttribute) :1907 def __init__(self, class_manager, buff) :1908 self.__CM = class_manager1909 super(InnerClassesAttribute, self).__init__()1910 # u2 attribute_name_index;1911 # u4 attribute_length1912 # u2 number_of_classes;1913 self.number_of_classes = SV( '>H', buff.read(2) )1914 # { u2 inner_class_info_index;1915 # u2 outer_class_info_index;1916 # u2 inner_name_index;1917 # u2 inner_class_access_flags;1918 # } classes[number_of_classes];1919 self.__classes = []1920 for i in range(0, self.number_of_classes.get_value()) :1921 self.__classes.append( InnerClassesDesc( self.__CM, buff ) )1922 def get_classes(self) :1923 return self.__classes1924 def show(self) :1925 print self.number_of_classes1926 for i in self.__classes :1927 i.show()1928 def set_cm(self, cm) :1929 self.__CM = cm1930 for i in self.__classes :1931 i.set_cm( cm )1932 def get_raw(self) :1933 return self.number_of_classes.get_value_buff() + \1934 ''.join(x.get_raw() for x in self.__classes)1935class ConstantValueAttribute(BasicAttribute) :1936 def __init__(self, class_manager, buff) :1937 self.__CM = class_manager1938 super(ConstantValueAttribute, self).__init__()1939 # u2 attribute_name_index;1940 # u4 attribute_length;1941 # u2 constantvalue_index;1942 self.constantvalue_index = SV( '>H', buff.read(2) )1943 def show(self) :1944 print self.constantvalue_index1945 def set_cm(self, cm) :1946 self.__CM = cm1947 def get_raw(self) :1948 return self.constantvalue_index.get_value_buff()1949class EnclosingMethodAttribute(BasicAttribute) :1950 def __init__(self, class_manager, buff) :1951 ENCLOSING_METHOD_FORMAT = [ '>HH', "class_index method_index" ]1952 self.__CM = class_manager1953 super(EnclosingMethodAttribute, self).__init__()1954 # u2 attribute_name_index;1955 # u4 attribute_length;1956 # u2 class_index1957 # u2 method_index;1958 self.__raw_buff = buff.read( calcsize( ENCLOSING_METHOD_FORMAT[0] ) )1959 self.format = SVs( ENCLOSING_METHOD_FORMAT[0], namedtuple( "EnclosingMethodFormat", ENCLOSING_METHOD_FORMAT[1] ), self.__raw_buff )1960 def show(self) :1961 print self.format1962 def set_cm(self, cm) :1963 self.__CM = cm1964 def get_raw(self) :1965 return self.format.get_value_buff()1966ATTRIBUTE_INFO_DESCR = {1967 "Code" : CodeAttribute,1968 "Deprecated" : DeprecatedAttribute,1969 "SourceFile" : SourceFileAttribute,1970 "Exceptions" : ExceptionsAttribute,1971 "LineNumberTable" : LineNumberTableAttribute,1972 "LocalVariableTable" : LocalVariableTableAttribute,1973 "LocalVariableTypeTable" : LocalVariableTypeTableAttribute,1974 "StackMapTable" : StackMapTableAttribute,1975 "InnerClasses" : InnerClassesAttribute,1976 "ConstantValue" : ConstantValueAttribute,1977 "EnclosingMethod" : EnclosingMethodAttribute,1978 "Signature" : SignatureAttribute,1979 "Synthetic" : SyntheticAttribute,1980 "SourceDebugExtension" : SourceDebugExtensionAttribute,1981 "RuntimeVisibleAnnotations" : RuntimeVisibleAnnotationsAttribute,1982 "RuntimeInvisibleAnnotations" : RuntimeInvisibleAnnotationsAttribute,1983 "RuntimeVisibleParameterAnnotations" : RuntimeVisibleParameterAnnotationsAttribute,1984 "RuntimeInvisibleParameterAnnotations" : RuntimeInvisibleParameterAnnotationsAttribute,1985 "AnnotationDefault" : AnnotationDefaultAttribute,1986}1987class AttributeInfo :1988 """AttributeInfo manages each attribute info (Code, SourceFile ....)"""1989 def __init__(self, class_manager, buff) :1990 self.__CM = class_manager1991 self.__raw_buff = buff.read( calcsize( ATTRIBUTE_INFO[0] ) )1992 self.format = SVs( ATTRIBUTE_INFO[0], ATTRIBUTE_INFO[1], self.__raw_buff )1993 self.__name = self.__CM.get_string( self.format.get_value().attribute_name_index )1994 try :1995 self._info = ATTRIBUTE_INFO_DESCR[ self.__name ](self.__CM, buff)1996 except KeyError, ke :1997 bytecode.Exit( "AttributeInfo %s doesn't exit" % self.__name )1998 def get_item(self) :1999 """Return the specific attribute info"""2000 return self._info2001 def get_name(self) :2002 """Return the name of the attribute"""2003 return self.__name2004 def get_raw(self) :2005 v1 = self.format.get_value().attribute_length2006 v2 = len(self._info.get_raw())2007 if v1 != v2 :2008 self.set_attribute_length( v2 )2009 return self.format.get_value_buff() + self._info.get_raw()2010 def get_attribute_name_index(self) :2011 return self.format.get_value().attribute_name_index2012 def set_attribute_name_index(self, value) :2013 self.format.set_value( { "attribute_name_index" : value } )2014 def set_attribute_length(self, value) :2015 self.format.set_value( { "attribute_length" : value } )2016 def get_attributes(self) :2017 return self.format2018 def _fix_attributes(self, new_cm) :2019 self._info._fix_attributes( new_cm )2020 def set_cm(self, cm) :2021 self.__CM = cm2022 self._info.set_cm( cm )2023 def show(self) :2024 print self.format, self.__name2025 if self._info != None :2026 self._info.show()2027 def pretty_show(self, m_a) :2028 print self.format, self.__name2029 if self._info != None :2030 if isinstance(self._info, CodeAttribute) :2031 self._info.pretty_show(m_a)2032 else :2033 self._info.show()2034class ClassManager :2035 """ClassManager can be used by all classes to get more information"""2036 def __init__(self, constant_pool, constant_pool_count) :2037 self.constant_pool = constant_pool2038 self.constant_pool_count = constant_pool_count2039 self.__this_class = None2040 def get_value(self, idx) :2041 name = self.get_item(idx[0]).get_name()2042 if name == "CONSTANT_Integer" :2043 return [ name, self.get_item(idx[0]).get_format().get_value().bytes ]2044 elif name == "CONSTANT_String" :2045 return [ name, self.get_string( self.get_item(idx[0]).get_format().get_value().string_index ) ]2046 elif name == "CONSTANT_Class" :2047 return [ name, self.get_class( idx[0] ) ]2048 elif name == "CONSTANT_Fieldref" :2049 return [ name, self.get_field( idx[0] ) ]2050 elif name == "CONSTANT_Float" :2051 return [ name, self.get_item(idx[0]).get_format().get_value().bytes ]2052 bytecode.Exit( "get_value not yet implemented for %s" % name )2053 def get_item(self, idx) :2054 return self.constant_pool[ idx - 1]2055 def get_interface(self, idx) :2056 if self.get_item(idx).get_name() != "CONSTANT_InterfaceMethodref" :2057 return []2058 class_idx = self.get_item(idx).get_class_index()2059 name_and_type_idx = self.get_item(idx).get_name_and_type_index()2060 return [ self.get_string( self.get_item(class_idx).get_name_index() ),2061 self.get_string( self.get_item(name_and_type_idx).get_name_index() ),2062 self.get_string( self.get_item(name_and_type_idx).get_descriptor_index() )2063 ]2064 def get_interface_index(self, class_name, name, descriptor) :2065 raise("ooo")2066 def get_method(self, idx) :2067 if self.get_item(idx).get_name() != "CONSTANT_Methodref" :2068 return []2069 class_idx = self.get_item(idx).get_class_index()2070 name_and_type_idx = self.get_item(idx).get_name_and_type_index()2071 return [ self.get_string( self.get_item(class_idx).get_name_index() ),2072 self.get_string( self.get_item(name_and_type_idx).get_name_index() ),2073 self.get_string( self.get_item(name_and_type_idx).get_descriptor_index() )2074 ]2075 def get_method_index(self, class_name, name, descriptor) :2076 idx = 12077 for i in self.constant_pool :2078 res = self.get_method( idx )2079 if res != [] :2080 m_class_name, m_name, m_descriptor = res2081 if m_class_name == class_name and m_name == name and m_descriptor == descriptor :2082 return idx2083 idx += 12084 return -12085 def get_field(self, idx) :2086 if self.get_item(idx).get_name() != "CONSTANT_Fieldref" :2087 return []2088 class_idx = self.get_item(idx).get_class_index()2089 name_and_type_idx = self.get_item(idx).get_name_and_type_index()2090 return [ self.get_string( self.get_item(class_idx).get_name_index() ),2091 self.get_string( self.get_item(name_and_type_idx).get_name_index() ),2092 self.get_string( self.get_item(name_and_type_idx).get_descriptor_index() )2093 ]2094 def get_field_index(self, name, descriptor) :2095 idx = 12096 for i in self.constant_pool :2097 res = self.get_field( idx )2098 if res != [] :2099 _, m_name, m_descriptor = res2100 if m_name == name and m_descriptor == descriptor :2101 return idx2102 idx += 12103 def get_class(self, idx) :2104 if self.get_item(idx).get_name() != "CONSTANT_Class" :2105 return []2106 return [ self.get_string( self.get_item(idx).get_name_index() ) ]2107 def get_array_type(self, idx) :2108 return ARRAY_TYPE[ idx[0] ]2109 def get_string_index(self, name) :2110 idx = 12111 for i in self.constant_pool :2112 if i.get_name() == "CONSTANT_Utf8" :2113 if i.get_bytes() == name :2114 return idx2115 idx += 12116 return -12117 def get_integer_index(self, value) :2118 idx = 12119 for i in self.constant_pool :2120 if i.get_name() == "CONSTANT_Integer" :2121 if i.get_format().get_value().bytes == value :2122 return idx2123 idx += 12124 return -12125 def get_cstring_index(self, value) :2126 idx = 12127 for i in self.constant_pool :2128 if i.get_name() == "CONSTANT_String" :2129 if self.get_string( i.get_format().get_value().string_index ) == value :2130 return idx2131 idx += 12132 return -12133 def get_name_and_type_index(self, name_method_index, descriptor_method_index) :2134 idx = 12135 for i in self.constant_pool :2136 if i.get_name() == "CONSTANT_NameAndType" :2137 value = i.get_format().get_value()2138 if value.name_index == name_method_index and value.descriptor_index == descriptor_method_index :2139 return idx2140 idx += 12141 return -12142 def get_class_by_index(self, name_index) :2143 idx = 12144 for i in self.constant_pool :2145 if i.get_name() == "CONSTANT_Class" :2146 value = i.get_format().get_value()2147 if value.name_index == name_index :2148 return idx2149 idx += 12150 return -12151 def get_method_ref_index(self, new_class_index, new_name_and_type_index) :2152 idx = 12153 for i in self.constant_pool :2154 if i.get_name() == "CONSTANT_Methodref" :2155 value = i.get_format().get_value()2156 if value.class_index == new_class_index and value.name_and_type_index == new_name_and_type_index :2157 return idx2158 idx += 12159 return -12160 def get_field_ref_index(self, new_class_index, new_name_and_type_index) :2161 idx = 12162 for i in self.constant_pool :2163 if i.get_name() == "CONSTANT_Fieldref" :2164 value = i.get_format().get_value()2165 if value.class_index == new_class_index and value.name_and_type_index == new_name_and_type_index :2166 return idx2167 idx += 12168 return -12169 def get_class_index(self, method_name) :2170 idx = 12171 for i in self.constant_pool :2172 res = self.get_method( idx )2173 if res != [] :2174 _, name, _ = res2175 if name == method_name :2176 return i.get_class_index()2177 idx += 12178 return -12179 def get_class_index2(self, class_name) :2180 idx = 12181 for i in self.constant_pool :2182 res = self.get_class( idx )2183 if res != [] :2184 name = res[0]2185 if name == class_name :2186 return idx2187 idx += 12188 return -12189 def get_used_fields(self) :2190 l = []2191 for i in self.constant_pool :2192 if i.get_name() == "CONSTANT_Fieldref" :2193 l.append( i )2194 return l2195 def get_used_methods(self) :2196 l = []2197 for i in self.constant_pool :2198 if i.get_name() == "CONSTANT_Methodref" :2199 l.append( i )2200 return l2201 def get_string(self, idx) :2202 if self.constant_pool[idx - 1].get_name() == "CONSTANT_Utf8" :2203 return self.constant_pool[idx - 1].get_bytes()2204 return None2205 def set_string(self, idx, name) :2206 if self.constant_pool[idx - 1].get_name() == "CONSTANT_Utf8" :2207 self.constant_pool[idx - 1].set_bytes( name )2208 else :2209 bytecode.Exit( "invalid index %d to set string %s" % (idx, name) )2210 def add_string(self, name) :2211 name_index = self.get_string_index(name)2212 if name_index != -1 :2213 return name_index2214 tag_value = INVERT_CONSTANT_INFO[ "CONSTANT_Utf8" ]2215 buff = pack( CONSTANT_INFO[ tag_value ][1], tag_value, len(name) ) + pack( ">%ss" % len(name), name )2216 ci = CONSTANT_INFO[ tag_value ][-1]( self, bytecode.BuffHandle( buff ) )2217 self.constant_pool.append( ci )2218 self.constant_pool_count.set_value( self.constant_pool_count.get_value() + 1 )2219 return self.constant_pool_count.get_value() - 12220 def set_this_class(self, this_class) :2221 self.__this_class = this_class2222 def get_this_class(self) :2223 return self.__this_class.get_value()2224 def get_this_class_name(self) :2225 return self.get_class( self.__this_class.get_value() )[0]2226 def add_constant_pool(self, elem) :2227 self.constant_pool.append( elem )2228 self.constant_pool_count.set_value( self.constant_pool_count.get_value() + 1 )2229 def get_constant_pool_count(self) :2230 return self.constant_pool_count.get_value()2231 def create_class(self, name) :2232 class_name_index = self.add_string( name )2233 return self._create_class( class_name_index )2234 def _create_class(self, class_name_index) :2235 class_index = self.get_class_by_index( class_name_index )2236 if class_index == -1 :2237 new_class = CreateClass( self, class_name_index )2238 self.add_constant_pool( Class( self, bytecode.BuffHandle( new_class.get_raw() ) ) )2239 class_index = self.get_constant_pool_count() - 12240 return class_index2241 def create_name_and_type(self, name, desc) :2242 name_index = self.add_string( name )2243 descriptor_index = self.add_string( desc )2244 return self._create_name_and_type( name_index, descriptor_index )2245 def create_name_and_type_by_index(self, name_method_index, descriptor_method_index) :2246 return self._create_name_and_type( name_method_index, descriptor_method_index )2247 def _create_name_and_type(self, name_method_index, descriptor_method_index) :2248 name_and_type_index = self.get_name_and_type_index( name_method_index, descriptor_method_index )2249 if name_and_type_index == -1 :2250 new_nat = CreateNameAndType( self, name_method_index, descriptor_method_index )2251 self.add_constant_pool( NameAndType( self, bytecode.BuffHandle( new_nat.get_raw() ) ) )2252 name_and_type_index = self.get_constant_pool_count() - 12253 return name_and_type_index2254 def create_method_ref(self, new_class_index, new_name_and_type_index) :2255 new_mr_index = self.get_method_ref_index( new_class_index, new_name_and_type_index )2256 if new_mr_index == -1 :2257 new_mr = CreateMethodRef( self, new_class_index, new_name_and_type_index )2258 self.add_constant_pool( MethodRef( self, bytecode.BuffHandle( new_mr.get_raw() ) ) )2259 new_mr_index = self.get_constant_pool_count() - 12260 return new_mr_index2261 def create_field_ref(self, new_class_index, new_name_and_type_index) :2262 new_fr_index = self.get_field_ref_index( new_class_index, new_name_and_type_index )2263 if new_fr_index == -1 :2264 new_fr = CreateFieldRef( self, new_class_index, new_name_and_type_index )2265 self.add_constant_pool( FieldRef( self, bytecode.BuffHandle( new_fr.get_raw() ) ) )2266 new_fr_index = self.get_constant_pool_count() - 12267 return new_fr_index2268 def create_integer(self, value) :2269 new_int_index = self.get_integer_index( value )2270 if new_int_index == -1 :2271 new_int = CreateInteger( value )2272 self.add_constant_pool( Integer( self, bytecode.BuffHandle( new_int.get_raw() ) ) )2273 new_int_index = self.get_constant_pool_count() - 12274 return new_int_index2275 def create_string(self, value) :2276 new_string_index = self.get_cstring_index( value )2277 if new_string_index == -1 :2278 new_string = CreateString( self, value )2279 self.add_constant_pool( String( self, bytecode.BuffHandle( new_string.get_raw() ) ) )2280 new_string_index = self.get_constant_pool_count() - 12281 return new_string_index2282class JVMFormat(bytecode._Bytecode) :2283 """2284 An object which is the main class to handle properly a class file.2285 Exported fields : magic, minor_version, major_version, constant_pool_count, access_flags, this_class, super_class, interfaces_count, fields_count, methods_count, attributes_count2286 """2287 def __init__(self, buff) :2288 """2289 @param buff : the buffer which represents the open file2290 """2291 super(JVMFormat, self).__init__( buff )2292 self._load_class()2293 def _load_class(self) :2294 # u4 magic;2295 # u2 minor_version;2296 # u2 major_version;2297 self.magic = SV( '>L', self.read( 4 ) )2298 self.minor_version = SV( '>H', self.read( 2 ) )2299 self.major_version = SV( '>H', self.read( 2 ) )2300 # u2 constant_pool_count;2301 self.constant_pool_count = SV( '>H', self.read( 2 ) )2302 # cp_info constant_pool[constant_pool_count-1];2303 self.constant_pool = []2304 self.__CM = ClassManager( self.constant_pool, self.constant_pool_count )2305 i = 12306 while(i < self.constant_pool_count.get_value()) :2307 tag = SV( '>B', self.read_b( 1 ) )2308 if tag.get_value() not in CONSTANT_INFO :2309 bytecode.Exit( "tag %d not in CONSTANT_INFO" % tag.get_value() )2310 ci = CONSTANT_INFO[ tag.get_value() ][-1]( self.__CM, self )2311 self.constant_pool.append( ci )2312 i = i + 12313 # CONSTANT_Long or CONSTANT_Double2314 # If a CONSTANT_Long_info or CONSTANT_Double_info structure is the item2315 # in the constant_pool table at index n, then the next usable item in the pool is2316 # located at index n + 2. The constant_pool index n + 1 must be valid but is2317 # considered unusable.2318 if tag.get_value() == 5 or tag.get_value() == 6 :2319 self.constant_pool.append( EmptyConstant() )2320 i = i + 12321 # u2 access_flags;2322 # u2 this_class;2323 # u2 super_class;2324 self.access_flags = SV( '>H', self.read( 2 ) )2325 self.this_class = SV( '>H', self.read( 2 ) )2326 self.super_class = SV( '>H', self.read( 2 ) )2327 self.__CM.set_this_class( self.this_class )2328 # u2 interfaces_count;2329 self.interfaces_count = SV( '>H', self.read( 2 ) )2330 # u2 interfaces[interfaces_count];2331 self.interfaces = []2332 for i in range(0, self.interfaces_count.get_value()) :2333 tag = SV( '>H', self.read( 2 ) )2334 self.interfaces.append( tag )2335 # u2 fields_count;2336 self.fields_count = SV( '>H', self.read( 2 ) )2337 # field_info fields[fields_count];2338 self.fields = []2339 for i in range(0, self.fields_count.get_value()) :2340 fi = FieldInfo( self.__CM, self )2341 self.fields.append( fi )2342 # u2 methods_count;2343 self.methods_count = SV( '>H', self.read( 2 ) )2344 # method_info methods[methods_count];2345 self.methods = []2346 for i in range(0, self.methods_count.get_value()) :2347 mi = MethodInfo( self.__CM, self )2348 self.methods.append( mi )2349 # u2 attributes_count;2350 self.attributes_count = SV( '>H', self.read( 2 ) )2351 # attribute_info attributes[attributes_count];2352 self.__attributes = []2353 for i in range(0, self.attributes_count.get_value()) :2354 ai = AttributeInfo( self.__CM, self )2355 self.__attributes.append( ai )2356 def get_class(self, class_name) :2357 """2358 Verify the name of the class2359 @param class_name : the name of the class2360 @rtype : True if the class name is valid, otherwise it's False2361 """2362 x = self.__CM.get_this_class_name() == class_name2363 if x == True :2364 return x2365 return self.__CM.get_this_class_name() == class_name.replace(".", "/")2366 def get_classes_names(self) :2367 """2368 Return the names of classes2369 """2370 return [ self.__CM.get_this_class_name() ]2371 def get_name(self) :2372 """2373 """2374 return self.__CM.get_this_class_name()2375 def get_classes(self) :2376 """2377 """2378 return [ self ]2379 def get_field(self, name) :2380 """2381 Return into a list all fields which corresponds to the regexp2382 @param name : the name of the field (a regexp)2383 """2384 prog = re.compile( name )2385 fields = []2386 for i in self.fields :2387 if prog.match( i.get_name() ) :2388 fields.append( i )2389 return fields2390 def get_method_descriptor(self, class_name, method_name, descriptor) :2391 """2392 Return the specific method2393 @param class_name : the class name of the method2394 @param method_name : the name of the method2395 @param descriptor : the descriptor of the method2396 @rtype: L{MethodInfo}2397 """2398 # FIXME : handle multiple class name ?2399 if class_name != None :2400 if class_name != self.__CM.get_this_class_name() :2401 return None2402 for i in self.methods :2403 if method_name == i.get_name() and descriptor == i.get_descriptor() :2404 return i2405 return None2406 def get_field_descriptor(self, class_name, field_name, descriptor) :2407 """2408 Return the specific field2409 @param class_name : the class name of the field2410 @param field_name : the name of the field2411 @param descriptor : the descriptor of the field2412 @rtype: L{FieldInfo}2413 """2414 # FIXME : handle multiple class name ?2415 if class_name != None :2416 if class_name != self.__CM.get_this_class_name() :2417 return None2418 for i in self.fields :2419 if field_name == i.get_name() and descriptor == i.get_descriptor() :2420 return i2421 return None2422 def get_method(self, name) :2423 """Return into a list all methods which corresponds to the regexp2424 @param name : the name of the method (a regexp)2425 """2426 prog = re.compile( name )2427 methods = []2428 for i in self.methods :2429 if prog.match( i.get_name() ) :2430 methods.append( i )2431 return methods2432 def get_all_fields(self) :2433 return self.fields2434 def get_fields(self) :2435 """Return all objects fields"""2436 return self.fields2437 def get_methods(self) :2438 """Return all objects methods"""2439 return self.methods2440 def get_constant_pool(self) :2441 """Return the constant pool list"""2442 return self.constant_pool2443 def get_strings(self) :2444 """Return all strings into the class"""2445 l = []2446 for i in self.constant_pool :2447 if i.get_name() == "CONSTANT_Utf8" :2448 l.append( i.get_bytes() )2449 return l2450 def get_class_manager(self) :2451 """2452 Return directly the class manager2453 @rtype : L{ClassManager}2454 """2455 return self.__CM2456 def set_used_field(self, old, new) :2457 """2458 Change the description of a field2459 @param old : a list of string which contained the original class name, the original field name and the original descriptor2460 @param new : a list of string which contained the new class name, the new field name and the new descriptor2461 """2462 used_fields = self.__CM.get_used_fields()2463 for i in used_fields :2464 class_idx = i.format.get_value().class_index2465 name_and_type_idx = i.format.get_value().name_and_type_index2466 class_name = self.__CM.get_string( self.__CM.get_item(class_idx).get_name_index() )2467 field_name = self.__CM.get_string( self.__CM.get_item(name_and_type_idx).get_name_index() )2468 descriptor = self.__CM.get_string( self.__CM.get_item(name_and_type_idx).get_descriptor_index() )2469 if old[0] == class_name and old[1] == field_name and old[2] == descriptor :2470# print "SET USED FIELD", class_name, method_name, descriptor2471 self.__CM.set_string( self.__CM.get_item(class_idx).get_name_index(), new[0] )2472 self.__CM.set_string( self.__CM.get_item(name_and_type_idx).get_name_index(), new[1] )2473 self.__CM.set_string( self.__CM.get_item(name_and_type_idx).get_descriptor_index(), new[2] )2474 def set_used_method(self, old, new) :2475 """2476 Change the description of a method2477 @param old : a list of string which contained the original class name, the original method name and the original descriptor2478 @param new : a list of string which contained the new class name, the new method name and the new descriptor2479 """2480 used_methods = self.__CM.get_used_methods()2481 for i in used_methods :2482 class_idx = i.format.get_value().class_index2483 name_and_type_idx = i.format.get_value().name_and_type_index2484 class_name = self.__CM.get_string( self.__CM.get_item(class_idx).get_name_index() )2485 method_name = self.__CM.get_string( self.__CM.get_item(name_and_type_idx).get_name_index() )2486 descriptor = self.__CM.get_string( self.__CM.get_item(name_and_type_idx).get_descriptor_index() )2487 if old[0] == class_name and old[1] == method_name and old[2] == descriptor :2488# print "SET USED METHOD", class_name, method_name, descriptor2489 self.__CM.set_string( self.__CM.get_item(class_idx).get_name_index(), new[0] )2490 self.__CM.set_string( self.__CM.get_item(name_and_type_idx).get_name_index(), new[1] )2491 self.__CM.set_string( self.__CM.get_item(name_and_type_idx).get_descriptor_index(), new[2] )2492 def show(self) :2493 """2494 Show the .class format into a human readable format2495 """2496 bytecode._Print( "MAGIC", self.magic.get_value() )2497 bytecode._Print( "MINOR VERSION", self.minor_version.get_value() )2498 bytecode._Print( "MAJOR VERSION", self.major_version.get_value() )2499 bytecode._Print( "CONSTANT POOL COUNT", self.constant_pool_count.get_value() )2500 nb = 02501 for i in self.constant_pool :2502 print nb,2503 i.show()2504 nb += 12505 bytecode._Print( "ACCESS FLAGS", self.access_flags.get_value() )2506 bytecode._Print( "THIS CLASS", self.this_class.get_value() )2507 bytecode._Print( "SUPER CLASS", self.super_class.get_value() )2508 bytecode._Print( "INTERFACE COUNT", self.interfaces_count.get_value() )2509 nb = 02510 for i in self.interfaces :2511 print nb,2512 print i2513 bytecode._Print( "FIELDS COUNT", self.fields_count.get_value() )2514 nb = 02515 for i in self.fields :2516 print nb,2517 i.show()2518 nb += 12519 bytecode._Print( "METHODS COUNT", self.methods_count.get_value() )2520 nb = 02521 for i in self.methods :2522 print nb,2523 i.show()2524 nb += 12525 bytecode._Print( "ATTRIBUTES COUNT", self.attributes_count.get_value() )2526 nb = 02527 for i in self.__attributes :2528 print nb,2529 i.show()2530 nb += 12531 def pretty_show(self, vm_a) :2532 """2533 Show the .class format into a human readable format2534 """2535 bytecode._Print( "MAGIC", self.magic.get_value() )2536 bytecode._Print( "MINOR VERSION", self.minor_version.get_value() )2537 bytecode._Print( "MAJOR VERSION", self.major_version.get_value() )2538 bytecode._Print( "CONSTANT POOL COUNT", self.constant_pool_count.get_value() )2539 nb = 02540 for i in self.constant_pool :2541 print nb,2542 i.show()2543 nb += 12544 bytecode._Print( "ACCESS FLAGS", self.access_flags.get_value() )2545 bytecode._Print( "THIS CLASS", self.this_class.get_value() )2546 bytecode._Print( "SUPER CLASS", self.super_class.get_value() )2547 bytecode._Print( "INTERFACE COUNT", self.interfaces_count.get_value() )2548 nb = 02549 for i in self.interfaces :2550 print nb,2551 i.show()2552 bytecode._Print( "FIELDS COUNT", self.fields_count.get_value() )2553 nb = 02554 for i in self.fields :2555 print nb,2556 i.show()2557 nb += 12558 bytecode._Print( "METHODS COUNT", self.methods_count.get_value() )2559 nb = 02560 for i in self.methods :2561 print nb,2562 i.pretty_show(vm_a)2563 nb += 12564 bytecode._Print( "ATTRIBUTES COUNT", self.attributes_count.get_value() )2565 nb = 02566 for i in self.__attributes :2567 print nb,2568 i.show()2569 def insert_string(self, value) :2570 """Insert a string into the constant pool list (Constant_Utf8)2571 @param value : the new string2572 """2573 self.__CM.add_string( value )2574 def insert_field(self, class_name, name, descriptor) :2575 """2576 Insert a field into the class2577 @param class_name : the class of the field2578 @param name : the name of the field2579 @param descriptor : a list with the access_flag and the descriptor ( [ "ACC_PUBLIC", "I" ] )2580 """2581 new_field = CreateFieldInfo( self.__CM, name, descriptor )2582 new_field = FieldInfo( self.__CM, bytecode.BuffHandle( new_field.get_raw() ) )2583 self.fields.append( new_field )2584 self.fields_count.set_value( self.fields_count.get_value() + 1 )2585 # Add a FieldRef and a NameAndType2586 name_and_type_index = self.__CM.create_name_and_type_by_index( new_field.get_name_index(), new_field.get_descriptor_index() )2587 self.__CM.create_field_ref( self.__CM.get_this_class(), name_and_type_index )2588 def insert_craft_method(self, name, proto, codes) :2589 """2590 Insert a craft method into the class2591 @param name : the name of the new method2592 @param proto : a list which describe the method ( [ ACCESS_FLAGS, RETURN_TYPE, ARGUMENTS ], ie : [ "ACC_PUBLIC", "[B", "[B" ] )2593 @param codes : a list which represents the code into a human readable format ( [ "aconst_null" ], [ "areturn" ] ] )2594 """2595 # Create new method2596 new_method = CreateMethodInfo(self.__CM, name, proto, codes)2597 # Insert the method by casting it directly into a MethodInfo with the raw buffer2598 self._insert_basic_method( MethodInfo( self.__CM, bytecode.BuffHandle( new_method.get_raw() ) ) )2599 def insert_direct_method(self, name, ref_method) :2600 """2601 Insert a direct method (MethodInfo object) into the class2602 @param name : the name of the new method2603 @param ref_method : the MethodInfo Object2604 """2605 if ref_method == None :2606 return2607 # Change the name_index2608 name_index = self.__CM.get_string_index( name )2609 if name_index != -1 :2610 bytecode.Exit( "method %s already exits" % name )2611 name_index = self.__CM.add_string( name )2612 ref_method.set_name_index( name_index )2613 # Change the descriptor_index2614 descriptor_index = self.__CM.get_string_index( ref_method.get_descriptor() )2615 if descriptor_index == -1 :2616 descriptor_index = self.__CM.add_string( ref_method.get_descriptor() )2617 ref_method.set_descriptor_index( descriptor_index )2618 # Change attributes name index2619 self._fix_attributes_external( ref_method )2620 # Change internal index2621 self._fix_attributes_internal( ref_method )2622 # Insert the method2623 self._insert_basic_method( ref_method )2624 def _fix_attributes_external(self, ref_method) :2625 for i in ref_method.get_attributes() :2626 attribute_name_index = self.__CM.add_string( i.get_name() )2627 i.set_attribute_name_index( attribute_name_index )2628 self._fix_attributes_external( i.get_item() )2629 def _fix_attributes_internal(self, ref_method) :2630 for i in ref_method.get_attributes() :2631 attribute_name_index = self.__CM.add_string( i.get_name() )2632 i._fix_attributes( self.__CM )2633 i.set_attribute_name_index( attribute_name_index )2634 def _insert_basic_method(self, ref_method) :2635 # Add a MethodRef and a NameAndType2636 name_and_type_index = self.__CM.create_name_and_type_by_index( ref_method.get_name_index(), ref_method.get_descriptor_index() )2637 self.__CM.create_method_ref( self.__CM.get_this_class(), name_and_type_index )2638 # Change the class manager2639 ref_method.set_cm( self.__CM )2640 # Insert libraries/constants dependances2641 methods = ref_method._patch_bytecodes()2642 # FIXME : insert needed fields + methods2643 prog = re.compile( "^java*" )2644 for i in methods :2645 if prog.match( i[0] ) == None :2646 bytecode.Exit( "ooooops" )2647 #ref_method.show()2648 # Insert the method2649 self.methods.append( ref_method )2650 self.methods_count.set_value( self.methods_count.get_value() + 1 )2651 def _get_raw(self) :2652 # u4 magic;2653 # u2 minor_version;2654 # u2 major_version;2655 buff = self.magic.get_value_buff()2656 buff += self.minor_version.get_value_buff()2657 buff += self.major_version.get_value_buff()2658 # u2 constant_pool_count;2659 buff += self.constant_pool_count.get_value_buff()2660 # cp_info constant_pool[constant_pool_count-1];2661 for i in self.constant_pool :2662 buff += i.get_raw()2663 # u2 access_flags;2664 # u2 this_class;2665 # u2 super_class;2666 buff += self.access_flags.get_value_buff()2667 buff += self.this_class.get_value_buff()2668 buff += self.super_class.get_value_buff()2669 # u2 interfaces_count;2670 buff += self.interfaces_count.get_value_buff()2671 # u2 interfaces[interfaces_count];2672 for i in self.interfaces :2673 buff += i.get_value_buff()2674 # u2 fields_count;2675 buff += self.fields_count.get_value_buff()2676 # field_info fields[fields_count];2677 for i in self.fields :2678 buff += i.get_raw()2679 # u2 methods_count;2680 buff += self.methods_count.get_value_buff()2681 # method_info methods[methods_count];2682 for i in self.methods :2683 buff += i.get_raw()2684 # u2 attributes_count;2685 buff += self.attributes_count.get_value_buff()2686 # attribute_info attributes[attributes_count];2687 for i in self.__attributes :2688 buff += i.get_raw()2689 return buff2690 def save(self) :2691 """2692 Return the class (with the modifications) into raw format2693 @rtype: string2694 """2695 return self._get_raw()2696 2697 def set_vmanalysis(self, vmanalysis) :2698 pass2699 def get_generator(self) :...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!