Skip to content

Commit

Permalink
fix: don't apply node positions and prevent eager loading for custom …
Browse files Browse the repository at this point in the history
…decompile modes (#2116)
  • Loading branch information
skylot committed Mar 19, 2024
1 parent bff00d1 commit 463d2b9
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 41 deletions.
13 changes: 0 additions & 13 deletions jadx-core/src/main/java/jadx/api/impl/AnnotatedCodeWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ private void attachSourceLine(int decompiledLine, int sourceLine) {

@Override
public ICodeInfo finish() {
processDefinitionAnnotations();
validateAnnotations();
String code = buf.toString();
buf = null;
Expand All @@ -166,18 +165,6 @@ public Map<Integer, ICodeAnnotation> getRawAnnotations() {
return annotations;
}

private void processDefinitionAnnotations() {
if (!annotations.isEmpty()) {
annotations.forEach((k, v) -> {
if (v instanceof NodeDeclareRef) {
NodeDeclareRef declareRef = (NodeDeclareRef) v;
declareRef.setDefPos(k);
declareRef.getNode().setDefPosition(k);
}
});
}
}

private void validateAnnotations() {
if (annotations.isEmpty()) {
return;
Expand Down
61 changes: 46 additions & 15 deletions jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import jadx.api.JadxArgs;
import jadx.api.JavaClass;
import jadx.api.impl.SimpleCodeInfo;
import jadx.api.metadata.ICodeAnnotation;
import jadx.api.metadata.annotations.NodeDeclareRef;
import jadx.api.plugins.input.data.IClassData;
import jadx.api.plugins.input.data.IFieldData;
import jadx.api.plugins.input.data.IMethodData;
Expand Down Expand Up @@ -312,6 +314,8 @@ public ICodeInfo decompile() {
return decompile(true);
}

private static final Object DECOMPILE_WITH_MODE_SYNC = new Object();

/**
* WARNING: Slow operation! Use with caution!
*/
Expand All @@ -320,15 +324,18 @@ public ICodeInfo decompileWithMode(DecompilationMode mode) {
if (mode == baseMode) {
return decompile(true);
}
JadxArgs args = root.getArgs();
try {
unload();
args.setDecompilationMode(mode);
ProcessClass process = new ProcessClass(args);
process.initPasses(root);
return process.generateCode(this);
} finally {
args.setDecompilationMode(baseMode);
synchronized (DECOMPILE_WITH_MODE_SYNC) {
JadxArgs args = root.getArgs();
try {
unload();
args.setDecompilationMode(mode);
ProcessClass process = new ProcessClass(args);
process.initPasses(root);
return process.generateCode(this);
} finally {
args.setDecompilationMode(baseMode);
unload();
}
}
}

Expand Down Expand Up @@ -383,20 +390,44 @@ private synchronized ICodeInfo decompile(boolean searchInCache) {
return code;
}
}
ICodeInfo codeInfo;
ICodeInfo codeInfo = generateClassCode();
if (codeInfo != ICodeInfo.EMPTY) {
codeCache.add(clsRawName, codeInfo);
}
return codeInfo;
}

private ICodeInfo generateClassCode() {
try {
if (Consts.DEBUG) {
LOG.debug("Decompiling class: {}", this);
}
codeInfo = root.getProcessClasses().generateCode(this);
ICodeInfo codeInfo = root.getProcessClasses().generateCode(this);
processDefinitionAnnotations(codeInfo);
return codeInfo;
} catch (Throwable e) {
addError("Code generation failed", e);
codeInfo = new SimpleCodeInfo(Utils.getStackTrace(e));
return new SimpleCodeInfo(Utils.getStackTrace(e));
}
if (codeInfo != ICodeInfo.EMPTY) {
codeCache.add(clsRawName, codeInfo);
}

/**
* Save node definition positions found in code
*/
private static void processDefinitionAnnotations(ICodeInfo codeInfo) {
Map<Integer, ICodeAnnotation> annotations = codeInfo.getCodeMetadata().getAsMap();
if (annotations.isEmpty()) {
return;
}
for (Map.Entry<Integer, ICodeAnnotation> entry : annotations.entrySet()) {
ICodeAnnotation ann = entry.getValue();
if (ann.getAnnType() == AnnType.DECLARATION) {
NodeDeclareRef declareRef = (NodeDeclareRef) ann;
int pos = entry.getKey();
declareRef.setDefPos(pos);
declareRef.getNode().setDefPosition(pos);
}
}
return codeInfo;
}

@Nullable
Expand Down
30 changes: 20 additions & 10 deletions jadx-gui/src/main/java/jadx/gui/ui/codearea/CodePanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,22 @@ private synchronized void initLineNumbers() {
codeScrollPane.setLineNumbersEnabled(true);
}

private static final LineNumberFormatter SIMPLE_LINE_FORMATTER = new LineNumberFormatter() {
@Override
public String format(int lineNumber) {
return Integer.toString(lineNumber);
}

@Override
public int getMaxLength(int maxLineNumber) {
return SourceLineFormatter.getNumberLength(maxLineNumber);
}
};

private synchronized void applyLineFormatter() {
LineNumberFormatter linesFormatter = useSourceLines
? new SourceLineFormatter(codeArea.getCodeInfo())
: LineNumberList.DEFAULT_LINE_NUMBER_FORMATTER;
: SIMPLE_LINE_FORMATTER;
codeScrollPane.getGutter().setLineNumberFormatter(linesFormatter);
}

Expand Down Expand Up @@ -170,15 +182,13 @@ private boolean canShowDebugLines() {
}

private void initLinesModeSwitch() {
if (canShowDebugLines()) {
MousePressedHandler lineModeSwitch = new MousePressedHandler(ev -> {
useSourceLines = !useSourceLines;
applyLineFormatter();
});
for (Component gutterComp : codeScrollPane.getGutter().getComponents()) {
if (gutterComp instanceof LineNumberList) {
gutterComp.addMouseListener(lineModeSwitch);
}
MousePressedHandler lineModeSwitch = new MousePressedHandler(ev -> {
useSourceLines = !useSourceLines;
applyLineFormatter();
});
for (Component gutterComp : codeScrollPane.getGutter().getComponents()) {
if (gutterComp instanceof LineNumberList) {
gutterComp.addMouseListener(lineModeSwitch);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ private static int calcMaxLength(ICodeInfo codeInfo) {
.values().stream()
.mapToInt(Integer::intValue)
.max().orElse(1);
// maxLine can be anything including zero and negative numbers,
// so use safe 'stringify' method instead faster 'Math.log10'
return Integer.toString(maxLine).length();
return getNumberLength(maxLine);
}

public static int getNumberLength(int num) {
return num < 10 ? 1 : 1 + (int) Math.log10(num);
}
}

0 comments on commit 463d2b9

Please sign in to comment.