Skip to content

Commit

Permalink
fix(gui): improve smali disasm method param write (#1739)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Dec 13, 2022
1 parent e3fdbaf commit 0fafcfa
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 36 deletions.
79 changes: 44 additions & 35 deletions jadx-gui/src/main/java/jadx/gui/device/debugger/smali/Smali.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jadx.api.ICodeInfo;
import jadx.api.plugins.input.data.AccessFlags;
Expand Down Expand Up @@ -46,6 +48,7 @@
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException;

import static jadx.api.plugins.input.data.AccessFlagsScope.FIELD;
Expand All @@ -67,6 +70,7 @@
import static jadx.api.plugins.input.insns.Opcode.SPARSE_SWITCH_PAYLOAD;

public class Smali {
private static final Logger LOG = LoggerFactory.getLogger(Smali.class);

private static SmaliInsnDecoder insnDecoder = null;

Expand Down Expand Up @@ -219,7 +223,15 @@ private void writeClass(SmaliWriter smali, ClassNode cls) {
writeFields(smali, clsData, fields, colWidths);
fields.clear();
}
writeMethod(smali, cls.getMethods().get(mthIndex[0]++), m, line);
try {
writeMethod(smali, cls.getMethods().get(mthIndex[0]++), m, line);
} catch (Throwable e) {
IMethodRef methodRef = m.getMethodRef();
String mthFullName = methodRef.getParentClassType() + "->" + methodRef.getName();
smali.setIndent(0);
smali.startLine("Failed to write method: " + mthFullName + "\n" + Utils.getStackTrace(e));
LOG.error("Failed to write smali code for method: {}", mthFullName, e);
}
line.reset();
});

Expand Down Expand Up @@ -451,48 +463,45 @@ private boolean formatMthParamInfo(IMethodData mth, SmaliWriter smali, ICodeRead
if (types.isEmpty()) {
return false;
}
int paramCount = 0;
int paramStart = 0;
int regNum = line.smaliMthNode.getParamRegStart();
if (!hasStaticFlag(mth.getAccessFlags())) {
line.addRegName(regNum, "p0");
line.smaliMthNode.setParamReg(regNum, "p0");
regNum += 1;
paramStart = 1;
}
ILocalVar[] params = new ILocalVar[codeReader.getRegistersCount()];
IDebugInfo dbgInfo = codeReader.getDebugInfo();
if (dbgInfo != null) {
for (ILocalVar var : dbgInfo.getLocalVars()) {
if (var.getRegNum() == regNum) {
int i = writeParamInfo(smali, line, regNum, paramStart, var.getName(), var.getType());
regNum += i;
paramStart += i;
paramCount++;
// collect only method parameters
if (var.getStartOffset() <= 0) {
params[var.getRegNum()] = var;
}
}
}
for (; paramCount < types.size(); paramCount++) {
int i = writeParamInfo(smali, line, regNum, paramStart, "", types.get(paramCount));
regNum += i;
paramStart += i;
}
return true;
}

private static int writeParamInfo(SmaliWriter smali, LineInfo line,
int regNum, int paramNum, String dbgInfoName, String type) {
smali.startLine(String.format(".param p%d, \"%s\":%s", paramNum, dbgInfoName, type));
String pName = "p" + paramNum;
line.addRegName(regNum, pName);
line.smaliMthNode.setParamReg(regNum, pName);
if (isWideType(type)) {
int paramStart = 0;
int regNum = line.smaliMthNode.getParamRegStart();
if (!hasStaticFlag(mth.getAccessFlags())) {
// add 'this' register
line.addRegName(regNum, "p0");
line.smaliMthNode.setParamReg(regNum, "p0");
regNum++;
dbgInfoName = "p" + (paramNum + 1);
line.addRegName(regNum, dbgInfoName);
line.smaliMthNode.setParamReg(regNum, dbgInfoName);
return 2;
paramStart++;
}
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 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 1;
return true;
}

private static int getParamStartRegNum(IMethodData mth) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;

import static org.assertj.core.api.Assertions.assertThat;

class DbgSmaliTest extends SmaliTest {
private static final Logger LOG = LoggerFactory.getLogger(DbgSmaliTest.class);

Expand All @@ -17,10 +19,20 @@ public void initProject() {
}

@Test
void test() {
void testSwitch() {
disableCompilation();
ClassNode cls = getClassNodeFromSmali("switch", "SwitchTest");
Smali disasm = Smali.disassemble(cls);
LOG.debug("{}", disasm.getCode());
}

@Test
void testParams() {
disableCompilation();
ClassNode cls = getClassNodeFromSmali("params", "ParamsTest");
Smali disasm = Smali.disassemble(cls);
String code = disasm.getCode();
LOG.debug("{}", code);
assertThat(code).doesNotContain("Failed to write method");
}
}
58 changes: 58 additions & 0 deletions jadx-gui/src/test/smali/params.smali
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
.class LParamsTest;
.super Ljava/lang/Object;

.method public test(Landroid/widget/AdapterView;Landroid/view/View;IJ)V
.registers 10
.param p2, "arg1" # Landroid/view/View;
.param p3, "arg2" # I
.param p4, "arg3" # J
.annotation system Ldalvik/annotation/Signature;
value = {
"(",
"Landroid/widget/AdapterView",
"<*>;",
"Landroid/view/View;",
"IJ)V"
}
.end annotation

.prologue
.line 69
.local p1, "arg0":Landroid/widget/AdapterView;, "Landroid/widget/AdapterView<*>;"
iget-object v2, p0, LParamsTest;->this$0:Ltest/ColorListActivity;

.line 72
iget-object v2, v2, Ltest/ColorListActivity;->mSortedColorList:[Ljava/lang/String;

.line 75
aget-object v0, v2, p3

.line 80
.local v0, "colorString":Ljava/lang/String;
new-instance v1, Landroid/content/Intent;

.line 83
iget-object v2, p0, LParamsTest;->this$0:Ltest/ColorListActivity;

.line 86
const-class v3, Ltest/ColorItemActivity;

.line 89
invoke-direct {v1, v2, v3}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V

.line 94
.local v1, "intent":Landroid/content/Intent;
const-string v2, "colorString"

.line 97
invoke-virtual {v1, v2, v0}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;

.line 101
iget-object v2, p0, LParamsTest;->this$0:Ltest/ColorListActivity;

.line 104
invoke-virtual {v2, v1}, Ltest/ColorListActivity;->startActivity(Landroid/content/Intent;)V

.line 108
return-void
.end method

0 comments on commit 0fafcfa

Please sign in to comment.