use of org.jf.dexlib2.iface.Method in project atlas by alibaba.
the class MethodDefinition method writeEmptyMethodTo.
public static void writeEmptyMethodTo(IndentingWriter writer, Method method, baksmaliOptions options) throws IOException {
writer.write(".method ");
writeAccessFlags(writer, method.getAccessFlags());
writer.write(method.getName());
writer.write("(");
ImmutableList<MethodParameter> methodParameters = ImmutableList.copyOf(method.getParameters());
for (MethodParameter parameter : methodParameters) {
writer.write(parameter.getType());
}
writer.write(")");
writer.write(method.getReturnType());
writer.write('\n');
writer.indent(4);
writeParameters(writer, method, methodParameters, options);
String containingClass = null;
if (options.useImplicitReferences) {
containingClass = method.getDefiningClass();
}
//如果是修改的方法,需要添加ReplaceAnnotation
if (DexDiffInfo.modifiedMethods.contains(method)) {
MethodReplaceAnnotation replaceAnnotation = new MethodReplaceAnnotation(method.getDefiningClass(), method.getName());
AnnotationFormatter.writeTo(writer, method.getAnnotations(), containingClass, replaceAnnotation);
} else {
AnnotationFormatter.writeTo(writer, method.getAnnotations(), containingClass);
}
writer.deindent(4);
writer.write(".end method\n");
}
use of org.jf.dexlib2.iface.Method in project atlas by alibaba.
the class MethodDefinition method addAnalyzedInstructionMethodItems.
private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) {
MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classDef.options.classPath, method, classDef.options.inlineResolver);
AnalysisException analysisException = methodAnalyzer.getAnalysisException();
if (analysisException != null) {
// TODO: need to keep track of whether any errors occurred, so we can exit with a non-zero result
methodItems.add(new CommentMethodItem(String.format("AnalysisException: %s", analysisException.getMessage()), analysisException.codeAddress, Integer.MIN_VALUE));
analysisException.printStackTrace(System.err);
}
List<AnalyzedInstruction> instructions = methodAnalyzer.getAnalyzedInstructions();
int currentCodeAddress = 0;
for (int i = 0; i < instructions.size(); i++) {
AnalyzedInstruction instruction = instructions.get(i);
MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, currentCodeAddress, instruction.getInstruction());
methodItems.add(methodItem);
if (instruction.getInstruction().getOpcode().format == Format.UnresolvedOdexInstruction) {
methodItems.add(new CommentedOutMethodItem(InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, currentCodeAddress, instruction.getOriginalInstruction())));
}
if (i != instructions.size() - 1) {
methodItems.add(new BlankMethodItem(currentCodeAddress));
}
if (classDef.options.addCodeOffsets) {
methodItems.add(new MethodItem(currentCodeAddress) {
@Override
public double getSortOrder() {
return -1000;
}
@Override
public boolean writeTo(IndentingWriter writer) throws IOException {
writer.write("#@");
writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL);
return true;
}
});
}
if (classDef.options.registerInfo != 0 && !instruction.getInstruction().getOpcode().format.isPayloadFormat) {
methodItems.add(new PreInstructionRegisterInfoMethodItem(classDef.options.registerInfo, methodAnalyzer, registerFormatter, instruction, currentCodeAddress));
methodItems.add(new PostInstructionRegisterInfoMethodItem(registerFormatter, instruction, currentCodeAddress));
}
currentCodeAddress += instruction.getInstruction().getCodeUnits();
}
}
use of org.jf.dexlib2.iface.Method in project atlas by alibaba.
the class ClassDefinition method writeDirectMethods.
private Set<String> writeDirectMethods(IndentingWriter writer) throws IOException {
boolean wroteHeader = false;
Set<String> writtenMethods = new HashSet<String>();
Iterable<? extends Method> directMethods;
Set<? extends Method> modifieds = null;
if (classDef instanceof DexBackedClassDef) {
directMethods = ((DexBackedClassDef) classDef).getDirectMethods(false);
modifieds = (Set<? extends Method>) DexDiffInfo.modifiedMethods;
} else {
directMethods = classDef.getDirectMethods();
}
MethodReplaceAnnotation replaceAnnotaion;
for (Method method : directMethods) {
if (!fullMethod && !DexDiffInfo.addedClasses.contains(classDef)) {
if (!modifieds.contains(method) && !DexDiffInfo.addedMethods.contains(method)) {
continue;
}
}
if (!wroteHeader) {
writer.write("\n\n");
writer.write("# direct methods");
wroteHeader = true;
}
writer.write('\n');
// TODO: check for method validation errors
String methodString = ReferenceUtil.getMethodDescriptor(method, true);
IndentingWriter methodWriter = writer;
if (!writtenMethods.add(methodString)) {
writer.write("# duplicate method ignored\n");
methodWriter = new CommentingIndentingWriter(writer);
}
MethodImplementation methodImpl = method.getImplementation();
if (methodImpl == null) {
MethodDefinition.writeEmptyMethodTo(methodWriter, method, options);
} else {
MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
methodDefinition.setFullMethod(fullMethod);
methodDefinition.writeTo(methodWriter);
}
}
return writtenMethods;
}
use of org.jf.dexlib2.iface.Method in project atlas by alibaba.
the class ClassDefinition method writeVirtualMethods.
private void writeVirtualMethods(IndentingWriter writer, Set<String> directMethods) throws IOException {
boolean wroteHeader = false;
Set<String> writtenMethods = new HashSet<String>();
Iterable<? extends Method> virtualMethods;
Set<? extends Method> modifieds = null;
if (classDef instanceof DexBackedClassDef) {
virtualMethods = ((DexBackedClassDef) classDef).getVirtualMethods(false);
modifieds = (Set<? extends Method>) DexDiffInfo.modifiedMethods;
} else {
virtualMethods = classDef.getVirtualMethods();
}
MethodReplaceAnnotation replaceAnnotaion;
for (Method method : virtualMethods) {
if (!fullMethod && !DexDiffInfo.addedClasses.contains(classDef)) {
if (!modifieds.contains(method) && !DexDiffInfo.addedMethods.contains(method)) {
continue;
}
}
if (!wroteHeader) {
writer.write("\n\n");
writer.write("# virtual methods");
wroteHeader = true;
}
writer.write('\n');
// TODO: check for method validation errors
String methodString = ReferenceUtil.getMethodDescriptor(method, true);
IndentingWriter methodWriter = writer;
if (!writtenMethods.add(methodString)) {
writer.write("# duplicate method ignored\n");
methodWriter = new CommentingIndentingWriter(writer);
} else if (directMethods.contains(methodString)) {
writer.write("# There is both a direct and virtual method with this signature.\n" + "# You will need to rename one of these methods, including all references.\n");
System.err.println(String.format("Duplicate direct+virtual method found: %s->%s", classDef.getType(), methodString));
System.err.println("You will need to rename one of these methods, including all references.");
}
MethodImplementation methodImpl = method.getImplementation();
if (methodImpl == null) {
MethodDefinition.writeEmptyMethodTo(methodWriter, method, options);
} else {
MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
methodDefinition.writeTo(methodWriter);
}
}
}
use of org.jf.dexlib2.iface.Method in project atlas by alibaba.
the class FastPatchTool method doPatch.
public void doPatch() throws IOException, PatchException, RecognitionException {
MappingReader mappingReader = null;
MappingProcessor mappingProcessor = null;
if (outDir == null || !outDir.exists()) {
return;
}
outPatchFile = new File(outDir, "apatch-unsigned.apatch");
if (mappingFile != null && mappingFile.exists()) {
mappingReader = new MappingReader(mappingFile);
mappingProcessor = new MappingProcessorImpl(superClassMap);
mappingReader.pump(mappingProcessor);
mappingProcessor.updateMethod();
mappingProcessor.updateFieldType();
}
for (FastPatchObject fastPatchObject : patchObjects) {
Set<ClassDef> classes = new HashSet<ClassDef>();
Map<ClassDef, List<Method>> patchClassDefs = new HashMap<ClassDef, List<Method>>();
Set<ClassDef> addedClasses = new HashSet<ClassDef>();
Map<ClassDef, List<Method>> newClassDef = new HashMap<ClassDef, List<Method>>();
ArrayList<Method> methods = new ArrayList<Method>();
for (File dexFile : fastPatchObject.DexFiles) {
DexFile dFile = DexFileFactory.loadDexFile(dexFile.getAbsolutePath(), 19, true);
classes.addAll(dFile.getClasses());
}
final Set<ClassDef> newClasses = new HashSet<ClassDef>();
for (ClassDef classDef : classes) {
String type = classDef.getType();
if (fastPatchObject.addedClass.contains(SmaliUtils.getDalvikClassName(type))) {
System.out.println("patch added class:" + type);
addedClasses.add(classDef);
continue;
}
for (Map.Entry<String, List<String>> entry : fastPatchObject.modifyClasses.entrySet()) {
if (entry.getKey().equals(SmaliUtils.getDalvikClassName(type))) {
ArrayList<Method> newMethods = new ArrayList<Method>();
for (Method method : classDef.getMethods()) {
System.err.println(getMethodFullName(method));
if (entry.getValue().contains(getMethodFullName(method))) {
newMethods.add(method);
}
}
patchClassDefs.put(classDef, newMethods);
break;
}
}
}
if (patchClassDefs.size() == 0 && addedClasses.size() == 0) {
continue;
}
if (mappingFile != null && mappingFile.exists()) {
//第一步先将prepareclass混淆掉
for (String className : fastPatchObject.prepareClasses) {
ApkPatch.prepareClasses.add(mappingProcessor.getNewClassName(className).className);
}
//将replaceanatation混淆掉
MethodReplaceAnnotation.ANNOTATION = DefineUtils.getDefineClassName(mappingProcessor.getNewClassName(DefineUtils.getDalvikClassName("Lcom/alipay/euler/andfix/annotation/MethodReplace;")).className, false);
//将dex代码混淆掉
InsTructionsReIClassDef insTructionsReDef = new InsTructionsReIClassDef(new MappingClassProcessor(mappingProcessor));
for (ClassDef c : classes) {
if (patchClassDefs.containsKey(c)) {
for (Method method : c.getMethods()) {
if (patchClassDefs.get(c).contains(method)) {
methods.add(insTructionsReDef.reMethod(method));
}
}
newClassDef.put(insTructionsReDef.reClassDef(c), methods);
} else if (addedClasses.contains(c)) {
newClassDef.put(insTructionsReDef.reClassDef(c), new ArrayList<Method>());
}
if (c.getType().contains("/R$")) {
continue;
}
newClasses.add(insTructionsReDef.reClassDef(c));
}
} else {
ApkPatch.prepareClasses.addAll(fastPatchObject.prepareClasses);
}
File patchDexFile = new File(outDir, "patch.dex");
for (ClassDef classDef : newClassDef.keySet()) {
System.out.println("modify class:" + classDef.getType());
}
if (newClassDef.size() > 0) {
DexFileFactory.writeDexFile(patchDexFile.getAbsolutePath(), new ImmutableDexFile(newClassDef.keySet()));
} else if (patchClassDefs.size() > 0) {
DexFileFactory.writeDexFile(patchDexFile.getAbsolutePath(), new ImmutableDexFile(patchClassDefs.keySet()));
}
File tempDexFile = new File(outDir, "temp.dex");
if (newClasses.size() > 0) {
DexFileFactory.writeDexFile(tempDexFile.getAbsolutePath(), new DexFile() {
@Nonnull
@Override
public Set<? extends ClassDef> getClasses() {
return new AbstractSet<ClassDef>() {
@Nonnull
@Override
public Iterator<ClassDef> iterator() {
return newClasses.iterator();
}
@Override
public int size() {
return newClasses.size();
}
};
}
});
} else if (classes.size() > 0) {
DexFileFactory.writeDexFile(tempDexFile.getAbsolutePath(), new ImmutableDexFile(classes));
}
SmaliDiffUtils.scanClasses(new File(outDir, "smali2"), Lists.newArrayList(tempDexFile));
DexFile patchDex = DexFileFactory.loadDexFile(patchDexFile.getAbsolutePath(), 19, true);
DexFile tempDex = DexFileFactory.loadDexFile(tempDexFile.getAbsolutePath(), 19, true);
Set<? extends ClassDef> patchClasses = patchDex.getClasses();
DexDiffInfo dexDiffInfo = new DexDiffInfo();
for (ClassDef patchClassDef : patchClasses) {
String type = patchClassDef.getType();
if (fastPatchObject.addedClass.contains(SmaliUtils.getDalvikClassName(type))) {
dexDiffInfo.getAddedClasses().add((DexBackedClassDef) patchClassDef);
dexDiffInfo.addManifestAddClass(type);
continue;
}
for (Method method : patchClassDef.getMethods()) {
List<? extends CharSequence> parameters = method.getParameterTypes();
if (methods.size() > 0) {
for (Method modifyMethod : methods) {
List<? extends CharSequence> modifyParameters = modifyMethod.getParameterTypes();
if (parameters.size() != modifyParameters.size() || !isEqualObj(parameters, modifyParameters)) {
continue;
}
if (modifyMethod.getName().equals(method.getName()))
dexDiffInfo.addModifiedMethods((DexBackedMethod) method);
}
} else if (patchClassDefs.size() > 0) {
for (ClassDef classDef : patchClassDefs.keySet()) {
if (classDef.getType().equals(patchClassDef.getType())) {
List<Method> methodList = patchClassDefs.get(classDef);
for (Method method1 : methodList) {
if (method1.getName().equals(method.getName())) {
dexDiffInfo.addModifiedMethods((DexBackedMethod) method);
}
}
}
}
}
}
}
FastBuild fastBuild = new FastBuild(fastPatchObject.bundleName, new File(outDir, bundleName));
fastBuild.setClasses(tempDex.getClasses());
fastBuild.setDiffInfo(dexDiffInfo);
new AndFixFilterImpl(dexDiffInfo).filterDex();
dexDiffInfo.update();
APatchTool.isApatch = true;
File adiffFile = new File(outDir, "apatch-diff.txt");
File adiffJsonFile = new File(outDir, "apatch-diff.json");
dexDiffInfo.writeToFile(fastPatchObject.bundleName, adiffFile, adiffJsonFile);
try {
File patchJarFile = fastBuild.dopatch();
patchJarFiles.add(patchJarFile);
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (UnrecoverableEntryException e) {
e.printStackTrace();
}
}
File[] aPatchFiles = new File[patchJarFiles.size()];
aPatchFiles = patchJarFiles.toArray(aPatchFiles);
File mergePatchFile = null;
if (null != aPatchFiles && aPatchFiles.length > 1) {
MergePatch mergePatch = new MergePatch(aPatchFiles, "com_taobao_android", outDir);
mergePatchFile = mergePatch.doMerge();
} else if (null != aPatchFiles && aPatchFiles.length == 1) {
mergePatchFile = aPatchFiles[0];
}
if (null != mergePatchFile && mergePatchFile.exists()) {
FileUtils.moveFile(mergePatchFile, outPatchFile);
}
}
Aggregations