├── go.mod ├── core ├── goto.go ├── new.go ├── nop.go ├── ret.go ├── lcmp.go ├── swap.go ├── anewarray.go ├── athrow.go ├── checkcast.go ├── getfield.go ├── getstatic.go ├── putfield.go ├── putstatic.go ├── instanceof.go ├── arraylength.go ├── invokenative.go ├── or.go ├── and.go ├── dcmp.go ├── fcmp.go ├── ifnull.go ├── pop.go ├── xor.go ├── if_acmp.go ├── monitor.go ├── ldc.go ├── d2x.go ├── f2x.go ├── l2x.go ├── add.go ├── div.go ├── mul.go ├── neg.go ├── rem.go ├── sub.go ├── insn_set.go ├── thread.go ├── aload.go ├── dload.go ├── fload.go ├── iload.go ├── lload.go ├── astore.go ├── dstore.go ├── fstore.go ├── istore.go ├── lstore.go ├── ifcond.go ├── i2x.go ├── goto_w.go ├── sh.go ├── dup.go ├── if_icmp.go ├── return.go ├── invokedynamic.go ├── jsr.go ├── multianewarray.go ├── xaload.go ├── xastore.go ├── iinc.go ├── newarray.go ├── lookupswitch.go ├── tableswitch.go ├── ipush.go ├── const.go ├── invokespecial.go ├── invokestatic.go ├── invokevirtual.go ├── invokeinterface.go ├── bytecode_reader.go ├── instruction.go ├── wide.go └── factory.go ├── global └── global.go ├── classfile ├── attr_markers.go ├── attr_deprecate.go ├── attr_synthetic.go ├── cp_field_ref.go ├── cp_method_ref.go ├── cp_interface_method_ref.go ├── field_info.go ├── method_info.go ├── cp_method_type.go ├── cp_integer.go ├── cp_long.go ├── cp_class.go ├── cp_float.go ├── cp_name_and_type.go ├── cp_method_handle.go ├── cp_string.go ├── cp_double.go ├── attr_unparsed.go ├── cp_invoke_dynamic.go ├── attr_constant_value.go ├── attr_signature.go ├── attr_source_file.go ├── attr_exceptions.go ├── cp_member_ref.go ├── attr_enclosing_method.go ├── attr_bootstrap_methods.go ├── class_reader.go ├── attr_inner_classes.go ├── attr_line_number_table.go ├── attr_local_variable_table.go ├── constant_pool.go ├── attr_local_variable_type_table.go ├── attribute_info.go ├── member_info.go ├── cp_utf8.go ├── constant_info.go ├── attr_code.go └── class_file.go ├── files ├── common.go ├── files.go └── jar.go ├── rule.txt ├── .gitignore ├── ref ├── field.go ├── access_flags.go ├── method.go ├── class_member.go └── class.go ├── rule └── rule.go ├── LICENSE ├── main.go ├── doc └── README.md └── README.md /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/4ra1n/accelerator 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /core/goto.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type GOTO struct{ BranchInstruction } 4 | -------------------------------------------------------------------------------- /core/new.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type NEW struct{ Index16Instruction } 4 | -------------------------------------------------------------------------------- /core/nop.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type NOP struct{ NoOperandsInstruction } 4 | -------------------------------------------------------------------------------- /core/ret.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type RET struct{ Index8Instruction } 4 | -------------------------------------------------------------------------------- /core/lcmp.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type LCMP struct{ NoOperandsInstruction } 4 | -------------------------------------------------------------------------------- /core/swap.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type SWAP struct{ NoOperandsInstruction } 4 | -------------------------------------------------------------------------------- /core/anewarray.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type ANEW_ARRAY struct{ Index16Instruction } 4 | -------------------------------------------------------------------------------- /core/athrow.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type ATHROW struct{ NoOperandsInstruction } 4 | -------------------------------------------------------------------------------- /core/checkcast.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type CHECK_CAST struct{ Index16Instruction } 4 | -------------------------------------------------------------------------------- /core/getfield.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type GET_FIELD struct{ Index16Instruction } 4 | -------------------------------------------------------------------------------- /core/getstatic.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type GET_STATIC struct{ Index16Instruction } 4 | -------------------------------------------------------------------------------- /core/putfield.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type PUTFIELD struct{ Index16Instruction } 4 | -------------------------------------------------------------------------------- /core/putstatic.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type PUTSTATIC struct{ Index16Instruction } 4 | -------------------------------------------------------------------------------- /core/instanceof.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type INSTANCEOF struct{ Index16Instruction } 4 | -------------------------------------------------------------------------------- /core/arraylength.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type ARRAY_LENGTH struct{ NoOperandsInstruction } 4 | -------------------------------------------------------------------------------- /core/invokenative.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type INVOKENATIVE struct{ NoOperandsInstruction } 4 | -------------------------------------------------------------------------------- /core/or.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type IOR struct{ NoOperandsInstruction } 4 | 5 | type LOR struct{ NoOperandsInstruction } 6 | -------------------------------------------------------------------------------- /core/and.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type IAND struct{ NoOperandsInstruction } 4 | 5 | type LAND struct{ NoOperandsInstruction } 6 | -------------------------------------------------------------------------------- /core/dcmp.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type DCMPG struct{ NoOperandsInstruction } 4 | 5 | type DCMPL struct{ NoOperandsInstruction } 6 | -------------------------------------------------------------------------------- /core/fcmp.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type FCMPG struct{ NoOperandsInstruction } 4 | 5 | type FCMPL struct{ NoOperandsInstruction } 6 | -------------------------------------------------------------------------------- /core/ifnull.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type IFNULL struct{ BranchInstruction } 4 | 5 | type IFNONNULL struct{ BranchInstruction } 6 | -------------------------------------------------------------------------------- /core/pop.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type POP struct{ NoOperandsInstruction } 4 | 5 | type POP2 struct{ NoOperandsInstruction } 6 | -------------------------------------------------------------------------------- /core/xor.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type IXOR struct{ NoOperandsInstruction } 4 | 5 | type LXOR struct{ NoOperandsInstruction } 6 | -------------------------------------------------------------------------------- /global/global.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | import "github.com/4ra1n/accelerator/classfile" 4 | 5 | var CP classfile.ConstantPool 6 | -------------------------------------------------------------------------------- /core/if_acmp.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type IF_ACMPEQ struct{ BranchInstruction } 4 | 5 | type IF_ACMPNE struct{ BranchInstruction } 6 | -------------------------------------------------------------------------------- /core/monitor.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type MONITORENTER struct{ NoOperandsInstruction } 4 | 5 | type MONITOREXIT struct{ NoOperandsInstruction } 6 | -------------------------------------------------------------------------------- /classfile/attr_markers.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | type MarkerAttribute struct{} 4 | 5 | func (c *MarkerAttribute) readInfo(_ *ClassReader) { 6 | } 7 | -------------------------------------------------------------------------------- /core/ldc.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type LDC struct{ Index8Instruction } 4 | 5 | type LDC_W struct{ Index16Instruction } 6 | 7 | type LDC2_W struct{ Index16Instruction } 8 | -------------------------------------------------------------------------------- /core/d2x.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type D2F struct{ NoOperandsInstruction } 4 | 5 | type D2I struct{ NoOperandsInstruction } 6 | 7 | type D2L struct{ NoOperandsInstruction } 8 | -------------------------------------------------------------------------------- /core/f2x.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type F2D struct{ NoOperandsInstruction } 4 | 5 | type F2I struct{ NoOperandsInstruction } 6 | 7 | type F2L struct{ NoOperandsInstruction } 8 | -------------------------------------------------------------------------------- /core/l2x.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type L2D struct{ NoOperandsInstruction } 4 | 5 | type L2F struct{ NoOperandsInstruction } 6 | 7 | type L2I struct{ NoOperandsInstruction } 8 | -------------------------------------------------------------------------------- /files/common.go: -------------------------------------------------------------------------------- 1 | package files 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | ) 7 | 8 | func RemoveTempFiles() { 9 | dir, _ := filepath.Abs("temp") 10 | _ = os.RemoveAll(dir) 11 | } 12 | -------------------------------------------------------------------------------- /core/add.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type DADD struct{ NoOperandsInstruction } 4 | 5 | type FADD struct{ NoOperandsInstruction } 6 | 7 | type IADD struct{ NoOperandsInstruction } 8 | 9 | type LADD struct{ NoOperandsInstruction } 10 | -------------------------------------------------------------------------------- /core/div.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type DDIV struct{ NoOperandsInstruction } 4 | 5 | type FDIV struct{ NoOperandsInstruction } 6 | 7 | type IDIV struct{ NoOperandsInstruction } 8 | 9 | type LDIV struct{ NoOperandsInstruction } 10 | -------------------------------------------------------------------------------- /core/mul.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type DMUL struct{ NoOperandsInstruction } 4 | 5 | type FMUL struct{ NoOperandsInstruction } 6 | 7 | type IMUL struct{ NoOperandsInstruction } 8 | 9 | type LMUL struct{ NoOperandsInstruction } 10 | -------------------------------------------------------------------------------- /core/neg.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type DNEG struct{ NoOperandsInstruction } 4 | 5 | type FNEG struct{ NoOperandsInstruction } 6 | 7 | type INEG struct{ NoOperandsInstruction } 8 | 9 | type LNEG struct{ NoOperandsInstruction } 10 | -------------------------------------------------------------------------------- /core/rem.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type DREM struct{ NoOperandsInstruction } 4 | 5 | type FREM struct{ NoOperandsInstruction } 6 | 7 | type IREM struct{ NoOperandsInstruction } 8 | 9 | type LREM struct{ NoOperandsInstruction } 10 | -------------------------------------------------------------------------------- /core/sub.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type DSUB struct{ NoOperandsInstruction } 4 | 5 | type FSUB struct{ NoOperandsInstruction } 6 | 7 | type ISUB struct{ NoOperandsInstruction } 8 | 9 | type LSUB struct{ NoOperandsInstruction } 10 | -------------------------------------------------------------------------------- /classfile/attr_deprecate.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | Deprecated_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | } 8 | */ 9 | 10 | type DeprecatedAttribute struct { 11 | MarkerAttribute 12 | } 13 | -------------------------------------------------------------------------------- /classfile/attr_synthetic.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | Synthetic_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | } 8 | */ 9 | 10 | type SyntheticAttribute struct { 11 | MarkerAttribute 12 | } 13 | -------------------------------------------------------------------------------- /classfile/cp_field_ref.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | CONSTANT_Fieldref_info { 5 | u1 tag; 6 | u2 class_index; 7 | u2 name_and_type_index; 8 | } 9 | */ 10 | 11 | type ConstantFieldRefInfo struct{ ConstantMemberRefInfo } 12 | -------------------------------------------------------------------------------- /classfile/cp_method_ref.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | CONSTANT_Methodref_info { 5 | u1 tag; 6 | u2 class_index; 7 | u2 name_and_type_index; 8 | } 9 | */ 10 | 11 | type ConstantMethodRefInfo struct{ ConstantMemberRefInfo } 12 | -------------------------------------------------------------------------------- /rule.txt: -------------------------------------------------------------------------------- 1 | INVOKESPECIAL org/springframework/expression/spel/support/StandardEvaluationContext. * 2 | INVOKEVIRTUAL org/springframework/expression/spel/standard/SpelExpressionParser.parseExpression * 3 | INVOKEINTERFACE org/springframework/expression/Expression.getValue * -------------------------------------------------------------------------------- /classfile/cp_interface_method_ref.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | CONSTANT_InterfaceMethodref_info { 5 | u1 tag; 6 | u2 class_index; 7 | u2 name_and_type_index; 8 | } 9 | */ 10 | 11 | type ConstantInterfaceMethodRefInfo struct{ ConstantMemberRefInfo } 12 | -------------------------------------------------------------------------------- /core/insn_set.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type InstructionSet struct { 4 | ClassName string 5 | MethodName string 6 | Desc string 7 | InstArray []InstructionEntry 8 | } 9 | 10 | type InstructionEntry struct { 11 | Instrument string 12 | Operands []string 13 | } 14 | -------------------------------------------------------------------------------- /core/thread.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type Thread struct { 4 | pc int 5 | } 6 | 7 | func NewThread() *Thread { 8 | return &Thread{pc: 0} 9 | } 10 | 11 | func (self *Thread) PC() int { 12 | return self.pc 13 | } 14 | func (self *Thread) SetPC(pc int) { 15 | self.pc = pc 16 | } 17 | -------------------------------------------------------------------------------- /core/aload.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type ALOAD struct{ Index8Instruction } 4 | 5 | type ALOAD_0 struct{ NoOperandsInstruction } 6 | 7 | type ALOAD_1 struct{ NoOperandsInstruction } 8 | 9 | type ALOAD_2 struct{ NoOperandsInstruction } 10 | 11 | type ALOAD_3 struct{ NoOperandsInstruction } 12 | -------------------------------------------------------------------------------- /core/dload.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type DLOAD struct{ Index8Instruction } 4 | 5 | type DLOAD_0 struct{ NoOperandsInstruction } 6 | 7 | type DLOAD_1 struct{ NoOperandsInstruction } 8 | 9 | type DLOAD_2 struct{ NoOperandsInstruction } 10 | 11 | type DLOAD_3 struct{ NoOperandsInstruction } 12 | -------------------------------------------------------------------------------- /core/fload.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type FLOAD struct{ Index8Instruction } 4 | 5 | type FLOAD_0 struct{ NoOperandsInstruction } 6 | 7 | type FLOAD_1 struct{ NoOperandsInstruction } 8 | 9 | type FLOAD_2 struct{ NoOperandsInstruction } 10 | 11 | type FLOAD_3 struct{ NoOperandsInstruction } 12 | -------------------------------------------------------------------------------- /core/iload.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type ILOAD struct{ Index8Instruction } 4 | 5 | type ILOAD_0 struct{ NoOperandsInstruction } 6 | 7 | type ILOAD_1 struct{ NoOperandsInstruction } 8 | 9 | type ILOAD_2 struct{ NoOperandsInstruction } 10 | 11 | type ILOAD_3 struct{ NoOperandsInstruction } 12 | -------------------------------------------------------------------------------- /core/lload.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type LLOAD struct{ Index8Instruction } 4 | 5 | type LLOAD_0 struct{ NoOperandsInstruction } 6 | 7 | type LLOAD_1 struct{ NoOperandsInstruction } 8 | 9 | type LLOAD_2 struct{ NoOperandsInstruction } 10 | 11 | type LLOAD_3 struct{ NoOperandsInstruction } 12 | -------------------------------------------------------------------------------- /core/astore.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type ASTORE struct{ Index8Instruction } 4 | 5 | type ASTORE_0 struct{ NoOperandsInstruction } 6 | 7 | type ASTORE_1 struct{ NoOperandsInstruction } 8 | 9 | type ASTORE_2 struct{ NoOperandsInstruction } 10 | 11 | type ASTORE_3 struct{ NoOperandsInstruction } 12 | -------------------------------------------------------------------------------- /core/dstore.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type DSTORE struct{ Index8Instruction } 4 | 5 | type DSTORE_0 struct{ NoOperandsInstruction } 6 | 7 | type DSTORE_1 struct{ NoOperandsInstruction } 8 | 9 | type DSTORE_2 struct{ NoOperandsInstruction } 10 | 11 | type DSTORE_3 struct{ NoOperandsInstruction } 12 | -------------------------------------------------------------------------------- /core/fstore.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type FSTORE struct{ Index8Instruction } 4 | 5 | type FSTORE_0 struct{ NoOperandsInstruction } 6 | 7 | type FSTORE_1 struct{ NoOperandsInstruction } 8 | 9 | type FSTORE_2 struct{ NoOperandsInstruction } 10 | 11 | type FSTORE_3 struct{ NoOperandsInstruction } 12 | -------------------------------------------------------------------------------- /core/istore.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type ISTORE struct{ Index8Instruction } 4 | 5 | type ISTORE_0 struct{ NoOperandsInstruction } 6 | 7 | type ISTORE_1 struct{ NoOperandsInstruction } 8 | 9 | type ISTORE_2 struct{ NoOperandsInstruction } 10 | 11 | type ISTORE_3 struct{ NoOperandsInstruction } 12 | -------------------------------------------------------------------------------- /core/lstore.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type LSTORE struct{ Index8Instruction } 4 | 5 | type LSTORE_0 struct{ NoOperandsInstruction } 6 | 7 | type LSTORE_1 struct{ NoOperandsInstruction } 8 | 9 | type LSTORE_2 struct{ NoOperandsInstruction } 10 | 11 | type LSTORE_3 struct{ NoOperandsInstruction } 12 | -------------------------------------------------------------------------------- /core/ifcond.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type IFEQ struct{ BranchInstruction } 4 | 5 | type IFNE struct{ BranchInstruction } 6 | 7 | type IFLT struct{ BranchInstruction } 8 | 9 | type IFLE struct{ BranchInstruction } 10 | 11 | type IFGT struct{ BranchInstruction } 12 | 13 | type IFGE struct{ BranchInstruction } 14 | -------------------------------------------------------------------------------- /core/i2x.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type I2B struct{ NoOperandsInstruction } 4 | 5 | type I2C struct{ NoOperandsInstruction } 6 | 7 | type I2S struct{ NoOperandsInstruction } 8 | 9 | type I2L struct{ NoOperandsInstruction } 10 | 11 | type I2F struct{ NoOperandsInstruction } 12 | 13 | type I2D struct{ NoOperandsInstruction } 14 | -------------------------------------------------------------------------------- /core/goto_w.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type GOTO_W struct { 4 | offset int 5 | } 6 | 7 | func (self *GOTO_W) FetchOperands(reader *BytecodeReader) { 8 | self.offset = int(reader.ReadInt32()) 9 | } 10 | 11 | func (self *GOTO_W) GetOperands() []string { 12 | ret := make([]string, 1) 13 | ret[0] = "[not support]" 14 | return ret 15 | } 16 | -------------------------------------------------------------------------------- /core/sh.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type ISHL struct{ NoOperandsInstruction } 4 | 5 | type ISHR struct{ NoOperandsInstruction } 6 | 7 | type IUSHR struct{ NoOperandsInstruction } 8 | 9 | type LSHL struct{ NoOperandsInstruction } 10 | 11 | type LSHR struct{ NoOperandsInstruction } 12 | 13 | type LUSHR struct{ NoOperandsInstruction } 14 | -------------------------------------------------------------------------------- /core/dup.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type DUP struct{ NoOperandsInstruction } 4 | 5 | type DUP_X1 struct{ NoOperandsInstruction } 6 | 7 | type DUP_X2 struct{ NoOperandsInstruction } 8 | 9 | type DUP2 struct{ NoOperandsInstruction } 10 | 11 | type DUP2_X1 struct{ NoOperandsInstruction } 12 | 13 | type DUP2_X2 struct{ NoOperandsInstruction } 14 | -------------------------------------------------------------------------------- /core/if_icmp.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type IF_ICMPEQ struct{ BranchInstruction } 4 | 5 | type IF_ICMPNE struct{ BranchInstruction } 6 | 7 | type IF_ICMPLT struct{ BranchInstruction } 8 | 9 | type IF_ICMPLE struct{ BranchInstruction } 10 | 11 | type IF_ICMPGT struct{ BranchInstruction } 12 | 13 | type IF_ICMPGE struct{ BranchInstruction } 14 | -------------------------------------------------------------------------------- /classfile/field_info.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | field_info { 5 | u2 access_flags; 6 | u2 name_index; 7 | u2 descriptor_index; 8 | u2 attributes_count; 9 | attribute_info attributes[attributes_count]; 10 | } 11 | */ 12 | 13 | type FieldInfo struct { 14 | MemberInfo 15 | } 16 | -------------------------------------------------------------------------------- /classfile/method_info.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | method_info { 5 | u2 access_flags; 6 | u2 name_index; 7 | u2 descriptor_index; 8 | u2 attributes_count; 9 | attribute_info attributes[attributes_count]; 10 | } 11 | */ 12 | 13 | type MethodInfo struct { 14 | MemberInfo 15 | } 16 | -------------------------------------------------------------------------------- /core/return.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type RETURN struct{ NoOperandsInstruction } 4 | 5 | type ARETURN struct{ NoOperandsInstruction } 6 | 7 | type DRETURN struct{ NoOperandsInstruction } 8 | 9 | type FRETURN struct{ NoOperandsInstruction } 10 | 11 | type IRETURN struct{ NoOperandsInstruction } 12 | 13 | type LRETURN struct{ NoOperandsInstruction } 14 | -------------------------------------------------------------------------------- /classfile/cp_method_type.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | CONSTANT_MethodType_info { 5 | u1 tag; 6 | u2 descriptor_index; 7 | } 8 | */ 9 | 10 | type ConstantMethodTypeInfo struct { 11 | descriptorIndex uint16 12 | } 13 | 14 | func (c *ConstantMethodTypeInfo) readInfo(reader *ClassReader) { 15 | c.descriptorIndex = reader.readUint16() 16 | } 17 | -------------------------------------------------------------------------------- /core/invokedynamic.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type INVOKEDYNAMIC struct { 4 | } 5 | 6 | func (self INVOKEDYNAMIC) FetchOperands(reader *BytecodeReader) { 7 | reader.ReadInt8() 8 | reader.ReadInt8() 9 | reader.ReadInt8() 10 | reader.ReadInt8() 11 | } 12 | 13 | func (self *INVOKEDYNAMIC) GetOperands() []string { 14 | ret := make([]string, 1) 15 | ret[0] = "[not support]" 16 | return ret 17 | } 18 | -------------------------------------------------------------------------------- /files/files.go: -------------------------------------------------------------------------------- 1 | package files 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | ) 7 | 8 | func ReadAllClasses() []string { 9 | var data []string 10 | path, _ := filepath.Abs("temp") 11 | _ = filepath.Walk(path, func(path string, info os.FileInfo, err error) error { 12 | if info.IsDir() { 13 | return nil 14 | } 15 | data = append(data, path) 16 | return nil 17 | }) 18 | return data 19 | } 20 | -------------------------------------------------------------------------------- /core/jsr.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type JSR struct{ Index16Instruction } 4 | 5 | type JSR_W struct { 6 | } 7 | 8 | func (J JSR_W) FetchOperands(reader *BytecodeReader) { 9 | reader.ReadUint8() 10 | reader.ReadUint8() 11 | reader.ReadUint8() 12 | reader.ReadUint8() 13 | } 14 | 15 | func (self *JSR_W) GetOperands() []string { 16 | ret := make([]string, 1) 17 | ret[0] = "[not support]" 18 | return ret 19 | } 20 | -------------------------------------------------------------------------------- /classfile/cp_integer.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | CONSTANT_Integer_info { 5 | u1 tag; 6 | u4 bytes; 7 | } 8 | */ 9 | 10 | type ConstantIntegerInfo struct { 11 | val int32 12 | } 13 | 14 | func (c *ConstantIntegerInfo) readInfo(reader *ClassReader) { 15 | bytes := reader.readUint32() 16 | c.val = int32(bytes) 17 | } 18 | 19 | func (c *ConstantIntegerInfo) Value() int32 { 20 | return c.val 21 | } 22 | -------------------------------------------------------------------------------- /classfile/cp_long.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | CONSTANT_Long_info { 5 | u1 tag; 6 | u4 high_bytes; 7 | u4 low_bytes; 8 | } 9 | */ 10 | 11 | type ConstantLongInfo struct { 12 | val int64 13 | } 14 | 15 | func (c *ConstantLongInfo) readInfo(reader *ClassReader) { 16 | bytes := reader.readUint64() 17 | c.val = int64(bytes) 18 | } 19 | func (c *ConstantLongInfo) Value() int64 { 20 | return c.val 21 | } 22 | -------------------------------------------------------------------------------- /core/multianewarray.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type MULTIANEWARRAY struct { 4 | index uint16 5 | dimensions uint8 6 | } 7 | 8 | func (self *MULTIANEWARRAY) FetchOperands(reader *BytecodeReader) { 9 | self.index = reader.ReadUint16() 10 | self.dimensions = reader.ReadUint8() 11 | } 12 | 13 | func (self *MULTIANEWARRAY) GetOperands() []string { 14 | ret := make([]string, 1) 15 | ret[0] = "[not support]" 16 | return ret 17 | } 18 | -------------------------------------------------------------------------------- /classfile/cp_class.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | CONSTANT_Class_info { 5 | u1 tag; 6 | u2 name_index; 7 | } 8 | */ 9 | 10 | type ConstantClassInfo struct { 11 | cp ConstantPool 12 | nameIndex uint16 13 | } 14 | 15 | func (c *ConstantClassInfo) readInfo(reader *ClassReader) { 16 | c.nameIndex = reader.readUint16() 17 | } 18 | func (c *ConstantClassInfo) Name() string { 19 | return c.cp.GetUtf8(c.nameIndex) 20 | } 21 | -------------------------------------------------------------------------------- /classfile/cp_float.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | import "math" 4 | 5 | /* 6 | CONSTANT_Float_info { 7 | u1 tag; 8 | u4 bytes; 9 | } 10 | */ 11 | 12 | type ConstantFloatInfo struct { 13 | val float32 14 | } 15 | 16 | func (c *ConstantFloatInfo) readInfo(reader *ClassReader) { 17 | bytes := reader.readUint32() 18 | c.val = math.Float32frombits(bytes) 19 | } 20 | func (c *ConstantFloatInfo) Value() float32 { 21 | return c.val 22 | } 23 | -------------------------------------------------------------------------------- /classfile/cp_name_and_type.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | CONSTANT_NameAndType_info { 5 | u1 tag; 6 | u2 name_index; 7 | u2 descriptor_index; 8 | } 9 | */ 10 | 11 | type ConstantNameAndTypeInfo struct { 12 | nameIndex uint16 13 | descriptorIndex uint16 14 | } 15 | 16 | func (c *ConstantNameAndTypeInfo) readInfo(reader *ClassReader) { 17 | c.nameIndex = reader.readUint16() 18 | c.descriptorIndex = reader.readUint16() 19 | } 20 | -------------------------------------------------------------------------------- /core/xaload.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type AALOAD struct{ NoOperandsInstruction } 4 | 5 | type BALOAD struct{ NoOperandsInstruction } 6 | 7 | type CALOAD struct{ NoOperandsInstruction } 8 | 9 | type DALOAD struct{ NoOperandsInstruction } 10 | 11 | type FALOAD struct{ NoOperandsInstruction } 12 | 13 | type IALOAD struct{ NoOperandsInstruction } 14 | 15 | type LALOAD struct{ NoOperandsInstruction } 16 | 17 | type SALOAD struct{ NoOperandsInstruction } 18 | -------------------------------------------------------------------------------- /classfile/cp_method_handle.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | CONSTANT_MethodHandle_info { 5 | u1 tag; 6 | u1 reference_kind; 7 | u2 reference_index; 8 | } 9 | */ 10 | 11 | type ConstantMethodHandleInfo struct { 12 | referenceKind uint8 13 | referenceIndex uint16 14 | } 15 | 16 | func (c *ConstantMethodHandleInfo) readInfo(reader *ClassReader) { 17 | c.referenceKind = reader.readUint8() 18 | c.referenceIndex = reader.readUint16() 19 | } 20 | -------------------------------------------------------------------------------- /classfile/cp_string.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | CONSTANT_String_info { 5 | u1 tag; 6 | u2 string_index; 7 | } 8 | */ 9 | 10 | type ConstantStringInfo struct { 11 | cp ConstantPool 12 | stringIndex uint16 13 | } 14 | 15 | func (c *ConstantStringInfo) readInfo(reader *ClassReader) { 16 | c.stringIndex = reader.readUint16() 17 | } 18 | func (c *ConstantStringInfo) String() string { 19 | return c.cp.GetUtf8(c.stringIndex) 20 | } 21 | -------------------------------------------------------------------------------- /core/xastore.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type AASTORE struct{ NoOperandsInstruction } 4 | 5 | type BASTORE struct{ NoOperandsInstruction } 6 | 7 | type CASTORE struct{ NoOperandsInstruction } 8 | 9 | type DASTORE struct{ NoOperandsInstruction } 10 | 11 | type FASTORE struct{ NoOperandsInstruction } 12 | 13 | type IASTORE struct{ NoOperandsInstruction } 14 | 15 | type LASTORE struct{ NoOperandsInstruction } 16 | 17 | type SASTORE struct{ NoOperandsInstruction } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .DS_Store 3 | output/ 4 | 5 | # Binaries for programs and plugins 6 | *.exe 7 | *.exe~ 8 | *.dll 9 | *.so 10 | *.dylib 11 | 12 | # Test binary, built with `go test -c` 13 | *.test 14 | 15 | # Output of the go coverage tool, specifically when used with LiteIDE 16 | *.out 17 | 18 | # Dependency directories (remove the comment below to include it) 19 | # vendor/ 20 | 21 | # User Add 22 | *.class 23 | *.java 24 | *.jar 25 | *.zip 26 | temp/ 27 | test/ -------------------------------------------------------------------------------- /classfile/cp_double.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | import "math" 4 | 5 | /* 6 | CONSTANT_Double_info { 7 | u1 tag; 8 | u4 high_bytes; 9 | u4 low_bytes; 10 | } 11 | */ 12 | 13 | type ConstantDoubleInfo struct { 14 | val float64 15 | } 16 | 17 | func (c *ConstantDoubleInfo) readInfo(reader *ClassReader) { 18 | bytes := reader.readUint64() 19 | c.val = math.Float64frombits(bytes) 20 | } 21 | func (c *ConstantDoubleInfo) Value() float64 { 22 | return c.val 23 | } 24 | -------------------------------------------------------------------------------- /core/iinc.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "strconv" 4 | 5 | type IINC struct { 6 | Index uint 7 | Const int32 8 | } 9 | 10 | func (self *IINC) FetchOperands(reader *BytecodeReader) { 11 | self.Index = uint(reader.ReadUint8()) 12 | self.Const = int32(reader.ReadInt8()) 13 | } 14 | 15 | func (self *IINC) GetOperands() []string { 16 | ret := make([]string, 2) 17 | ret[0] = strconv.Itoa(int(self.Index)) 18 | ret[1] = strconv.Itoa(int(self.Const)) 19 | return ret 20 | } 21 | -------------------------------------------------------------------------------- /classfile/attr_unparsed.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | attribute_info { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u1 info[attribute_length]; 8 | } 9 | */ 10 | 11 | type UnparsedAttribute struct { 12 | name string 13 | length uint32 14 | info []byte 15 | } 16 | 17 | func (c *UnparsedAttribute) readInfo(reader *ClassReader) { 18 | c.info = reader.readBytes(c.length) 19 | } 20 | 21 | func (c *UnparsedAttribute) Info() []byte { 22 | return c.info 23 | } 24 | -------------------------------------------------------------------------------- /core/newarray.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | /* 4 | T_BOOLEAN 4 5 | T_CHAR 5 6 | T_FLOAT 6 7 | T_DOUBLE 7 8 | T_BYTE 8 9 | T_SHORT 9 10 | T_INT 10 11 | T_LONG 11 12 | */ 13 | 14 | type NEWARRAY struct { 15 | arrayType uint8 16 | } 17 | 18 | func (self *NEWARRAY) FetchOperands(reader *BytecodeReader) { 19 | self.arrayType = reader.ReadUint8() 20 | } 21 | 22 | func (self *NEWARRAY) GetOperands() []string { 23 | ret := make([]string, 1) 24 | ret[0] = string(self.arrayType) 25 | return ret 26 | } 27 | -------------------------------------------------------------------------------- /classfile/cp_invoke_dynamic.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | CONSTANT_InvokeDynamic_info { 5 | u1 tag; 6 | u2 bootstrap_method_attr_index; 7 | u2 name_and_type_index; 8 | } 9 | */ 10 | 11 | type ConstantInvokeDynamicInfo struct { 12 | bootstrapMethodAttrIndex uint16 13 | nameAndTypeIndex uint16 14 | } 15 | 16 | func (c *ConstantInvokeDynamicInfo) readInfo(reader *ClassReader) { 17 | c.bootstrapMethodAttrIndex = reader.readUint16() 18 | c.nameAndTypeIndex = reader.readUint16() 19 | } 20 | -------------------------------------------------------------------------------- /classfile/attr_constant_value.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | ConstantValue_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u2 constantvalue_index; 8 | } 9 | */ 10 | 11 | type ConstantValueAttribute struct { 12 | constantValueIndex uint16 13 | } 14 | 15 | func (c *ConstantValueAttribute) readInfo(reader *ClassReader) { 16 | c.constantValueIndex = reader.readUint16() 17 | } 18 | 19 | func (c *ConstantValueAttribute) ConstantValueIndex() uint16 { 20 | return c.constantValueIndex 21 | } 22 | -------------------------------------------------------------------------------- /classfile/attr_signature.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | Signature_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u2 signature_index; 8 | } 9 | */ 10 | 11 | type SignatureAttribute struct { 12 | cp ConstantPool 13 | signatureIndex uint16 14 | } 15 | 16 | func (c *SignatureAttribute) readInfo(reader *ClassReader) { 17 | c.signatureIndex = reader.readUint16() 18 | } 19 | 20 | func (c *SignatureAttribute) Signature() string { 21 | return c.cp.GetUtf8(c.signatureIndex) 22 | } 23 | -------------------------------------------------------------------------------- /classfile/attr_source_file.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | SourceFile_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u2 sourcefile_index; 8 | } 9 | */ 10 | 11 | type SourceFileAttribute struct { 12 | cp ConstantPool 13 | sourceFileIndex uint16 14 | } 15 | 16 | func (c *SourceFileAttribute) readInfo(reader *ClassReader) { 17 | c.sourceFileIndex = reader.readUint16() 18 | } 19 | 20 | func (c *SourceFileAttribute) FileName() string { 21 | return c.cp.GetUtf8(c.sourceFileIndex) 22 | } 23 | -------------------------------------------------------------------------------- /core/lookupswitch.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type LOOKUPSWITCH struct { 4 | defaultOffset int32 5 | npairs int32 6 | matchOffsets []int32 7 | } 8 | 9 | func (self *LOOKUPSWITCH) FetchOperands(reader *BytecodeReader) { 10 | reader.SkipPadding() 11 | self.defaultOffset = reader.ReadInt32() 12 | self.npairs = reader.ReadInt32() 13 | self.matchOffsets = reader.ReadInt32s(self.npairs * 2) 14 | } 15 | 16 | func (self *LOOKUPSWITCH) GetOperands() []string { 17 | ret := make([]string, 1) 18 | ret[0] = "[not support]" 19 | return ret 20 | } 21 | -------------------------------------------------------------------------------- /classfile/attr_exceptions.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | Exceptions_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u2 number_of_exceptions; 8 | u2 exception_index_table[number_of_exceptions]; 9 | } 10 | */ 11 | 12 | type ExceptionsAttribute struct { 13 | exceptionIndexTable []uint16 14 | } 15 | 16 | func (c *ExceptionsAttribute) readInfo(reader *ClassReader) { 17 | c.exceptionIndexTable = reader.readUint16s() 18 | } 19 | 20 | func (c *ExceptionsAttribute) ExceptionIndexTable() []uint16 { 21 | return c.exceptionIndexTable 22 | } 23 | -------------------------------------------------------------------------------- /classfile/cp_member_ref.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | type ConstantMemberRefInfo struct { 4 | cp ConstantPool 5 | classIndex uint16 6 | nameAndTypeIndex uint16 7 | } 8 | 9 | func (c *ConstantMemberRefInfo) readInfo(reader *ClassReader) { 10 | c.classIndex = reader.readUint16() 11 | c.nameAndTypeIndex = reader.readUint16() 12 | } 13 | 14 | func (c *ConstantMemberRefInfo) ClassName() string { 15 | return c.cp.GetClassName(c.classIndex) 16 | } 17 | func (c *ConstantMemberRefInfo) NameAndDescriptor() (string, string) { 18 | return c.cp.GetNameAndType(c.nameAndTypeIndex) 19 | } 20 | -------------------------------------------------------------------------------- /core/tableswitch.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type TABLESWITCH struct { 4 | defaultOffset int32 5 | low int32 6 | high int32 7 | jumpOffsets []int32 8 | } 9 | 10 | func (self *TABLESWITCH) FetchOperands(reader *BytecodeReader) { 11 | reader.SkipPadding() 12 | self.defaultOffset = reader.ReadInt32() 13 | self.low = reader.ReadInt32() 14 | self.high = reader.ReadInt32() 15 | jumpOffsetsCount := self.high - self.low + 1 16 | self.jumpOffsets = reader.ReadInt32s(jumpOffsetsCount) 17 | } 18 | 19 | func (self *TABLESWITCH) GetOperands() []string { 20 | ret := make([]string, 1) 21 | ret[0] = "[not support]" 22 | return ret 23 | } 24 | -------------------------------------------------------------------------------- /core/ipush.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "strconv" 4 | 5 | type BIPUSH struct { 6 | val int8 7 | } 8 | 9 | func (self *BIPUSH) FetchOperands(reader *BytecodeReader) { 10 | self.val = reader.ReadInt8() 11 | } 12 | 13 | func (self *BIPUSH) GetOperands() []string { 14 | ret := make([]string, 1) 15 | ret[0] = strconv.Itoa(int(self.val)) 16 | return ret 17 | } 18 | 19 | type SIPUSH struct { 20 | val int16 21 | } 22 | 23 | func (self *SIPUSH) FetchOperands(reader *BytecodeReader) { 24 | self.val = reader.ReadInt16() 25 | } 26 | 27 | func (self *SIPUSH) GetOperands() []string { 28 | ret := make([]string, 1) 29 | ret[0] = strconv.Itoa(int(self.val)) 30 | return ret 31 | } 32 | -------------------------------------------------------------------------------- /ref/field.go: -------------------------------------------------------------------------------- 1 | package ref 2 | 3 | import ( 4 | "github.com/4ra1n/accelerator/classfile" 5 | ) 6 | 7 | type Field struct { 8 | ClassMember 9 | } 10 | 11 | func newFields(class *Class, cfFields []*classfile.MemberInfo) []*Field { 12 | fields := make([]*Field, len(cfFields)) 13 | for i, cfField := range cfFields { 14 | fields[i] = &Field{} 15 | fields[i].class = class 16 | fields[i].copyMemberInfo(cfField) 17 | } 18 | return fields 19 | } 20 | 21 | func (self *Field) IsVolatile() bool { 22 | return 0 != self.accessFlags&ACC_VOLATILE 23 | } 24 | 25 | func (self *Field) IsTransient() bool { 26 | return 0 != self.accessFlags&ACC_TRANSIENT 27 | } 28 | 29 | func (self *Field) IsEnum() bool { 30 | return 0 != self.accessFlags&ACC_ENUM 31 | } 32 | -------------------------------------------------------------------------------- /classfile/attr_enclosing_method.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | EnclosingMethod_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u2 class_index; 8 | u2 method_index; 9 | } 10 | */ 11 | 12 | type EnclosingMethodAttribute struct { 13 | cp ConstantPool 14 | classIndex uint16 15 | methodIndex uint16 16 | } 17 | 18 | func (c *EnclosingMethodAttribute) readInfo(reader *ClassReader) { 19 | c.classIndex = reader.readUint16() 20 | c.methodIndex = reader.readUint16() 21 | } 22 | 23 | func (c *EnclosingMethodAttribute) ClassName() string { 24 | return c.cp.GetClassName(c.classIndex) 25 | } 26 | 27 | func (c *EnclosingMethodAttribute) MethodNameAndDescriptor() (string, string) { 28 | if c.methodIndex > 0 { 29 | return c.cp.GetNameAndType(c.methodIndex) 30 | } else { 31 | return "", "" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /core/const.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type ACONST_NULL struct{ NoOperandsInstruction } 4 | 5 | type DCONST_0 struct{ NoOperandsInstruction } 6 | 7 | type DCONST_1 struct{ NoOperandsInstruction } 8 | 9 | type FCONST_0 struct{ NoOperandsInstruction } 10 | 11 | type FCONST_1 struct{ NoOperandsInstruction } 12 | 13 | type FCONST_2 struct{ NoOperandsInstruction } 14 | 15 | type ICONST_M1 struct{ NoOperandsInstruction } 16 | 17 | type ICONST_0 struct{ NoOperandsInstruction } 18 | 19 | type ICONST_1 struct{ NoOperandsInstruction } 20 | 21 | type ICONST_2 struct{ NoOperandsInstruction } 22 | 23 | type ICONST_3 struct{ NoOperandsInstruction } 24 | 25 | type ICONST_4 struct{ NoOperandsInstruction } 26 | 27 | type ICONST_5 struct{ NoOperandsInstruction } 28 | 29 | type LCONST_0 struct{ NoOperandsInstruction } 30 | 31 | type LCONST_1 struct{ NoOperandsInstruction } 32 | -------------------------------------------------------------------------------- /ref/access_flags.go: -------------------------------------------------------------------------------- 1 | package ref 2 | 3 | const ( 4 | ACC_PUBLIC = 0x0001 // class field method 5 | ACC_PRIVATE = 0x0002 // field method 6 | ACC_PROTECTED = 0x0004 // field method 7 | ACC_STATIC = 0x0008 // field method 8 | ACC_FINAL = 0x0010 // class field method 9 | ACC_SUPER = 0x0020 // class 10 | ACC_SYNCHRONIZED = 0x0020 // method 11 | ACC_VOLATILE = 0x0040 // field 12 | ACC_BRIDGE = 0x0040 // method 13 | ACC_TRANSIENT = 0x0080 // field 14 | ACC_VARARGS = 0x0080 // method 15 | ACC_NATIVE = 0x0100 // method 16 | ACC_INTERFACE = 0x0200 // class 17 | ACC_ABSTRACT = 0x0400 // class method 18 | ACC_STRICT = 0x0800 // method 19 | ACC_SYNTHETIC = 0x1000 // class field method 20 | ACC_ANNOTATION = 0x2000 // class 21 | ACC_ENUM = 0x4000 // class field 22 | ) 23 | -------------------------------------------------------------------------------- /classfile/attr_bootstrap_methods.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | BootstrapMethods_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u2 num_bootstrap_methods; 8 | { u2 bootstrap_method_ref; 9 | u2 num_bootstrap_arguments; 10 | u2 bootstrap_arguments[num_bootstrap_arguments]; 11 | } bootstrap_methods[num_bootstrap_methods]; 12 | } 13 | */ 14 | 15 | type BootstrapMethodsAttribute struct { 16 | bootstrapMethods []*BootstrapMethod 17 | } 18 | 19 | func (c *BootstrapMethodsAttribute) readInfo(reader *ClassReader) { 20 | numBootstrapMethods := reader.readUint16() 21 | c.bootstrapMethods = make([]*BootstrapMethod, numBootstrapMethods) 22 | for i := range c.bootstrapMethods { 23 | c.bootstrapMethods[i] = &BootstrapMethod{ 24 | bootstrapMethodRef: reader.readUint16(), 25 | bootstrapArguments: reader.readUint16s(), 26 | } 27 | } 28 | } 29 | 30 | type BootstrapMethod struct { 31 | bootstrapMethodRef uint16 32 | bootstrapArguments []uint16 33 | } 34 | -------------------------------------------------------------------------------- /rule/rule.go: -------------------------------------------------------------------------------- 1 | package rule 2 | 3 | import ( 4 | "io/ioutil" 5 | "strings" 6 | ) 7 | 8 | func GetRule(ruleFile string) [][]string { 9 | var rule [][]string 10 | data, _ := ioutil.ReadFile(ruleFile) 11 | lines := strings.Split(string(data)+"\n", "\n") 12 | for _, line := range lines { 13 | line = strings.Trim(line, "\r") 14 | line = strings.TrimSpace(line) 15 | if line == "" { 16 | continue 17 | } 18 | if strings.Contains(line, " ") { 19 | inst := strings.Split(line, " ")[0] 20 | var ( 21 | methodName string 22 | methodDesc string 23 | ) 24 | if strings.HasPrefix(strings.ToUpper(inst), "INVOKE") { 25 | methodName = strings.Split(line, " ")[1] 26 | methodDesc = strings.Split(line, " ")[2] 27 | } else { 28 | panic("not support yet") 29 | } 30 | instData := make([]string, 3) 31 | instData[0] = strings.ToUpper(inst) 32 | instData[1] = methodName 33 | instData[2] = methodDesc 34 | rule = append(rule, instData) 35 | } else { 36 | panic("parse error") 37 | } 38 | } 39 | return rule 40 | } 41 | -------------------------------------------------------------------------------- /classfile/class_reader.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | import "encoding/binary" 4 | 5 | type ClassReader struct { 6 | data []byte 7 | } 8 | 9 | // u1 10 | func (c *ClassReader) readUint8() uint8 { 11 | val := c.data[0] 12 | c.data = c.data[1:] 13 | return val 14 | } 15 | 16 | // u2 17 | func (c *ClassReader) readUint16() uint16 { 18 | val := binary.BigEndian.Uint16(c.data) 19 | c.data = c.data[2:] 20 | return val 21 | } 22 | 23 | // u4 24 | func (c *ClassReader) readUint32() uint32 { 25 | val := binary.BigEndian.Uint32(c.data) 26 | c.data = c.data[4:] 27 | return val 28 | } 29 | 30 | func (c *ClassReader) readUint64() uint64 { 31 | val := binary.BigEndian.Uint64(c.data) 32 | c.data = c.data[8:] 33 | return val 34 | } 35 | 36 | // uint16 table 37 | func (c *ClassReader) readUint16s() []uint16 { 38 | n := c.readUint16() 39 | s := make([]uint16, n) 40 | for i := range s { 41 | s[i] = c.readUint16() 42 | } 43 | return s 44 | } 45 | 46 | func (c *ClassReader) readBytes(n uint32) []byte { 47 | bytes := c.data[:n] 48 | c.data = c.data[n:] 49 | return bytes 50 | } 51 | -------------------------------------------------------------------------------- /classfile/attr_inner_classes.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | InnerClasses_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u2 number_of_classes; 8 | { u2 inner_class_info_index; 9 | u2 outer_class_info_index; 10 | u2 inner_name_index; 11 | u2 inner_class_access_flags; 12 | } classes[number_of_classes]; 13 | } 14 | */ 15 | 16 | type InnerClassesAttribute struct { 17 | classes []*InnerClassInfo 18 | } 19 | 20 | type InnerClassInfo struct { 21 | innerClassInfoIndex uint16 22 | outerClassInfoIndex uint16 23 | innerNameIndex uint16 24 | innerClassAccessFlags uint16 25 | } 26 | 27 | func (c *InnerClassesAttribute) readInfo(reader *ClassReader) { 28 | numberOfClasses := reader.readUint16() 29 | c.classes = make([]*InnerClassInfo, numberOfClasses) 30 | for i := range c.classes { 31 | c.classes[i] = &InnerClassInfo{ 32 | innerClassInfoIndex: reader.readUint16(), 33 | outerClassInfoIndex: reader.readUint16(), 34 | innerNameIndex: reader.readUint16(), 35 | innerClassAccessFlags: reader.readUint16(), 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /core/invokespecial.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | "github.com/4ra1n/accelerator/classfile" 6 | "github.com/4ra1n/accelerator/global" 7 | "reflect" 8 | ) 9 | 10 | type INVOKESPECIAL struct{ Index16Instruction } 11 | 12 | func (self *INVOKESPECIAL) GetOperands() []string { 13 | name := global.CP.GetConstantInfo(uint16(self.Index)) 14 | typeName := reflect.TypeOf(name).String() 15 | 16 | var ( 17 | className string 18 | methodName string 19 | desc string 20 | ) 21 | 22 | switch typeName { 23 | case "*classfile.ConstantInterfaceMethodRefInfo": 24 | className = name.(*classfile.ConstantInterfaceMethodRefInfo).ClassName() 25 | methodName, desc = name.(*classfile.ConstantInterfaceMethodRefInfo).NameAndDescriptor() 26 | case "*classfile.ConstantMethodRefInfo": 27 | className = name.(*classfile.ConstantMethodRefInfo).ClassName() 28 | methodName, desc = name.(*classfile.ConstantMethodRefInfo).NameAndDescriptor() 29 | default: 30 | panic("error") 31 | } 32 | 33 | ret := make([]string, 1) 34 | out := fmt.Sprintf("%s.%s %s", className, methodName, desc) 35 | ret[0] = out 36 | return ret 37 | } 38 | -------------------------------------------------------------------------------- /core/invokestatic.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | "github.com/4ra1n/accelerator/classfile" 6 | "github.com/4ra1n/accelerator/global" 7 | "reflect" 8 | ) 9 | 10 | type INVOKESTATIC struct{ Index16Instruction } 11 | 12 | func (self *INVOKESTATIC) GetOperands() []string { 13 | name := global.CP.GetConstantInfo(uint16(self.Index)) 14 | typeName := reflect.TypeOf(name).String() 15 | 16 | var ( 17 | className string 18 | methodName string 19 | desc string 20 | ) 21 | 22 | switch typeName { 23 | case "*classfile.ConstantInterfaceMethodRefInfo": 24 | className = name.(*classfile.ConstantInterfaceMethodRefInfo).ClassName() 25 | methodName, desc = name.(*classfile.ConstantInterfaceMethodRefInfo).NameAndDescriptor() 26 | case "*classfile.ConstantMethodRefInfo": 27 | className = name.(*classfile.ConstantMethodRefInfo).ClassName() 28 | methodName, desc = name.(*classfile.ConstantMethodRefInfo).NameAndDescriptor() 29 | default: 30 | panic("error") 31 | } 32 | 33 | ret := make([]string, 1) 34 | out := fmt.Sprintf("%s.%s %s", className, methodName, desc) 35 | ret[0] = out 36 | return ret 37 | } 38 | -------------------------------------------------------------------------------- /core/invokevirtual.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | "github.com/4ra1n/accelerator/classfile" 6 | "github.com/4ra1n/accelerator/global" 7 | "reflect" 8 | ) 9 | 10 | type INVOKEVIRTUAL struct{ Index16Instruction } 11 | 12 | func (self *INVOKEVIRTUAL) GetOperands() []string { 13 | name := global.CP.GetConstantInfo(uint16(self.Index)) 14 | typeName := reflect.TypeOf(name).String() 15 | 16 | var ( 17 | className string 18 | methodName string 19 | desc string 20 | ) 21 | 22 | switch typeName { 23 | case "*classfile.ConstantInterfaceMethodRefInfo": 24 | className = name.(*classfile.ConstantInterfaceMethodRefInfo).ClassName() 25 | methodName, desc = name.(*classfile.ConstantInterfaceMethodRefInfo).NameAndDescriptor() 26 | case "*classfile.ConstantMethodRefInfo": 27 | className = name.(*classfile.ConstantMethodRefInfo).ClassName() 28 | methodName, desc = name.(*classfile.ConstantMethodRefInfo).NameAndDescriptor() 29 | default: 30 | panic("error") 31 | } 32 | 33 | ret := make([]string, 1) 34 | out := fmt.Sprintf("%s.%s %s", className, methodName, desc) 35 | ret[0] = out 36 | return ret 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 4ra1n 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /classfile/attr_line_number_table.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | LineNumberTable_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u2 line_number_table_length; 8 | { u2 start_pc; 9 | u2 line_number; 10 | } line_number_table[line_number_table_length]; 11 | } 12 | */ 13 | 14 | type LineNumberTableAttribute struct { 15 | lineNumberTable []*LineNumberTableEntry 16 | } 17 | 18 | type LineNumberTableEntry struct { 19 | startPc uint16 20 | lineNumber uint16 21 | } 22 | 23 | func (c *LineNumberTableAttribute) readInfo(reader *ClassReader) { 24 | lineNumberTableLength := reader.readUint16() 25 | c.lineNumberTable = make([]*LineNumberTableEntry, lineNumberTableLength) 26 | for i := range c.lineNumberTable { 27 | c.lineNumberTable[i] = &LineNumberTableEntry{ 28 | startPc: reader.readUint16(), 29 | lineNumber: reader.readUint16(), 30 | } 31 | } 32 | } 33 | 34 | func (c *LineNumberTableAttribute) GetLineNumber(pc int) int { 35 | for i := len(c.lineNumberTable) - 1; i >= 0; i-- { 36 | entry := c.lineNumberTable[i] 37 | if pc >= int(entry.startPc) { 38 | return int(entry.lineNumber) 39 | } 40 | } 41 | return -1 42 | } 43 | -------------------------------------------------------------------------------- /ref/method.go: -------------------------------------------------------------------------------- 1 | package ref 2 | 3 | import "github.com/4ra1n/accelerator/classfile" 4 | 5 | type Method struct { 6 | ClassMember 7 | } 8 | 9 | func newMethods(class *Class, cfMethods []*classfile.MemberInfo) []*Method { 10 | methods := make([]*Method, len(cfMethods)) 11 | for i, cfMethod := range cfMethods { 12 | methods[i] = newMethod(class, cfMethod) 13 | } 14 | return methods 15 | } 16 | 17 | func newMethod(class *Class, cfMethod *classfile.MemberInfo) *Method { 18 | method := &Method{} 19 | method.class = class 20 | method.copyMemberInfo(cfMethod) 21 | return method 22 | } 23 | 24 | func (self *Method) IsSynchronized() bool { 25 | return 0 != self.accessFlags&ACC_SYNCHRONIZED 26 | } 27 | 28 | func (self *Method) IsBridge() bool { 29 | return 0 != self.accessFlags&ACC_BRIDGE 30 | } 31 | 32 | func (self *Method) IsVarargs() bool { 33 | return 0 != self.accessFlags&ACC_VARARGS 34 | } 35 | 36 | func (self *Method) IsNative() bool { 37 | return 0 != self.accessFlags&ACC_NATIVE 38 | } 39 | 40 | func (self *Method) IsAbstract() bool { 41 | return 0 != self.accessFlags&ACC_ABSTRACT 42 | } 43 | 44 | func (self *Method) IsStrict() bool { 45 | return 0 != self.accessFlags&ACC_STRICT 46 | } 47 | -------------------------------------------------------------------------------- /classfile/attr_local_variable_table.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | LocalVariableTable_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u2 local_variable_table_length; 8 | { u2 start_pc; 9 | u2 length; 10 | u2 name_index; 11 | u2 descriptor_index; 12 | u2 index; 13 | } local_variable_table[local_variable_table_length]; 14 | } 15 | */ 16 | 17 | type LocalVariableTableAttribute struct { 18 | localVariableTable []*LocalVariableTableEntry 19 | } 20 | 21 | type LocalVariableTableEntry struct { 22 | startPc uint16 23 | length uint16 24 | nameIndex uint16 25 | descriptorIndex uint16 26 | index uint16 27 | } 28 | 29 | func (c *LocalVariableTableAttribute) readInfo(reader *ClassReader) { 30 | localVariableTableLength := reader.readUint16() 31 | c.localVariableTable = make([]*LocalVariableTableEntry, localVariableTableLength) 32 | for i := range c.localVariableTable { 33 | c.localVariableTable[i] = &LocalVariableTableEntry{ 34 | startPc: reader.readUint16(), 35 | length: reader.readUint16(), 36 | nameIndex: reader.readUint16(), 37 | descriptorIndex: reader.readUint16(), 38 | index: reader.readUint16(), 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /classfile/constant_pool.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | import "fmt" 4 | 5 | type ConstantPool []ConstantInfo 6 | 7 | func readConstantPool(reader *ClassReader) ConstantPool { 8 | cpCount := int(reader.readUint16()) 9 | cp := make([]ConstantInfo, cpCount) 10 | for i := 1; i < cpCount; i++ { 11 | cp[i] = readConstantInfo(reader, cp) 12 | switch cp[i].(type) { 13 | case *ConstantLongInfo, *ConstantDoubleInfo: 14 | i++ 15 | } 16 | } 17 | return cp 18 | } 19 | 20 | func (c ConstantPool) GetConstantInfo(index uint16) ConstantInfo { 21 | if cpInfo := c[index]; cpInfo != nil { 22 | return cpInfo 23 | } 24 | panic(fmt.Errorf("invalid constant pool index: %v", index)) 25 | } 26 | 27 | func (c ConstantPool) GetNameAndType(index uint16) (string, string) { 28 | ntInfo := c.GetConstantInfo(index).(*ConstantNameAndTypeInfo) 29 | name := c.GetUtf8(ntInfo.nameIndex) 30 | _type := c.GetUtf8(ntInfo.descriptorIndex) 31 | return name, _type 32 | } 33 | 34 | func (c ConstantPool) GetClassName(index uint16) string { 35 | classInfo := c.GetConstantInfo(index).(*ConstantClassInfo) 36 | return c.GetUtf8(classInfo.nameIndex) 37 | } 38 | 39 | func (c ConstantPool) GetUtf8(index uint16) string { 40 | utf8Info := c.GetConstantInfo(index).(*ConstantUtf8Info) 41 | return utf8Info.str 42 | } 43 | -------------------------------------------------------------------------------- /files/jar.go: -------------------------------------------------------------------------------- 1 | package files 2 | 3 | import ( 4 | "archive/zip" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | "path/filepath" 9 | "strconv" 10 | "strings" 11 | ) 12 | 13 | func unzipJar(path string, id string) { 14 | absPath, err := filepath.Abs(path) 15 | if err != nil { 16 | panic(fmt.Errorf("error jar path: %s", path)) 17 | } 18 | r, err := zip.OpenReader(absPath) 19 | if r == nil { 20 | panic(fmt.Errorf("cannot read file: %s", absPath)) 21 | } 22 | for _, f := range r.File { 23 | tempPath := filepath.Join("temp", id, f.Name) 24 | if strings.HasSuffix(f.Name, "/") { 25 | _ = os.MkdirAll(tempPath, 0644) 26 | } else { 27 | if !strings.HasSuffix(f.Name, ".class") { 28 | continue 29 | } 30 | reader, _ := f.Open() 31 | data, _ := ioutil.ReadAll(reader) 32 | _ = ioutil.WriteFile(tempPath, data, 0644) 33 | } 34 | } 35 | } 36 | 37 | func UnzipJars(dir string) { 38 | dirPath, err := filepath.Abs(dir) 39 | if err != nil { 40 | panic(fmt.Errorf("error dir path: %s", dir)) 41 | } 42 | fileList, _ := ioutil.ReadDir(dirPath) 43 | for i, f := range fileList { 44 | if strings.HasSuffix(f.Name(), ".jar") { 45 | finalPath := filepath.Join(dirPath, f.Name()) 46 | id := strconv.Itoa(i) + "_" + f.Name() 47 | unzipJar(finalPath, id) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /core/invokeinterface.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | "github.com/4ra1n/accelerator/classfile" 6 | "github.com/4ra1n/accelerator/global" 7 | "reflect" 8 | ) 9 | 10 | type INVOKEINTERFACE struct { 11 | index uint 12 | } 13 | 14 | func (self *INVOKEINTERFACE) FetchOperands(reader *BytecodeReader) { 15 | self.index = uint(reader.ReadUint16()) 16 | reader.ReadUint8() 17 | reader.ReadUint8() 18 | } 19 | 20 | func (self *INVOKEINTERFACE) GetOperands() []string { 21 | name := global.CP.GetConstantInfo(uint16(self.index)) 22 | typeName := reflect.TypeOf(name).String() 23 | 24 | var ( 25 | className string 26 | methodName string 27 | desc string 28 | ) 29 | 30 | switch typeName { 31 | case "*classfile.ConstantInterfaceMethodRefInfo": 32 | className = name.(*classfile.ConstantInterfaceMethodRefInfo).ClassName() 33 | methodName, desc = name.(*classfile.ConstantInterfaceMethodRefInfo).NameAndDescriptor() 34 | case "*classfile.ConstantMethodRefInfo": 35 | className = name.(*classfile.ConstantMethodRefInfo).ClassName() 36 | methodName, desc = name.(*classfile.ConstantMethodRefInfo).NameAndDescriptor() 37 | default: 38 | panic("error") 39 | } 40 | 41 | ret := make([]string, 1) 42 | out := fmt.Sprintf("%s.%s %s", className, methodName, desc) 43 | ret[0] = out 44 | return ret 45 | } 46 | -------------------------------------------------------------------------------- /classfile/attr_local_variable_type_table.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | LocalVariableTypeTable_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u2 local_variable_type_table_length; 8 | { u2 start_pc; 9 | u2 length; 10 | u2 name_index; 11 | u2 signature_index; 12 | u2 index; 13 | } local_variable_type_table[local_variable_type_table_length]; 14 | } 15 | */ 16 | 17 | type LocalVariableTypeTableAttribute struct { 18 | localVariableTypeTable []*LocalVariableTypeTableEntry 19 | } 20 | 21 | type LocalVariableTypeTableEntry struct { 22 | startPc uint16 23 | length uint16 24 | nameIndex uint16 25 | signatureIndex uint16 26 | index uint16 27 | } 28 | 29 | func (c *LocalVariableTypeTableAttribute) readInfo(reader *ClassReader) { 30 | localVariableTypeTableLength := reader.readUint16() 31 | c.localVariableTypeTable = make([]*LocalVariableTypeTableEntry, localVariableTypeTableLength) 32 | for i := range c.localVariableTypeTable { 33 | c.localVariableTypeTable[i] = &LocalVariableTypeTableEntry{ 34 | startPc: reader.readUint16(), 35 | length: reader.readUint16(), 36 | nameIndex: reader.readUint16(), 37 | signatureIndex: reader.readUint16(), 38 | index: reader.readUint16(), 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /core/bytecode_reader.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type BytecodeReader struct { 4 | code []byte 5 | pc int 6 | } 7 | 8 | func (self *BytecodeReader) Reset(code []byte, pc int) { 9 | self.code = code 10 | self.pc = pc 11 | } 12 | 13 | func (self *BytecodeReader) PC() int { 14 | return self.pc 15 | } 16 | 17 | func (self *BytecodeReader) ReadInt8() int8 { 18 | return int8(self.ReadUint8()) 19 | } 20 | 21 | func (self *BytecodeReader) ReadUint8() uint8 { 22 | i := self.code[self.pc] 23 | self.pc++ 24 | return i 25 | } 26 | 27 | func (self *BytecodeReader) ReadInt16() int16 { 28 | return int16(self.ReadUint16()) 29 | } 30 | 31 | func (self *BytecodeReader) ReadUint16() uint16 { 32 | byte1 := uint16(self.ReadUint8()) 33 | byte2 := uint16(self.ReadUint8()) 34 | return (byte1 << 8) | byte2 35 | } 36 | 37 | func (self *BytecodeReader) ReadInt32() int32 { 38 | byte1 := int32(self.ReadUint8()) 39 | byte2 := int32(self.ReadUint8()) 40 | byte3 := int32(self.ReadUint8()) 41 | byte4 := int32(self.ReadUint8()) 42 | return (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4 43 | } 44 | 45 | func (self *BytecodeReader) ReadInt32s(n int32) []int32 { 46 | ints := make([]int32, n) 47 | for i := range ints { 48 | ints[i] = self.ReadInt32() 49 | } 50 | return ints 51 | } 52 | 53 | func (self *BytecodeReader) SkipPadding() { 54 | for self.pc%4 != 0 { 55 | self.ReadUint8() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /core/instruction.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "strconv" 5 | ) 6 | 7 | type Instruction interface { 8 | FetchOperands(reader *BytecodeReader) 9 | GetOperands() []string 10 | } 11 | 12 | type NoOperandsInstruction struct { 13 | } 14 | 15 | func (self *NoOperandsInstruction) FetchOperands(_ *BytecodeReader) { 16 | } 17 | 18 | func (self *NoOperandsInstruction) GetOperands() []string { 19 | return make([]string, 0) 20 | } 21 | 22 | type BranchInstruction struct { 23 | Offset int 24 | } 25 | 26 | func (self *BranchInstruction) FetchOperands(reader *BytecodeReader) { 27 | self.Offset = int(reader.ReadInt16()) 28 | } 29 | 30 | func (self *BranchInstruction) GetOperands() []string { 31 | ret := make([]string, 1) 32 | ret[0] = strconv.Itoa(self.Offset) 33 | return ret 34 | } 35 | 36 | type Index8Instruction struct { 37 | Index uint 38 | } 39 | 40 | func (self *Index8Instruction) FetchOperands(reader *BytecodeReader) { 41 | self.Index = uint(reader.ReadUint8()) 42 | } 43 | 44 | func (self *Index8Instruction) GetOperands() []string { 45 | ret := make([]string, 1) 46 | ret[0] = strconv.Itoa(int(self.Index)) 47 | return ret 48 | } 49 | 50 | type Index16Instruction struct { 51 | Index uint 52 | } 53 | 54 | func (self *Index16Instruction) FetchOperands(reader *BytecodeReader) { 55 | self.Index = uint(reader.ReadUint16()) 56 | } 57 | 58 | func (self *Index16Instruction) GetOperands() []string { 59 | ret := make([]string, 1) 60 | ret[0] = strconv.Itoa(int(self.Index)) 61 | return ret 62 | } 63 | -------------------------------------------------------------------------------- /ref/class_member.go: -------------------------------------------------------------------------------- 1 | package ref 2 | 3 | import "github.com/4ra1n/accelerator/classfile" 4 | 5 | type ClassMember struct { 6 | accessFlags uint16 7 | name string 8 | descriptor string 9 | signature string 10 | class *Class 11 | } 12 | 13 | func (self *ClassMember) copyMemberInfo(memberInfo *classfile.MemberInfo) { 14 | self.accessFlags = memberInfo.AccessFlags() 15 | self.name = memberInfo.Name() 16 | self.descriptor = memberInfo.Descriptor() 17 | } 18 | 19 | func (self *ClassMember) IsPublic() bool { 20 | return 0 != self.accessFlags&ACC_PUBLIC 21 | } 22 | 23 | func (self *ClassMember) IsPrivate() bool { 24 | return 0 != self.accessFlags&ACC_PRIVATE 25 | } 26 | 27 | func (self *ClassMember) IsProtected() bool { 28 | return 0 != self.accessFlags&ACC_PROTECTED 29 | } 30 | 31 | func (self *ClassMember) IsStatic() bool { 32 | return 0 != self.accessFlags&ACC_STATIC 33 | } 34 | 35 | func (self *ClassMember) IsFinal() bool { 36 | return 0 != self.accessFlags&ACC_FINAL 37 | } 38 | 39 | func (self *ClassMember) IsSynthetic() bool { 40 | return 0 != self.accessFlags&ACC_SYNTHETIC 41 | } 42 | 43 | func (self *ClassMember) AccessFlags() uint16 { 44 | return self.accessFlags 45 | } 46 | 47 | func (self *ClassMember) Name() string { 48 | return self.name 49 | } 50 | 51 | func (self *ClassMember) Descriptor() string { 52 | return self.descriptor 53 | } 54 | 55 | func (self *ClassMember) Signature() string { 56 | return self.signature 57 | } 58 | 59 | func (self *ClassMember) Class() *Class { 60 | return self.class 61 | } 62 | -------------------------------------------------------------------------------- /classfile/attribute_info.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | attribute_info { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u1 info[attribute_length]; 8 | } 9 | */ 10 | 11 | type AttributeInfo interface { 12 | readInfo(reader *ClassReader) 13 | } 14 | 15 | func readAttributes(reader *ClassReader, cp ConstantPool) []AttributeInfo { 16 | attributesCount := reader.readUint16() 17 | attributes := make([]AttributeInfo, attributesCount) 18 | for i := range attributes { 19 | attributes[i] = readAttribute(reader, cp) 20 | } 21 | return attributes 22 | } 23 | 24 | func readAttribute(reader *ClassReader, cp ConstantPool) AttributeInfo { 25 | attrNameIndex := reader.readUint16() 26 | attrName := cp.GetUtf8(attrNameIndex) 27 | attrLen := reader.readUint32() 28 | attrInfo := newAttributeInfo(attrName, attrLen, cp) 29 | attrInfo.readInfo(reader) 30 | return attrInfo 31 | } 32 | 33 | func newAttributeInfo(attrName string, attrLen uint32, cp ConstantPool) AttributeInfo { 34 | switch attrName { 35 | case "Code": 36 | return &CodeAttribute{cp: cp} 37 | case "ConstantValue": 38 | return &ConstantValueAttribute{} 39 | case "Deprecated": 40 | return &DeprecatedAttribute{} 41 | case "Exceptions": 42 | return &ExceptionsAttribute{} 43 | case "LineNumberTable": 44 | return &LineNumberTableAttribute{} 45 | case "LocalVariableTable": 46 | return &LocalVariableTableAttribute{} 47 | case "SourceFile": 48 | return &SourceFileAttribute{cp: cp} 49 | case "Synthetic": 50 | return &SyntheticAttribute{} 51 | default: 52 | return &UnparsedAttribute{attrName, attrLen, nil} 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /classfile/member_info.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | type MemberInfo struct { 4 | cp ConstantPool 5 | accessFlags uint16 6 | nameIndex uint16 7 | descriptorIndex uint16 8 | attributes []AttributeInfo 9 | } 10 | 11 | func readMembers(reader *ClassReader, cp ConstantPool) []*MemberInfo { 12 | memberCount := reader.readUint16() 13 | members := make([]*MemberInfo, memberCount) 14 | for i := range members { 15 | members[i] = readMember(reader, cp) 16 | } 17 | return members 18 | } 19 | 20 | func readMember(reader *ClassReader, cp ConstantPool) *MemberInfo { 21 | return &MemberInfo{ 22 | cp: cp, 23 | accessFlags: reader.readUint16(), 24 | nameIndex: reader.readUint16(), 25 | descriptorIndex: reader.readUint16(), 26 | attributes: readAttributes(reader, cp), 27 | } 28 | } 29 | 30 | func (self *MemberInfo) AccessFlags() uint16 { 31 | return self.accessFlags 32 | } 33 | func (self *MemberInfo) Name() string { 34 | return self.cp.GetUtf8(self.nameIndex) 35 | } 36 | func (self *MemberInfo) Descriptor() string { 37 | return self.cp.GetUtf8(self.descriptorIndex) 38 | } 39 | 40 | func (self *MemberInfo) CodeAttribute() *CodeAttribute { 41 | for _, attrInfo := range self.attributes { 42 | switch attrInfo.(type) { 43 | case *CodeAttribute: 44 | return attrInfo.(*CodeAttribute) 45 | } 46 | } 47 | return nil 48 | } 49 | 50 | func (self *MemberInfo) ConstantValueAttribute() *ConstantValueAttribute { 51 | for _, attrInfo := range self.attributes { 52 | switch attrInfo.(type) { 53 | case *ConstantValueAttribute: 54 | return attrInfo.(*ConstantValueAttribute) 55 | } 56 | } 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /core/wide.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type WIDE struct { 4 | modifiedInstruction Instruction 5 | } 6 | 7 | func (self *WIDE) FetchOperands(reader *BytecodeReader) { 8 | opcode := reader.ReadUint8() 9 | switch opcode { 10 | case 0x15: 11 | inst := &ILOAD{} 12 | inst.Index = uint(reader.ReadUint16()) 13 | self.modifiedInstruction = inst 14 | case 0x16: 15 | inst := &LLOAD{} 16 | inst.Index = uint(reader.ReadUint16()) 17 | self.modifiedInstruction = inst 18 | case 0x17: 19 | inst := &FLOAD{} 20 | inst.Index = uint(reader.ReadUint16()) 21 | self.modifiedInstruction = inst 22 | case 0x18: 23 | inst := &DLOAD{} 24 | inst.Index = uint(reader.ReadUint16()) 25 | self.modifiedInstruction = inst 26 | case 0x19: 27 | inst := &ALOAD{} 28 | inst.Index = uint(reader.ReadUint16()) 29 | self.modifiedInstruction = inst 30 | case 0x36: 31 | inst := &ISTORE{} 32 | inst.Index = uint(reader.ReadUint16()) 33 | self.modifiedInstruction = inst 34 | case 0x37: 35 | inst := &LSTORE{} 36 | inst.Index = uint(reader.ReadUint16()) 37 | self.modifiedInstruction = inst 38 | case 0x38: 39 | inst := &FSTORE{} 40 | inst.Index = uint(reader.ReadUint16()) 41 | self.modifiedInstruction = inst 42 | case 0x39: 43 | inst := &DSTORE{} 44 | inst.Index = uint(reader.ReadUint16()) 45 | self.modifiedInstruction = inst 46 | case 0x3a: 47 | inst := &ASTORE{} 48 | inst.Index = uint(reader.ReadUint16()) 49 | self.modifiedInstruction = inst 50 | case 0x84: 51 | inst := &IINC{} 52 | inst.Index = uint(reader.ReadUint16()) 53 | inst.Const = int32(reader.ReadInt16()) 54 | self.modifiedInstruction = inst 55 | case 0xa9: 56 | panic("unsupported opcode: 0xa9") 57 | } 58 | } 59 | 60 | func (self *WIDE) GetOperands() []string { 61 | ret := make([]string, 1) 62 | ret[0] = "[not support]" 63 | return ret 64 | } 65 | -------------------------------------------------------------------------------- /ref/class.go: -------------------------------------------------------------------------------- 1 | package ref 2 | 3 | import ( 4 | "github.com/4ra1n/accelerator/classfile" 5 | ) 6 | 7 | type Class struct { 8 | accessFlags uint16 9 | name string 10 | superClassName string 11 | interfaceNames []string 12 | fields []*Field 13 | methods []*Method 14 | superClass *Class 15 | interfaces []*Class 16 | } 17 | 18 | func NewClass(cf *classfile.ClassFile) *Class { 19 | class := &Class{} 20 | class.accessFlags = cf.AccessFlags() 21 | class.name = cf.ClassName() 22 | class.superClassName = cf.SuperClassName() 23 | class.interfaceNames = cf.InterfaceNames() 24 | class.fields = newFields(class, cf.Fields()) 25 | class.methods = newMethods(class, cf.Methods()) 26 | return class 27 | } 28 | 29 | func (self *Class) IsPublic() bool { 30 | return 0 != self.accessFlags&ACC_PUBLIC 31 | } 32 | 33 | func (self *Class) IsFinal() bool { 34 | return 0 != self.accessFlags&ACC_FINAL 35 | } 36 | 37 | func (self *Class) IsSuper() bool { 38 | return 0 != self.accessFlags&ACC_SUPER 39 | } 40 | 41 | func (self *Class) IsInterface() bool { 42 | return 0 != self.accessFlags&ACC_INTERFACE 43 | } 44 | 45 | func (self *Class) IsAbstract() bool { 46 | return 0 != self.accessFlags&ACC_ABSTRACT 47 | } 48 | 49 | func (self *Class) IsSynthetic() bool { 50 | return 0 != self.accessFlags&ACC_SYNTHETIC 51 | } 52 | 53 | func (self *Class) IsAnnotation() bool { 54 | return 0 != self.accessFlags&ACC_ANNOTATION 55 | } 56 | 57 | func (self *Class) IsEnum() bool { 58 | return 0 != self.accessFlags&ACC_ENUM 59 | } 60 | 61 | func (self *Class) AccessFlags() uint16 { 62 | return self.accessFlags 63 | } 64 | 65 | func (self *Class) Name() string { 66 | return self.name 67 | } 68 | 69 | func (self *Class) Fields() []*Field { 70 | return self.fields 71 | } 72 | 73 | func (self *Class) Methods() []*Method { 74 | return self.methods 75 | } 76 | 77 | func (self *Class) SuperClass() *Class { 78 | return self.superClass 79 | } 80 | 81 | func (self *Class) Interfaces() []*Class { 82 | return self.interfaces 83 | } 84 | -------------------------------------------------------------------------------- /classfile/cp_utf8.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | import ( 4 | "fmt" 5 | "unicode/utf16" 6 | ) 7 | 8 | /* 9 | CONSTANT_Utf8_info { 10 | u1 tag; 11 | u2 length; 12 | u1 bytes[length]; 13 | } 14 | */ 15 | 16 | type ConstantUtf8Info struct { 17 | str string 18 | } 19 | 20 | func (c *ConstantUtf8Info) readInfo(reader *ClassReader) { 21 | length := uint32(reader.readUint16()) 22 | bytes := reader.readBytes(length) 23 | c.str = decodeMUTF8(bytes) 24 | } 25 | 26 | func (c *ConstantUtf8Info) Str() string { 27 | return c.str 28 | } 29 | 30 | func decodeMUTF8(byteArr []byte) string { 31 | utfLen := len(byteArr) 32 | charArr := make([]uint16, utfLen) 33 | var c, char2, char3 uint16 34 | count := 0 35 | charArrCount := 0 36 | for count < utfLen { 37 | c = uint16(byteArr[count]) 38 | if c > 127 { 39 | break 40 | } 41 | count++ 42 | charArr[charArrCount] = c 43 | charArrCount++ 44 | } 45 | for count < utfLen { 46 | c = uint16(byteArr[count]) 47 | switch c >> 4 { 48 | case 0, 1, 2, 3, 4, 5, 6, 7: 49 | count++ 50 | charArr[charArrCount] = c 51 | charArrCount++ 52 | case 12, 13: 53 | count += 2 54 | if count > utfLen { 55 | panic("malformed input: partial character at end") 56 | } 57 | char2 = uint16(byteArr[count-1]) 58 | if char2&0xC0 != 0x80 { 59 | panic(fmt.Errorf("malformed input around byte %v", count)) 60 | } 61 | charArr[charArrCount] = c&0x1F<<6 | char2&0x3F 62 | charArrCount++ 63 | case 14: 64 | count += 3 65 | if count > utfLen { 66 | panic("malformed input: partial character at end") 67 | } 68 | char2 = uint16(byteArr[count-2]) 69 | char3 = uint16(byteArr[count-1]) 70 | if char2&0xC0 != 0x80 || char3&0xC0 != 0x80 { 71 | panic(fmt.Errorf("malformed input around byte %v", count-1)) 72 | } 73 | charArr[charArrCount] = c&0x0F<<12 | char2&0x3F<<6 | char3&0x3F<<0 74 | charArrCount++ 75 | default: 76 | panic(fmt.Errorf("malformed input around byte %v", count)) 77 | } 78 | } 79 | charArr = charArr[0:charArrCount] 80 | runes := utf16.Decode(charArr) 81 | return string(runes) 82 | } 83 | -------------------------------------------------------------------------------- /classfile/constant_info.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | const ( 4 | ConstantClass = 7 5 | ConstantFieldRef = 9 6 | ConstantMethodRef = 10 7 | ConstantInterfaceMethodRef = 11 8 | ConstantString = 8 9 | ConstantInteger = 3 10 | ConstantFloat = 4 11 | ConstantLong = 5 12 | ConstantDouble = 6 13 | ConstantNameAndType = 12 14 | ConstantUtf8 = 1 15 | ConstantMethodHandle = 15 16 | ConstantMethodType = 16 17 | ConstantInvokeDynamic = 18 18 | ) 19 | 20 | /* 21 | cp_info { 22 | u1 tag; 23 | u1 info[]; 24 | } 25 | */ 26 | 27 | type ConstantInfo interface { 28 | readInfo(reader *ClassReader) 29 | } 30 | 31 | func readConstantInfo(reader *ClassReader, cp ConstantPool) ConstantInfo { 32 | tag := reader.readUint8() 33 | c := newConstantInfo(tag, cp) 34 | c.readInfo(reader) 35 | return c 36 | } 37 | 38 | func newConstantInfo(tag uint8, cp ConstantPool) ConstantInfo { 39 | switch tag { 40 | case ConstantInteger: 41 | return &ConstantIntegerInfo{} 42 | case ConstantFloat: 43 | return &ConstantFloatInfo{} 44 | case ConstantLong: 45 | return &ConstantLongInfo{} 46 | case ConstantDouble: 47 | return &ConstantDoubleInfo{} 48 | case ConstantUtf8: 49 | return &ConstantUtf8Info{} 50 | case ConstantString: 51 | return &ConstantStringInfo{cp: cp} 52 | case ConstantClass: 53 | return &ConstantClassInfo{cp: cp} 54 | case ConstantFieldRef: 55 | return &ConstantFieldRefInfo{ConstantMemberRefInfo{cp: cp}} 56 | case ConstantMethodRef: 57 | return &ConstantMethodRefInfo{ConstantMemberRefInfo{cp: cp}} 58 | case ConstantInterfaceMethodRef: 59 | return &ConstantInterfaceMethodRefInfo{ConstantMemberRefInfo{cp: cp}} 60 | case ConstantNameAndType: 61 | return &ConstantNameAndTypeInfo{} 62 | case ConstantMethodType: 63 | return &ConstantMethodTypeInfo{} 64 | case ConstantMethodHandle: 65 | return &ConstantMethodHandleInfo{} 66 | case ConstantInvokeDynamic: 67 | return &ConstantInvokeDynamicInfo{} 68 | default: 69 | panic("java.lang.ClassFormatError: constant pool tag!") 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /classfile/attr_code.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | /* 4 | Code_attribute { 5 | u2 attribute_name_index; 6 | u4 attribute_length; 7 | u2 max_stack; 8 | u2 max_locals; 9 | u4 code_length; 10 | u1 code[code_length]; 11 | u2 exception_table_length; 12 | { u2 start_pc; 13 | u2 end_pc; 14 | u2 handler_pc; 15 | u2 catch_type; 16 | } exception_table[exception_table_length]; 17 | u2 attributes_count; 18 | attribute_info attributes[attributes_count]; 19 | } 20 | */ 21 | 22 | type CodeAttribute struct { 23 | cp ConstantPool 24 | maxStack uint16 25 | maxLocals uint16 26 | code []byte 27 | exceptionTable []*ExceptionTableEntry 28 | attributes []AttributeInfo 29 | } 30 | 31 | func (c *CodeAttribute) readInfo(reader *ClassReader) { 32 | c.maxStack = reader.readUint16() 33 | c.maxLocals = reader.readUint16() 34 | codeLength := reader.readUint32() 35 | c.code = reader.readBytes(codeLength) 36 | c.exceptionTable = readExceptionTable(reader) 37 | c.attributes = readAttributes(reader, c.cp) 38 | } 39 | 40 | func (c *CodeAttribute) MaxStack() uint { 41 | return uint(c.maxStack) 42 | } 43 | 44 | func (c *CodeAttribute) MaxLocals() uint { 45 | return uint(c.maxLocals) 46 | } 47 | 48 | func (c *CodeAttribute) Code() []byte { 49 | return c.code 50 | } 51 | 52 | func (c *CodeAttribute) ExceptionTable() []*ExceptionTableEntry { 53 | return c.exceptionTable 54 | } 55 | 56 | type ExceptionTableEntry struct { 57 | startPc uint16 58 | endPc uint16 59 | handlerPc uint16 60 | catchType uint16 61 | } 62 | 63 | func readExceptionTable(reader *ClassReader) []*ExceptionTableEntry { 64 | exceptionTableLength := reader.readUint16() 65 | exceptionTable := make([]*ExceptionTableEntry, exceptionTableLength) 66 | for i := range exceptionTable { 67 | exceptionTable[i] = &ExceptionTableEntry{ 68 | startPc: reader.readUint16(), 69 | endPc: reader.readUint16(), 70 | handlerPc: reader.readUint16(), 71 | catchType: reader.readUint16(), 72 | } 73 | } 74 | return exceptionTable 75 | } 76 | 77 | func (c *ExceptionTableEntry) StartPc() uint16 { 78 | return c.startPc 79 | } 80 | 81 | func (c *ExceptionTableEntry) EndPc() uint16 { 82 | return c.endPc 83 | } 84 | 85 | func (c *ExceptionTableEntry) HandlerPc() uint16 { 86 | return c.handlerPc 87 | } 88 | 89 | func (c *ExceptionTableEntry) CatchType() uint16 { 90 | return c.catchType 91 | } 92 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "github.com/4ra1n/accelerator/classfile" 7 | "github.com/4ra1n/accelerator/core" 8 | "github.com/4ra1n/accelerator/files" 9 | "github.com/4ra1n/accelerator/global" 10 | "github.com/4ra1n/accelerator/ref" 11 | "github.com/4ra1n/accelerator/rule" 12 | "io/ioutil" 13 | "strings" 14 | ) 15 | 16 | var ( 17 | ruleFile string 18 | jarsDir string 19 | ) 20 | 21 | func main() { 22 | // resolve input 23 | flag.StringVar(&ruleFile, "rule", "rule.txt", "rule file") 24 | flag.StringVar(&jarsDir, "jars", ".", "your jars dir") 25 | flag.Parse() 26 | // delete temp dir 27 | files.RemoveTempFiles() 28 | // extract all jars to temp dir 29 | files.UnzipJars(jarsDir) 30 | // traverse to get all class files 31 | classes := files.ReadAllClasses() 32 | for _, c := range classes { 33 | // analyze each class file separately 34 | start(c) 35 | } 36 | files.RemoveTempFiles() 37 | } 38 | 39 | func start(class string) { 40 | data, err := ioutil.ReadFile(class) 41 | cf, err := classfile.Parse(data) 42 | if err != nil { 43 | panic(err) 44 | } 45 | cl := ref.NewClass(cf) 46 | // constant pool cache 47 | // refresh cp in each new class file 48 | global.CP = cf.ConstantPool() 49 | for _, method := range cf.Methods() { 50 | codeAttr := method.CodeAttribute() 51 | if codeAttr == nil { 52 | // interface or abstract 53 | continue 54 | } 55 | bytecode := codeAttr.Code() 56 | // virtual thread 57 | thread := core.Thread{} 58 | reader := &core.BytecodeReader{} 59 | // save all instructions to struct 60 | instSet := core.InstructionSet{} 61 | instSet.ClassName = cl.Name() 62 | instSet.MethodName = method.Name() 63 | instSet.Desc = method.Descriptor() 64 | for { 65 | // read finish 66 | if thread.PC() >= len(bytecode) { 67 | break 68 | } 69 | // offset 70 | reader.Reset(bytecode, thread.PC()) 71 | // read instruction 72 | opcode := reader.ReadUint8() 73 | inst := core.NewInstruction(opcode) 74 | // read operands of the instruction 75 | inst.FetchOperands(reader) 76 | ops := inst.GetOperands() 77 | instEntry := core.InstructionEntry{ 78 | Instrument: getInstructionName(inst), 79 | Operands: ops, 80 | } 81 | instSet.InstArray = append(instSet.InstArray, instEntry) 82 | // offset++ 83 | thread.SetPC(reader.PC()) 84 | } 85 | doAnalysis(instSet) 86 | } 87 | } 88 | 89 | func getInstructionName(instruction core.Instruction) string { 90 | // type name -> instruction name 91 | i := fmt.Sprintf("%T", instruction) 92 | return strings.Split(i, ".")[1] 93 | } 94 | 95 | func doAnalysis(instSet core.InstructionSet) { 96 | analysisRule := rule.GetRule(ruleFile) 97 | if len(analysisRule) == 0 { 98 | panic("error rule file") 99 | } 100 | ruleLen := len(analysisRule) 101 | var ruleLenState []bool 102 | i := 0 103 | for _, inst := range instSet.InstArray { 104 | if inst.Instrument != analysisRule[i][0] { 105 | continue 106 | } 107 | splits := strings.Split(inst.Operands[0], " ") 108 | stdName := splits[0] 109 | stdDesc := splits[1] 110 | if analysisRule[i][1] != stdName { 111 | continue 112 | } 113 | if analysisRule[i][2] == stdDesc || 114 | analysisRule[i][2] == "*" { 115 | ruleLenState = append(ruleLenState, true) 116 | if i != ruleLen-1 { 117 | i++ 118 | } else { 119 | break 120 | } 121 | } 122 | } 123 | if len(ruleLenState) == ruleLen { 124 | fmt.Println(instSet.ClassName, instSet.MethodName) 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /classfile/class_file.go: -------------------------------------------------------------------------------- 1 | package classfile 2 | 3 | import "fmt" 4 | 5 | /* 6 | classfile { 7 | u4 magic; 8 | u2 minor_version; 9 | u2 major_version; 10 | u2 constant_pool_count; 11 | cp_info constant_pool[constant_pool_count-1]; 12 | u2 access_flags; 13 | u2 this_class; 14 | u2 super_class; 15 | u2 interfaces_count; 16 | u2 interfaces[interfaces_count]; 17 | u2 fields_count; 18 | field_info fields[fields_count]; 19 | u2 methods_count; 20 | method_info methods[methods_count]; 21 | u2 attributes_count; 22 | attribute_info attributes[attributes_count]; 23 | } 24 | */ 25 | 26 | type ClassFile struct { 27 | magic uint32 28 | minorVersion uint16 29 | majorVersion uint16 30 | constantPool ConstantPool 31 | accessFlags uint16 32 | thisClass uint16 33 | superClass uint16 34 | interfaces []uint16 35 | fields []*MemberInfo 36 | methods []*MemberInfo 37 | attributes []AttributeInfo 38 | } 39 | 40 | func Parse(classData []byte) (cf *ClassFile, err error) { 41 | defer func() { 42 | if r := recover(); r != nil { 43 | var ok bool 44 | err, ok = r.(error) 45 | if !ok { 46 | err = fmt.Errorf("%v", r) 47 | } 48 | } 49 | }() 50 | cr := &ClassReader{classData} 51 | cf = &ClassFile{} 52 | cf.read(cr) 53 | return 54 | } 55 | 56 | func (c *ClassFile) read(reader *ClassReader) { 57 | c.readAndCheckMagic(reader) 58 | c.readAndCheckVersion(reader) 59 | c.constantPool = readConstantPool(reader) 60 | c.accessFlags = reader.readUint16() 61 | c.thisClass = reader.readUint16() 62 | c.superClass = reader.readUint16() 63 | c.interfaces = reader.readUint16s() 64 | c.fields = readMembers(reader, c.constantPool) 65 | c.methods = readMembers(reader, c.constantPool) 66 | c.attributes = readAttributes(reader, c.constantPool) 67 | } 68 | 69 | func (c *ClassFile) readAndCheckMagic(reader *ClassReader) { 70 | magic := reader.readUint32() 71 | if magic != 0xCAFEBABE { 72 | panic("java.lang.ClassFormatError: magic!") 73 | } 74 | c.magic = magic 75 | } 76 | 77 | func (c *ClassFile) readAndCheckVersion(reader *ClassReader) { 78 | c.minorVersion = reader.readUint16() 79 | c.majorVersion = reader.readUint16() 80 | switch c.majorVersion { 81 | case 45: 82 | // JDK 1.0.2 83 | return 84 | case 46, 47, 48, 49, 50, 51, 52: 85 | // JDK 1.2 - JDK 1.8 86 | if c.minorVersion == 0 { 87 | return 88 | } 89 | } 90 | panic("java.lang.UnsupportedClassVersionError!") 91 | } 92 | 93 | func (c *ClassFile) MinorVersion() uint16 { 94 | return c.minorVersion 95 | } 96 | 97 | func (c *ClassFile) MajorVersion() uint16 { 98 | return c.majorVersion 99 | } 100 | 101 | func (c *ClassFile) ConstantPool() ConstantPool { 102 | return c.constantPool 103 | } 104 | 105 | func (c *ClassFile) AccessFlags() uint16 { 106 | return c.accessFlags 107 | } 108 | 109 | func (c *ClassFile) Fields() []*MemberInfo { 110 | return c.fields 111 | } 112 | 113 | func (c *ClassFile) Methods() []*MemberInfo { 114 | return c.methods 115 | } 116 | 117 | func (c *ClassFile) ClassName() string { 118 | return c.constantPool.GetClassName(c.thisClass) 119 | } 120 | 121 | func (c *ClassFile) SuperClassName() string { 122 | if c.superClass > 0 { 123 | return c.constantPool.GetClassName(c.superClass) 124 | } 125 | return "" 126 | } 127 | 128 | func (c *ClassFile) InterfaceNames() []string { 129 | interfaceNames := make([]string, len(c.interfaces)) 130 | for i, cpIndex := range c.interfaces { 131 | interfaceNames[i] = c.constantPool.GetClassName(cpIndex) 132 | } 133 | return interfaceNames 134 | } 135 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | # Accelerator 2 | 3 | 基于`Golang`批量分析Jar包,用于检测`Java`安全漏洞 4 | 5 | 这将比`Java ASM`更容易上手使用,且有更高的执行效率 6 | 7 | 该工具是一个辅助工具,可以帮助安全研究人员快速分析`jar`文件,尤其是对于一些闭源项目 8 | 9 | 使用此功能的优点是易于上手并检测效率较高(比编写`ASM`的`MethodVisitor`简单很多) 10 | 11 | 使用这种方法的缺点是不能进行太多定制操作,并且在多指令规则下可能会出现误报 12 | 13 | ## 快速开始 14 | 15 | `accelerator`需要指定一个规则文件(默认:rule.txt) 16 | 17 | 并且需要输入`jar`文件的目录,然后`accelerator`会解压该目录中所有`jar`并扫描其中的`class`文件 18 | 19 | ```shell 20 | ./accelerator -rule your_rule_file -jars your_jar_dir 21 | ``` 22 | 23 | 目前编写规则仅支持`INVOKE`相关的指令(实际上这也是最主要的指令) 24 | 25 | ```text 26 | INVOKEVIRTUAL ... * 27 | ``` 28 | 29 | 如果是单一的`INVOKE`指令,对某方法的指令集进行检测的过程中只要匹配到则认为成功 30 | 31 | 通常方法的`desc`属性并不容易记,所以可以使用通配符`*`来代替该位置 32 | 33 | ```text 34 | INVOKEVIRTUAL [first rule] * 35 | INVOKEVIRTUAL [next rule] * 36 | ... 37 | ``` 38 | 39 | 支持多条`INVOKE`指令的规则,将会按照顺序进行匹配 40 | 41 | 无论中间夹杂多少其他指令,只要按照顺序可以匹配到每一条指令,则认为成功 42 | 43 | ## 工作原理 44 | 45 | (1) 解压缩`jar`文件以获取所有`class`文件 46 | 47 | (2) 根据`Oracle Java`规范对`class`文件进行解析 48 | 49 | (3) 解析所有类的方法区域中的所有方法以获得指令集(在`attr`属性中) 50 | 51 | (4) 通过寻找常量池来改进指令内容(方法名和字符串索引等) 52 | 53 | (5) 解析用户规则并将其与当前方法的指令集匹配 54 | 55 | ## 使用示例 56 | 57 | 原生的SQL注入规则(拼接字符串) 58 | ```text 59 | INVOKEVIRTUAL java/lang/StringBuilder.append * 60 | INVOKEINTERFACE java/sql/Statement.executeQuery * 61 | ``` 62 | 63 | 基于`JdbcTemplate`的SQL注入规则(拼接字符串) 64 | ```text 65 | INVOKEVIRTUAL java/lang/StringBuilder.append * 66 | INVOKEVIRTUAL org/springframework/jdbc/core/JdbcTemplate.query * 67 | ``` 68 | 69 | 简单的`RCE`检测 70 | ```text 71 | INVOKEVIRTUAL java/lang/Runtime.exec * 72 | ``` 73 | 74 | 简单的`RCE`检测(由于字符串拼接导致的命令注入) 75 | ```text 76 | INVOKEVIRTUAL java/lang/StringBuilder.append * 77 | INVOKEVIRTUAL java/lang/Runtime.exec * 78 | ``` 79 | 80 | 一些`SSRF`规则 81 | - INVOKEVIRTUAL java/net/URL.openConnection * 82 | - INVOKEVIRTUAL org/apache/http/impl/client/CloseableHttpClient.execute * 83 | - INVOKEINTERFACE okhttp3/Call.execute * 84 | 85 | ## 实践 86 | 87 | ### log4j-core-2.14.0.jar 88 | 89 | Rule 90 | ```text 91 | INVOKEINTERFACE javax/naming/Context.lookup * 92 | ``` 93 | 94 | Result 95 | ```text 96 | org/apache/logging/log4j/core/net/JndiManager lookup 97 | ``` 98 | 99 | ### spring-cloud-gateway-server-3.0.6.jar 100 | 101 | Rule 102 | ```text 103 | INVOKEINTERFACE org/springframework/expression/Expression.getValue * 104 | ``` 105 | 106 | Result 107 | ```text 108 | org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocator buildRouteDefinition 109 | org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocator getValueFromExpr 110 | org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocator lambda$getRouteDefinitions$2 111 | org/springframework/cloud/gateway/support/ShortcutConfigurable getValue 112 | ``` 113 | 114 | Rule 115 | ```text 116 | INVOKESPECIAL org/springframework/expression/spel/support/StandardEvaluationContext. * 117 | INVOKEVIRTUAL org/springframework/expression/spel/standard/SpelExpressionParser.parseExpression * 118 | INVOKEINTERFACE org/springframework/expression/Expression.getValue * 119 | ``` 120 | 121 | Result 122 | ```text 123 | org/springframework/cloud/gateway/support/ShortcutConfigurable getValue 124 | ``` 125 | 126 | ### spring-cloud-function-context-3.1.0.jar 127 | 128 | Rule 129 | ```text 130 | INVOKEINTERFACE org/springframework/expression/Expression.getValue * 131 | ``` 132 | 133 | Result 134 | ```text 135 | org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry$FunctionInvocationWrapper parseMultipleValueArguments 136 | org/springframework/cloud/function/context/config/RoutingFunction functionFromExpression 137 | ``` 138 | 139 | Rule 140 | ```text 141 | INVOKESPECIAL org/springframework/expression/spel/support/StandardEvaluationContext. * 142 | ``` 143 | 144 | Result 145 | ```text 146 | org/springframework/cloud/function/context/config/RoutingFunction 147 | ``` 148 | 149 | ## 成果 150 | 151 | 一些未公开的CVE 152 | 153 | Oracle深度安全贡献者 154 | 155 | ## 参考 156 | 157 | [Java Class File Format](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html) 158 | 159 | [JVM Instruction Set](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html) 160 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Accelerator 2 | 3 | [中文介绍](https://github.com/4ra1n/accelerator/tree/master/doc) 4 | 5 | Batch analysis jar packages using Golang 6 | 7 | Use to detect security vulnerabilities 8 | 9 | This will be much simpler and faster than Java ASM 10 | 11 | The tool is an auxiliary tool that can help security researchers analyze jar files quickly, especially for some closed source projects 12 | 13 | The advantage of using this is that it is easy to start and efficient detection 14 | 15 | The disadvantage of using this is that it cannot be customized too much, and there is the possibility of false positives in the case of multiple instructions 16 | 17 | ## Quick Start 18 | 19 | accelerator need a rule file (default: rule.txt) 20 | 21 | Enter a directory of jar files, accelerator will scan all jar files and extract them 22 | 23 | ```shell 24 | ./accelerator -rule your_rule_file -jars your_jar_dir 25 | ``` 26 | 27 | In the writing of rule, only **INVOKE** instruction is supported at present 28 | 29 | ```text 30 | INVOKEVIRTUAL ... * 31 | ``` 32 | 33 | If a single instruction is written, the detection is successful if the corresponding instruction in a method 34 | 35 | Usually, the desc attribute is not easy to remember, so wildcards such as * are supported 36 | 37 | ```text 38 | INVOKEVIRTUAL [first rule] * 39 | INVOKEVIRTUAL [next rule] * 40 | ... 41 | ``` 42 | 43 | Rules that support multiple **INVOKE** instructions at the same time 44 | 45 | If the instruction set in the target method matches the calling order of multiple instructions, it is considered to match 46 | 47 | ## How it Works 48 | 49 | (1) Unzip the jar file to get all the class files 50 | 51 | (2) The class file is parsed according to the Oracle Java Specification 52 | 53 | (3) Parse all methods in the method area of all classes to obtain the instruction set 54 | 55 | (4) Improve instruction content by finding constant pool 56 | 57 | (5) Parse the user rule and match it with the current method instruction set 58 | 59 | ## Examples 60 | 61 | Native SQL Inject Rule 62 | ```text 63 | INVOKEVIRTUAL java/lang/StringBuilder.append * 64 | INVOKEINTERFACE java/sql/Statement.executeQuery * 65 | ``` 66 | 67 | SQL Inject JdbcTemplate Rule 68 | ```text 69 | INVOKEVIRTUAL java/lang/StringBuilder.append * 70 | INVOKEVIRTUAL org/springframework/jdbc/core/JdbcTemplate.query * 71 | ``` 72 | 73 | Simple RCE Rule 74 | ```text 75 | INVOKEVIRTUAL java/lang/Runtime.exec * 76 | ``` 77 | 78 | Simple RCE Rule (Command Inject) 79 | ```text 80 | INVOKEVIRTUAL java/lang/StringBuilder.append * 81 | INVOKEVIRTUAL java/lang/Runtime.exec * 82 | ``` 83 | 84 | Some SSRF Rule 85 | - INVOKEVIRTUAL java/net/URL.openConnection * 86 | - INVOKEVIRTUAL org/apache/http/impl/client/CloseableHttpClient.execute * 87 | - INVOKEINTERFACE okhttp3/Call.execute * 88 | 89 | ## Practice 90 | 91 | ### log4j-core-2.14.0.jar 92 | 93 | Rule 94 | ```text 95 | INVOKEINTERFACE javax/naming/Context.lookup * 96 | ``` 97 | 98 | Result 99 | ```text 100 | org/apache/logging/log4j/core/net/JndiManager lookup 101 | ``` 102 | 103 | ### spring-cloud-gateway-server-3.0.6.jar 104 | 105 | Rule 106 | ```text 107 | INVOKEINTERFACE org/springframework/expression/Expression.getValue * 108 | ``` 109 | 110 | Result 111 | ```text 112 | org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocator buildRouteDefinition 113 | org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocator getValueFromExpr 114 | org/springframework/cloud/gateway/discovery/DiscoveryClientRouteDefinitionLocator lambda$getRouteDefinitions$2 115 | org/springframework/cloud/gateway/support/ShortcutConfigurable getValue 116 | ``` 117 | 118 | Rule 119 | ```text 120 | INVOKESPECIAL org/springframework/expression/spel/support/StandardEvaluationContext. * 121 | INVOKEVIRTUAL org/springframework/expression/spel/standard/SpelExpressionParser.parseExpression * 122 | INVOKEINTERFACE org/springframework/expression/Expression.getValue * 123 | ``` 124 | 125 | Result 126 | ```text 127 | org/springframework/cloud/gateway/support/ShortcutConfigurable getValue 128 | ``` 129 | 130 | ### spring-cloud-function-context-3.1.0.jar 131 | 132 | Rule 133 | ```text 134 | INVOKEINTERFACE org/springframework/expression/Expression.getValue * 135 | ``` 136 | 137 | Result 138 | ```text 139 | org/springframework/cloud/function/context/catalog/SimpleFunctionRegistry$FunctionInvocationWrapper parseMultipleValueArguments 140 | org/springframework/cloud/function/context/config/RoutingFunction functionFromExpression 141 | ``` 142 | 143 | Rule 144 | ```text 145 | INVOKESPECIAL org/springframework/expression/spel/support/StandardEvaluationContext. * 146 | ``` 147 | 148 | Result 149 | ```text 150 | org/springframework/cloud/function/context/config/RoutingFunction 151 | ``` 152 | 153 | ## reference 154 | 155 | [Java Class File Format](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html) 156 | 157 | [JVM Instruction Set](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html) -------------------------------------------------------------------------------- /core/factory.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | var ( 8 | nop = &NOP{} 9 | aconst_null = &ACONST_NULL{} 10 | iconst_m1 = &ICONST_M1{} 11 | iconst_0 = &ICONST_0{} 12 | iconst_1 = &ICONST_1{} 13 | iconst_2 = &ICONST_2{} 14 | iconst_3 = &ICONST_3{} 15 | iconst_4 = &ICONST_4{} 16 | iconst_5 = &ICONST_5{} 17 | lconst_0 = &LCONST_0{} 18 | lconst_1 = &LCONST_1{} 19 | fconst_0 = &FCONST_0{} 20 | fconst_1 = &FCONST_1{} 21 | fconst_2 = &FCONST_2{} 22 | dconst_0 = &DCONST_0{} 23 | dconst_1 = &DCONST_1{} 24 | iload_0 = &ILOAD_0{} 25 | iload_1 = &ILOAD_1{} 26 | iload_2 = &ILOAD_2{} 27 | iload_3 = &ILOAD_3{} 28 | lload_0 = &LLOAD_0{} 29 | lload_1 = &LLOAD_1{} 30 | lload_2 = &LLOAD_2{} 31 | lload_3 = &LLOAD_3{} 32 | fload_0 = &FLOAD_0{} 33 | fload_1 = &FLOAD_1{} 34 | fload_2 = &FLOAD_2{} 35 | fload_3 = &FLOAD_3{} 36 | dload_0 = &DLOAD_0{} 37 | dload_1 = &DLOAD_1{} 38 | dload_2 = &DLOAD_2{} 39 | dload_3 = &DLOAD_3{} 40 | aload_0 = &ALOAD_0{} 41 | aload_1 = &ALOAD_1{} 42 | aload_2 = &ALOAD_2{} 43 | aload_3 = &ALOAD_3{} 44 | iaload = &IALOAD{} 45 | laload = &LALOAD{} 46 | faload = &FALOAD{} 47 | daload = &DALOAD{} 48 | aaload = &AALOAD{} 49 | baload = &BALOAD{} 50 | caload = &CALOAD{} 51 | saload = &SALOAD{} 52 | istore_0 = &ISTORE_0{} 53 | istore_1 = &ISTORE_1{} 54 | istore_2 = &ISTORE_2{} 55 | istore_3 = &ISTORE_3{} 56 | lstore_0 = &LSTORE_0{} 57 | lstore_1 = &LSTORE_1{} 58 | lstore_2 = &LSTORE_2{} 59 | lstore_3 = &LSTORE_3{} 60 | fstore_0 = &FSTORE_0{} 61 | fstore_1 = &FSTORE_1{} 62 | fstore_2 = &FSTORE_2{} 63 | fstore_3 = &FSTORE_3{} 64 | dstore_0 = &DSTORE_0{} 65 | dstore_1 = &DSTORE_1{} 66 | dstore_2 = &DSTORE_2{} 67 | dstore_3 = &DSTORE_3{} 68 | astore_0 = &ASTORE_0{} 69 | astore_1 = &ASTORE_1{} 70 | astore_2 = &ASTORE_2{} 71 | astore_3 = &ASTORE_3{} 72 | iastore = &IASTORE{} 73 | lastore = &LASTORE{} 74 | fastore = &FASTORE{} 75 | dastore = &DASTORE{} 76 | aastore = &AASTORE{} 77 | bastore = &BASTORE{} 78 | castore = &CASTORE{} 79 | sastore = &SASTORE{} 80 | pop = &POP{} 81 | pop2 = &POP2{} 82 | dup = &DUP{} 83 | dup_x1 = &DUP_X1{} 84 | dup_x2 = &DUP_X2{} 85 | dup2 = &DUP2{} 86 | dup2_x1 = &DUP2_X1{} 87 | dup2_x2 = &DUP2_X2{} 88 | swap = &SWAP{} 89 | iadd = &IADD{} 90 | ladd = &LADD{} 91 | fadd = &FADD{} 92 | dadd = &DADD{} 93 | isub = &ISUB{} 94 | lsub = &LSUB{} 95 | fsub = &FSUB{} 96 | dsub = &DSUB{} 97 | imul = &IMUL{} 98 | lmul = &LMUL{} 99 | fmul = &FMUL{} 100 | dmul = &DMUL{} 101 | idiv = &IDIV{} 102 | ldiv = &LDIV{} 103 | fdiv = &FDIV{} 104 | ddiv = &DDIV{} 105 | irem = &IREM{} 106 | lrem = &LREM{} 107 | frem = &FREM{} 108 | drem = &DREM{} 109 | ineg = &INEG{} 110 | lneg = &LNEG{} 111 | fneg = &FNEG{} 112 | dneg = &DNEG{} 113 | ishl = &ISHL{} 114 | lshl = &LSHL{} 115 | ishr = &ISHR{} 116 | lshr = &LSHR{} 117 | iushr = &IUSHR{} 118 | lushr = &LUSHR{} 119 | iand = &IAND{} 120 | land = &LAND{} 121 | ior = &IOR{} 122 | lor = &LOR{} 123 | ixor = &IXOR{} 124 | lxor = &LXOR{} 125 | i2l = &I2L{} 126 | i2f = &I2F{} 127 | i2d = &I2D{} 128 | l2i = &L2I{} 129 | l2f = &L2F{} 130 | l2d = &L2D{} 131 | f2i = &F2I{} 132 | f2l = &F2L{} 133 | f2d = &F2D{} 134 | d2i = &D2I{} 135 | d2l = &D2L{} 136 | d2f = &D2F{} 137 | i2b = &I2B{} 138 | i2c = &I2C{} 139 | i2s = &I2S{} 140 | lcmp = &LCMP{} 141 | fcmpl = &FCMPL{} 142 | fcmpg = &FCMPG{} 143 | dcmpl = &DCMPL{} 144 | dcmpg = &DCMPG{} 145 | ireturn = &IRETURN{} 146 | lreturn = &LRETURN{} 147 | freturn = &FRETURN{} 148 | dreturn = &DRETURN{} 149 | areturn = &ARETURN{} 150 | _return = &RETURN{} 151 | arraylength = &ARRAY_LENGTH{} 152 | athrow = &ATHROW{} 153 | monitorenter = &MONITORENTER{} 154 | monitorexit = &MONITOREXIT{} 155 | invoke_native = &INVOKENATIVE{} 156 | ) 157 | 158 | func NewInstruction(opcode byte) Instruction { 159 | switch opcode { 160 | case 0x00: 161 | return nop 162 | case 0x01: 163 | return aconst_null 164 | case 0x02: 165 | return iconst_m1 166 | case 0x03: 167 | return iconst_0 168 | case 0x04: 169 | return iconst_1 170 | case 0x05: 171 | return iconst_2 172 | case 0x06: 173 | return iconst_3 174 | case 0x07: 175 | return iconst_4 176 | case 0x08: 177 | return iconst_5 178 | case 0x09: 179 | return lconst_0 180 | case 0x0a: 181 | return lconst_1 182 | case 0x0b: 183 | return fconst_0 184 | case 0x0c: 185 | return fconst_1 186 | case 0x0d: 187 | return fconst_2 188 | case 0x0e: 189 | return dconst_0 190 | case 0x0f: 191 | return dconst_1 192 | case 0x10: 193 | return &BIPUSH{} 194 | case 0x11: 195 | return &SIPUSH{} 196 | case 0x12: 197 | return &LDC{} 198 | case 0x13: 199 | return &LDC_W{} 200 | case 0x14: 201 | return &LDC2_W{} 202 | case 0x15: 203 | return &ILOAD{} 204 | case 0x16: 205 | return &LLOAD{} 206 | case 0x17: 207 | return &FLOAD{} 208 | case 0x18: 209 | return &DLOAD{} 210 | case 0x19: 211 | return &ALOAD{} 212 | case 0x1a: 213 | return iload_0 214 | case 0x1b: 215 | return iload_1 216 | case 0x1c: 217 | return iload_2 218 | case 0x1d: 219 | return iload_3 220 | case 0x1e: 221 | return lload_0 222 | case 0x1f: 223 | return lload_1 224 | case 0x20: 225 | return lload_2 226 | case 0x21: 227 | return lload_3 228 | case 0x22: 229 | return fload_0 230 | case 0x23: 231 | return fload_1 232 | case 0x24: 233 | return fload_2 234 | case 0x25: 235 | return fload_3 236 | case 0x26: 237 | return dload_0 238 | case 0x27: 239 | return dload_1 240 | case 0x28: 241 | return dload_2 242 | case 0x29: 243 | return dload_3 244 | case 0x2a: 245 | return aload_0 246 | case 0x2b: 247 | return aload_1 248 | case 0x2c: 249 | return aload_2 250 | case 0x2d: 251 | return aload_3 252 | case 0x2e: 253 | return iaload 254 | case 0x2f: 255 | return laload 256 | case 0x30: 257 | return faload 258 | case 0x31: 259 | return daload 260 | case 0x32: 261 | return aaload 262 | case 0x33: 263 | return baload 264 | case 0x34: 265 | return caload 266 | case 0x35: 267 | return saload 268 | case 0x36: 269 | return &ISTORE{} 270 | case 0x37: 271 | return &LSTORE{} 272 | case 0x38: 273 | return &FSTORE{} 274 | case 0x39: 275 | return &DSTORE{} 276 | case 0x3a: 277 | return &ASTORE{} 278 | case 0x3b: 279 | return istore_0 280 | case 0x3c: 281 | return istore_1 282 | case 0x3d: 283 | return istore_2 284 | case 0x3e: 285 | return istore_3 286 | case 0x3f: 287 | return lstore_0 288 | case 0x40: 289 | return lstore_1 290 | case 0x41: 291 | return lstore_2 292 | case 0x42: 293 | return lstore_3 294 | case 0x43: 295 | return fstore_0 296 | case 0x44: 297 | return fstore_1 298 | case 0x45: 299 | return fstore_2 300 | case 0x46: 301 | return fstore_3 302 | case 0x47: 303 | return dstore_0 304 | case 0x48: 305 | return dstore_1 306 | case 0x49: 307 | return dstore_2 308 | case 0x4a: 309 | return dstore_3 310 | case 0x4b: 311 | return astore_0 312 | case 0x4c: 313 | return astore_1 314 | case 0x4d: 315 | return astore_2 316 | case 0x4e: 317 | return astore_3 318 | case 0x4f: 319 | return iastore 320 | case 0x50: 321 | return lastore 322 | case 0x51: 323 | return fastore 324 | case 0x52: 325 | return dastore 326 | case 0x53: 327 | return aastore 328 | case 0x54: 329 | return bastore 330 | case 0x55: 331 | return castore 332 | case 0x56: 333 | return sastore 334 | case 0x57: 335 | return pop 336 | case 0x58: 337 | return pop2 338 | case 0x59: 339 | return dup 340 | case 0x5a: 341 | return dup_x1 342 | case 0x5b: 343 | return dup_x2 344 | case 0x5c: 345 | return dup2 346 | case 0x5d: 347 | return dup2_x1 348 | case 0x5e: 349 | return dup2_x2 350 | case 0x5f: 351 | return swap 352 | case 0x60: 353 | return iadd 354 | case 0x61: 355 | return ladd 356 | case 0x62: 357 | return fadd 358 | case 0x63: 359 | return dadd 360 | case 0x64: 361 | return isub 362 | case 0x65: 363 | return lsub 364 | case 0x66: 365 | return fsub 366 | case 0x67: 367 | return dsub 368 | case 0x68: 369 | return imul 370 | case 0x69: 371 | return lmul 372 | case 0x6a: 373 | return fmul 374 | case 0x6b: 375 | return dmul 376 | case 0x6c: 377 | return idiv 378 | case 0x6d: 379 | return ldiv 380 | case 0x6e: 381 | return fdiv 382 | case 0x6f: 383 | return ddiv 384 | case 0x70: 385 | return irem 386 | case 0x71: 387 | return lrem 388 | case 0x72: 389 | return frem 390 | case 0x73: 391 | return drem 392 | case 0x74: 393 | return ineg 394 | case 0x75: 395 | return lneg 396 | case 0x76: 397 | return fneg 398 | case 0x77: 399 | return dneg 400 | case 0x78: 401 | return ishl 402 | case 0x79: 403 | return lshl 404 | case 0x7a: 405 | return ishr 406 | case 0x7b: 407 | return lshr 408 | case 0x7c: 409 | return iushr 410 | case 0x7d: 411 | return lushr 412 | case 0x7e: 413 | return iand 414 | case 0x7f: 415 | return land 416 | case 0x80: 417 | return ior 418 | case 0x81: 419 | return lor 420 | case 0x82: 421 | return ixor 422 | case 0x83: 423 | return lxor 424 | case 0x84: 425 | return &IINC{} 426 | case 0x85: 427 | return i2l 428 | case 0x86: 429 | return i2f 430 | case 0x87: 431 | return i2d 432 | case 0x88: 433 | return l2i 434 | case 0x89: 435 | return l2f 436 | case 0x8a: 437 | return l2d 438 | case 0x8b: 439 | return f2i 440 | case 0x8c: 441 | return f2l 442 | case 0x8d: 443 | return f2d 444 | case 0x8e: 445 | return d2i 446 | case 0x8f: 447 | return d2l 448 | case 0x90: 449 | return d2f 450 | case 0x91: 451 | return i2b 452 | case 0x92: 453 | return i2c 454 | case 0x93: 455 | return i2s 456 | case 0x94: 457 | return lcmp 458 | case 0x95: 459 | return fcmpl 460 | case 0x96: 461 | return fcmpg 462 | case 0x97: 463 | return dcmpl 464 | case 0x98: 465 | return dcmpg 466 | case 0x99: 467 | return &IFEQ{} 468 | case 0x9a: 469 | return &IFNE{} 470 | case 0x9b: 471 | return &IFLT{} 472 | case 0x9c: 473 | return &IFGE{} 474 | case 0x9d: 475 | return &IFGT{} 476 | case 0x9e: 477 | return &IFLE{} 478 | case 0x9f: 479 | return &IF_ICMPEQ{} 480 | case 0xa0: 481 | return &IF_ICMPNE{} 482 | case 0xa1: 483 | return &IF_ICMPLT{} 484 | case 0xa2: 485 | return &IF_ICMPGE{} 486 | case 0xa3: 487 | return &IF_ICMPGT{} 488 | case 0xa4: 489 | return &IF_ICMPLE{} 490 | case 0xa5: 491 | return &IF_ACMPEQ{} 492 | case 0xa6: 493 | return &IF_ACMPNE{} 494 | case 0xa7: 495 | return &GOTO{} 496 | case 0xa8: 497 | return &JSR{} 498 | case 0xa9: 499 | return &RET{} 500 | case 0xaa: 501 | return &TABLESWITCH{} 502 | case 0xab: 503 | return &LOOKUPSWITCH{} 504 | case 0xac: 505 | return ireturn 506 | case 0xad: 507 | return lreturn 508 | case 0xae: 509 | return freturn 510 | case 0xaf: 511 | return dreturn 512 | case 0xb0: 513 | return areturn 514 | case 0xb1: 515 | return _return 516 | case 0xb2: 517 | return &GET_STATIC{} 518 | case 0xb3: 519 | return &PUTSTATIC{} 520 | case 0xb4: 521 | return &GET_FIELD{} 522 | case 0xb5: 523 | return &PUTFIELD{} 524 | case 0xb6: 525 | return &INVOKEVIRTUAL{} 526 | case 0xb7: 527 | return &INVOKESPECIAL{} 528 | case 0xb8: 529 | return &INVOKESTATIC{} 530 | case 0xb9: 531 | return &INVOKEINTERFACE{} 532 | case 0xba: 533 | return &INVOKEDYNAMIC{} 534 | case 0xbb: 535 | return &NEW{} 536 | case 0xbc: 537 | return &NEWARRAY{} 538 | case 0xbd: 539 | return &ANEW_ARRAY{} 540 | case 0xbe: 541 | return arraylength 542 | case 0xbf: 543 | return athrow 544 | case 0xc0: 545 | return &CHECK_CAST{} 546 | case 0xc1: 547 | return &INSTANCEOF{} 548 | case 0xc2: 549 | return monitorenter 550 | case 0xc3: 551 | return monitorexit 552 | case 0xc4: 553 | return &WIDE{} 554 | case 0xc5: 555 | return &MULTIANEWARRAY{} 556 | case 0xc6: 557 | return &IFNULL{} 558 | case 0xc7: 559 | return &IFNONNULL{} 560 | case 0xc8: 561 | return &GOTO_W{} 562 | case 0xc9: 563 | return &JSR_W{} 564 | case 0xca: 565 | panic("reserved opcodes: breakpoint") 566 | case 0xfe: 567 | return invoke_native 568 | case 0xff: 569 | panic("reserved opcodes: impdep2") 570 | default: 571 | panic(fmt.Errorf("unsupported opcode: 0x%x", opcode)) 572 | } 573 | } 574 | --------------------------------------------------------------------------------