fix: correct arg replace in PHI instruction (#462)
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
package jadx.core.dex.instructions;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
@@ -17,11 +18,12 @@ import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
public final class PhiInsn extends InsnNode {
|
||||
|
||||
private final Map<RegisterArg, BlockNode> blockBinds;
|
||||
// map arguments to blocks (in same order as in arguments list)
|
||||
private final List<BlockNode> blockBinds;
|
||||
|
||||
public PhiInsn(int regNum, int predecessors) {
|
||||
super(InsnType.PHI, predecessors);
|
||||
this.blockBinds = new LinkedHashMap<>(predecessors);
|
||||
this.blockBinds = new ArrayList<>(predecessors);
|
||||
setResult(InsnArg.reg(regNum, ArgType.UNKNOWN));
|
||||
add(AFlag.DONT_INLINE);
|
||||
add(AFlag.DONT_GENERATE);
|
||||
@@ -34,19 +36,24 @@ public final class PhiInsn extends InsnNode {
|
||||
}
|
||||
|
||||
public void bindArg(RegisterArg arg, BlockNode pred) {
|
||||
if (blockBinds.containsValue(pred)) {
|
||||
if (blockBinds.contains(pred)) {
|
||||
throw new JadxRuntimeException("Duplicate predecessors in PHI insn: " + pred + ", " + this);
|
||||
}
|
||||
addArg(arg);
|
||||
blockBinds.put(arg, pred);
|
||||
super.addArg(arg);
|
||||
blockBinds.add(pred);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BlockNode getBlockByArg(RegisterArg arg) {
|
||||
return blockBinds.get(arg);
|
||||
int index = getArgIndex(arg);
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
return blockBinds.get(index);
|
||||
}
|
||||
|
||||
public Map<RegisterArg, BlockNode> getBlockBinds() {
|
||||
return blockBinds;
|
||||
public BlockNode getBlockByArgIndex(int argIndex) {
|
||||
return blockBinds.get(argIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -57,17 +64,20 @@ public final class PhiInsn extends InsnNode {
|
||||
|
||||
@Override
|
||||
public boolean removeArg(InsnArg arg) {
|
||||
if (!(arg instanceof RegisterArg)) {
|
||||
int index = getArgIndex(arg);
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
RegisterArg reg = (RegisterArg) arg;
|
||||
if (super.removeArg(reg)) {
|
||||
blockBinds.remove(reg);
|
||||
reg.getSVar().removeUse(reg);
|
||||
InsnRemover.fixUsedInPhiFlag(reg);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
removeArg(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RegisterArg removeArg(int index) {
|
||||
RegisterArg reg = (RegisterArg) super.removeArg(index);
|
||||
blockBinds.remove(index);
|
||||
InsnRemover.fixUsedInPhiFlag(reg);
|
||||
return reg;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,21 +85,31 @@ public final class PhiInsn extends InsnNode {
|
||||
if (!(from instanceof RegisterArg) || !(to instanceof RegisterArg)) {
|
||||
return false;
|
||||
}
|
||||
BlockNode pred = getBlockByArg((RegisterArg) from);
|
||||
|
||||
int argIndex = getArgIndex(from);
|
||||
if (argIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
BlockNode pred = getBlockByArgIndex(argIndex);
|
||||
if (pred == null) {
|
||||
throw new JadxRuntimeException("Unknown predecessor block by arg " + from + " in PHI: " + this);
|
||||
}
|
||||
if (removeArg(from)) {
|
||||
RegisterArg reg = (RegisterArg) to;
|
||||
bindArg(reg, pred);
|
||||
reg.getSVar().setUsedInPhi(this);
|
||||
}
|
||||
removeArg(argIndex);
|
||||
|
||||
RegisterArg reg = (RegisterArg) to;
|
||||
bindArg(reg, pred);
|
||||
reg.getSVar().setUsedInPhi(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addArg(InsnArg arg) {
|
||||
throw new JadxRuntimeException("Direct addArg is forbidden for PHI insn, bindArg must be used");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setArg(int n, InsnArg arg) {
|
||||
throw new JadxRuntimeException("Unsupported operation for PHI node");
|
||||
throw new JadxRuntimeException("Direct setArg is forbidden for PHI insn, bindArg must be used");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -139,15 +139,29 @@ public class InsnNode extends LineAttrNode {
|
||||
}
|
||||
|
||||
protected boolean removeArg(InsnArg arg) {
|
||||
int index = getArgIndex(arg);
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
removeArg(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected InsnArg removeArg(int index) {
|
||||
InsnArg arg = arguments.get(index);
|
||||
arguments.remove(index);
|
||||
InsnRemover.unbindArgUsage(null, arg);
|
||||
return arg;
|
||||
}
|
||||
|
||||
protected int getArgIndex(InsnArg arg) {
|
||||
int count = getArgsCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (arg == arguments.get(i)) {
|
||||
arguments.remove(i);
|
||||
InsnRemover.unbindArgUsage(null, arg);
|
||||
return true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected void addReg(DecodedInstruction insn, int i, ArgType type) {
|
||||
|
||||
+5
-4
@@ -3,7 +3,6 @@ package jadx.core.dex.visitors.typeinference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@@ -318,10 +317,12 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (Map.Entry<RegisterArg, BlockNode> entry : phiInsn.getBlockBinds().entrySet()) {
|
||||
RegisterArg reg = entry.getKey();
|
||||
|
||||
int argsCount = phiInsn.getArgsCount();
|
||||
for (int argIndex = 0; argIndex < argsCount; argIndex++) {
|
||||
RegisterArg reg = phiInsn.getArg(argIndex);
|
||||
if (reg.getSVar() == var) {
|
||||
BlockNode blockNode = entry.getValue();
|
||||
BlockNode blockNode = phiInsn.getBlockByArgIndex(argIndex);
|
||||
InsnNode lastInsn = BlockUtils.getLastInsn(blockNode);
|
||||
if (lastInsn != null && BlockSplitter.makeSeparate(lastInsn.getType())) {
|
||||
if (Consts.DEBUG) {
|
||||
|
||||
@@ -162,9 +162,6 @@ public class DebugUtils {
|
||||
if (insn.getType() == InsnType.PHI) {
|
||||
PhiInsn phi = (PhiInsn) insn;
|
||||
phis.add(phi);
|
||||
if (phi.getArgsCount() != phi.getBlockBinds().size()) {
|
||||
throw new JadxRuntimeException("Incorrect args and binds in PHI");
|
||||
}
|
||||
if (phi.getArgsCount() == 0) {
|
||||
throw new JadxRuntimeException("No args and binds in PHI");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user