use of jadx.core.dex.instructions.mods.ConstructorInsn in project jadx by skylot.
the class SimplifyVisitor method convertInvoke.
private static InsnNode convertInvoke(MethodNode mth, InsnNode insn) {
MethodInfo callMth = ((InvokeNode) insn).getCallMth();
// convert it to STRING_CONCAT pseudo instruction.
if (callMth.getDeclClass().getFullName().equals(Consts.CLASS_STRING_BUILDER) && callMth.getShortId().equals(Consts.MTH_TOSTRING_SIGNATURE) && insn.getArg(0).isInsnWrap()) {
try {
List<InsnNode> chain = flattenInsnChain(insn);
//RAF
int constrIndex = -1;
// string is created using .append() calls:
if (chain.size() > 1 && chain.get(0).getType() == InsnType.CONSTRUCTOR) {
constrIndex = 0;
} else if (chain.size() > 2 && chain.get(1).getType() == InsnType.CONSTRUCTOR) {
//RAF Case where the first string element is String arg to the
// new StringBuilder("xxx") constructor
constrIndex = 1;
} else if (chain.size() > 3 && chain.get(2).getType() == InsnType.CONSTRUCTOR) {
//RAF Case where the first string element is String.valueOf() arg
// to the new StringBuilder(String.valueOf(zzz)) constructor
constrIndex = 2;
}
if (constrIndex != -1) {
// If we found a CONSTRUCTOR, is it a StringBuilder?
ConstructorInsn constr = (ConstructorInsn) chain.get(constrIndex);
if (constr.getClassType().getFullName().equals(Consts.CLASS_STRING_BUILDER)) {
int len = chain.size(), argInd = 1;
InsnNode concatInsn = new InsnNode(InsnType.STR_CONCAT, len - 1);
InsnNode argInsn;
if (constrIndex > 0) {
// There was an arg to the StringBuilder constr
InsnWrapArg iwa;
if (constrIndex == 2 && (argInsn = chain.get(1)).getType() == InsnType.INVOKE && ((InvokeNode) argInsn).getCallMth().getName().compareTo("valueOf") == 0) {
// The argument of new StringBuilder() is a String.valueOf(chainElement0)
iwa = (InsnWrapArg) argInsn.getArg(0);
// Cause for loop below to skip to after the constructor
argInd = 3;
} else {
InsnNode firstNode = chain.get(0);
if (firstNode instanceof ConstStringNode) {
ConstStringNode csn = (ConstStringNode) firstNode;
iwa = new InsnWrapArg(csn);
// Cause for loop below to skip to after the constructor
argInd = 2;
} else {
return null;
}
}
concatInsn.addArg(iwa);
}
for (; argInd < len; argInd++) {
// Add the .append(xxx) arg string to concat
concatInsn.addArg(chain.get(argInd).getArg(1));
}
concatInsn.setResult(insn.getResult());
return concatInsn;
}
// end of if constructor is for StringBuilder
}
// end of if we found a constructor early in the chain
} catch (Throwable e) {
LOG.debug("Can't convert string concatenation: {} insn: {}", mth, insn, e);
}
}
return null;
}
use of jadx.core.dex.instructions.mods.ConstructorInsn in project jadx by skylot.
the class ModVisitor method getArgsToFieldsMapping.
private static Map<InsnArg, FieldNode> getArgsToFieldsMapping(MethodNode callMthNode, ConstructorInsn co) {
Map<InsnArg, FieldNode> map = new LinkedHashMap<InsnArg, FieldNode>();
ClassNode parentClass = callMthNode.getParentClass();
List<RegisterArg> argList = callMthNode.getArguments(false);
int startArg = parentClass.getAccessFlags().isStatic() ? 0 : 1;
int argsCount = argList.size();
for (int i = startArg; i < argsCount; i++) {
RegisterArg arg = argList.get(i);
InsnNode useInsn = getParentInsnSkipMove(arg);
if (useInsn == null) {
return Collections.emptyMap();
}
FieldNode fieldNode = null;
if (useInsn.getType() == InsnType.IPUT) {
FieldInfo field = (FieldInfo) ((IndexInsnNode) useInsn).getIndex();
fieldNode = parentClass.searchField(field);
if (fieldNode == null || !fieldNode.getAccessFlags().isSynthetic()) {
return Collections.emptyMap();
}
} else if (useInsn.getType() == InsnType.CONSTRUCTOR) {
ConstructorInsn superConstr = (ConstructorInsn) useInsn;
if (!superConstr.isSuper()) {
return Collections.emptyMap();
}
} else {
return Collections.emptyMap();
}
map.put(co.getArg(i), fieldNode);
}
return map;
}
use of jadx.core.dex.instructions.mods.ConstructorInsn in project jadx by skylot.
the class ClassGen method addEnumFields.
private void addEnumFields(CodeWriter code) throws CodegenException {
EnumClassAttr enumFields = cls.get(AType.ENUM_CLASS);
if (enumFields == null) {
return;
}
InsnGen igen = null;
for (Iterator<EnumField> it = enumFields.getFields().iterator(); it.hasNext(); ) {
EnumField f = it.next();
code.startLine(f.getField().getAlias());
ConstructorInsn constrInsn = f.getConstrInsn();
if (constrInsn.getArgsCount() > f.getStartArg()) {
if (igen == null) {
igen = makeInsnGen(enumFields.getStaticMethod());
}
MethodNode callMth = cls.dex().resolveMethod(constrInsn.getCallMth());
igen.generateMethodArguments(code, constrInsn, f.getStartArg(), callMth);
}
if (f.getCls() != null) {
code.add(' ');
new ClassGen(f.getCls(), this).addClassBody(code);
}
if (it.hasNext()) {
code.add(',');
}
}
if (isMethodsPresents() || isFieldsPresents() || isInnerClassesPresents()) {
if (enumFields.getFields().isEmpty()) {
code.startLine();
}
code.add(';');
if (isFieldsPresents()) {
code.startLine();
}
}
}
use of jadx.core.dex.instructions.mods.ConstructorInsn in project jadx by skylot.
the class NameGen method makeNameFromInsn.
private String makeNameFromInsn(InsnNode insn) {
switch(insn.getType()) {
case INVOKE:
InvokeNode inv = (InvokeNode) insn;
return makeNameFromInvoke(inv.getCallMth());
case CONSTRUCTOR:
ConstructorInsn co = (ConstructorInsn) insn;
return makeNameForObject(co.getClassType().getType());
case ARRAY_LENGTH:
return "length";
case ARITH:
case TERNARY:
case CAST:
for (InsnArg arg : insn.getArguments()) {
if (arg.isInsnWrap()) {
InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn();
String wName = makeNameFromInsn(wrapInsn);
if (wName != null) {
return wName;
}
}
}
break;
default:
break;
}
return null;
}
use of jadx.core.dex.instructions.mods.ConstructorInsn 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);
}
Aggregations