use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.
the class FillArrayNode method getLiteralArgs.
public List<LiteralArg> getLiteralArgs() {
List<LiteralArg> list = new ArrayList<LiteralArg>(size);
Object array = data;
if (array instanceof int[]) {
for (int b : (int[]) array) {
list.add(InsnArg.lit(b, elemType));
}
} else if (array instanceof byte[]) {
for (byte b : (byte[]) array) {
list.add(InsnArg.lit(b, elemType));
}
} else if (array instanceof short[]) {
for (short b : (short[]) array) {
list.add(InsnArg.lit(b, elemType));
}
} else if (array instanceof long[]) {
for (long b : (long[]) array) {
list.add(InsnArg.lit(b, elemType));
}
} else {
throw new JadxRuntimeException("Unknown type: " + data.getClass() + ", expected: " + elemType);
}
return list;
}
use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.
the class PostTypeInference method process.
public static boolean process(MethodNode mth, InsnNode insn) {
DexNode dex = mth.dex();
switch(insn.getType()) {
case CONST:
RegisterArg res = insn.getResult();
LiteralArg litArg = (LiteralArg) insn.getArg(0);
if (res.getType().isObject()) {
long lit = litArg.getLiteral();
if (lit != 0) {
// incorrect literal value for object
ArgType type = lit == 1 ? ArgType.BOOLEAN : ArgType.INT;
// can't merge with object -> force it
litArg.setType(type);
res.getSVar().setType(type);
return true;
}
}
return litArg.merge(dex, res);
case MOVE:
{
boolean change = false;
if (insn.getResult().merge(dex, insn.getArg(0))) {
change = true;
}
if (insn.getArg(0).merge(dex, insn.getResult())) {
change = true;
}
return change;
}
case AGET:
return fixArrayTypes(dex, insn.getArg(0), insn.getResult());
case APUT:
return fixArrayTypes(dex, insn.getArg(0), insn.getArg(2));
case IF:
{
boolean change = false;
if (insn.getArg(1).merge(dex, insn.getArg(0))) {
change = true;
}
if (insn.getArg(0).merge(dex, insn.getArg(1))) {
change = true;
}
return change;
}
// check argument types for overloaded methods
case INVOKE:
{
boolean change = false;
InvokeNode inv = (InvokeNode) insn;
MethodInfo callMth = inv.getCallMth();
MethodNode node = mth.dex().resolveMethod(callMth);
if (node != null && node.isArgsOverload()) {
List<ArgType> args = callMth.getArgumentsTypes();
int j = inv.getArgsCount() - 1;
for (int i = args.size() - 1; i >= 0; i--) {
ArgType argType = args.get(i);
InsnArg insnArg = inv.getArg(j--);
if (insnArg.isRegister() && !argType.equals(insnArg.getType())) {
insnArg.setType(argType);
change = true;
}
}
}
return change;
}
case CHECK_CAST:
{
ArgType castType = (ArgType) ((IndexInsnNode) insn).getIndex();
RegisterArg result = insn.getResult();
ArgType resultType = result.getType();
// don't override generic types of same base class
boolean skip = castType.isObject() && resultType.isObject() && castType.getObject().equals(resultType.getObject());
if (!skip) {
// workaround for compiler bug (see TestDuplicateCast)
result.getSVar().setType(castType);
}
return true;
}
case PHI:
case MERGE:
{
ArgType type = insn.getResult().getType();
if (!type.isTypeKnown()) {
for (InsnArg arg : insn.getArguments()) {
if (arg.getType().isTypeKnown()) {
type = arg.getType();
break;
}
}
}
boolean changed = false;
if (updateType(insn.getResult(), type)) {
changed = true;
}
for (int i = 0; i < insn.getArgsCount(); i++) {
RegisterArg arg = (RegisterArg) insn.getArg(i);
if (updateType(arg, type)) {
changed = true;
}
}
return changed;
}
default:
break;
}
return false;
}
use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.
the class InsnGen method makeArithOneArg.
private void makeArithOneArg(ArithNode insn, CodeWriter code) throws CodegenException {
ArithOp op = insn.getOp();
InsnArg arg = insn.getArg(1);
// "++" or "--"
if (arg.isLiteral() && (op == ArithOp.ADD || op == ArithOp.SUB)) {
LiteralArg lit = (LiteralArg) arg;
if (lit.isInteger() && lit.getLiteral() == 1) {
assignVar(code, insn);
String opSymbol = op.getSymbol();
code.add(opSymbol).add(opSymbol);
return;
}
}
// +=, -= ...
assignVar(code, insn);
code.add(' ').add(op.getSymbol()).add("= ");
addArg(code, arg, false);
}
use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.
the class InsnGen method makeInsnBody.
private void makeInsnBody(CodeWriter code, InsnNode insn, Set<Flags> state) throws CodegenException {
switch(insn.getType()) {
case CONST_STR:
String str = ((ConstStringNode) insn).getString();
code.add(mth.dex().root().getStringUtils().unescapeString(str));
break;
case CONST_CLASS:
ArgType clsType = ((ConstClassNode) insn).getClsType();
useType(code, clsType);
code.add(".class");
break;
case CONST:
LiteralArg arg = (LiteralArg) insn.getArg(0);
code.add(lit(arg));
break;
case MOVE:
addArg(code, insn.getArg(0), false);
break;
case CHECK_CAST:
case CAST:
{
boolean wrap = state.contains(Flags.BODY_ONLY);
if (wrap) {
code.add('(');
}
code.add('(');
useType(code, (ArgType) ((IndexInsnNode) insn).getIndex());
code.add(") ");
addArg(code, insn.getArg(0), true);
if (wrap) {
code.add(')');
}
break;
}
case ARITH:
makeArith((ArithNode) insn, code, state);
break;
case NEG:
{
boolean wrap = state.contains(Flags.BODY_ONLY);
if (wrap) {
code.add('(');
}
code.add('-');
addArg(code, insn.getArg(0));
if (wrap) {
code.add(')');
}
break;
}
case RETURN:
if (insn.getArgsCount() != 0) {
code.add("return ");
addArg(code, insn.getArg(0), false);
} else {
code.add("return");
}
break;
case BREAK:
code.add("break");
LoopLabelAttr labelAttr = insn.get(AType.LOOP_LABEL);
if (labelAttr != null) {
code.add(' ').add(mgen.getNameGen().getLoopLabel(labelAttr));
}
break;
case CONTINUE:
code.add("continue");
break;
case THROW:
code.add("throw ");
addArg(code, insn.getArg(0), true);
break;
case CMP_L:
case CMP_G:
code.add('(');
addArg(code, insn.getArg(0));
code.add(" > ");
addArg(code, insn.getArg(1));
code.add(" ? 1 : (");
addArg(code, insn.getArg(0));
code.add(" == ");
addArg(code, insn.getArg(1));
code.add(" ? 0 : -1))");
break;
case INSTANCE_OF:
{
boolean wrap = state.contains(Flags.BODY_ONLY);
if (wrap) {
code.add('(');
}
addArg(code, insn.getArg(0));
code.add(" instanceof ");
useType(code, (ArgType) ((IndexInsnNode) insn).getIndex());
if (wrap) {
code.add(')');
}
break;
}
case CONSTRUCTOR:
makeConstructor((ConstructorInsn) insn, code);
break;
case INVOKE:
makeInvoke((InvokeNode) insn, code);
break;
case NEW_ARRAY:
{
ArgType arrayType = ((NewArrayNode) insn).getArrayType();
code.add("new ");
useType(code, arrayType.getArrayRootElement());
code.add('[');
addArg(code, insn.getArg(0));
code.add(']');
int dim = arrayType.getArrayDimension();
for (int i = 0; i < dim - 1; i++) {
code.add("[]");
}
break;
}
case ARRAY_LENGTH:
addArg(code, insn.getArg(0));
code.add(".length");
break;
case FILLED_NEW_ARRAY:
filledNewArray((FilledNewArrayNode) insn, code);
break;
case AGET:
addArg(code, insn.getArg(0));
code.add('[');
addArg(code, insn.getArg(1), false);
code.add(']');
break;
case APUT:
addArg(code, insn.getArg(0));
code.add('[');
addArg(code, insn.getArg(1), false);
code.add("] = ");
addArg(code, insn.getArg(2), false);
break;
case IGET:
{
FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) insn).getIndex();
instanceField(code, fieldInfo, insn.getArg(0));
break;
}
case IPUT:
{
FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) insn).getIndex();
instanceField(code, fieldInfo, insn.getArg(1));
code.add(" = ");
addArg(code, insn.getArg(0), false);
break;
}
case SGET:
staticField(code, (FieldInfo) ((IndexInsnNode) insn).getIndex());
break;
case SPUT:
FieldInfo field = (FieldInfo) ((IndexInsnNode) insn).getIndex();
staticField(code, field);
code.add(" = ");
addArg(code, insn.getArg(0), false);
break;
case STR_CONCAT:
boolean wrap = state.contains(Flags.BODY_ONLY);
if (wrap) {
code.add('(');
}
for (Iterator<InsnArg> it = insn.getArguments().iterator(); it.hasNext(); ) {
addArg(code, it.next());
if (it.hasNext()) {
code.add(" + ");
}
}
if (wrap) {
code.add(')');
}
break;
case MONITOR_ENTER:
if (isFallback()) {
code.add("monitor-enter(");
addArg(code, insn.getArg(0));
code.add(')');
}
break;
case MONITOR_EXIT:
if (isFallback()) {
code.add("monitor-exit(");
addArg(code, insn.getArg(0));
code.add(')');
}
break;
case TERNARY:
makeTernary((TernaryInsn) insn, code, state);
break;
case ONE_ARG:
addArg(code, insn.getArg(0));
break;
/* fallback mode instructions */
case IF:
fallbackOnlyInsn(insn);
IfNode ifInsn = (IfNode) insn;
code.add("if (");
addArg(code, insn.getArg(0));
code.add(' ');
code.add(ifInsn.getOp().getSymbol()).add(' ');
addArg(code, insn.getArg(1));
code.add(") goto ").add(MethodGen.getLabelName(ifInsn.getTarget()));
break;
case GOTO:
fallbackOnlyInsn(insn);
code.add("goto ").add(MethodGen.getLabelName(((GotoNode) insn).getTarget()));
break;
case MOVE_EXCEPTION:
fallbackOnlyInsn(insn);
code.add("move-exception");
break;
case SWITCH:
fallbackOnlyInsn(insn);
SwitchNode sw = (SwitchNode) insn;
code.add("switch(");
addArg(code, insn.getArg(0));
code.add(") {");
code.incIndent();
for (int i = 0; i < sw.getCasesCount(); i++) {
String key = sw.getKeys()[i].toString();
code.startLine("case ").add(key).add(": goto ");
code.add(MethodGen.getLabelName(sw.getTargets()[i])).add(';');
}
code.startLine("default: goto ");
code.add(MethodGen.getLabelName(sw.getDefaultCaseOffset())).add(';');
code.decIndent();
code.startLine('}');
break;
case FILL_ARRAY:
fallbackOnlyInsn(insn);
FillArrayNode arrayNode = (FillArrayNode) insn;
Object data = arrayNode.getData();
String arrStr;
if (data instanceof int[]) {
arrStr = Arrays.toString((int[]) data);
} else if (data instanceof short[]) {
arrStr = Arrays.toString((short[]) data);
} else if (data instanceof byte[]) {
arrStr = Arrays.toString((byte[]) data);
} else if (data instanceof long[]) {
arrStr = Arrays.toString((long[]) data);
} else {
arrStr = "?";
}
code.add('{').add(arrStr.substring(1, arrStr.length() - 1)).add('}');
break;
case NEW_INSTANCE:
// only fallback - make new instance in constructor invoke
fallbackOnlyInsn(insn);
code.add("new ").add(insn.getResult().getType().toString());
break;
case PHI:
case MERGE:
fallbackOnlyInsn(insn);
code.add(insn.getType().toString()).add("(");
for (InsnArg insnArg : insn.getArguments()) {
addArg(code, insnArg);
code.add(' ');
}
code.add(")");
break;
default:
throw new CodegenException(mth, "Unknown instruction: " + insn.getType());
}
}
use of jadx.core.dex.instructions.args.LiteralArg in project jadx by skylot.
the class ConditionGen method addCompare.
private void addCompare(CodeWriter code, CondStack stack, Compare compare) throws CodegenException {
IfOp op = compare.getOp();
InsnArg firstArg = compare.getA();
InsnArg secondArg = compare.getB();
if (firstArg.getType().equals(ArgType.BOOLEAN) && secondArg.isLiteral() && secondArg.getType().equals(ArgType.BOOLEAN)) {
LiteralArg lit = (LiteralArg) secondArg;
if (lit.getLiteral() == 0) {
op = op.invert();
}
if (op == IfOp.EQ) {
// == true
if (stack.getStack().size() == 1) {
addArg(code, firstArg, false);
} else {
wrap(code, firstArg);
}
return;
} else if (op == IfOp.NE) {
// != true
code.add('!');
wrap(code, firstArg);
return;
}
LOG.warn(ErrorsCounter.formatErrorMsg(mth, "Unsupported boolean condition " + op.getSymbol()));
}
addArg(code, firstArg, isArgWrapNeeded(firstArg));
code.add(' ').add(op.getSymbol()).add(' ');
addArg(code, secondArg, isArgWrapNeeded(secondArg));
}
Aggregations