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

fix(gui): make `bytecode` output closer to smali (#1739)

上级 5d186e56
...@@ -1286,7 +1286,10 @@ public class SmaliDebugger { ...@@ -1286,7 +1286,10 @@ public class SmaliDebugger {
@Override @Override
public String getType() { public String getType() {
String gen = getSignature(); String gen = getSignature();
return gen.isEmpty() ? this.slot.signature : gen; if (gen == null || gen.isEmpty()) {
return this.slot.signature;
}
return gen;
} }
@NonNull @NonNull
...@@ -1304,6 +1307,11 @@ public class SmaliDebugger { ...@@ -1304,6 +1307,11 @@ public class SmaliDebugger {
public int getEndOffset() { public int getEndOffset() {
return (int) (slot.codeIndex + slot.length); return (int) (slot.codeIndex + slot.length);
} }
@Override
public boolean isMarkedAsParameter() {
return false;
}
} }
public static class RuntimeDebugInfo { public static class RuntimeDebugInfo {
......
...@@ -285,24 +285,25 @@ public class Smali { ...@@ -285,24 +285,25 @@ public class Smali {
writeMethodDef(smali, mth, line); writeMethodDef(smali, mth, line);
ICodeReader codeReader = mth.getCodeReader(); ICodeReader codeReader = mth.getCodeReader();
if (codeReader != null) { if (codeReader != null) {
int regsCount = codeReader.getRegistersCount();
line.smaliMthNode.setParamRegStart(getParamStartRegNum(mth)); line.smaliMthNode.setParamRegStart(getParamStartRegNum(mth));
line.smaliMthNode.setRegCount(codeReader.getRegistersCount()); line.smaliMthNode.setRegCount(regsCount);
Map<Long, InsnNode> nodes = new HashMap<>(codeReader.getUnitsCount() / 2); Map<Long, InsnNode> nodes = new HashMap<>(codeReader.getUnitsCount() / 2);
line.smaliMthNode.setInsnNodes(nodes, codeReader.getUnitsCount()); line.smaliMthNode.setInsnNodes(nodes, codeReader.getUnitsCount());
line.smaliMthNode.initRegInfoList(codeReader.getRegistersCount(), codeReader.getUnitsCount()); line.smaliMthNode.initRegInfoList(regsCount, codeReader.getUnitsCount());
smali.incIndent(); smali.incIndent();
smali.startLine(".registers ") smali.startLine(".registers ").add(Integer.toString(regsCount));
.add("" + codeReader.getRegistersCount())
.startLine();
writeTries(codeReader, line); writeTries(codeReader, line);
if (formatMthParamInfo(mth, smali, codeReader, line)) { IDebugInfo debugInfo = codeReader.getDebugInfo();
smali.startLine(); List<ILocalVar> localVars = debugInfo != null ? debugInfo.getLocalVars() : Collections.emptyList();
formatMthParamInfo(mth, smali, line, regsCount, localVars);
if (debugInfo != null) {
formatDbgInfo(debugInfo, localVars, line);
} }
smali.newLine();
smali.startLine(); smali.startLine();
if (codeReader.getDebugInfo() != null) {
formatDbgInfo(codeReader.getDebugInfo(), line);
}
// first pass to fill payload offsets for switch instructions // first pass to fill payload offsets for switch instructions
codeReader.visitInstructions(insn -> { codeReader.visitInstructions(insn -> {
Opcode opcode = insn.getOpcode(); Opcode opcode = insn.getOpcode();
...@@ -458,20 +459,11 @@ public class Smali { ...@@ -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<ILocalVar> localVars) {
List<String> types = mth.getMethodRef().getArgTypes(); List<String> types = mth.getMethodRef().getArgTypes();
if (types.isEmpty()) { if (types.isEmpty()) {
return false; return;
}
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;
}
}
} }
int paramStart = 0; int paramStart = 0;
int regNum = line.smaliMthNode.getParamRegStart(); int regNum = line.smaliMthNode.getParamRegStart();
...@@ -482,26 +474,30 @@ public class Smali { ...@@ -482,26 +474,30 @@ public class Smali {
regNum++; regNum++;
paramStart++; 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) { for (String paramType : types) {
String name;
String type;
ILocalVar param = params[regNum]; ILocalVar param = params[regNum];
if (param != null) { if (param != null) {
name = Utils.getOrElse(param.getName(), ""); String name = Utils.getOrElse(param.getName(), "");
type = Utils.getOrElse(param.getSignature(), paramType); String type = Utils.getOrElse(param.getSignature(), paramType);
} else { String varName = "p" + paramStart;
name = ""; smali.startLine(String.format(".param %s, \"%s\" # %s", varName, name, type));
type = paramType; 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; int regSize = isWideType(paramType) ? 2 : 1;
regNum += regSize; regNum += regSize;
paramStart += regSize; paramStart += regSize;
} }
return true;
} }
private static int getParamStartRegNum(IMethodData mth) { private static int getParamStartRegNum(IMethodData mth) {
...@@ -558,30 +554,42 @@ public class Smali { ...@@ -558,30 +554,42 @@ public class Smali {
smali.startLine(".end annotation"); smali.startLine(".end annotation");
} }
private void formatDbgInfo(IDebugInfo dbgInfo, LineInfo line) { private void formatDbgInfo(IDebugInfo dbgInfo, List<ILocalVar> localVars, LineInfo line) {
dbgInfo.getSourceLineMapping().forEach((codeOffset, srcLine) -> { dbgInfo.getSourceLineMapping().forEach((codeOffset, srcLine) -> {
if (codeOffset > -1) { if (codeOffset > -1) {
line.addDebugLineTip(codeOffset, String.format(".line %d", srcLine), ""); line.addDebugLineTip(codeOffset, String.format(".line %d", srcLine), "");
} }
}); });
for (ILocalVar localVar : dbgInfo.getLocalVars()) { for (ILocalVar localVar : localVars) {
String type = localVar.getSignature(); if (localVar.isMarkedAsParameter()) {
if (type == null || type.trim().isEmpty()) { continue;
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));
} }
if (localVar.getEndOffset() > -1) { String type = localVar.getType();
line.addTip( String sign = localVar.getSignature();
localVar.getEndOffset(), String longTypeStr;
String.format(".end local v%d", localVar.getRegNum()), if (sign == null || sign.trim().isEmpty()) {
String.format(" # \"%s\":%s", localVar.getName(), type)); 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) { private void writeEncodedValue(SmaliWriter smali, EncodedValue value, boolean wrapArray) {
......
...@@ -94,7 +94,6 @@ class SmaliMethodNode { ...@@ -94,7 +94,6 @@ class SmaliMethodNode {
protected void setParamReg(int regNum, String name) { protected void setParamReg(int regNum, String name) {
SmaliRegister r = regList.get(regNum); SmaliRegister r = regList.get(regNum);
r.setParam(name); r.setParam(name);
r.setStartOffset(-1);
} }
protected void setParamRegStart(int paramRegStart) { protected void setParamRegStart(int paramRegStart) {
......
...@@ -33,10 +33,6 @@ public class SmaliRegister extends RegisterInfo { ...@@ -33,10 +33,6 @@ public class SmaliRegister extends RegisterInfo {
} }
protected void setStartOffset(int off) { protected void setStartOffset(int off) {
if (startOffset == -1 && !isParam) {
startOffset = off;
return;
}
if (off < startOffset) { if (off < startOffset) {
startOffset = off; startOffset = off;
} }
...@@ -71,4 +67,9 @@ public class SmaliRegister extends RegisterInfo { ...@@ -71,4 +67,9 @@ public class SmaliRegister extends RegisterInfo {
public int getEndOffset() { public int getEndOffset() {
return endOffset; return endOffset;
} }
@Override
public boolean isMarkedAsParameter() {
return isParam;
}
} }
...@@ -33,6 +33,9 @@ class DbgSmaliTest extends SmaliTest { ...@@ -33,6 +33,9 @@ class DbgSmaliTest extends SmaliTest {
Smali disasm = Smali.disassemble(cls); Smali disasm = Smali.disassemble(cls);
String code = disasm.getCode(); String code = disasm.getCode();
LOG.debug("{}", code); 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<*>;\"");
} }
} }
...@@ -96,8 +96,9 @@ public class DebugInfoParser { ...@@ -96,8 +96,9 @@ public class DebugInfoParser {
int nameId = in.readUleb128p1(); int nameId = in.readUleb128p1();
String name = ext.getString(nameId); String name = ext.getString(nameId);
if (name != null && i < argsCount) { if (name != null && i < argsCount) {
int regNum = argRegs[i]; DexLocalVar paramVar = new DexLocalVar(argRegs[i], name, argTypes.get(i));
startVar(new DexLocalVar(regNum, name, argTypes.get(i)), -1); startVar(paramVar, addr);
paramVar.markAsParameter();
varsInfoFound = true; varsInfoFound = true;
} }
} }
......
...@@ -7,6 +7,8 @@ import jadx.api.plugins.utils.Utils; ...@@ -7,6 +7,8 @@ import jadx.api.plugins.utils.Utils;
import jadx.plugins.input.dex.sections.SectionReader; import jadx.plugins.input.dex.sections.SectionReader;
public class DexLocalVar implements ILocalVar { public class DexLocalVar implements ILocalVar {
private static final int PARAM_START_OFFSET = -1;
private final int regNum; private final int regNum;
private final String name; private final String name;
private final String type; private final String type;
...@@ -78,6 +80,15 @@ public class DexLocalVar implements ILocalVar { ...@@ -78,6 +80,15 @@ public class DexLocalVar implements ILocalVar {
return startOffset; return startOffset;
} }
public void markAsParameter() {
startOffset = PARAM_START_OFFSET;
}
@Override
public boolean isMarkedAsParameter() {
return startOffset == PARAM_START_OFFSET;
}
@Override @Override
public int getEndOffset() { public int getEndOffset() {
return endOffset; return endOffset;
......
...@@ -61,6 +61,11 @@ public class JavaLocalVar implements ILocalVar { ...@@ -61,6 +61,11 @@ public class JavaLocalVar implements ILocalVar {
return endOffset; return endOffset;
} }
@Override
public boolean isMarkedAsParameter() {
return false;
}
@Override @Override
public int hashCode() { public int hashCode() {
int result = regNum; int result = regNum;
......
...@@ -15,4 +15,10 @@ public interface ILocalVar { ...@@ -15,4 +15,10 @@ public interface ILocalVar {
int getStartOffset(); int getStartOffset();
int getEndOffset(); int getEndOffset();
/**
* Hint if variable is a method parameter.
* Can be incorrect and shouldn't be trusted.
*/
boolean isMarkedAsParameter();
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册