From 4ae2d747cfaed30e6fdba9ef5d8e05ad49ec1e54 Mon Sep 17 00:00:00 2001 From: Vincent Rasquier Date: Thu, 14 Dec 2017 17:14:23 +0100 Subject: [PATCH] Add missing types such as Handle, Frame or TypePath --- README.md | 1 + asm/classreader.go | 25 ++++--- asm/classvisitor.go | 2 +- asm/context.go | 2 +- asm/fieldvisitor.go | 2 +- asm/frame.go | 13 ++++ asm/handle.go | 9 +++ asm/label.go | 4 +- asm/methodvisitor.go | 10 +-- asm/typepath.go | 52 ++++++++++++++ asm/typereference.go | 108 ----------------------------- asm/typereference/typereference.go | 26 +++++++ simplevisitor.go | 2 +- 13 files changed, 127 insertions(+), 129 deletions(-) create mode 100644 asm/frame.go create mode 100644 asm/handle.go create mode 100644 asm/typepath.go create mode 100644 asm/typereference/typereference.go diff --git a/README.md b/README.md index 755a498..e5c5bd4 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Second reason could be to provide different tools for JVM manipulation through G | FieldVisitor | 100% | | ModuleVisitor | 100% | | AnnotationVisitor | 100% | +| Handle | 100% | | Attribute | ? | | Context | ? | | Label | ? | diff --git a/asm/classreader.go b/asm/classreader.go index 699a62f..fabf73c 100644 --- a/asm/classreader.go +++ b/asm/classreader.go @@ -2,12 +2,12 @@ package asm import ( "errors" - "fmt" "github.com/leaklessgfy/asm/asm/constants" "github.com/leaklessgfy/asm/asm/frame" "github.com/leaklessgfy/asm/asm/opcodes" "github.com/leaklessgfy/asm/asm/symbol" + "github.com/leaklessgfy/asm/asm/typereference" ) // ClassReader A parser to make a {@link ClassVisitor} visit a ClassFile structure, as defined in the Java @@ -324,7 +324,7 @@ func (c ClassReader) AcceptB(classVisitor ClassVisitor, attributePrototypes []At currentAnnotationOffset = c.readTypeAnnotationTarget(context, currentAnnotationOffset) annotationDescriptor := c.readUTF8(currentAnnotationOffset, charBuffer) currentAnnotationOffset += 2 - currentAnnotationOffset = c.readElementValues(classVisitor.VisitTypeAnnotation(context.currentTypeAnnotationTarget, context.currentTypeAnnotationTargetPath.(int), annotationDescriptor, false), currentAnnotationOffset, true, charBuffer) + currentAnnotationOffset = c.readElementValues(classVisitor.VisitTypeAnnotation(context.currentTypeAnnotationTarget, context.currentTypeAnnotationTargetPath, annotationDescriptor, false), currentAnnotationOffset, true, charBuffer) numAnnotations-- } } @@ -878,6 +878,7 @@ func (c ClassReader) readCode(methodVisitor MethodVisitor, context *Context, cod break default: //throw error + break } } @@ -1229,15 +1230,14 @@ func (c ClassReader) readCode(methodVisitor MethodVisitor, context *Context, cod name := c.readUTF8(nameAndTypeCpInfoOffset, charBuffer) desc := c.readUTF8(nameAndTypeCpInfoOffset+2, charBuffer) bootstrapMethodOffset := context.bootstrapMethodOffsets[c.readUnsignedShort(cpInfoOffset)] - var handle interface{} - //handle = (Handle) readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer); + handle, _ := c.readConst(c.readUnsignedShort(bootstrapMethodOffset), charBuffer) bootstrapMethodArguments := make([]interface{}, c.readUnsignedShort(bootstrapMethodOffset+2)) bootstrapMethodOffset += 4 for i := 0; i < len(bootstrapMethodArguments); i++ { bootstrapMethodArguments[i], _ = c.readConst(c.readUnsignedShort(bootstrapMethodOffset), charBuffer) bootstrapMethodOffset += 2 } - methodVisitor.VisitInvokeDynamicInsn(name, desc, handle, bootstrapMethodArguments) + methodVisitor.VisitInvokeDynamicInsn(name, desc, handle.(*Handle), bootstrapMethodArguments) currentOffset += 5 break } @@ -1326,7 +1326,7 @@ func (c ClassReader) readCode(methodVisitor MethodVisitor, context *Context, cod if visibleTypeAnnotationOffsets != nil { for i := 0; i < len(visibleTypeAnnotationOffsets); i++ { targetType := c.readByte(visibleTypeAnnotationOffsets[i]) - if targetType == LOCAL_VARIABLE || targetType == RESOURCE_VARIABLE { + if targetType == typereference.LOCAL_VARIABLE || targetType == typereference.RESOURCE_VARIABLE { currentOffset = c.readTypeAnnotationTarget(context, visibleTypeAnnotationOffsets[i]) annotationDescriptor := c.readUTF8(currentOffset, charBuffer) currentOffset += 2 @@ -1347,7 +1347,7 @@ func (c ClassReader) readCode(methodVisitor MethodVisitor, context *Context, cod if invisibleTypeAnnotationOffsets != nil { for i := 0; i < len(invisibleTypeAnnotationOffsets); i++ { targetType := c.readByte(visibleTypeAnnotationOffsets[i]) - if targetType == LOCAL_VARIABLE || targetType == RESOURCE_VARIABLE { + if targetType == typereference.LOCAL_VARIABLE || targetType == typereference.RESOURCE_VARIABLE { currentOffset = c.readTypeAnnotationTarget(context, invisibleTypeAnnotationOffsets[i]) annotationDescriptor := c.readUTF8(currentOffset, charBuffer) currentOffset += 2 @@ -1404,7 +1404,7 @@ func (c ClassReader) readTypeAnnotations(methodVisitor MethodVisitor, context *C } func (c ClassReader) getTypeAnnotationBytecodeOffset(typeAnnotationOffsets []int, typeAnnotationIndex int) int { - if typeAnnotationOffsets == nil || typeAnnotationIndex >= len(typeAnnotationOffsets) || c.readByte(typeAnnotationOffsets[typeAnnotationIndex]) < INSTANCEOF { + if typeAnnotationOffsets == nil || typeAnnotationIndex >= len(typeAnnotationOffsets) || c.readByte(typeAnnotationOffsets[typeAnnotationIndex]) < typereference.INSTANCEOF { return -1 } return c.readUnsignedShort(typeAnnotationOffsets[typeAnnotationIndex] + 1) @@ -1620,8 +1620,13 @@ func (c ClassReader) readConst(constantPoolEntryIndex int, charBuffer []rune) (i name := c.readUTF8(nameAndTypeCpInfoOffset, charBuffer) desc := c.readUTF8(nameAndTypeCpInfoOffset+2, charBuffer) itf := c.b[referenceCpInfoOffset-1] == byte(symbol.CONSTANT_INTERFACE_METHODREF_TAG) - fmt.Println(referenceKind, owner, name, desc, itf) - return 0, nil //new Handle(referenceKind, owner, name, desc, itf) + return &Handle{ + tag: int(referenceKind), + owner: owner, + name: name, + descriptor: desc, + isInterface: itf, + }, nil default: return nil, errors.New("Assertion Error") } diff --git a/asm/classvisitor.go b/asm/classvisitor.go index 3c19e5f..94301ab 100644 --- a/asm/classvisitor.go +++ b/asm/classvisitor.go @@ -10,7 +10,7 @@ type ClassVisitor interface { VisitModule(name string, access int, version string) ModuleVisitor VisitOuterClass(owner, name, descriptor string) VisitAnnotation(descriptor string, visible bool) AnnotationVisitor - VisitTypeAnnotation(typeRef, typePath int, descriptor string, visible bool) AnnotationVisitor //typePath : TypePath + VisitTypeAnnotation(typeRef int, typePath *TypePath, descriptor string, visible bool) AnnotationVisitor VisitAttribute(attribute *Attribute) VisitInnerClass(name, outerName, innerName string, access int) VisitField(access int, name, descriptor, signature string, value interface{}) FieldVisitor diff --git a/asm/context.go b/asm/context.go index 185471b..c7f9686 100644 --- a/asm/context.go +++ b/asm/context.go @@ -11,7 +11,7 @@ type Context struct { currentMethodDescriptor string currentMethodLabels []*Label currentTypeAnnotationTarget int - currentTypeAnnotationTargetPath interface{} //TypePath + currentTypeAnnotationTargetPath *TypePath currentLocalVariableAnnotationRangeStarts []*Label currentLocalVariableAnnotationRangeEnds []*Label currentLocalVariableAnnotationRangeIndices []int diff --git a/asm/fieldvisitor.go b/asm/fieldvisitor.go index 5f3262a..4dd2bb1 100644 --- a/asm/fieldvisitor.go +++ b/asm/fieldvisitor.go @@ -5,7 +5,7 @@ package asm // visitEnd. type FieldVisitor interface { VisitAnnotation(descriptor string, visible bool) AnnotationVisitor - VisitTypeAnnotation(typeRef int, typePath interface{}, descriptor string, visible bool) AnnotationVisitor //TypePath + VisitTypeAnnotation(typeRef int, typePath *TypePath, descriptor string, visible bool) AnnotationVisitor VisitAttribute(attribute *Attribute) VisitEnd() } diff --git a/asm/frame.go b/asm/frame.go new file mode 100644 index 0000000..ebae4f7 --- /dev/null +++ b/asm/frame.go @@ -0,0 +1,13 @@ +package asm + +type Frame struct { + owner *Label + inputLocals []int + inputStack []int + outputLocals []int + outputStack []int + outputStackStart int16 + outputStackTop int16 + initializationCount int + initializations []int +} diff --git a/asm/handle.go b/asm/handle.go new file mode 100644 index 0000000..b0dfa34 --- /dev/null +++ b/asm/handle.go @@ -0,0 +1,9 @@ +package asm + +type Handle struct { + tag int + owner string + name string + descriptor string + isInterface bool +} diff --git a/asm/label.go b/asm/label.go index 1545fa9..fc89905 100644 --- a/asm/label.go +++ b/asm/label.go @@ -30,7 +30,7 @@ type Label struct { inputStackSize int16 outputStackSize int16 outputStackMax int16 - frame interface{} //Frame + frame *Frame nextBasicBlock *Label outgoingEdges interface{} //Edge nextListElement *Label @@ -47,7 +47,7 @@ func (l Label) getCanonicalInstance() *Label { if l.frame == nil { return &l } - return nil //l.frame.owner + return l.frame.owner } func (l *Label) addLineNumber(lineNumber int) { diff --git a/asm/methodvisitor.go b/asm/methodvisitor.go index 41f619f..9cb7427 100644 --- a/asm/methodvisitor.go +++ b/asm/methodvisitor.go @@ -19,7 +19,7 @@ type MethodVisitor interface { VisitParameter(name string, access int) VisitAnnotationDefault() AnnotationVisitor VisitAnnotation(descriptor string, visible bool) AnnotationVisitor - VisitTypeAnnotation(typeRef int, typePath interface{}, descriptor string, visible bool) AnnotationVisitor //TypePath + VisitTypeAnnotation(typeRef int, typePath *TypePath, descriptor string, visible bool) AnnotationVisitor VisitAnnotableParameterCount(parameterCount int, visible bool) VisitParameterAnnotation(parameter int, descriptor string, visible bool) AnnotationVisitor VisitAttribute(attribute *Attribute) @@ -32,7 +32,7 @@ type MethodVisitor interface { VisitFieldInsn(opcode int, owner, name, descriptor string) VisitMethodInsn(opcode int, owner, name, descriptor string) VisitMethodInsnB(opcode int, owner, name, descriptor string, isInterface bool) - VisitInvokeDynamicInsn(name, descriptor string, bootstrapMethodHande interface{}, bootstrapMethodArguments ...interface{}) //Handle + VisitInvokeDynamicInsn(name, descriptor string, bootstrapMethodHande *Handle, bootstrapMethodArguments ...interface{}) VisitJumpInsn(opcode int, label *Label) VisitLabel(label *Label) VisitLdcInsn(value interface{}) @@ -40,11 +40,11 @@ type MethodVisitor interface { VisitTableSwitchInsn(min, max int, dflt *Label, labels ...*Label) VisitLookupSwitchInsn(dflt *Label, keys []int, labels []*Label) VisitMultiANewArrayInsn(descriptor string, numDimensions int) - VisitInsnAnnotation(typeRef int, typePath interface{}, descriptor string, visible bool) AnnotationVisitor //TypePath + VisitInsnAnnotation(typeRef int, typePath *TypePath, descriptor string, visible bool) AnnotationVisitor VisitTryCatchBlock(start, end, handler *Label, typed string) - VisitTryCatchAnnotation(typeRef int, typePath interface{}, descriptor string, visible bool) AnnotationVisitor //TypePath + VisitTryCatchAnnotation(typeRef int, typePath *TypePath, descriptor string, visible bool) AnnotationVisitor VisitLocalVariable(name, descriptor, signature string, start, end *Label, index int) - VisitLocalVariableAnnotation(typeRef int, typePath interface{}, start, end []*Label, index []int, descriptor string, visible bool) AnnotationVisitor //TypePath + VisitLocalVariableAnnotation(typeRef int, typePath *TypePath, start, end []*Label, index []int, descriptor string, visible bool) AnnotationVisitor VisitLineNumber(line int, start *Label) VisitMaxs(maxStack int, maxLocals int) VisitEnd() diff --git a/asm/typepath.go b/asm/typepath.go new file mode 100644 index 0000000..c60b565 --- /dev/null +++ b/asm/typepath.go @@ -0,0 +1,52 @@ +package asm + +type TypePath struct { + typePathContainer []byte + typePathOffset int +} + +func NewTypePathFromString(typePath string) *TypePath { + if typePath == "" || len(typePath) == 0 { + return nil + } + + //typePathLength := len(typePath) + /* + ByteVector output = new ByteVector(typePathLength); + output.putByte(0); + for (int i = 0; i < typePathLength; ) { + char c = typePath.charAt(i++); + if (c == '[') { + output.put11(ARRAY_ELEMENT, 0); + } else if (c == '.') { + output.put11(INNER_TYPE, 0); + } else if (c == '*') { + output.put11(WILDCARD_BOUND, 0); + } else if (c >= '0' && c <= '9') { + int typeArg = c - '0'; + while (i < typePathLength && (c = typePath.charAt(i)) >= '0' && c <= '9') { + typeArg = typeArg * 10 + c - '0'; + i += 1; + } + if (i < typePathLength && typePath.charAt(i) == ';') { + i += 1; + } + output.put11(TYPE_ARGUMENT, typeArg); + } + } + output.data[0] = (byte) (output.length / 2); + */ + return &TypePath{} +} + +func (t TypePath) getLength() int { + return int(t.typePathContainer[t.typePathOffset]) +} + +func (t TypePath) getStep(index int) int { + return int(t.typePathContainer[t.typePathOffset+2*index+1]) +} + +func (t TypePath) getStepArgument(index int) int { + return int(t.typePathContainer[t.typePathOffset+2*index+2]) +} diff --git a/asm/typereference.go b/asm/typereference.go index 0d43ed5..d9a29db 100644 --- a/asm/typereference.go +++ b/asm/typereference.go @@ -1,109 +1 @@ package asm - -// CLASS_TYPE_PARAMETER the sort of type references that target a type parameter of a generic class. See {@link #getSort}. -const CLASS_TYPE_PARAMETER = 0x00 - -// METHOD_TYPE_PARAMETER the sort of type references that target a type parameter of a generic method. See {@link #getSort}. -const METHOD_TYPE_PARAMETER = 0x01 - -// CLASS_EXTENDS The sort of type references that target the super class of a class or one of the interfaces it implements. See {@link #getSort}. -const CLASS_EXTENDS = 0x10 - -// CLASS_TYPE_PARAMETER_BOUND the sort of type references that target a bound of a type parameter of a generic class. See {@link #getSort}. -const CLASS_TYPE_PARAMETER_BOUND = 0x11 - -// METHOD_TYPE_PARAMETER_BOUND the sort of type references that target a bound of a type parameter of a generic method. See {@link #getSort}. -const METHOD_TYPE_PARAMETER_BOUND = 0x12 - -// FIELD the sort of type references that target the type of a field. See {@link #getSort}. -const FIELD = 0x13 - -// METHOD_RETURN the sort of type references that target the return type of a method. See {@link #getSort}. -const METHOD_RETURN = 0x14 - -// METHOD_RECEIVER the sort of type references that target the receiver type of a method. See {@link #getSort}. -const METHOD_RECEIVER = 0x15 - -/** -* The sort of type references that target the type of a formal parameter of a method. See {@link -* #getSort}. - */ -const METHOD_FORMAL_PARAMETER = 0x16 - -/** -* The sort of type references that target the type of an exception declared in the throws clause -* of a method. See {@link #getSort}. - */ -const THROWS = 0x17 - -/** -* The sort of type references that target the type of a local variable in a method. See {@link -* #getSort}. - */ -const LOCAL_VARIABLE = 0x40 - -/** -* The sort of type references that target the type of a resource variable in a method. See {@link -* #getSort}. - */ -const RESOURCE_VARIABLE = 0x41 - -/** -* The sort of type references that target the type of the exception of a 'catch' clause in a -* method. See {@link #getSort}. - */ -const EXCEPTION_PARAMETER = 0x42 - -/** -* The sort of type references that target the type declared in an 'instanceof' instruction. See -* {@link #getSort}. - */ -const INSTANCEOF = 0x43 - -/** -* The sort of type references that target the type of the object created by a 'new' instruction. -* See {@link #getSort}. - */ -const NEW = 0x44 - -/** -* The sort of type references that target the receiver type of a constructor reference. See -* {@link #getSort}. - */ -const CONSTRUCTOR_REFERENCE = 0x45 - -/** -* The sort of type references that target the receiver type of a method reference. See {@link -* #getSort}. - */ -const METHOD_REFERENCE = 0x46 - -/** -* The sort of type references that target the type declared in an explicit or implicit cast -* instruction. See {@link #getSort}. - */ -const CAST = 0x47 - -/** -* The sort of type references that target a type parameter of a generic constructor in a -* constructor call. See {@link #getSort}. - */ -const CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48 - -/** -* The sort of type references that target a type parameter of a generic method in a method call. -* See {@link #getSort}. - */ -const METHOD_INVOCATION_TYPE_ARGUMENT = 0x49 - -/** -* The sort of type references that target a type parameter of a generic constructor in a -* constructor reference. See {@link #getSort}. - */ -const CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A - -/** -* The sort of type references that target a type parameter of a generic method in a method -* reference. See {@link #getSort}. - */ -const METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B diff --git a/asm/typereference/typereference.go b/asm/typereference/typereference.go new file mode 100644 index 0000000..70db710 --- /dev/null +++ b/asm/typereference/typereference.go @@ -0,0 +1,26 @@ +package typereference + +const ( + CLASS_TYPE_PARAMETER = 0x00 + METHOD_TYPE_PARAMETER = 0x01 + CLASS_EXTENDS = 0x10 + CLASS_TYPE_PARAMETER_BOUND = 0x11 + METHOD_TYPE_PARAMETER_BOUND = 0x12 + FIELD = 0x13 + METHOD_RETURN = 0x14 + METHOD_RECEIVER = 0x15 + METHOD_FORMAL_PARAMETER = 0x16 + THROWS = 0x17 + LOCAL_VARIABLE = 0x40 + RESOURCE_VARIABLE = 0x41 + EXCEPTION_PARAMETER = 0x42 + INSTANCEOF = 0x43 + NEW = 0x44 + RUCTOR_REFERENCE = 0x45 + METHOD_REFERENCE = 0x46 + CAST = 0x47 + CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48 + METHOD_INVOCATION_TYPE_ARGUMENT = 0x49 + CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A + METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B +) diff --git a/simplevisitor.go b/simplevisitor.go index dd171a9..25bbb05 100644 --- a/simplevisitor.go +++ b/simplevisitor.go @@ -33,7 +33,7 @@ func (s SimpleVisitor) VisitAnnotation(descriptor string, visible bool) asm.Anno return nil } -func (s SimpleVisitor) VisitTypeAnnotation(typeRef, typePath int, descriptor string, visible bool) asm.AnnotationVisitor { +func (s SimpleVisitor) VisitTypeAnnotation(typeRef int, typePath *asm.TypePath, descriptor string, visible bool) asm.AnnotationVisitor { return nil }