/** * Constructs a <code>method_info</code> structure. The initial value of <code>access_flags</code> * is zero. * * @param cp a constant pool table * @param methodname method name * @param desc method descriptor * @see Descriptor */ public MethodInfo(ConstPool cp, String methodname, String desc) { this(cp); accessFlags = 0; name = cp.addUtf8Info(methodname); cachedName = methodname; descriptor = constPool.addUtf8Info(desc); }
/* skipSuper 1: this(), 0: super(), -1: both. */ private int skipSuperConstructor0(int skipThis) throws BadBytecode { begin(); ConstPool cp = codeAttr.getConstPool(); String thisClassName = codeAttr.getDeclaringClass(); int nested = 0; while (hasNext()) { int index = next(); int c = byteAt(index); if (c == NEW) ++nested; else if (c == INVOKESPECIAL) { int mref = ByteArray.readU16bit(bytecode, index + 1); if (cp.getMethodrefName(mref).equals(MethodInfo.nameInit)) if (--nested < 0) { if (skipThis < 0) return index; String cname = cp.getMethodrefClassName(mref); if (cname.equals(thisClassName) == (skipThis > 0)) return index; else break; } } } begin(); return -1; }
@Override public AttributeInfo copy(final ConstPool newCp, final Map classnames) { final byte[] src = this.get(); final byte[] dest = new byte[src.length]; final ConstPool cp = this.getConstPool(); final InnerClassesAttribute attr = new InnerClassesAttribute(newCp, dest); final int n = ByteArray.readU16bit(src, 0); ByteArray.write16bit(n, dest, 0); int j = 2; for (int i = 0; i < n; ++i) { int innerClass = ByteArray.readU16bit(src, j); int outerClass = ByteArray.readU16bit(src, j + 2); int innerName = ByteArray.readU16bit(src, j + 4); final int innerAccess = ByteArray.readU16bit(src, j + 6); if (innerClass != 0) { innerClass = cp.copy(innerClass, newCp, classnames); } ByteArray.write16bit(innerClass, dest, j); if (outerClass != 0) { outerClass = cp.copy(outerClass, newCp, classnames); } ByteArray.write16bit(outerClass, dest, j + 2); if (innerName != 0) { innerName = cp.copy(innerName, newCp, classnames); } ByteArray.write16bit(innerName, dest, j + 4); ByteArray.write16bit(innerAccess, dest, j + 6); j += 8; } return attr; }
void prune(ConstPool cp) { LinkedList newAttributes = new LinkedList(); AttributeInfo invisibleAnnotations = getAttribute(AnnotationsAttribute.invisibleTag); if (invisibleAnnotations != null) { invisibleAnnotations = invisibleAnnotations.copy(cp, null); newAttributes.add(invisibleAnnotations); } AttributeInfo visibleAnnotations = getAttribute(AnnotationsAttribute.visibleTag); if (visibleAnnotations != null) { visibleAnnotations = visibleAnnotations.copy(cp, null); newAttributes.add(visibleAnnotations); } AttributeInfo signature = getAttribute(SignatureAttribute.tag); if (signature != null) { signature = signature.copy(cp, null); newAttributes.add(signature); } int index = getConstantValue(); if (index != 0) { index = constPool.copy(index, cp, null); newAttributes.add(new ConstantAttribute(cp, index)); } attribute = newAttributes; name = cp.addUtf8Info(getName()); descriptor = cp.addUtf8Info(getDescriptor()); constPool = cp; }
private void renameType(int pos, int index) { String name = cpool.getUtf8Info(index); String newName = Descriptor.rename(name, classnames); if (!name.equals(newName)) { int index2 = cpool.addUtf8Info(newName); ByteArray.write16bit(index2, info, pos); } }
public EnclosingMethodAttribute( final ConstPool cp, final String className, final String methodName, final String methodDesc) { super(cp, "EnclosingMethod"); final int ci = cp.addClassInfo(className); final int ni = cp.addNameAndTypeInfo(methodName, methodDesc); final byte[] bvalue = {(byte) (ci >>> 8), (byte) ci, (byte) (ni >>> 8), (byte) ni}; this.set(bvalue); }
private static String fieldInfo(ConstPool pool, int index) { return "#" + index + " = Field " + pool.getFieldrefClassName(index) + "." + pool.getFieldrefName(index) + "(" + pool.getFieldrefType(index) + ")"; }
private static String methodInfo(ConstPool pool, int index) { return "#" + index + " = Method " + pool.getMethodrefClassName(index) + "." + pool.getMethodrefName(index) + "(" + pool.getMethodrefType(index) + ")"; }
/** * Copies the contents from a source attribute. Specified class names are replaced during the * copy. * * @param srcAttr source Exceptions attribute * @param classnames pairs of replaced and substituted class names. */ private void copyFrom(ExceptionsAttribute srcAttr, Map classnames) { ConstPool srcCp = srcAttr.constPool; ConstPool destCp = this.constPool; byte[] src = srcAttr.info; int num = src.length; byte[] dest = new byte[num]; dest[0] = src[0]; dest[1] = src[1]; // the number of elements. for (int i = 2; i < num; i += 2) { int index = ByteArray.readU16bit(src, i); ByteArray.write16bit(srcCp.copy(index, destCp, classnames), dest, i); } this.info = dest; }
/** * Changes a super constructor called by this constructor. * * <p>This method modifies a call to <code>super()</code>, which should be at the head of a * constructor body, so that a constructor in a different super class is called. This method does * not change actural parameters. Hence the new super class must have a constructor with the same * signature as the original one. * * <p>This method should be called when the super class of the class declaring this method is * changed. * * <p>This method does not perform anything unless this <code>MethodInfo</code> represents a * constructor. * * @param superclass the new super class */ public void setSuperclass(String superclass) throws BadBytecode { if (!isConstructor()) return; CodeAttribute ca = getCodeAttribute(); byte[] code = ca.getCode(); CodeIterator iterator = ca.iterator(); int pos = iterator.skipSuperConstructor(); if (pos >= 0) { // not this() ConstPool cp = constPool; int mref = ByteArray.readU16bit(code, pos + 1); int nt = cp.getMethodrefNameAndType(mref); int sc = cp.addClassInfo(superclass); int mref2 = cp.addMethodrefInfo(sc, nt); ByteArray.write16bit(mref2, code, pos + 1); } }
private static void copyConstPoolInfo( int i, byte[] code, ConstPool srcCp, byte[] newcode, ConstPool destCp, Map classnameMap) { int index = ((code[i] & 0xff) << 8) | (code[i + 1] & 0xff); index = srcCp.copy(index, destCp, classnameMap); newcode[i] = (byte) (index >> 8); newcode[i + 1] = (byte) index; }
void prune(ConstPool cp) { LinkedList newAttributes = new LinkedList(); AttributeInfo invisibleAnnotations = getAttribute(AnnotationsAttribute.invisibleTag); if (invisibleAnnotations != null) { invisibleAnnotations = invisibleAnnotations.copy(cp, null); newAttributes.add(invisibleAnnotations); } AttributeInfo visibleAnnotations = getAttribute(AnnotationsAttribute.visibleTag); if (visibleAnnotations != null) { visibleAnnotations = visibleAnnotations.copy(cp, null); newAttributes.add(visibleAnnotations); } AttributeInfo parameterInvisibleAnnotations = getAttribute(ParameterAnnotationsAttribute.invisibleTag); if (parameterInvisibleAnnotations != null) { parameterInvisibleAnnotations = parameterInvisibleAnnotations.copy(cp, null); newAttributes.add(parameterInvisibleAnnotations); } AttributeInfo parameterVisibleAnnotations = getAttribute(ParameterAnnotationsAttribute.visibleTag); if (parameterVisibleAnnotations != null) { parameterVisibleAnnotations = parameterVisibleAnnotations.copy(cp, null); newAttributes.add(parameterVisibleAnnotations); } AnnotationDefaultAttribute defaultAttribute = (AnnotationDefaultAttribute) getAttribute(AnnotationDefaultAttribute.tag); if (defaultAttribute != null) newAttributes.add(defaultAttribute); ExceptionsAttribute ea = getExceptionsAttribute(); if (ea != null) newAttributes.add(ea); AttributeInfo signature = getAttribute(SignatureAttribute.tag); if (signature != null) { signature = signature.copy(cp, null); newAttributes.add(signature); } attribute = newAttributes; name = cp.addUtf8Info(getName()); descriptor = cp.addUtf8Info(getDescriptor()); constPool = cp; }
private void read(MethodInfo src, String methodname, Map classnames) throws BadBytecode { ConstPool destCp = constPool; accessFlags = src.accessFlags; name = destCp.addUtf8Info(methodname); cachedName = methodname; ConstPool srcCp = src.constPool; String desc = srcCp.getUtf8Info(src.descriptor); String desc2 = Descriptor.rename(desc, classnames); descriptor = destCp.addUtf8Info(desc2); attribute = new LinkedList(); ExceptionsAttribute eattr = src.getExceptionsAttribute(); if (eattr != null) attribute.add(eattr.copy(destCp, classnames)); CodeAttribute cattr = src.getCodeAttribute(); if (cattr != null) attribute.add(cattr.copy(destCp, classnames)); }
protected int[] copyData(int[] tags, int[] data) { int[] newData = new int[data.length]; for (int i = 0; i < data.length; i++) if (tags[i] == OBJECT) newData[i] = srcPool.copy(data[i], destPool, classnames); else newData[i] = data[i]; return newData; }
static AttributeInfo read(ConstPool cp, DataInputStream in) throws IOException { int name = in.readUnsignedShort(); String nameStr = cp.getUtf8Info(name); if (nameStr.charAt(0) < 'L') { if (nameStr.equals(AnnotationDefaultAttribute.tag)) return new AnnotationDefaultAttribute(cp, name, in); else if (nameStr.equals(CodeAttribute.tag)) return new CodeAttribute(cp, name, in); else if (nameStr.equals(ConstantAttribute.tag)) return new ConstantAttribute(cp, name, in); else if (nameStr.equals(DeprecatedAttribute.tag)) return new DeprecatedAttribute(cp, name, in); else if (nameStr.equals(EnclosingMethodAttribute.tag)) return new EnclosingMethodAttribute(cp, name, in); else if (nameStr.equals(ExceptionsAttribute.tag)) return new ExceptionsAttribute(cp, name, in); else if (nameStr.equals(InnerClassesAttribute.tag)) return new InnerClassesAttribute(cp, name, in); } else { /* Note that the names of Annotations attributes begin with 'R'. */ if (nameStr.equals(LineNumberAttribute.tag)) return new LineNumberAttribute(cp, name, in); else if (nameStr.equals(LocalVariableAttribute.tag) || nameStr.equals(LocalVariableAttribute.typeTag)) return new LocalVariableAttribute(cp, name, in); else if (nameStr.equals(AnnotationsAttribute.visibleTag) || nameStr.equals(AnnotationsAttribute.invisibleTag)) { // RuntimeVisibleAnnotations or RuntimeInvisibleAnnotations return new AnnotationsAttribute(cp, name, in); } else if (nameStr.equals(ParameterAnnotationsAttribute.visibleTag) || nameStr.equals(ParameterAnnotationsAttribute.invisibleTag)) return new ParameterAnnotationsAttribute(cp, name, in); else if (nameStr.equals(SignatureAttribute.tag)) return new SignatureAttribute(cp, name, in); else if (nameStr.equals(SourceFileAttribute.tag)) return new SourceFileAttribute(cp, name, in); else if (nameStr.equals(SyntheticAttribute.tag)) return new SyntheticAttribute(cp, name, in); else if (nameStr.equals(StackMapTable.tag)) return new StackMapTable(cp, name, in); } return new AttributeInfo(cp, name, in); }
private static String ldc(ConstPool pool, int index) { int tag = pool.getTag(index); switch (tag) { case ConstPool.CONST_String: return "#" + index + " = \"" + pool.getStringInfo(index) + "\""; case ConstPool.CONST_Integer: return "#" + index + " = int " + pool.getIntegerInfo(index); case ConstPool.CONST_Float: return "#" + index + " = float " + pool.getFloatInfo(index); case ConstPool.CONST_Long: return "#" + index + " = long " + pool.getLongInfo(index); case ConstPool.CONST_Double: return "#" + index + " = int " + pool.getDoubleInfo(index); case ConstPool.CONST_Class: return classInfo(pool, index); default: throw new RuntimeException("bad LDC: " + tag); } }
/** * Returns a method descriptor. * * @see Descriptor */ public String getDescriptor() { return constPool.getUtf8Info(descriptor); }
/** * Constructs an <code>attribute_info</code> structure. * * @param cp constant pool table * @param attrname attribute name * @param attrinfo <code>info</code> field of <code>attribute_info</code> structure. */ public AttributeInfo(ConstPool cp, String attrname, byte[] attrinfo) { this(cp, cp.addUtf8Info(attrname), attrinfo); }
/** Returns an attribute name. */ public String getName() { return constPool.getUtf8Info(name); }
/** * Copies a constant pool entry into the destination constant pool and returns the index of the * copied entry. That entry must be a Utf8Info representing a class name in the L<class name>; * form. * * @param srcIndex the index of the copied entry into the source constant pool. * @return the index of the copied item into the destination constant pool. */ int copyType(int srcIndex) { String name = srcPool.getUtf8Info(srcIndex); String newName = Descriptor.rename(name, classnames); return destPool.addUtf8Info(newName); }
/** * Copies a constant pool entry into the destination constant pool and returns the index of the * copied entry. * * @param srcIndex the index of the copied entry into the source constant pool. * @return the index of the copied item into the destination constant pool. */ int copy(int srcIndex) { return srcPool.copy(srcIndex, destPool, classnames); }
public String methodName() { final ConstPool cp = this.getConstPool(); final int mi = this.methodIndex(); final int ni = cp.getNameAndTypeName(mi); return cp.getUtf8Info(ni); }
public boolean match(String filename, ClassFile classFile, ClassMap tempClassMap) { for (Object o : classFile.getMethods()) { MethodInfo methodInfo = (MethodInfo) o; classMod.methodInfo = methodInfo; CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); if (codeAttribute == null) { continue; } if (getClassMap().hasMap(deobfMethod)) { MethodRef obfTarget = (MethodRef) getClassMap().map(deobfMethod); if (!methodInfo.getName().equals(obfTarget.getName())) { continue; } } ArrayList<String> deobfTypes = null; ArrayList<String> obfTypes = null; if (deobfMethod != null && deobfMethod.getType() != null) { deobfTypes = ConstPoolUtils.parseDescriptor(deobfMethod.getType()); obfTypes = ConstPoolUtils.parseDescriptor(methodInfo.getDescriptor()); if (!isPotentialTypeMatch(deobfTypes, obfTypes)) { continue; } } ConstPool constPool = methodInfo.getConstPool(); CodeIterator codeIterator = codeAttribute.iterator(); initMatcher(); ArrayList<JavaRef> tempMappings = new ArrayList<JavaRef>(); try { match: for (int offset = 0; offset < codeIterator.getCodeLength() && matcher.match(methodInfo, offset); offset = codeIterator.next()) { tempMappings.clear(); for (Map.Entry<Integer, JavaRef> entry : xrefs.entrySet()) { int captureGroup = entry.getKey(); JavaRef xref = entry.getValue(); byte[] code = matcher.getCaptureGroup(captureGroup); int index = Util.demarshal(code, 1, 2); ConstPoolUtils.matchOpcodeToRefType(code[0], xref); ConstPoolUtils.matchConstPoolTagToRefType(constPool.getTag(index), xref); JavaRef newRef = ConstPoolUtils.getRefForIndex(constPool, index); if (!isPotentialTypeMatch(xref.getType(), newRef.getType())) { if (deobfMethod != null) { Logger.log( Logger.LOG_METHOD, "method %s %s matches %s %s, but", methodInfo.getName(), methodInfo.getDescriptor(), deobfMethod.getName(), deobfMethod.getType()); } Logger.log( Logger.LOG_METHOD, "method %s %s failed xref #%d %s %s -> %s %s", methodInfo.getName(), methodInfo.getDescriptor(), captureGroup, xref.getName(), xref.getType(), newRef.getName(), newRef.getType()); continue match; } tempMappings.add(xref); tempMappings.add(newRef); } for (int i = 0; i + 1 < tempMappings.size(); i += 2) { tempClassMap.addMap(tempMappings.get(i), tempMappings.get(i + 1)); } if (deobfMethod != null) { String deobfName = classMod.getDeobfClass(); tempClassMap.addClassMap(deobfName, ClassMap.filenameToClassName(filename)); tempClassMap.addMethodMap( deobfName, deobfMethod.getName(), methodInfo.getName(), methodInfo.getDescriptor()); if (deobfTypes != null && obfTypes != null) { for (int i = 0; i < deobfTypes.size(); i++) { String desc = ClassMap.descriptorToClassName(deobfTypes.get(i)); String obf = ClassMap.descriptorToClassName(obfTypes.get(i)); if (!obf.equals(desc)) { tempClassMap.addClassMap(desc, obf); } } } } afterMatch(classFile, methodInfo); classMod.methodInfo = null; return true; } } catch (BadBytecode e) { Logger.log(e); } } classMod.methodInfo = null; return false; }
/** Returns the name of the class declaring the method including this code attribute. */ public String getDeclaringClass() { ConstPool cp = getConstPool(); return cp.getClassName(); }
private static LdcEntry copyCode( byte[] code, int beginPos, int endPos, ConstPool srcCp, byte[] newcode, ConstPool destCp, Map classnameMap) throws BadBytecode { int i2, index; LdcEntry ldcEntry = null; for (int i = beginPos; i < endPos; i = i2) { i2 = CodeIterator.nextOpcode(code, i); byte c = code[i]; newcode[i] = c; switch (c & 0xff) { case LDC_W: case LDC2_W: case GETSTATIC: case PUTSTATIC: case GETFIELD: case PUTFIELD: case INVOKEVIRTUAL: case INVOKESPECIAL: case INVOKESTATIC: case NEW: case ANEWARRAY: case CHECKCAST: case INSTANCEOF: copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp, classnameMap); break; case LDC: index = code[i + 1] & 0xff; index = srcCp.copy(index, destCp, classnameMap); if (index < 0x100) newcode[i + 1] = (byte) index; else { newcode[i] = NOP; newcode[i + 1] = NOP; LdcEntry ldc = new LdcEntry(); ldc.where = i; ldc.index = index; ldc.next = ldcEntry; ldcEntry = ldc; } break; case INVOKEINTERFACE: copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp, classnameMap); newcode[i + 3] = code[i + 3]; newcode[i + 4] = code[i + 4]; break; case INVOKEDYNAMIC: copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp, classnameMap); newcode[i + 3] = 0; newcode[i + 4] = 0; break; case MULTIANEWARRAY: copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp, classnameMap); newcode[i + 3] = code[i + 3]; break; default: while (++i < i2) newcode[i] = code[i]; break; } } return ldcEntry; }
public String methodDescriptor() { final ConstPool cp = this.getConstPool(); final int mi = this.methodIndex(); final int ti = cp.getNameAndTypeDescriptor(mi); return cp.getUtf8Info(ti); }
/** * Copies all constant pool items to a given new constant pool and replaces the original items * with the new ones. This is used for garbage collecting the items of removed fields and methods. * * @param cp the destination */ void compact(ConstPool cp) { name = cp.addUtf8Info(getName()); descriptor = cp.addUtf8Info(getDescriptor()); attribute = AttributeInfo.copyAll(attribute, cp); constPool = cp; }
/** Returns a method name. */ public String getName() { if (cachedName == null) cachedName = constPool.getUtf8Info(name); return cachedName; }
/** * Sets a method descriptor. * * @see Descriptor */ public void setDescriptor(String desc) { if (!desc.equals(getDescriptor())) descriptor = constPool.addUtf8Info(desc); }
/** Sets a method name. */ public void setName(String newName) { name = constPool.addUtf8Info(newName); cachedName = newName; }