use of jadx.core.dex.nodes.MethodNode in project jadx by skylot.
the class Deobfuscator method resolveOverridingInternal.
@Nullable
private static ClassNode resolveOverridingInternal(DexNode dex, ClassNode cls, String signature, Set<MethodInfo> overrideSet, ClassNode rootClass) {
ClassNode result = null;
for (MethodNode m : cls.getMethods()) {
if (m.getMethodInfo().getShortId().startsWith(signature)) {
result = cls;
if (!overrideSet.contains(m.getMethodInfo())) {
overrideSet.add(m.getMethodInfo());
}
break;
}
}
ArgType superClass = cls.getSuperClass();
if (superClass != null) {
ClassNode superNode = dex.resolveClass(superClass);
if (superNode != null) {
ClassNode clsWithMth = resolveOverridingInternal(dex, superNode, signature, overrideSet, rootClass);
if (clsWithMth != null) {
if ((result != null) && (result != cls)) {
if (clsWithMth != result) {
LOG.warn(String.format("Multiple overriding '%s' from '%s' and '%s' in '%s'", signature, result.getFullName(), clsWithMth.getFullName(), rootClass.getFullName()));
}
} else {
result = clsWithMth;
}
}
}
}
for (ArgType iFaceType : cls.getInterfaces()) {
ClassNode iFaceNode = dex.resolveClass(iFaceType);
if (iFaceNode != null) {
ClassNode clsWithMth = resolveOverridingInternal(dex, iFaceNode, signature, overrideSet, rootClass);
if (clsWithMth != null) {
if ((result != null) && (result != cls)) {
if (clsWithMth != result) {
LOG.warn(String.format("Multiple overriding '%s' from '%s' and '%s' in '%s'", signature, result.getFullName(), clsWithMth.getFullName(), rootClass.getFullName()));
}
} else {
result = clsWithMth;
}
}
}
}
return result;
}
use of jadx.core.dex.nodes.MethodNode in project jadx by skylot.
the class ModVisitor method processInvoke.
private static void processInvoke(MethodNode mth, BlockNode block, int insnNumber, InstructionRemover remover) {
ClassNode parentClass = mth.getParentClass();
InsnNode insn = block.getInstructions().get(insnNumber);
InvokeNode inv = (InvokeNode) insn;
MethodInfo callMth = inv.getCallMth();
if (!callMth.isConstructor()) {
return;
}
InsnNode instArgAssignInsn = ((RegisterArg) inv.getArg(0)).getAssignInsn();
ConstructorInsn co = new ConstructorInsn(mth, inv);
boolean remove = false;
if (co.isSuper() && (co.getArgsCount() == 0 || parentClass.isEnum())) {
remove = true;
} else if (co.isThis() && co.getArgsCount() == 0) {
MethodNode defCo = parentClass.searchMethodByName(callMth.getShortId());
if (defCo == null || defCo.isNoCode()) {
// default constructor not implemented
remove = true;
}
}
// remove super() call in instance initializer
if (parentClass.isAnonymous() && mth.isDefaultConstructor() && co.isSuper()) {
remove = true;
}
if (remove) {
remover.add(insn);
return;
}
if (co.isNewInstance()) {
InsnNode newInstInsn = removeAssignChain(instArgAssignInsn, remover, InsnType.NEW_INSTANCE);
if (newInstInsn != null) {
RegisterArg instArg = newInstInsn.getResult();
RegisterArg resultArg = co.getResult();
if (!resultArg.equals(instArg)) {
// replace all usages of 'instArg' with result of this constructor instruction
for (RegisterArg useArg : new ArrayList<RegisterArg>(instArg.getSVar().getUseList())) {
RegisterArg dup = resultArg.duplicate();
InsnNode parentInsn = useArg.getParentInsn();
parentInsn.replaceArg(useArg, dup);
dup.setParentInsn(parentInsn);
resultArg.getSVar().use(dup);
}
}
}
}
ConstructorInsn replace = processConstructor(mth, co);
if (replace != null) {
co = replace;
}
replaceInsn(block, insnNumber, co);
processAnonymousConstructor(mth, co);
}
use of jadx.core.dex.nodes.MethodNode in project jadx by skylot.
the class ModVisitor method processConstructor.
/**
* Replace call of synthetic constructor
*/
private static ConstructorInsn processConstructor(MethodNode mth, ConstructorInsn co) {
MethodNode callMth = mth.dex().resolveMethod(co.getCallMth());
if (callMth == null || !callMth.getAccessFlags().isSynthetic() || !allArgsNull(co)) {
return null;
}
ClassNode classNode = mth.dex().resolveClass(callMth.getParentClass().getClassInfo());
if (classNode == null) {
return null;
}
boolean passThis = co.getArgsCount() >= 1 && co.getArg(0).isThis();
String ctrId = "<init>(" + (passThis ? TypeGen.signature(co.getArg(0).getType()) : "") + ")V";
MethodNode defCtr = classNode.searchMethodByName(ctrId);
if (defCtr == null) {
return null;
}
ConstructorInsn newInsn = new ConstructorInsn(defCtr.getMethodInfo(), co.getCallType(), co.getInstanceArg());
newInsn.setResult(co.getResult());
return newInsn;
}
use of jadx.core.dex.nodes.MethodNode in project jadx by skylot.
the class ReSugarCode method getEnumMap.
private static EnumMapAttr.KeyValueMap getEnumMap(MethodNode mth, FieldNode field) {
ClassNode syntheticClass = field.getParentClass();
EnumMapAttr mapAttr = syntheticClass.get(AType.ENUM_MAP);
if (mapAttr != null) {
return mapAttr.getMap(field);
}
mapAttr = new EnumMapAttr();
syntheticClass.addAttr(mapAttr);
MethodNode clsInitMth = syntheticClass.searchMethodByName("<clinit>()V");
if (clsInitMth == null || clsInitMth.isNoCode()) {
return null;
}
if (clsInitMth.getBasicBlocks() == null) {
try {
clsInitMth.load();
} catch (DecodeException e) {
LOG.error("Load failed", e);
return null;
}
if (clsInitMth.getBasicBlocks() == null) {
// TODO:
return null;
}
}
for (BlockNode block : clsInitMth.getBasicBlocks()) {
for (InsnNode insn : block.getInstructions()) {
if (insn.getType() == InsnType.APUT) {
addToEnumMap(mth, mapAttr, insn);
}
}
}
return mapAttr.getMap(field);
}
use of jadx.core.dex.nodes.MethodNode in project jadx by skylot.
the class EnumVisitor method visit.
@Override
public boolean visit(ClassNode cls) throws JadxException {
if (!cls.isEnum()) {
return true;
}
// search class init method
MethodNode staticMethod = null;
for (MethodNode mth : cls.getMethods()) {
MethodInfo mi = mth.getMethodInfo();
if (mi.isClassInit()) {
staticMethod = mth;
break;
}
}
if (staticMethod == null) {
ErrorsCounter.classError(cls, "Enum class init method not found");
return true;
}
ArgType clsType = cls.getClassInfo().getType();
String enumConstructor = "<init>(Ljava/lang/String;I)V";
// TODO: detect these methods by analyzing method instructions
String valuesOfMethod = "valueOf(Ljava/lang/String;)" + TypeGen.signature(clsType);
String valuesMethod = "values()" + TypeGen.signature(ArgType.array(clsType));
// collect enum fields, remove synthetic
List<FieldNode> enumFields = new ArrayList<FieldNode>();
for (FieldNode f : cls.getFields()) {
if (f.getAccessFlags().isEnum()) {
enumFields.add(f);
f.add(AFlag.DONT_GENERATE);
} else if (f.getAccessFlags().isSynthetic()) {
f.add(AFlag.DONT_GENERATE);
}
}
// remove synthetic methods
for (MethodNode mth : cls.getMethods()) {
MethodInfo mi = mth.getMethodInfo();
if (mi.isClassInit()) {
continue;
}
String shortId = mi.getShortId();
boolean isSynthetic = mth.getAccessFlags().isSynthetic();
if (mi.isConstructor() && !isSynthetic) {
if (shortId.equals(enumConstructor)) {
mth.add(AFlag.DONT_GENERATE);
}
} else if (isSynthetic || shortId.equals(valuesMethod) || shortId.equals(valuesOfMethod)) {
mth.add(AFlag.DONT_GENERATE);
}
}
EnumClassAttr attr = new EnumClassAttr(enumFields.size());
cls.addAttr(attr);
attr.setStaticMethod(staticMethod);
ClassInfo classInfo = cls.getClassInfo();
// move enum specific instruction from static method to separate list
BlockNode staticBlock = staticMethod.getBasicBlocks().get(0);
List<InsnNode> enumPutInsns = new ArrayList<InsnNode>();
List<InsnNode> list = staticBlock.getInstructions();
int size = list.size();
for (int i = 0; i < size; i++) {
InsnNode insn = list.get(i);
if (insn.getType() != InsnType.SPUT) {
continue;
}
FieldInfo f = (FieldInfo) ((IndexInsnNode) insn).getIndex();
if (!f.getDeclClass().equals(classInfo)) {
continue;
}
FieldNode fieldNode = cls.searchField(f);
if (fieldNode != null && isEnumArrayField(classInfo, fieldNode)) {
if (i == size - 1) {
staticMethod.add(AFlag.DONT_GENERATE);
} else {
list.subList(0, i + 1).clear();
}
break;
} else {
enumPutInsns.add(insn);
}
}
for (InsnNode putInsn : enumPutInsns) {
ConstructorInsn co = getConstructorInsn(putInsn);
if (co == null || co.getArgsCount() < 2) {
continue;
}
ClassInfo clsInfo = co.getClassType();
ClassNode constrCls = cls.dex().resolveClass(clsInfo);
if (constrCls == null) {
continue;
}
if (!clsInfo.equals(classInfo) && !constrCls.getAccessFlags().isEnum()) {
continue;
}
FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) putInsn).getIndex();
String name = getConstString(cls.dex(), co.getArg(0));
if (name != null && !fieldInfo.getAlias().equals(name) && NameMapper.isValidIdentifier(name)) {
// LOG.debug("Rename enum field: '{}' to '{}' in {}", fieldInfo.getName(), name, cls);
fieldInfo.setAlias(name);
}
EnumField field = new EnumField(fieldInfo, co, 2);
attr.getFields().add(field);
if (!co.getClassType().equals(classInfo)) {
// enum contains additional methods
for (ClassNode innerCls : cls.getInnerClasses()) {
processEnumInnerCls(co, field, innerCls);
}
}
}
return false;
}
Aggregations