delete unused functions

--HG--
branch : 2.x
This commit is contained in:
Bob Pan 2014-11-13 22:01:24 +08:00
parent e2404c1805
commit 84a7ac9c2e
9 changed files with 0 additions and 1631 deletions

View File

@ -1,103 +0,0 @@
package com.googlecode.d2j.map;
import com.googlecode.dex2jar.ir.IrMethod;
import com.googlecode.dex2jar.ir.expr.*;
import com.googlecode.dex2jar.ir.stmt.Stmt;
import java.util.HashSet;
import java.util.Set;
public class AntiObf {
private boolean initEnumNames = false;
private boolean initSourceNames = false;
private boolean initAssertionNames = false;
public AntiObf initEnumNames() {
this.initEnumNames = true;
return this;
}
public AntiObf initSourceNames() {
this.initSourceNames = true;
return this;
}
public AntiObf initAssertionNames() {
this.initAssertionNames = true;
return this;
}
static class CodeResolver {
IrMethod find(String owner, String name, String[] pas, String ret) {
return null;
};
}
public void suggestNames(InheritanceTree tree, CodeResolver codeResolver) {
if (initEnumNames) {
for (InheritanceTree.Clz clz : tree.clzMap.values()) {
if (clz.stat == InheritanceTree.Stat.APP) {
if (clz.superClz.name.oldValue.equals("Ljava/lang/Enum;")) {
String clzDesc = clz.name.oldValue;
Set<String> enumClzs = new HashSet<>();
enumClzs.add(clzDesc);
for (InheritanceTree.Clz d : clz.children) {
enumClzs.add(d.name.oldValue);
}
IrMethod ir = codeResolver.find(clzDesc, "<clinit>", new String[0], "V");
// InheritanceTree$Stat.UNKNOW = new InheritanceTree$Stat("UNKNOW",0)
// InheritanceTree$Stat.LIBRARY = new InheritanceTree$Stat("LIBRARY",1)
// InheritanceTree$Stat.APP = new InheritanceTree$Stat("APP",2)
// InheritanceTree$Stat.ENUM$VALUES = new InheritanceTree$Stat[]{InheritanceTree$Stat.UNKNOW,
// InheritanceTree$Stat.LIBRARY, InheritanceTree$Stat.APP}
for (Stmt stmt : ir.stmts) {
if (stmt.st == Stmt.ST.ASSIGN && stmt.getOp1().vt == Value.VT.STATIC_FIELD) {
StaticFieldExpr sfe = (StaticFieldExpr) stmt.getOp1();
if (sfe.owner.equals(clzDesc)) {
if (stmt.getOp2().vt == Value.VT.INVOKE_NEW) {
InvokeExpr n = (InvokeExpr) stmt.getOp2();
if (enumClzs.contains(n.owner) && n.args.length >= 2
&& n.args[0].equals("Ljava/lang/String;") && n.args[1].equals("I")) {
if (n.ops[0].vt == Value.VT.CONSTANT) {
String cst = (String) ((Constant) n.ops[0]).value;
InheritanceTree.Fld fld = clz.fields.get(InheritanceTree.toFieldKey(
sfe.name, sfe.type));
if (!cst.equals(fld.name.oldValue)) {
if (fld.name.newValue != null && !fld.name.newValue.equals(cst)) {
System.err.println(String.format(
"WARN: %s->%s is suggest different names: %s, %s",
sfe.owner, sfe.name, fld.name.newValue, cst));
}
fld.name.newValue = cst;
}
}
}
} else if (stmt.getOp2().vt == Value.VT.FILLED_ARRAY) {
FilledArrayExpr fae = (FilledArrayExpr) stmt.getOp2();
if (fae.type.equals("[" + clzDesc)) {
// TODO check more
InheritanceTree.Fld fld = clz.fields.get(InheritanceTree.toFieldKey(
sfe.name, sfe.type));
String cst = "ENUM$VALUES";
if (!cst.equals(fld.name.oldValue)) {
if (fld.name.newValue != null && !fld.name.newValue.equals(cst)) {
System.err.println(String.format(
"WARN: %s->%s is suggest different names: %s, %s",
sfe.owner, sfe.name, fld.name.newValue, cst));
}
fld.name.newValue = cst;
}
}
}
}
}
}
}
}
}
}
}
}

View File

@ -1,60 +0,0 @@
/*
* dex2jar - Tools to work with android .dex and java .class files
* Copyright (c) 2009-2013 Panxiaobo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.d2j.map;
import org.objectweb.asm.*;
public class AsmInheritanceClassVisitor extends ClassVisitor {
final InheritanceTree tree;
InheritanceTree.Clz clz;
public AsmInheritanceClassVisitor(InheritanceTree tree) {
super(Opcodes.ASM4);
this.tree = tree;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
clz = tree.addClz(access, "L" + name + ";");
if (superName != null) {
clz.relateSuper("L" + superName + ";");
}
if (interfaces != null) {
for (String s : interfaces) {
clz.relateInterface("L" + s + ";");
}
}
}
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
clz.addField(access, name, desc);
return null;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
Type[] aT = Type.getArgumentTypes(desc);
String[] aS = new String[aT.length];
for (int i = 0; i < aT.length; i++) {
aS[i] = aT[i].getDescriptor();
}
clz.addMethod(access, name, aS, Type.getReturnType(desc).getDescriptor());
return null;
}
}

View File

@ -1,97 +0,0 @@
/*
* dex2jar - Tools to work with android .dex and java .class files
* Copyright (c) 2009-2013 Panxiaobo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.d2j.map;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import com.googlecode.dex2jar.tools.BaseCmd;
public class AutoDetectSourceProcess {
public final void process(String file) throws IOException {
Path path = new File(file).toPath();
if (Files.isDirectory(path)) {
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
onFile(file, true);
return FileVisitResult.CONTINUE;
}
});
} else if (Files.isRegularFile(path)) {
onFile(path, true);
}
}
void onFile(Path file, boolean unzip) throws IOException {
String name = file.getFileName().toString().toLowerCase();
if (unzip) {
if (name.endsWith(".apk") || name.endsWith(".zip") || name.endsWith(".jar")) {
try (FileSystem fs = BaseCmd.openZip(file)) {
Path dex = fs.getPath("/", "classes.dex");
if (Files.exists(dex)) {
onFile(dex, true);
} else {
for (Path root : fs.getRootDirectories()) {
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
onFile(file, false);
return FileVisitResult.CONTINUE;
}
});
}
}
}
} else if (name.endsWith(".dex")) {
onDex(file);
}
}
if (name.endsWith(".class")) {
onClass(file);
} else if (name.endsWith(".j")) {
onJasmin(file);
} else if (name.endsWith(".smali")) {
onSmali(file);
}
}
protected void onDex(Path file) throws IOException {
}
protected void onClass(Path file) throws IOException {
}
protected void onSmali(Path file) throws IOException {
}
protected void onJasmin(Path file) throws IOException {
}
}

View File

@ -1,63 +0,0 @@
/*
* dex2jar - Tools to work with android .dex and java .class files
* Copyright (c) 2009-2013 Panxiaobo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.d2j.map;
import com.googlecode.d2j.Field;
import com.googlecode.d2j.Method;
import com.googlecode.d2j.visitors.DexClassVisitor;
import com.googlecode.d2j.visitors.DexFieldVisitor;
import com.googlecode.d2j.visitors.DexFileVisitor;
import com.googlecode.d2j.visitors.DexMethodVisitor;
public class DexInheritanceFileVisitor extends DexFileVisitor {
final InheritanceTree tree;
public DexInheritanceFileVisitor(InheritanceTree tree) {
this.tree = tree;
}
@Override
public DexClassVisitor visit(int access_flags, String className, String superClass, String[] interfaceNames) {
final InheritanceTree.Clz clz = tree.addClz(access_flags, className);
if(clz == null) { // skip the class
return null;
}
if (superClass != null) {
clz.relateSuper(superClass);
}
if (interfaceNames != null) {
for (String s : interfaceNames) {
clz.relateInterface(s);
}
}
return new DexClassVisitor() {
@Override
public DexFieldVisitor visitField(int accessFlags, Field field, Object value) {
clz.addField(accessFlags, field.getName(), field.getType());
return null;
}
@Override
public DexMethodVisitor visitMethod(int accessFlags, Method method) {
clz.addMethod(accessFlags, method.getName(), method.getParameterTypes(), method.getReturnType());
return null;
}
};
}
}

View File

@ -1,518 +0,0 @@
/*
* dex2jar - Tools to work with android .dex and java .class files
* Copyright (c) 2009-2013 Panxiaobo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.d2j.map;
import com.googlecode.d2j.*;
import com.googlecode.d2j.node.DexAnnotationNode;
import com.googlecode.d2j.reader.Op;
import com.googlecode.d2j.util.Mapper;
import com.googlecode.d2j.util.Types;
import com.googlecode.d2j.visitors.*;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureWriter;
public class DexMappingAdapter extends DexFileVisitor {
protected Mapper mapper;
public DexMappingAdapter(Mapper mapper, DexFileVisitor visitor) {
super(visitor);
this.mapper = mapper;
}
static String mapClassName(Mapper map, String oldDesc) {
if (oldDesc == null) {
return null;
}
int count = 0;
while (count < oldDesc.length() && oldDesc.charAt(count) == '[') {
count++;
}
if (count + 1 == oldDesc.length()) {// simple type
return oldDesc;
}
if (count > 0) {
String n = map.mapClassName(oldDesc.substring(count));
if (n == null) {
return oldDesc;
}
return oldDesc.substring(0, count) + n;
} else {
String n = map.mapClassName(oldDesc);
if (n == null) {
return oldDesc;
}
return n;
}
}
static String mapAnnotationElementName(Mapper map, String owner, String name) {
String n = map.mapMethodName(owner, name, null, null);
if (n == null) {
return name;
}
return n;
}
static String[] mapClassNames(Mapper map, String[] oldDescs) {
if (oldDescs != null && oldDescs.length > 0) {
String copy[] = new String[oldDescs.length];
for (int i = 0; i < oldDescs.length; i++) {
copy[i] = mapClassName(map, oldDescs[i]);
}
return copy;
} else {
return oldDescs;
}
}
static String mapFieldName(Mapper map, String owner, String name, String type) {
String n = map.mapFieldName(owner, name, type);
if (n == null) {
return name;
}
return n;
}
static Field mapField(Mapper map, Field f) {
String n = map.mapFieldName(f.getOwner(), f.getName(), f.getType());
if (n == null) {
n = f.getName();
}
return new Field(mapClassName(map, f.getOwner()), n, mapClassName(map, f.getType()));
}
static Field mapFieldNameAndOwner(Mapper map, Field f) {
String n = map.mapFieldName(f.getOwner(), f.getName(), f.getType());
if (n == null) {
n = f.getName();
}
return new Field(mapFieldOwner(map, f.getOwner(), f.getName(), f.getType()), n, mapClassName(map, f.getType()));
}
private static String mapFieldOwner(Mapper map, String owner, String name, String type) {
String n = map.mapFieldOwner(owner, name, type);
if (n == null) {
return owner;
}
return n;
}
private static Method mapMethod(Mapper map, Method m) {
String n = map.mapMethodName(m.getOwner(), m.getName(), m.getParameterTypes(), m.getReturnType());
if (n == null) {
n = m.getName();
}
return new Method(mapClassName(map, m.getOwner()), n, mapClassNames(map, m.getParameterTypes()), mapClassName(
map, m.getReturnType()));
}
private static Method mapMethodNameAndOwner(Mapper map, Method m) {
String n = map.mapMethodName(m.getOwner(), m.getName(), m.getParameterTypes(), m.getReturnType());
if (n == null) {
n = m.getName();
}
String owner = map.mapMethodOwner(m.getOwner(), m.getName(), m.getParameterTypes(), m.getReturnType());
if (owner == null) {
owner = m.getOwner();
}
return new Method(owner, n, mapClassNames(map, m.getParameterTypes()), mapClassName(map, m.getReturnType()));
}
static Object mapObject(Mapper map, Object value) {
if (value instanceof DexType) {
value = new DexType(mapClassName(map, ((DexType) value).desc));
} else if (value instanceof Field) {
Field f = (Field) value;
value = mapField(map, f);
} else if (value instanceof Method) {
Method m = (Method) value;
value = mapMethod(map, m);
}
return value;
}
@Override
public DexClassVisitor visit(int access_flags, final String className, String superClass, String[] interfaceNames) {
DexClassVisitor dcv = super.visit(access_flags, mapClassName(mapper, className),
mapClassName(mapper, superClass), mapClassNames(mapper, interfaceNames));
if (dcv != null) {
return new MappingCV(mapper, className, dcv);
}
return dcv;
}
public static class MappingAV extends DexAnnotationVisitor {
protected Mapper mapper;
protected String oldAnnotationClassName;
public MappingAV(String oldAnnotationClassName, Mapper mapper, DexAnnotationVisitor visitor) {
super(visitor);
this.mapper = mapper;
this.oldAnnotationClassName = oldAnnotationClassName;
}
@Override
public void visit(String name, Object value) {
if (name != null && oldAnnotationClassName != null) {
name = mapAnnotationElementName(mapper, oldAnnotationClassName, name);
}
super.visit(name, mapObject(mapper, value));
}
@Override
public DexAnnotationVisitor visitAnnotation(String name, String desc) {
if (name != null && oldAnnotationClassName != null) {
name = mapAnnotationElementName(mapper, oldAnnotationClassName, name);
}
DexAnnotationVisitor dav = super.visitAnnotation(name, mapClassName(mapper, desc));
if (dav != null) {
return new MappingAV(desc, mapper, dav);
}
return dav;
}
@Override
public DexAnnotationVisitor visitArray(String name) {
if (name != null && oldAnnotationClassName != null) {
name = mapAnnotationElementName(mapper, oldAnnotationClassName, name);
}
DexAnnotationVisitor dav = super.visitArray(name);
if (dav != null) {
return new MappingAV(null, mapper, dav);
}
return dav;
}
@Override
public void visitEnum(String name, String desc, String value) {
String fn = mapFieldName(mapper, desc, value, desc);
if (name != null && oldAnnotationClassName != null) {
name = mapAnnotationElementName(mapper, oldAnnotationClassName, name);
}
super.visitEnum(name, mapClassName(mapper, desc), fn);
}
}
public static class MappingCode extends DexCodeVisitor {
protected Mapper mapper;
public MappingCode(Mapper mapper, DexCodeVisitor dcv) {
super(dcv);
this.mapper = mapper;
}
@Override
public DexDebugVisitor visitDebug() {
DexDebugVisitor v = super.visitDebug();
if (v != null) {
return new DexDebugVisitor(v) {
@Override
public void visitStartLocal(int reg, DexLabel label, String name, String type, String signature) {
if (signature != null) {
signature = remapSignature(mapper, signature, true);
}
super.visitStartLocal(reg, label, name, mapClassName(mapper, type), signature);
}
};
}
return v;
}
@Override
public void visitConstStmt(Op op, int ra, Object value) {
super.visitConstStmt(op, ra, mapObject(mapper, value));
}
@Override
public void visitFieldStmt(Op op, int a, int b, Field field) {
super.visitFieldStmt(op, a, b, mapFieldNameAndOwner(mapper, field));
}
@Override
public void visitFilledNewArrayStmt(Op op, int[] args, String type) {
super.visitFilledNewArrayStmt(op, args, mapClassName(mapper, type));
}
@Override
public void visitMethodStmt(Op op, int[] args, Method method) {
switch (op) {
case INVOKE_DIRECT:
case INVOKE_DIRECT_RANGE:
case INVOKE_STATIC:
case INVOKE_STATIC_RANGE:
case INVOKE_INTERFACE:
case INVOKE_INTERFACE_RANGE:
super.visitMethodStmt(op, args, mapMethodNameAndOwner(mapper, method));
break;
default:
super.visitMethodStmt(op, args, mapMethod(mapper, method));
break;
}
}
@Override
public void visitTryCatch(DexLabel start, DexLabel end, DexLabel[] handler, String[] type) {
super.visitTryCatch(start, end, handler, mapClassNames(mapper, type));
}
@Override
public void visitTypeStmt(Op op, int a, int b, String type) {
super.visitTypeStmt(op, a, b, mapClassName(mapper, type));
}
}
public static class MappingCV extends DexClassVisitor {
protected String clzName;
protected Mapper mapper;
public MappingCV(Mapper mapper, String clzName, DexClassVisitor dcv) {
super(dcv);
this.mapper = mapper;
this.clzName = clzName;
}
@Override
public DexAnnotationVisitor visitAnnotation(String name, Visibility visibility) {
final DexAnnotationVisitor dav = super.visitAnnotation(mapClassName(mapper, name), visibility);
if (dav != null) {
switch (name) {
case DexConstants.ANNOTATION_SIGNATURE_TYPE:
return new DexAnnotationNode(name, visibility) {
@Override
public void visitEnd() {
super.visitEnd();
Item p = super.items.get(0);
Object[] newVs = remapSignature(mapper, (Object[]) p.value, false);
dav.visit(p.name, newVs);
dav.visitEnd();
}
};
case DexConstants.ANNOTATION_INNER_CLASS_TYPE:
return new DexAnnotationVisitor(dav) {
@Override
public void visit(String name, Object value) {
if (name.equals("name")) {
String simpleName = (String) value;
if (simpleName != null) {
if (clzName.endsWith("$" + simpleName + ";")) {
String nNameDesc = mapClassName(mapper, clzName);
String containd = mapClassName(mapper,
clzName.substring(0, clzName.length() - 2 - simpleName.length()) + ";");
String internalNameWitherOwner = nNameDesc.substring(1, nNameDesc.length() - 1);
String internalNameOwner = containd.substring(1, containd.length() - 1);
if (internalNameWitherOwner.startsWith(internalNameOwner + "$")) {
value = internalNameWitherOwner.substring(1 + internalNameOwner.length());
} else {
value = null;
}
} else {
value = null;
}
}
}
super.visit(name, value);
}
};
case DexConstants.ANNOTATION_ENCLOSING_CLASS_TYPE:
return new DexAnnotationVisitor(dav) {
@Override
public void visit(String name, Object value) {
if (name.equals("value")) {
super.visit(name, new DexType(mapClassName(mapper, ((DexType) value).desc)));
} else {
super.visit(name, value);
}
}
};
case DexConstants.ANNOTATION_ENCLOSING_METHOD_TYPE: {
return new DexAnnotationVisitor(dav) {
@Override
public void visit(String name, Object value) {
if (name.equals("value")) {
Method m = (Method) value;
super.visit(name, mapMethod(mapper, m));
} else {
super.visit(name, value);
}
}
};
}
default:
return new MappingAV(name, mapper, dav);
}
}
return dav;
}
@Override
public DexFieldVisitor visitField(int accessFlags, Field field, Object value) {
DexFieldVisitor dfv = super.visitField(accessFlags, mapField(mapper, field), mapObject(mapper, value));
if (dfv != null) {
return new MappingFV(mapper, dfv);
}
return null;
}
@Override
public DexMethodVisitor visitMethod(int accessFlags, Method method) {
DexMethodVisitor dmv = super.visitMethod(accessFlags, mapMethod(mapper, method));
if (dmv != null) {
return new MappingMV(mapper, dmv);
}
return dmv;
}
}
public static class MappingFV extends DexFieldVisitor {
protected Mapper mapper;
public MappingFV(Mapper mapper, DexFieldVisitor dfv) {
super(dfv);
this.mapper = mapper;
}
@Override
public DexAnnotationVisitor visitAnnotation(String name, Visibility visibility) {
final DexAnnotationVisitor dav = super.visitAnnotation(mapClassName(mapper, name), visibility);
if (dav != null) {
if (DexConstants.ANNOTATION_SIGNATURE_TYPE.equals(name)) {
return new DexAnnotationNode(name, visibility) {
@Override
public void visitEnd() {
super.visitEnd();
Item p = super.items.get(0);
Object[] newVs = remapSignature(mapper, (Object[]) p.value, true);
dav.visit(p.name, newVs);
dav.visitEnd();
}
};
}
return new MappingAV(name, mapper, dav);
}
return dav;
}
}
public static class MappingMV extends DexMethodVisitor {
protected Mapper mapper;
public MappingMV(Mapper mapper, DexMethodVisitor dmv) {
super(dmv);
this.mapper = mapper;
}
@Override
public DexAnnotationVisitor visitAnnotation(String name, Visibility visibility) {
final DexAnnotationVisitor dav = super.visitAnnotation(mapClassName(mapper, name), visibility);
if (dav != null) {
if (DexConstants.ANNOTATION_SIGNATURE_TYPE.equals(name)) {
return new DexAnnotationNode(name, visibility) {
@Override
public void visitEnd() {
super.visitEnd();
Item p = super.items.get(0);
Object[] newVs = remapSignature(mapper, (Object[]) p.value, false);
dav.visit(p.name, newVs);
dav.visitEnd();
}
};
}
return new MappingAV(name, mapper, dav);
}
return dav;
}
@Override
public DexCodeVisitor visitCode() {
DexCodeVisitor dcv = super.visitCode();
if (dcv != null) {
return new MappingCode(mapper, dcv);
}
return dcv;
}
@Override
public DexAnnotationAble visitParameterAnnotation(int index) {
final DexAnnotationAble a = super.visitParameterAnnotation(index);
if (a != null) {
return new DexAnnotationAble() {
@Override
public DexAnnotationVisitor visitAnnotation(String name, Visibility visibility) {
DexAnnotationVisitor dav = a.visitAnnotation(mapClassName(mapper, name), visibility);
if (dav != null) {
return new MappingAV(name, mapper, dav);
}
return dav;
}
};
}
return a;
}
}
static Object[] remapSignature(final Mapper mapper, Object vs[], boolean isType) {
StringBuilder sb = new StringBuilder();
for (Object v0 : vs) {
sb.append(v0);
}
return Types.buildDexStyleSignature(remapSignature(mapper, sb.toString(), isType));
}
static String remapSignature(final Mapper mapper, String sig, boolean isType) {
SignatureWriter w = new SignatureWriter() {
String clzName;
@Override
public void visitClassType(String name) {
super.visitClassType(mapClassName(mapper, name));
clzName = name;
}
@Override
public void visitInnerClassType(String simpleName) {
String value = simpleName;
if (simpleName != null) {
if (clzName.endsWith("$" + simpleName + ";")) {
String nNameDesc = mapClassName(mapper, clzName);
String containd = mapClassName(mapper,
clzName.substring(0, clzName.length() - 2 - simpleName.length()) + ";");
String internalNameWitherOwner = nNameDesc.substring(1, nNameDesc.length() - 1);
String internalNameOwner = containd.substring(1, containd.length() - 1);
if (internalNameWitherOwner.startsWith(internalNameOwner + "$")) {
value = internalNameWitherOwner.substring(1 + internalNameOwner.length());
} else {
value = null;
}
} else {
value = null;
}
}
super.visitInnerClassType(value);
}
};
if (isType) {
new SignatureReader(sig).acceptType(w);
} else {
new SignatureReader(sig).accept(w);
}
return w.toString();
}
}

View File

@ -1,476 +0,0 @@
/*
* dex2jar - Tools to work with android .dex and java .class files
* Copyright (c) 2009-2013 Panxiaobo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.d2j.map;
import com.googlecode.d2j.DexConstants;
import com.googlecode.d2j.util.Mapper;
import com.googlecode.dex2jar.ir.ts.UniqueQueue;
import java.util.*;
public class InheritanceTree implements Mapper {
Map<String, Clz> clzMap = new HashMap<>();
String from;
boolean isLibrary;
public InheritanceTree() {
}
public static void main(String... args) {
InheritanceTree tree = new InheritanceTree();
Clz a = tree.addClz(0, "La;");
a.addMethod(0, "abc", new String[0], "V");
Clz b = tree.addClz(0, "Lb;");
b.addMethod(0, "abc", new String[0], "V");
Clz c = tree.addClz(0, "Lc;");
c.relateSuper("Ljava/lang/Object;");
c.relateInterface("La;");
c.relateInterface("Lb;");
tree.link();
}
private static boolean isPrivate(int accessFlags) {
return ((DexConstants.ACC_PRIVATE) & accessFlags) != 0;
}
private static boolean isStaticOrPrivate(int accessFlags) {
return ((DexConstants.ACC_PRIVATE | DexConstants.ACC_STATIC) & accessFlags) != 0;
}
private static boolean isStaticOrPrivateOrFinal(int accessFlags) {
return ((DexConstants.ACC_PRIVATE | DexConstants.ACC_STATIC | DexConstants.ACC_FINAL) & accessFlags) != 0;
}
public void updateFrom(String from, boolean isLibrary) {
this.from = from;
this.isLibrary = isLibrary;
}
public String mapClassName(String name) {
Clz clz = clzMap.get(name);
if (clz == null) {
return null;
}
return clz.name.newValue;
}
public void recordClassRenameTo(String old, String newName) {
Clz clz = clzMap.get(old);
if (clz == null) {
WARN("WARN: cant find class %s", old);
return;
}
if (clz.name.noRename) {
WARN("WARN: cant rename class %s");
return;
}
clz.name.newValue = newName;
}
public void recordMethodRenameTo(String owner, String oldName, String[] args, String ret, String newName) {
Clz clz = clzMap.get(owner);
if (clz == null) {
WARN("WARN: cant find class %s", owner);
return;
}
String key = toMethodKey(oldName, args, ret);
Mtd mtd = clz.methods.get(key);
if (mtd == null) {
WARN("WARN: cant find method %s->%s", owner, key);
return;
}
if (mtd.name.noRename && !oldName.equals(newName)) {
WARN("WARN: cant rename method %s->%s to %s", owner, key, newName);
return;
}
if (mtd.name.newValue == null) {
mtd.name.newValue = newName;
} else if (!newName.equals(mtd.name.newValue)) {
WARN("WARN: cant rename method %s->%s to %s, pre rename to %s", owner, key, newName, mtd.name.newValue);
}
}
public void recordFieldRenameTo(String owner, String oldName, String type, String newName) {
Clz clz = clzMap.get(owner);
if (clz == null) {
WARN("WARN: cant find class %s", owner);
return;
}
String key = toFieldKey(oldName, type);
Fld fld = clz.fields.get(key);
if (fld == null) {
WARN("WARN: cant find field %s->%s", owner, key);
return;
}
if (fld.name.noRename && !oldName.equals(newName)) {
WARN("WARN: cant rename field %s->%s to %s", owner, key, newName);
return;
}
if (fld.name.newValue == null) {
fld.name.newValue = newName;
} else if (!newName.equals(fld.name.newValue)) {
WARN("WARN: cant rename field %s->%s to %s, pre rename to %s", owner, key, newName, fld.name.newValue);
}
}
public String mapFieldName(String owner, String name, String type) {
Clz clz = clzMap.get(owner);
if (clz == null) {
return null;
}
Fld fld = clz.fields.get(toFieldKey(name, type));
if (fld == null) {
return null;
}
return fld.name.newValue;
}
public String mapFieldOwner(String owner, String name, String type) {
Clz clz = clzMap.get(owner);
if (clz == null) {
return null;
}
Fld fld = clz.fields.get(toFieldKey(name, type));
if (fld == null) {
return clz.name.newValue;
}
Name fldName = fld.owner.name;
if (fldName.newValue == null) {
return fldName.oldValue;
} else {
return fldName.newValue;
}
}
public String mapMethodName(String owner, String name, String[] args, String ret) {
Clz clz = clzMap.get(owner);
if (clz == null) {
return null;
}
Mtd mtd = null;
if (args == null || ret == null) {
for (Mtd m : clz.methods.values()) {
if (m.args.length == 0 && m.name.oldValue.equals(name)) {
mtd = m;
break;
}
}
} else {
mtd = clz.methods.get(toMethodKey(name, args, ret));
}
if (mtd == null) {
return null;
}
return mtd.name.newValue;
}
public String mapMethodOwner(String owner, String name, String[] args, String ret) {
Clz clz = clzMap.get(owner);
if (clz == null) {
return null;
}
Mtd mtd = null;
if (args == null || ret == null) {
for (Mtd m : clz.methods.values()) {
if (m.args.length == 0 && m.name.oldValue.equals(name)) {
mtd = m;
break;
}
}
} else {
mtd = clz.methods.get(toMethodKey(name, args, ret));
}
if (mtd == null) {
return clz.name.newValue;
}
Name mtdName = mtd.owner.name;
if (mtdName.newValue == null) {
return mtdName.oldValue;
} else {
return mtdName.newValue;
}
}
/**
* @param accessFlags
* the access flags of the class
* @param name
* the descriptor of the class
* @return return null if the class is redefined
*/
Clz addClz(int accessFlags, String name) {
Clz clz = getOrCreateClz(name);
if (clz.stat != Stat.UNKNOWN) {
if (clz.stat == Stat.LIBRARY && !isLibrary) {
WARN("app class %s redefined, org %s, new %s, skiping.", name, clz.from, from);
return null;
} else {
WARN("class %s is defined in %s, skip redefine in %s", name, clz.from, from);
return null;
}
}
clz.stat = isLibrary ? Stat.LIBRARY : Stat.APP;
clz.accessFlags = accessFlags;
clz.from = from;
return clz;
}
public void link() {
Queue<Clz> q = new UniqueQueue<>();
q.addAll(clzMap.values());
while (!q.isEmpty()) {
Clz clz = q.poll();
for (Map.Entry<String, Mtd> e : clz.methods.entrySet()) {
String key = e.getKey();
Mtd mtd = e.getValue();
Name name = mtd.name.trim();
mtd.name = name;
if (name.oldValue.startsWith("<")) {
// constructor, skip
continue;
}
if (isPrivate(mtd.accessFlags)) {
continue;
}
if (clz.children.size() > 0) {
for (Clz child : clz.children) {
Mtd childMtd = child.methods.get(key);
if (childMtd != null) {
if (isStaticOrPrivateOrFinal(childMtd.accessFlags)) {
continue;
}
childMtd.name = merge(name, childMtd.name);
} else {
child.methods.put(key, mtd);
q.add(child);
}
}
}
if (clz.impls.size() > 0) {
for (Clz child : clz.impls) {
Mtd childMtd = child.methods.get(key);
if (childMtd != null) {
childMtd.name = merge(name, childMtd.name);
} else {
child.methods.put(key, mtd);
q.add(child);
}
}
}
}
}
q.addAll(clzMap.values());
while (!q.isEmpty()) {
Clz clz = q.poll();
if (clz.fields.size() > 0) {
for (Map.Entry<String, Fld> e : clz.fields.entrySet()) {
String key = e.getKey();
Fld fld = e.getValue();
if (isPrivate(fld.accessFlags)) { // also copy static method to sub
continue;
}
if (clz.children.size() > 0) {
for (Clz child : clz.children) {
if (!child.fields.containsKey(key)) {
child.fields.put(key, fld);
q.add(child);
}
}
}
}
}
}
for (Clz clz : clzMap.values()) {
if (clz.stat == Stat.UNKNOWN) {
WARN("clz %s is unknow", clz.name);
}
boolean noRename = clz.stat == Stat.UNKNOWN || clz.stat == Stat.LIBRARY;
clz.name.noRename = noRename;
if (clz.methods.size() > 0) {
for (Mtd mtd : clz.methods.values()) {
Name name = mtd.name.trim();
mtd.name = name;
if (noRename) {
name.noRename = true;
}
}
}
if (noRename && clz.fields.size() > 0) {
for (Fld fld : clz.fields.values()) {
fld.name.noRename = true;
}
}
// relationship is useless now
clz.children = null;
clz.impls = null;
clz.superClz = null;
clz.interfaces = null;
}
}
private Name merge(Name name, Name childMtd) {
childMtd = childMtd.trim();
if (childMtd != name) {
childMtd.next = name;
}
return name;
}
private boolean isPrivateOrFinal(int accessFlags) {
return ((DexConstants.ACC_PRIVATE | DexConstants.ACC_FINAL) & accessFlags) != 0;
}
private void WARN(String s, Object... args) {
System.err.println(String.format(s, args));
}
Clz getOrCreateClz(String name) {
Clz clz = clzMap.get(name);
if (clz == null) {
clz = new Clz(name);
clzMap.put(name, clz);
}
return clz;
}
public static String toFieldKey(String name, String type) {
return name + ":" + type;
}
public static String toMethodKey(String name, String args[], String ret) {
StringBuilder sb = new StringBuilder();
sb.append(name).append("(");
for (String arg : args) {
sb.append(arg);
}
sb.append(")").append(ret);
return sb.toString();
}
public enum Stat {
UNKNOWN, LIBRARY, APP
}
public static class Name {
final String oldValue;
boolean noRename = false;
String newValue;
Name next;
public Name(String name) {
this.oldValue = name;
}
public String toString() {
return oldValue;
}
public Name trim() {
Name n = this;
while (n.next != null) {
n = n.next;
}
return n;
}
}
public static class Fld {
public int accessFlags;
public Name name;
public Clz owner;
public String type;
}
public static class Mtd {
public int accessFlags;
public Name name;
public Clz owner;
public String ret;
public String[] args;
}
public class Clz {
public final Name name;
public Stat stat = Stat.UNKNOWN;
public String from;
public int accessFlags;
public Clz superClz;
public Set<Clz> interfaces = new HashSet<>();
public Set<Clz> children = new HashSet<>();
public Set<Clz> impls = new HashSet<>();
public Map<String, Mtd> methods = new HashMap<>();
public Map<String, Fld> fields = new HashMap<>();
Clz(String name) {
this.name = new Name(name);
}
public String toString() {
return name.toString();
}
public void relateSuper(String name) {
Clz s = getOrCreateClz(name);
superClz = s;
s.children.add(this);
}
public void relateInterface(String itf) {
Clz s = getOrCreateClz(itf);
interfaces.add(s);
s.impls.add(this);
}
public void addMethod(int accessFlags, String name, String args[], String ret) {
String key = toMethodKey(name, args, ret);
if (methods.containsKey(key)) {
WARN("DUP method: %s in class %s, skiping.", key, this.name);
return;
}
Mtd mtd = new Mtd();
mtd.owner = this;
mtd.accessFlags = accessFlags;
mtd.name = new Name(name);
mtd.ret = ret;
mtd.args = args;
methods.put(key, mtd);
}
public void addField(int accessFlags, String name, String type) {
String key = toFieldKey(name, type);
if (fields.containsKey(key)) {
WARN("DUP field: %s in class %s, skiping.", key, this.name);
return;
}
Fld fld = new Fld();
fld.owner = this;
fld.name = new Name(name);
fld.accessFlags = accessFlags;
fld.type = type;
fields.put(key, fld);
}
}
}

View File

@ -1,110 +0,0 @@
/*
* dex2jar - Tools to work with android .dex and java .class files
* Copyright (c) 2009-2013 Panxiaobo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.d2j.map;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
public class ProguardMappingParser {
private String j2d(String type) {
StringBuilder sb = new StringBuilder();
while (type.endsWith("[]")) {
sb.append("[");
type = type.substring(0, type.length() - 2);
}
switch (type) {
case "boolean":
sb.append("Z");
break;
case "byte":
sb.append("B");
break;
case "short":
sb.append("S");
break;
case "char":
sb.append("C");
break;
case "int":
sb.append("I");
break;
case "float":
sb.append("F");
break;
case "long":
sb.append("J");
break;
case "double":
sb.append("D");
break;
case "void":
sb.append("V");
break;
default:
sb.append("L").append(type.replace('.', '/')).append(";");
break;
}
return sb.toString();
}
public void parse(Reader in, InheritanceTree tree) throws IOException {
BufferedReader r = new BufferedReader(in);
String currentClz = null;
for (String ln = r.readLine(); ln != null; ln = r.readLine()) {
if (ln.startsWith(" ")) { // member mapping
// java.lang.String data -> a
// boolean equals(java.lang.Object) -> equals
ln = ln.trim();
String as[] = ln.split(" ");
String fieldDescOrMethodRet = j2d(as[0]);
String fieldNameOrMethodNameDesc = as[1];
String newName = as[3];
if (fieldNameOrMethodNameDesc.contains("(")) { // a method
int idx = fieldNameOrMethodNameDesc.indexOf('(');
String mName = fieldNameOrMethodNameDesc.substring(0, idx);
String args = fieldNameOrMethodNameDesc.substring(idx + 1,
fieldNameOrMethodNameDesc.length() - 1);
String[] ps;
if (args.length() != 0) {
ps = args.split(",");
for (int i = 0; i < ps.length; i++) {
ps[i] = j2d(ps[i]);
}
} else {
ps = new String[0];
}
tree.recordMethodRenameTo(currentClz, mName, ps, fieldDescOrMethodRet, newName);
} else {
tree.recordFieldRenameTo(currentClz, fieldNameOrMethodNameDesc, fieldDescOrMethodRet, newName);
}
} else { // clz mapping
// clz -> n:
String as[] = ln.split(" ");
currentClz = j2d(as[0]);
String newName = as[2];
if (newName.endsWith(":")) {
newName = newName.substring(0, newName.length() - 1);
}
tree.recordClassRenameTo(currentClz, j2d(newName));
}
}
}
}

View File

@ -1,132 +0,0 @@
package com.googlecode.dex2jar.tools;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.ClassNode;
import com.googlecode.d2j.dex.writer.DexFileWriter;
import com.googlecode.d2j.jasmin.Jasmins;
import com.googlecode.d2j.map.*;
import com.googlecode.d2j.reader.DexFileReader;
import com.googlecode.d2j.reader.zip.ZipUtil;
import com.googlecode.d2j.smali.Smali;
import com.googlecode.d2j.visitors.DexFileVisitor;
import com.googlecode.dex2jar.tools.BaseCmd.Syntax;
@Syntax(cmd = "d2j-dex-mapping", syntax = "[options] <dex>", desc = "remap names in dex file")
public class DexRemapCmd extends BaseCmd {
@Opt(opt = "o", longOpt = "output", description = "the name of the dex file that will be written. The default is out.dex", argName = "FILE")
private File output;
@Opt(opt = "L", longOpt = "library", description = "libraries we want load ',' separated")
private String library;
@Opt(opt = "C", longOpt = "config-file", description = "the config file generated by proguard", argName = "conf")
private Path config;
public static void main(String[] args) {
new DexRemapCmd().doMain(args);
}
void V(String fmt, Object... args) {
System.err.println(String.format(fmt, args));
}
@Override
protected void doCommandLine() throws Exception {
if (remainingArgs.length < 1) {
System.err.println("ERROR: no file to process");
return;
}
if (config == null) {
System.err.println("ERROR: please set the config file -L,--config-file");
return;
}
if (output == null) {
output = new File("out.dex");
}
final InheritanceTree tree = buildRenameTree();
DexFileWriter fw = new DexFileWriter();
DexFileVisitor fv = new DexFileVisitor(fw) {
@Override
public void visitEnd() {
//
}
};
fv = new DexMappingAdapter(tree, fv);
for (String s : remainingArgs) {
V(">> Remap %s -> %s", s, output);
DexFileReader reader = new DexFileReader(ZipUtil.readDex(new File(s)));
reader.accept(fv);
}
fw.visitEnd();
byte[] data = fw.toByteArray();
Files.write(output.toPath(),data);
}
private InheritanceTree buildRenameTree() throws IOException {
final InheritanceTree tree = new InheritanceTree();
AutoDetectSourceProcess processer = new AutoDetectSourceProcess() {
DexInheritanceFileVisitor dfv = new DexInheritanceFileVisitor(tree);
AsmInheritanceClassVisitor acv = new AsmInheritanceClassVisitor(tree);
@Override
protected void onDex(Path file) throws IOException {
DexFileReader r = new DexFileReader(ZipUtil.readDex(Files.readAllBytes(file)));
r.accept(dfv, DexFileReader.SKIP_CODE | DexFileReader.SKIP_ANNOTATION
| DexFileReader.SKIP_FIELD_CONSTANT);
}
@Override
protected void onClass(Path file) throws IOException {
ClassReader cr = new ClassReader(Files.readAllBytes(file));
cr.accept(acv, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
}
@Override
protected void onJasmin(Path file) throws IOException {
ClassNode cn = Jasmins.parse(file);
cn.accept(acv);
}
@Override
protected void onSmali(Path file) throws IOException {
Smali smali = new Smali();
smali.smaliFile(file, dfv);
}
};
for (String lib : library.split(",")) {
V("<< Load Lib %s", lib);
tree.updateFrom(lib, true);
processer.process(lib);
}
for (String s : remainingArgs) {
V("<< Load App %s", s);
tree.updateFrom(s, false);
processer.process(s);
}
V("<< Link for rename");
tree.link();
V("<< Apply config file %s", config);
try (Reader configReadre = Files.newBufferedReader(config, StandardCharsets.UTF_8)) {
new ProguardMappingParser().parse(configReadre, tree);
}
return tree;
}
}

View File

@ -1,72 +0,0 @@
/*
* dex2jar - Tools to work with android .dex and java .class files
* Copyright (c) 2009-2012 Panxiaobo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.dex2jar.tools;
import java.io.File;
import java.nio.file.Path;
import com.googlecode.dex2jar.tools.BaseCmd.Syntax;
@Syntax(cmd = "d2j-jar-remap", syntax = "[options] jar", desc = "rename package/class/method/field name in a jar", onlineHelp = "https://code.google.com/p/dex2jar/wiki/DeObfuscateJarWithDexTool")
public class JarRemap extends BaseCmd {
public static void main(String... args) {
new JarRemap().doMain(args);
}
@Opt(opt = "f", longOpt = "force", hasArg = false, description = "force overwrite")
private boolean forceOverwrite = false;
@Opt(opt = "o", longOpt = "output", description = "output .jar file, default is $current_dir/[jar-name]-remap.jar", argName = "out-jar")
private File output;
@Opt(opt = "c", longOpt = "config", required = true, description = "config file for remap, this is REQUIRED", argName = "config")
private Path config;
@Opt(opt = "L", longOpt = "library", description = "libraries we want load ',' separated")
private String library;
@Opt(opt = "C", longOpt = "config-file", description = "the config file generated by proguard", argName = "conf")
private Path proguardConfig;
@Override
protected void doCommandLine() throws Exception {
if (remainingArgs.length != 1) {
usage();
return;
}
File jar = new File(remainingArgs[0]);
if (!jar.exists()) {
System.err.println(jar + " is not exists");
usage();
return;
}
if (output == null) {
if (jar.isDirectory()) {
output = new File(jar.getName() + "-remap.jar");
} else {
output = new File(getBaseName(jar.getName()) + "-remap.jar");
}
}
if (output.exists() && !forceOverwrite) {
System.err.println(output + " exists, use --force to overwrite");
usage();
return;
}
System.out.println("remap " + jar + " -> " + output);
// new ReName().from(jar).withConfig(config).to(output);
}
}