Skip to content

Commit

Permalink
feat(gui): add class links for AndroidManifest.xml and other minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Jul 19, 2019
1 parent 3bc9671 commit c8df26f
Show file tree
Hide file tree
Showing 28 changed files with 357 additions and 256 deletions.
11 changes: 11 additions & 0 deletions jadx-core/src/main/java/jadx/api/ICodeInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package jadx.api;

import java.util.Map;

public interface ICodeInfo {
String getCodeStr();

Map<Integer, Integer> getLineMapping();

Map<CodePosition, Object> getAnnotations();
}
43 changes: 43 additions & 0 deletions jadx-core/src/main/java/jadx/api/JadxDecompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;

import org.jetbrains.annotations.Nullable;
import org.jf.baksmali.Adaptors.ClassDefinition;
import org.jf.baksmali.BaksmaliOptions;
import org.jf.dexlib2.DexFileFactory;
Expand All @@ -28,6 +29,7 @@
import jadx.core.Jadx;
import jadx.core.ProcessClass;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.MethodNode;
Expand Down Expand Up @@ -390,6 +392,47 @@ JavaField getJavaFieldByNode(FieldNode fld) {
return null;
}

@Nullable
JavaNode convertNode(Object obj) {
if (!(obj instanceof LineAttrNode)) {
return null;
}
if (obj instanceof ClassNode) {
return getClassesMap().get(obj);
}
if (obj instanceof MethodNode) {
return getJavaMethodByNode(((MethodNode) obj));
}
if (obj instanceof FieldNode) {
return getJavaFieldByNode((FieldNode) obj);
}
return null;
}

@Nullable
public JavaNode getJavaNodeAtPosition(ICodeInfo codeInfo, int line, int offset) {
Map<CodePosition, Object> map = codeInfo.getAnnotations();
if (map.isEmpty()) {
return null;
}
Object obj = map.get(new CodePosition(line, offset));
if (obj == null) {
return null;
}
return convertNode(obj);
}

@Nullable
public CodePosition getDefinitionPosition(JavaNode javaNode) {
JavaClass jCls = javaNode.getTopParentClass();
jCls.decompile();
int defLine = javaNode.getDecompiledLine();
if (defLine == 0) {
return null;
}
return new CodePosition(jCls, defLine, 0);
}

public JadxArgs getArgs() {
return args;
}
Expand Down
41 changes: 6 additions & 35 deletions jadx-core/src/main/java/jadx/api/JavaClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public Map<CodePosition, JavaNode> getUsageMap() {
CodePosition codePosition = entry.getKey();
Object obj = entry.getValue();
if (obj instanceof LineAttrNode) {
JavaNode node = convertNode(obj);
JavaNode node = getRootDecompiler().convertNode(obj);
if (node != null) {
resultMap.put(codePosition, node);
}
Expand All @@ -161,45 +161,15 @@ public Map<CodePosition, JavaNode> getUsageMap() {
return resultMap;
}

@Nullable
private JavaNode convertNode(Object obj) {
if (!(obj instanceof LineAttrNode)) {
return null;
}
if (obj instanceof ClassNode) {
return getRootDecompiler().getClassesMap().get(obj);
}
if (obj instanceof MethodNode) {
return getRootDecompiler().getJavaMethodByNode(((MethodNode) obj));
}
if (obj instanceof FieldNode) {
return getRootDecompiler().getJavaFieldByNode((FieldNode) obj);
}
return null;
}

@Nullable
public JavaNode getJavaNodeAtPosition(int line, int offset) {
Map<CodePosition, Object> map = getCodeAnnotations();
if (map.isEmpty()) {
return null;
}
Object obj = map.get(new CodePosition(line, offset));
if (obj == null) {
return null;
}
return convertNode(obj);
decompile();
return getRootDecompiler().getJavaNodeAtPosition(cls.getCode(), line, offset);
}

@Nullable
public CodePosition getDefinitionPosition(JavaNode javaNode) {
JavaClass jCls = javaNode.getTopParentClass();
jCls.decompile();
int defLine = javaNode.getDecompiledLine();
if (defLine == 0) {
return null;
}
return new CodePosition(jCls, defLine, 0);
public CodePosition getDefinitionPosition() {
return getRootDecompiler().getDefinitionPosition(this);
}

public Integer getSourceLine(int decompiledLine) {
Expand Down Expand Up @@ -250,6 +220,7 @@ public List<JavaMethod> getMethods() {
return methods;
}

@Override
public int getDecompiledLine() {
return cls.getDecompiledLine();
}
Expand Down
4 changes: 1 addition & 3 deletions jadx-core/src/main/java/jadx/api/ResourcesLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,8 @@ private void addEntry(List<ResourceFile> list, File zipFile, ZipEntry entry) {
}

public static CodeWriter loadToCodeWriter(InputStream is) throws IOException {
CodeWriter cw = new CodeWriter();
ByteArrayOutputStream baos = new ByteArrayOutputStream(READ_BUFFER_SIZE);
copyStream(is, baos);
cw.add(baos.toString("UTF-8"));
return cw;
return new CodeWriter(baos.toString("UTF-8"));
}
}
9 changes: 8 additions & 1 deletion jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
import org.slf4j.LoggerFactory;

import jadx.api.CodePosition;
import jadx.api.ICodeInfo;
import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.utils.StringUtils;
import jadx.core.utils.files.FileUtils;
import jadx.core.utils.files.ZipSecurity;

public class CodeWriter {
public class CodeWriter implements ICodeInfo {
private static final Logger LOG = LoggerFactory.getLogger(CodeWriter.class);

public static final String NL = System.getProperty("line.separator");
Expand Down Expand Up @@ -242,6 +243,7 @@ private Object attachAnnotation(Object obj, CodePosition pos) {
return annotations.put(pos, obj);
}

@Override
public Map<CodePosition, Object> getAnnotations() {
return annotations;
}
Expand All @@ -260,6 +262,7 @@ private void attachSourceLine(int decompiledLine, int sourceLine) {
lineMap.put(decompiledLine, sourceLine);
}

@Override
public Map<Integer, Integer> getLineMapping() {
return lineMap;
}
Expand Down Expand Up @@ -293,7 +296,11 @@ public int bufLength() {
return buf.length();
}

@Override
public String getCodeStr() {
if (code == null) {
throw new NullPointerException("Code not set");
}
return code;
}

Expand Down
14 changes: 14 additions & 0 deletions jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,20 @@ public ClassNode searchClassByName(String fullName) {
return resolveClass(clsInfo);
}

@Nullable
public ClassNode searchClassByFullAlias(String fullName) {
for (DexNode dexNode : dexNodes) {
for (ClassNode cls : dexNode.getClasses()) {
ClassInfo classInfo = cls.getClassInfo();
if (classInfo.getFullName().equals(fullName)
|| classInfo.getAliasFullName().equals(fullName)) {
return cls;
}
}
}
return null;
}

public List<ClassNode> searchClassByShortName(String shortName) {
List<ClassNode> list = new ArrayList<>();
for (DexNode dexNode : dexNodes) {
Expand Down
23 changes: 20 additions & 3 deletions jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import jadx.api.ResourcesLoader;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.info.ConstStorage;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode;
import jadx.core.utils.StringUtils;
import jadx.core.utils.exceptions.JadxRuntimeException;
Expand All @@ -32,7 +33,6 @@
* Check Element chunk size
*/

@SuppressWarnings("unused")
public class BinaryXMLParser extends CommonBinaryParser {

private static final Logger LOG = LoggerFactory.getLogger(BinaryXMLParser.class);
Expand Down Expand Up @@ -306,6 +306,7 @@ private void parseAttribute(int i, boolean newLine) throws IOException {
if (isDeobfCandidateAttr(shortNsName, attrName)) {
decodedAttr = deobfClassName(decodedAttr);
}
attachClassNode(writer, attrName, decodedAttr);
writer.add(StringUtils.escapeXML(decodedAttr));
} else {
decodeAttribute(attributeNS, attrValDataType, attrValData,
Expand Down Expand Up @@ -401,6 +402,7 @@ private void decodeAttribute(int attributeNS, int attrValDataType, int attrValDa
if (isDeobfCandidateAttr(shortNsName, attrName)) {
str = deobfClassName(str);
}
attachClassNode(writer, attrName, str);
writer.add(str != null ? StringUtils.escapeXML(str) : "null");
}
}
Expand Down Expand Up @@ -459,9 +461,24 @@ private static String generateTagAttrName() {
return sb.toString();
}

private void attachClassNode(CodeWriter writer, String attrName, String clsName) {
if (clsName == null || !attrName.equals("name")) {
return;
}
String clsFullName;
if (clsName.startsWith(".")) {
clsFullName = appPackageName + clsName;
} else {
clsFullName = clsName;
}
ClassNode classNode = rootNode.searchClassByFullAlias(clsFullName);
if (classNode != null) {
writer.attachAnnotation(classNode);
}
}

private String deobfClassName(String className) {
String newName = XmlDeobf.deobfClassName(rootNode, className,
appPackageName);
String newName = XmlDeobf.deobfClassName(rootNode, className, appPackageName);
if (newName != null) {
return newName;
}
Expand Down
7 changes: 4 additions & 3 deletions jadx-core/src/main/java/jadx/core/xmlgen/XmlDeobf.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.util.HashMap;
import java.util.Map;

import org.jetbrains.annotations.Nullable;

import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode;
Expand All @@ -17,9 +19,8 @@ public class XmlDeobf {
private XmlDeobf() {
}

public static String deobfClassName(RootNode rootNode, String potencialClassName,
String packageName) {

@Nullable
public static String deobfClassName(RootNode rootNode, String potencialClassName, String packageName) {
if (packageName != null && potencialClassName.startsWith(".")) {
potencialClassName = packageName + potencialClassName;
}
Expand Down
4 changes: 4 additions & 0 deletions jadx-gui/src/main/java/jadx/gui/JadxWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ public File getOpenFile() {
return openFile;
}

public JadxDecompiler getDecompiler() {
return decompiler;
}

public JadxArgs getArgs() {
return decompiler.getArgs();
}
Expand Down
13 changes: 8 additions & 5 deletions jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import javax.swing.*;

import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.jetbrains.annotations.Nullable;

import jadx.api.ICodeInfo;
import jadx.api.JavaClass;
import jadx.api.JavaField;
import jadx.api.JavaMethod;
Expand Down Expand Up @@ -76,6 +78,12 @@ public synchronized void update() {
}
}

@Override
public @Nullable ICodeInfo getCodeInfo() {
load();
return cls.getClassNode().getCode();
}

@Override
public String getContent() {
return cls.getCode();
Expand Down Expand Up @@ -147,11 +155,6 @@ public int getLine() {
return cls.getDecompiledLine();
}

@Override
public Integer getSourceLine(int line) {
return cls.getSourceLine(line);
}

@Override
public int hashCode() {
return cls.hashCode();
Expand Down
23 changes: 22 additions & 1 deletion jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
import javax.swing.tree.DefaultMutableTreeNode;

import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.jetbrains.annotations.Nullable;

import jadx.api.ICodeInfo;
import jadx.api.JadxDecompiler;
import jadx.api.JavaNode;

public abstract class JNode extends DefaultMutableTreeNode {
Expand Down Expand Up @@ -40,10 +43,28 @@ public int getLine() {
return 0;
}

public Integer getSourceLine(int line) {
@Nullable
public ICodeInfo getCodeInfo() {
return null;
}

public final Integer getSourceLine(int line) {
ICodeInfo codeInfo = getCodeInfo();
if (codeInfo == null) {
return null;
}
return codeInfo.getLineMapping().get(line);
}

@Nullable
public JavaNode getJavaNodeAtPosition(JadxDecompiler decompiler, int line, int offset) {
ICodeInfo codeInfo = getCodeInfo();
if (codeInfo == null) {
return null;
}
return decompiler.getJavaNodeAtPosition(codeInfo, line, offset);
}

public abstract Icon getIcon();

public String getName() {
Expand Down
Loading

0 comments on commit c8df26f

Please sign in to comment.