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

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

上级 5d186e56
......@@ -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 {
......
......@@ -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<Long, InsnNode> 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<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();
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<ILocalVar> localVars) {
List<String> 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);
}
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<ILocalVar> 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();
for (ILocalVar localVar : localVars) {
if (localVar.isMarkedAsParameter()) {
continue;
}
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());
}
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) {
".local " + formatVarName(line.smaliMthNode, localVar),
longTypeStr);
line.addTip(
localVar.getEndOffset(),
String.format(".end local v%d", localVar.getRegNum()),
".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) {
......
......@@ -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) {
......
......@@ -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;
}
}
......@@ -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<*>;\"");
}
}
......@@ -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;
}
}
......
......@@ -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;
......
......@@ -61,6 +61,11 @@ public class JavaLocalVar implements ILocalVar {
return endOffset;
}
@Override
public boolean isMarkedAsParameter() {
return false;
}
@Override
public int hashCode() {
int result = regNum;
......
......@@ -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();
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册