diff --git a/jadx-gui/src/main/java/jadx/gui/device/debugger/SmaliDebugger.java b/jadx-gui/src/main/java/jadx/gui/device/debugger/SmaliDebugger.java index a07063f8adc6e5df7b07ce26e0c8c55368e39f76..9f529465aa26c565c5f96d245a7e985c406b5c37 100644 --- a/jadx-gui/src/main/java/jadx/gui/device/debugger/SmaliDebugger.java +++ b/jadx-gui/src/main/java/jadx/gui/device/debugger/SmaliDebugger.java @@ -1286,7 +1286,10 @@ public class SmaliDebugger { @Override public String getType() { String gen = getSignature(); - return gen.isEmpty() ? this.slot.signature : gen; + if (gen == null || gen.isEmpty()) { + return this.slot.signature; + } + return gen; } @NonNull @@ -1304,6 +1307,11 @@ public class SmaliDebugger { public int getEndOffset() { return (int) (slot.codeIndex + slot.length); } + + @Override + public boolean isMarkedAsParameter() { + return false; + } } public static class RuntimeDebugInfo { diff --git a/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/Smali.java b/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/Smali.java index 1d606e438fb5201efbeb48af5628a440ef8a5acb..f3a1103d6d1f5aa0bbfb9e7dd572934b89346a75 100644 --- a/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/Smali.java +++ b/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/Smali.java @@ -285,24 +285,25 @@ public class Smali { writeMethodDef(smali, mth, line); ICodeReader codeReader = mth.getCodeReader(); if (codeReader != null) { + int regsCount = codeReader.getRegistersCount(); line.smaliMthNode.setParamRegStart(getParamStartRegNum(mth)); - line.smaliMthNode.setRegCount(codeReader.getRegistersCount()); + line.smaliMthNode.setRegCount(regsCount); Map nodes = new HashMap<>(codeReader.getUnitsCount() / 2); line.smaliMthNode.setInsnNodes(nodes, codeReader.getUnitsCount()); - line.smaliMthNode.initRegInfoList(codeReader.getRegistersCount(), codeReader.getUnitsCount()); + line.smaliMthNode.initRegInfoList(regsCount, codeReader.getUnitsCount()); smali.incIndent(); - smali.startLine(".registers ") - .add("" + codeReader.getRegistersCount()) - .startLine(); + smali.startLine(".registers ").add(Integer.toString(regsCount)); + writeTries(codeReader, line); - if (formatMthParamInfo(mth, smali, codeReader, line)) { - smali.startLine(); + IDebugInfo debugInfo = codeReader.getDebugInfo(); + List localVars = debugInfo != null ? debugInfo.getLocalVars() : Collections.emptyList(); + formatMthParamInfo(mth, smali, line, regsCount, localVars); + if (debugInfo != null) { + formatDbgInfo(debugInfo, localVars, line); } + smali.newLine(); smali.startLine(); - if (codeReader.getDebugInfo() != null) { - formatDbgInfo(codeReader.getDebugInfo(), line); - } // first pass to fill payload offsets for switch instructions codeReader.visitInstructions(insn -> { Opcode opcode = insn.getOpcode(); @@ -458,20 +459,11 @@ public class Smali { } } - private boolean formatMthParamInfo(IMethodData mth, SmaliWriter smali, ICodeReader codeReader, LineInfo line) { + private void formatMthParamInfo(IMethodData mth, SmaliWriter smali, LineInfo line, + int regsCount, List localVars) { List types = mth.getMethodRef().getArgTypes(); if (types.isEmpty()) { - return false; - } - ILocalVar[] params = new ILocalVar[codeReader.getRegistersCount()]; - IDebugInfo dbgInfo = codeReader.getDebugInfo(); - if (dbgInfo != null) { - for (ILocalVar var : dbgInfo.getLocalVars()) { - // collect only method parameters - if (var.getStartOffset() <= 0) { - params[var.getRegNum()] = var; - } - } + return; } int paramStart = 0; int regNum = line.smaliMthNode.getParamRegStart(); @@ -482,26 +474,30 @@ public class Smali { regNum++; paramStart++; } + if (localVars.isEmpty()) { + return; + } + ILocalVar[] params = new ILocalVar[regsCount]; + for (ILocalVar var : localVars) { + if (var.isMarkedAsParameter()) { + params[var.getRegNum()] = var; + } + } + smali.newLine(); for (String paramType : types) { - String name; - String type; ILocalVar param = params[regNum]; if (param != null) { - name = Utils.getOrElse(param.getName(), ""); - type = Utils.getOrElse(param.getSignature(), paramType); - } else { - name = ""; - type = paramType; + String name = Utils.getOrElse(param.getName(), ""); + String type = Utils.getOrElse(param.getSignature(), paramType); + String varName = "p" + paramStart; + smali.startLine(String.format(".param %s, \"%s\" # %s", varName, name, type)); + line.addRegName(regNum, varName); + line.smaliMthNode.setParamReg(regNum, varName); } - String varName = "p" + paramStart; - smali.startLine(String.format(".param %s, \"%s\" # %s", varName, name, type)); - line.addRegName(regNum, varName); - line.smaliMthNode.setParamReg(regNum, varName); int regSize = isWideType(paramType) ? 2 : 1; regNum += regSize; paramStart += regSize; } - return true; } private static int getParamStartRegNum(IMethodData mth) { @@ -558,30 +554,42 @@ public class Smali { smali.startLine(".end annotation"); } - private void formatDbgInfo(IDebugInfo dbgInfo, LineInfo line) { + private void formatDbgInfo(IDebugInfo dbgInfo, List localVars, LineInfo line) { dbgInfo.getSourceLineMapping().forEach((codeOffset, srcLine) -> { if (codeOffset > -1) { line.addDebugLineTip(codeOffset, String.format(".line %d", srcLine), ""); } }); - for (ILocalVar localVar : dbgInfo.getLocalVars()) { - String type = localVar.getSignature(); - if (type == null || type.trim().isEmpty()) { - type = localVar.getType(); - } - if (localVar.getStartOffset() > -1) { - line.addTip( - localVar.getStartOffset(), - String.format(".local v%d", localVar.getRegNum()), - String.format(", \"%s\":%s", localVar.getName(), type)); + for (ILocalVar localVar : localVars) { + if (localVar.isMarkedAsParameter()) { + continue; } - if (localVar.getEndOffset() > -1) { - line.addTip( - localVar.getEndOffset(), - String.format(".end local v%d", localVar.getRegNum()), - String.format(" # \"%s\":%s", localVar.getName(), type)); + String type = localVar.getType(); + String sign = localVar.getSignature(); + String longTypeStr; + if (sign == null || sign.trim().isEmpty()) { + longTypeStr = String.format(", \"%s\":%s", localVar.getName(), type); + } else { + longTypeStr = String.format(", \"%s\":%s, \"%s\"", localVar.getName(), type, localVar.getSignature()); } + line.addTip( + localVar.getStartOffset(), + ".local " + formatVarName(line.smaliMthNode, localVar), + longTypeStr); + line.addTip( + localVar.getEndOffset(), + ".end local " + formatVarName(line.smaliMthNode, localVar), + String.format(" # \"%s\":%s", localVar.getName(), type)); + } + } + + private String formatVarName(SmaliMethodNode smaliMthNode, ILocalVar localVar) { + int paramRegStart = smaliMthNode.getParamRegStart(); + int regNum = localVar.getRegNum(); + if (regNum < paramRegStart) { + return "v" + regNum; } + return "p" + (regNum - paramRegStart); } private void writeEncodedValue(SmaliWriter smali, EncodedValue value, boolean wrapArray) { diff --git a/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/SmaliMethodNode.java b/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/SmaliMethodNode.java index f0e287d105633efb992ad768104a4b9e430c061b..4a9f4c618a8cf5c7aab127057612a9d62fede5d3 100644 --- a/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/SmaliMethodNode.java +++ b/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/SmaliMethodNode.java @@ -94,7 +94,6 @@ class SmaliMethodNode { protected void setParamReg(int regNum, String name) { SmaliRegister r = regList.get(regNum); r.setParam(name); - r.setStartOffset(-1); } protected void setParamRegStart(int paramRegStart) { diff --git a/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/SmaliRegister.java b/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/SmaliRegister.java index 59097938b9faf7c29fc7ac83fcf86ee3982c0547..31ff7e38cb379dc006c1ba94743b8b4d4339d73d 100644 --- a/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/SmaliRegister.java +++ b/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/SmaliRegister.java @@ -33,10 +33,6 @@ public class SmaliRegister extends RegisterInfo { } protected void setStartOffset(int off) { - if (startOffset == -1 && !isParam) { - startOffset = off; - return; - } if (off < startOffset) { startOffset = off; } @@ -71,4 +67,9 @@ public class SmaliRegister extends RegisterInfo { public int getEndOffset() { return endOffset; } + + @Override + public boolean isMarkedAsParameter() { + return isParam; + } } diff --git a/jadx-gui/src/test/java/jadx/gui/device/debugger/smali/DbgSmaliTest.java b/jadx-gui/src/test/java/jadx/gui/device/debugger/smali/DbgSmaliTest.java index 43e6c54237f87d07c0966a4af1175d98566c340d..60c9ea1b5402a2305ab55daa4a2d1dea8d3aeb8c 100644 --- a/jadx-gui/src/test/java/jadx/gui/device/debugger/smali/DbgSmaliTest.java +++ b/jadx-gui/src/test/java/jadx/gui/device/debugger/smali/DbgSmaliTest.java @@ -33,6 +33,9 @@ class DbgSmaliTest extends SmaliTest { Smali disasm = Smali.disassemble(cls); String code = disasm.getCode(); LOG.debug("{}", code); - assertThat(code).doesNotContain("Failed to write method"); + assertThat(code) + .doesNotContain("Failed to write method") + .doesNotContain(".param p1") + .contains(".local p1, \"arg0\":Landroid/widget/AdapterView;, \"Landroid/widget/AdapterView<*>;\""); } } diff --git a/jadx-plugins/jadx-dex-input/src/main/java/jadx/plugins/input/dex/sections/debuginfo/DebugInfoParser.java b/jadx-plugins/jadx-dex-input/src/main/java/jadx/plugins/input/dex/sections/debuginfo/DebugInfoParser.java index fada61ab365be5e39f3585c8f8dd011f816cd503..adee2f08053422a1fb7dc54da220aa574f2e37e0 100644 --- a/jadx-plugins/jadx-dex-input/src/main/java/jadx/plugins/input/dex/sections/debuginfo/DebugInfoParser.java +++ b/jadx-plugins/jadx-dex-input/src/main/java/jadx/plugins/input/dex/sections/debuginfo/DebugInfoParser.java @@ -96,8 +96,9 @@ public class DebugInfoParser { int nameId = in.readUleb128p1(); String name = ext.getString(nameId); if (name != null && i < argsCount) { - int regNum = argRegs[i]; - startVar(new DexLocalVar(regNum, name, argTypes.get(i)), -1); + DexLocalVar paramVar = new DexLocalVar(argRegs[i], name, argTypes.get(i)); + startVar(paramVar, addr); + paramVar.markAsParameter(); varsInfoFound = true; } } diff --git a/jadx-plugins/jadx-dex-input/src/main/java/jadx/plugins/input/dex/sections/debuginfo/DexLocalVar.java b/jadx-plugins/jadx-dex-input/src/main/java/jadx/plugins/input/dex/sections/debuginfo/DexLocalVar.java index 4458fc249a264e0400a6f5eb0ee47cca8979999c..2a5efe64e81891b7f5aca880bfc8c54dd1e60226 100644 --- a/jadx-plugins/jadx-dex-input/src/main/java/jadx/plugins/input/dex/sections/debuginfo/DexLocalVar.java +++ b/jadx-plugins/jadx-dex-input/src/main/java/jadx/plugins/input/dex/sections/debuginfo/DexLocalVar.java @@ -7,6 +7,8 @@ import jadx.api.plugins.utils.Utils; import jadx.plugins.input.dex.sections.SectionReader; public class DexLocalVar implements ILocalVar { + private static final int PARAM_START_OFFSET = -1; + private final int regNum; private final String name; private final String type; @@ -78,6 +80,15 @@ public class DexLocalVar implements ILocalVar { return startOffset; } + public void markAsParameter() { + startOffset = PARAM_START_OFFSET; + } + + @Override + public boolean isMarkedAsParameter() { + return startOffset == PARAM_START_OFFSET; + } + @Override public int getEndOffset() { return endOffset; diff --git a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/debuginfo/JavaLocalVar.java b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/debuginfo/JavaLocalVar.java index 6edaf5d3723860a9d37a85d5d9bf357532be09b8..864e96c5b4b0dcc5f675fa7438f7f519cb4cee24 100644 --- a/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/debuginfo/JavaLocalVar.java +++ b/jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/debuginfo/JavaLocalVar.java @@ -61,6 +61,11 @@ public class JavaLocalVar implements ILocalVar { return endOffset; } + @Override + public boolean isMarkedAsParameter() { + return false; + } + @Override public int hashCode() { int result = regNum; diff --git a/jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/ILocalVar.java b/jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/ILocalVar.java index 24a52b283eacafa288596e22c45e9ae3760832de..3e68013e02c89368c260f9b7a259a59da4f72fe1 100644 --- a/jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/ILocalVar.java +++ b/jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/ILocalVar.java @@ -15,4 +15,10 @@ public interface ILocalVar { int getStartOffset(); int getEndOffset(); + + /** + * Hint if variable is a method parameter. + * Can be incorrect and shouldn't be trusted. + */ + boolean isMarkedAsParameter(); }