private static void merge(InsnArg arg, LocalVar var) { if (arg != null && arg.isRegister()) { RegisterArg reg = (RegisterArg) arg; if (var.getRegNum() == reg.getRegNum()) { reg.mergeDebugInfo(var.getType(), var.getName()); } } }
private static void renameVar(MethodNode mth, SSAVar[] vars, int[] vers, BlockNode block) { SSAVar[] inputVars = Arrays.copyOf(vars, vars.length); for (InsnNode insn : block.getInstructions()) { if (insn.getType() != InsnType.PHI) { for (InsnArg arg : insn.getArguments()) { if (!arg.isRegister()) { continue; } RegisterArg reg = (RegisterArg) arg; int regNum = reg.getRegNum(); SSAVar var = vars[regNum]; if (var == null) { throw new JadxRuntimeException( "Not initialized variable reg: " + regNum + ", insn: " + insn + ", block:" + block + ", method: " + mth); } var.use(reg); } } RegisterArg result = insn.getResult(); if (result != null) { int regNum = result.getRegNum(); vars[regNum] = mth.makeNewSVar(regNum, vers, result); } } for (BlockNode s : block.getSuccessors()) { PhiListAttr phiList = s.get(AType.PHI_LIST); if (phiList == null) { continue; } int j = s.getPredecessors().indexOf(block); if (j == -1) { throw new JadxRuntimeException("Can't find predecessor for " + block + " " + s); } for (PhiInsn phiInsn : phiList.getList()) { if (j >= phiInsn.getArgsCount()) { continue; } int regNum = phiInsn.getResult().getRegNum(); SSAVar var = vars[regNum]; if (var == null) { continue; } var.use(phiInsn.getArg(j)); var.setUsedInPhi(phiInsn); } } for (BlockNode domOn : block.getDominatesOn()) { renameVar(mth, vars, vers, domOn); } System.arraycopy(inputVars, 0, vars, 0, vars.length); }
private static void renameVariables(MethodNode mth) { int regsCount = mth.getRegsCount(); SSAVar[] vars = new SSAVar[regsCount]; int[] versions = new int[regsCount]; // init method arguments for (RegisterArg arg : mth.getArguments(true)) { int regNum = arg.getRegNum(); vars[regNum] = mth.makeNewSVar(regNum, versions, arg); } renameVar(mth, vars, versions, mth.getEnterBlock()); }
private static void fixLastTryCatchAssign(MethodNode mth) { for (BlockNode block : mth.getBasicBlocks()) { PhiListAttr phiList = block.get(AType.PHI_LIST); if (phiList == null || !block.contains(AType.EXC_HANDLER)) { continue; } for (PhiInsn phi : phiList.getList()) { for (int i = 0; i < phi.getArgsCount(); i++) { RegisterArg arg = phi.getArg(i); InsnNode parentInsn = arg.getAssignInsn(); if (parentInsn != null && parentInsn.getResult() != null && parentInsn.contains(AFlag.TRY_LEAVE)) { phi.removeArg(arg); } } } } }
private int addrChange(int addr, int addrInc, int line) { int newAddr = addr + addrInc; for (int i = addr + 1; i <= newAddr; i++) { InsnNode insn = insnByOffset[i]; if (insn == null) { continue; } for (InsnArg arg : insn.getArguments()) { if (arg.isRegister()) { activeRegisters[((RegisterArg) arg).getRegNum()] = arg; } } RegisterArg res = insn.getResult(); if (res != null) { activeRegisters[res.getRegNum()] = res; } } setSourceLines(addr, newAddr, line); return newAddr; }
public void process() throws DecodeException { int addr = 0; int line = section.readUleb128(); int paramsCount = section.readUleb128(); List<RegisterArg> mthArgs = mth.getArguments(false); assert paramsCount == mthArgs.size(); for (int i = 0; i < paramsCount; i++) { int id = section.readUleb128() - 1; if (id != DexNode.NO_INDEX) { String name = dex.getString(id); mthArgs.get(i).setName(name); } } for (RegisterArg arg : mthArgs) { int rn = arg.getRegNum(); locals[rn] = new LocalVar(arg); activeRegisters[rn] = arg; } // process '0' instruction addrChange(-1, 1, line); setLine(addr, line); int c = section.readByte() & 0xFF; while (c != DBG_END_SEQUENCE) { switch (c) { case DBG_ADVANCE_PC: { int addrInc = section.readUleb128(); addr = addrChange(addr, addrInc, line); setLine(addr, line); break; } case DBG_ADVANCE_LINE: { line += section.readSleb128(); break; } case DBG_START_LOCAL: { int regNum = section.readUleb128(); int nameId = section.readUleb128() - 1; int type = section.readUleb128() - 1; LocalVar var = new LocalVar(dex, regNum, nameId, type, DexNode.NO_INDEX); startVar(var, addr, line); break; } case DBG_START_LOCAL_EXTENDED: { int regNum = section.readUleb128(); int nameId = section.readUleb128() - 1; int type = section.readUleb128() - 1; int sign = section.readUleb128() - 1; LocalVar var = new LocalVar(dex, regNum, nameId, type, sign); startVar(var, addr, line); break; } case DBG_RESTART_LOCAL: { int regNum = section.readUleb128(); LocalVar var = locals[regNum]; if (var != null) { var.end(addr, line); setVar(var); var.start(addr, line); } break; } case DBG_END_LOCAL: { int regNum = section.readUleb128(); LocalVar var = locals[regNum]; if (var != null) { var.end(addr, line); setVar(var); } break; } case DBG_SET_PROLOGUE_END: case DBG_SET_EPILOGUE_BEGIN: // do nothing break; case DBG_SET_FILE: { int idx = section.readUleb128() - 1; if (idx != DexNode.NO_INDEX) { String sourceFile = dex.getString(idx); mth.addAttr(new SourceFileAttr(sourceFile)); } break; } default: { if (c >= DBG_FIRST_SPECIAL) { int adjustedOpcode = c - DBG_FIRST_SPECIAL; int addrInc = adjustedOpcode / DBG_LINE_RANGE; addr = addrChange(addr, addrInc, line); line += DBG_LINE_BASE + (adjustedOpcode % DBG_LINE_RANGE); setLine(addr, line); } else { throw new DecodeException("Unknown debug insn code: " + c); } break; } } c = section.readByte() & 0xFF; } for (LocalVar var : locals) { if (var != null && !var.isEnd()) { var.end(addr, line); setVar(var); } } setSourceLines(addr, insnByOffset.length, line); }