@Override public int lookupConstant(ConstantPoolGen cpg) { MethodRef method = getValue(); if (isInterfaceMethod()) { return cpg.lookupInterfaceMethodref( method.getClassName(), method.getName(), method.getDescriptor().toString()); } return cpg.lookupMethodref( method.getClassName(), method.getName(), method.getDescriptor().toString()); }
@Override public boolean apply(MethodRef input) { String owner = input.getOwner(); if (owner.charAt(0) == '[') { owner = "java/lang/Object"; } Map<Key, Boolean> map = this.map.get(owner); if (map == null) { try (InputStream in = loader.getResourceAsStream(owner + ".class")) { if (in == null) { throw new IllegalArgumentException("Object type " + owner + " not found"); } ClassReader reader = new ClassReader(in); map = new HashMap<>(); ClassAdapter adapter = new ClassAdapter(map); reader.accept(adapter, SKIP_DEBUG | SKIP_FRAMES); } catch (IOException e) { throw new IllegalArgumentException(e); } Map<Key, Boolean> prevMap = this.map.putIfAbsent(owner, map); if (prevMap != null) { map = prevMap; } } String name = input.getName(); String desc = input.getDesc(); Boolean suspendable = map.get(new Key(name, desc)); if (suspendable == null) { throw new IllegalArgumentException("Method " + owner + '.' + name + desc + " not found"); } return suspendable; }
@Override public Constant createConstant(ConstantPoolGen cpg) { MethodRef method = getValue(); int i = cpg.addClass(method.getClassName()); int n = cpg.addNameAndType(method.getName(), method.getDescriptor().toString()); return new ConstantMethodref(i, n); }
@Override void setClassMod(ClassMod classMod) { super.setClassMod(classMod); if (deobfMethod != null && deobfMethod.getClassName() == null) { deobfMethod = new MethodRef(classMod.getDeobfClass(), deobfMethod.getName(), deobfMethod.getType()); } }
/* * @see ASTVisitor#visit(MethodRef) * @since 3.0 */ @Override public boolean visit(MethodRef node) { if (node.getQualifier() != null) { node.getQualifier().accept(this); } this.fBuffer.append("#"); // $NON-NLS-1$ node.getName().accept(this); this.fBuffer.append("("); // $NON-NLS-1$ for (Iterator<MethodRefParameter> it = node.parameters().iterator(); it.hasNext(); ) { MethodRefParameter e = it.next(); e.accept(this); if (it.hasNext()) { this.fBuffer.append(","); // $NON-NLS-1$ } } this.fBuffer.append(")"); // $NON-NLS-1$ return false; }
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; }