未验证 提交 c27f2bad 编写于 作者: S Skylot

fix(gui): resolve payload offset for switch insns in debug smali code (#1575)

上级 1a877d65
......@@ -19,10 +19,15 @@ import static org.hamcrest.Matchers.notNullValue;
public abstract class SmaliTest extends IntegrationTest {
private static final String SMALI_TESTS_PROJECT = "jadx-core";
private static final String SMALI_TESTS_DIR = "src/test/smali";
private static final String SMALI_TESTS_EXT = ".smali";
private String currentProject = "jadx-core";
public void setCurrentProject(String currentProject) {
this.currentProject = currentProject;
}
@BeforeEach
public void init() {
Assumptions.assumeFalse(USE_JAVA_INPUT, "skip smali test for java input tests");
......@@ -89,24 +94,24 @@ public abstract class SmaliTest extends IntegrationTest {
.collect(Collectors.toList());
}
private static File getSmaliFile(String baseName) {
private File getSmaliFile(String baseName) {
File smaliFile = new File(SMALI_TESTS_DIR, baseName + SMALI_TESTS_EXT);
if (smaliFile.exists()) {
return smaliFile;
}
File pathFromRoot = new File(SMALI_TESTS_PROJECT, smaliFile.getPath());
File pathFromRoot = new File(currentProject, smaliFile.getPath());
if (pathFromRoot.exists()) {
return pathFromRoot;
}
throw new AssertionError("Smali file not found: " + smaliFile.getPath());
}
private static File getSmaliDir(String baseName) {
private File getSmaliDir(String baseName) {
File smaliDir = new File(SMALI_TESTS_DIR, baseName);
if (smaliDir.exists()) {
return smaliDir;
}
File pathFromRoot = new File(SMALI_TESTS_PROJECT, smaliDir.getPath());
File pathFromRoot = new File(currentProject, smaliDir.getPath());
if (pathFromRoot.exists()) {
return pathFromRoot;
}
......
......@@ -46,6 +46,7 @@ import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.exceptions.JadxRuntimeException;
import static jadx.api.plugins.input.data.AccessFlagsScope.FIELD;
import static jadx.api.plugins.input.data.AccessFlagsScope.METHOD;
......@@ -60,7 +61,9 @@ import static jadx.api.plugins.input.insns.Opcode.INVOKE_CUSTOM;
import static jadx.api.plugins.input.insns.Opcode.INVOKE_CUSTOM_RANGE;
import static jadx.api.plugins.input.insns.Opcode.INVOKE_POLYMORPHIC;
import static jadx.api.plugins.input.insns.Opcode.INVOKE_POLYMORPHIC_RANGE;
import static jadx.api.plugins.input.insns.Opcode.PACKED_SWITCH;
import static jadx.api.plugins.input.insns.Opcode.PACKED_SWITCH_PAYLOAD;
import static jadx.api.plugins.input.insns.Opcode.SPARSE_SWITCH;
import static jadx.api.plugins.input.insns.Opcode.SPARSE_SWITCH_PAYLOAD;
public class Smali {
......@@ -288,6 +291,14 @@ public class Smali {
if (codeReader.getDebugInfo() != null) {
formatDbgInfo(codeReader.getDebugInfo(), line);
}
// first pass to fill payload offsets for switch instructions
codeReader.visitInstructions(insn -> {
Opcode opcode = insn.getOpcode();
if (opcode == PACKED_SWITCH || opcode == SPARSE_SWITCH) {
insn.decode();
line.addPayloadOffset(insn.getOffset(), insn.getTarget());
}
});
codeReader.visitInstructions(insn -> {
InsnNode node = decodeInsn(insn, line);
nodes.put((long) insn.getOffset(), node);
......@@ -404,7 +415,6 @@ public class Smali {
line.addTip(target, String.format(FMT_S_SWITCH_TAG, target), "");
line.getLineWriter().append(", ").append(String.format(FMT_S_SWITCH, target));
}
line.addPayloadOffset(insn.getOffset(), target);
return true;
}
}
......@@ -733,7 +743,7 @@ public class Smali {
ISwitchPayload payload = (ISwitchPayload) insn.getPayload();
if (payload != null) {
fmtSwitchPayload(insn, FMT_P_SWITCH_CASE, FMT_P_SWITCH_CASE_TAG, line, payload, insn.getOffset());
fmtSwitchPayload(insn, FMT_P_SWITCH_CASE, FMT_P_SWITCH_CASE_TAG, line, payload);
}
return true;
}
......@@ -743,7 +753,7 @@ public class Smali {
ISwitchPayload payload = (ISwitchPayload) insn.getPayload();
if (payload != null) {
fmtSwitchPayload(insn, FMT_S_SWITCH_CASE, FMT_S_SWITCH_CASE_TAG, line, payload, insn.getOffset());
fmtSwitchPayload(insn, FMT_S_SWITCH_CASE, FMT_S_SWITCH_CASE_TAG, line, payload);
}
return true;
}
......@@ -755,17 +765,19 @@ public class Smali {
return false;
}
private void fmtSwitchPayload(InsnData insn, String fmtTarget, String fmtTag, LineInfo line,
ISwitchPayload payload, int curOffset) {
private void fmtSwitchPayload(InsnData insn, String fmtTarget, String fmtTag, LineInfo line, ISwitchPayload payload) {
int lineStart = getInsnColStart();
lineStart += CODE_OFFSET_COLUMN_WIDTH + 1 + 1; // plus 1s for space and the ':'
String basicIndent = new String(new byte[lineStart]).replace("\0", " ");
String indent = SmaliWriter.INDENT_STR + basicIndent;
int[] keys = payload.getKeys();
int[] targets = payload.getTargets();
int opcodeOffset = line.payloadOffsetMap.get(curOffset);
Integer switchOffset = line.payloadOffsetMap.get(insn.getOffset());
if (switchOffset == null) {
throw new JadxRuntimeException("Unknown switch insn for payload at " + insn.getOffset());
}
for (int i = 0; i < keys.length; i++) {
int target = opcodeOffset + targets[i];
int target = switchOffset + targets[i];
line.addInsnLine(insn.getOffset(),
String.format("%scase %d: -> " + fmtTarget, indent, keys[i], target));
line.addTip(target,
......
package jadx.gui.device.debugger.smali;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;
class DbgSmaliTest extends SmaliTest {
private static final Logger LOG = LoggerFactory.getLogger(DbgSmaliTest.class);
@BeforeEach
public void initProject() {
setCurrentProject("jadx-gui");
}
@Test
void test() {
disableCompilation();
ClassNode cls = getClassNodeFromSmali("switch", "SwitchTest");
Smali disasm = Smali.disassemble(cls);
LOG.debug("{}", disasm.getCode());
}
}
.class public final LSwitchTest;
.super Ljava/lang/Object;
.field public static final synthetic a:LSwitchTest;
.field public static final synthetic b:LSwitchTest;
.field private final synthetic c:I
.method public final test(Ljava/lang/Runnable;)Ljava/lang/Thread;
.registers 4
const v0, 0xa
const v1, 0xa
add-int v0, v0, v1
rem-int v0, v0, v1
if-gtz v0, :cond_f
goto/32 :goto_d2
:cond_f
:goto_f
goto/32 :goto_bf
:goto_18
const-string v1, "A"
goto/32 :goto_68
:goto_26
const-string v1, "B"
goto/32 :goto_7c
:goto_33
return-object v0
:pswitch_38
goto/32 :goto_4e
:goto_41
new-instance v0, Labo;
goto/32 :goto_84
:goto_4e
new-instance v0, Lwf;
goto/32 :goto_ab
:goto_5b
new-instance v0, Ljava/lang/Thread;
goto/32 :goto_18
:goto_68
invoke-direct {v0, p1, v1}, Ljava/lang/Thread;-><init>(Ljava/lang/Runnable;Ljava/lang/String;)V
goto/32 :goto_71
:goto_71
return-object v0
:pswitch_75
goto/32 :goto_b3
:goto_7c
invoke-direct {v0, p1, v1}, Ljava/lang/Thread;-><init>(Ljava/lang/Runnable;Ljava/lang/String;)V
goto/32 :goto_33
:goto_84
invoke-direct {v0, p1}, Labo;-><init>(Ljava/lang/Runnable;)V
goto/32 :goto_90
:goto_90
return-object v0
:pswitch_data_96
.packed-switch 0x0
:pswitch_a3
:pswitch_38
:pswitch_75
.end packed-switch
:goto_a0
return-object v0
:pswitch_a3
goto/32 :goto_41
:goto_ab
invoke-direct {v0, p1}, Lwf;-><init>(Ljava/lang/Runnable;)V
goto/32 :goto_a0
:goto_b3
new-instance v0, Ljava/lang/Thread;
goto/32 :goto_26
:goto_bf
iget v0, p0, LSwitchTest;->c:I
packed-switch v0, :pswitch_data_96
goto/32 :goto_5b
:goto_d2
goto/32 :goto_f
.end method
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册