mirror of
https://github.com/revanced/Apktool.git
synced 2025-01-08 11:05:52 +01:00
Updated smali to 1.3.0-brut6 .
This commit is contained in:
parent
5d05136ab7
commit
2aa7a70b74
@ -16,7 +16,7 @@
|
|||||||
<name>apktool library</name>
|
<name>apktool library</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<smaliVersion>1.2.6-brut5</smaliVersion>
|
<smaliVersion>1.3.0-brut6</smaliVersion>
|
||||||
<root.basedir>${project.parent.basedir}</root.basedir>
|
<root.basedir>${project.parent.basedir}</root.basedir>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
@ -1,220 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2011 Ryszard Wiśniewski <brut.alll@gmail.com>
|
|
||||||
*
|
|
||||||
* 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 brut.androlib.mod;
|
|
||||||
|
|
||||||
import brut.androlib.src.TypeName;
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import org.jf.baksmali.Adaptors.ClassDefinition;
|
|
||||||
import org.jf.baksmali.baksmali;
|
|
||||||
import org.jf.util.ClassFileNameHandler;
|
|
||||||
import org.jf.dexlib.ClassDefItem;
|
|
||||||
import org.jf.dexlib.Code.Analysis.ClassPath;
|
|
||||||
import org.jf.dexlib.DexFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
|
||||||
*/
|
|
||||||
public class BaksmaliMod {
|
|
||||||
|
|
||||||
public static void disassembleDexFile(boolean debug, String dexFilePath, DexFile dexFile, boolean deodex, String outputDirectory,
|
|
||||||
String[] classPathDirs, String bootClassPath, String extraBootClassPath,
|
|
||||||
boolean noParameterRegisters, boolean useLocalsDirective,
|
|
||||||
boolean useSequentialLabels, boolean outputDebugInfo, boolean addCodeOffsets,
|
|
||||||
int registerInfo, boolean verify, boolean ignoreErrors)
|
|
||||||
{
|
|
||||||
baksmali.noParameterRegisters = noParameterRegisters;
|
|
||||||
baksmali.useLocalsDirective = useLocalsDirective;
|
|
||||||
baksmali.useSequentialLabels = useSequentialLabels;
|
|
||||||
baksmali.outputDebugInfo = outputDebugInfo;
|
|
||||||
baksmali.addCodeOffsets = addCodeOffsets;
|
|
||||||
baksmali.deodex = deodex;
|
|
||||||
baksmali.registerInfo = registerInfo;
|
|
||||||
baksmali.bootClassPath = bootClassPath;
|
|
||||||
baksmali.verify = verify;
|
|
||||||
|
|
||||||
ClassPath.ClassPathErrorHandler classPathErrorHandler = null;
|
|
||||||
if (ignoreErrors) {
|
|
||||||
classPathErrorHandler = new ClassPath.ClassPathErrorHandler() {
|
|
||||||
public void ClassPathError(String className, Exception ex) {
|
|
||||||
System.err.println(String.format("Skipping %s", className));
|
|
||||||
ex.printStackTrace(System.err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean analyze = ! ClassPath.dontLoadClassPath
|
|
||||||
&& (registerInfo != 0 || deodex || verify);
|
|
||||||
|
|
||||||
if (analyze) {
|
|
||||||
try {
|
|
||||||
String[] extraBootClassPathArray = null;
|
|
||||||
if (extraBootClassPath != null && extraBootClassPath.length() > 0) {
|
|
||||||
assert extraBootClassPath.charAt(0) == ':';
|
|
||||||
extraBootClassPathArray = extraBootClassPath.substring(1).split(":");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dexFile.isOdex() && bootClassPath == null) {
|
|
||||||
//ext.jar is a special case - it is typically the 2nd jar in the boot class path, but it also
|
|
||||||
//depends on classes in framework.jar (typically the 3rd jar in the BCP). If the user didn't
|
|
||||||
//specify a -c option, we should add framework.jar to the boot class path by default, so that it
|
|
||||||
//"just works"
|
|
||||||
if (extraBootClassPathArray == null && isExtJar(dexFilePath)) {
|
|
||||||
extraBootClassPathArray = new String[] {"framework.jar"};
|
|
||||||
}
|
|
||||||
ClassPath.InitializeClassPathFromOdex(classPathDirs, extraBootClassPathArray, dexFilePath, dexFile,
|
|
||||||
classPathErrorHandler);
|
|
||||||
} else {
|
|
||||||
String[] bootClassPathArray = null;
|
|
||||||
if (bootClassPath != null) {
|
|
||||||
bootClassPathArray = bootClassPath.split(":");
|
|
||||||
}
|
|
||||||
ClassPath.InitializeClassPath(classPathDirs, bootClassPathArray, extraBootClassPathArray,
|
|
||||||
dexFilePath, dexFile, classPathErrorHandler);
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
System.err.println("\n\nError occured while loading boot class path files. Aborting.");
|
|
||||||
ex.printStackTrace(System.err);
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
File outputDirectoryFile = new File(outputDirectory);
|
|
||||||
if (!outputDirectoryFile.exists()) {
|
|
||||||
if (!outputDirectoryFile.mkdirs()) {
|
|
||||||
System.err.println("Can't create the output directory " + outputDirectory);
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//sort the classes, so that if we're on a case-insensitive file system and need to handle classes with file
|
|
||||||
//name collisions, then we'll use the same name for each class, if the dex file goes through multiple
|
|
||||||
//baksmali/smali cycles for some reason. If a class with a colliding name is added or removed, the filenames
|
|
||||||
//may still change of course
|
|
||||||
ArrayList<ClassDefItem> classDefItems = new ArrayList<ClassDefItem>(dexFile.ClassDefsSection.getItems());
|
|
||||||
Collections.sort(classDefItems, new Comparator<ClassDefItem>() {
|
|
||||||
public int compare(ClassDefItem classDefItem1, ClassDefItem classDefItem2) {
|
|
||||||
return classDefItem1.getClassType().getTypeDescriptor().compareTo(classDefItem1.getClassType().getTypeDescriptor());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ClassFileNameHandler fileNameHandler = new ClassFileNameHandler(outputDirectoryFile, ".smali");
|
|
||||||
|
|
||||||
for (ClassDefItem classDefItem: classDefItems) {
|
|
||||||
/**
|
|
||||||
* The path for the disassembly file is based on the package name
|
|
||||||
* The class descriptor will look something like:
|
|
||||||
* Ljava/lang/Object;
|
|
||||||
* Where the there is leading 'L' and a trailing ';', and the parts of the
|
|
||||||
* package name are separated by '/'
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (analyze) {
|
|
||||||
//If we are analyzing the bytecode, make sure that this class is loaded into the ClassPath. If it isn't
|
|
||||||
//then there was some error while loading it, and we should skip it
|
|
||||||
ClassPath.ClassDef classDef = ClassPath.getClassDef(classDefItem.getClassType(), false);
|
|
||||||
if (classDef == null || classDef instanceof ClassPath.UnresolvedClassDef) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String classDescriptor = classDefItem.getClassType().getTypeDescriptor();
|
|
||||||
|
|
||||||
//validate that the descriptor is formatted like we expect
|
|
||||||
if (classDescriptor.charAt(0) != 'L' ||
|
|
||||||
classDescriptor.charAt(classDescriptor.length()-1) != ';') {
|
|
||||||
System.err.println("Unrecognized class descriptor - " + classDescriptor + " - skipping class");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
File smaliFile = fileNameHandler.getUniqueFilenameForClass(classDescriptor);
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
String smaliPath = smaliFile.getPath();
|
|
||||||
smaliFile = new File(
|
|
||||||
smaliPath.substring(0, smaliPath.length() - 6) + ".java");
|
|
||||||
}
|
|
||||||
|
|
||||||
//create and initialize the top level string template
|
|
||||||
ClassDefinition classDefinition = new ClassDefinition(classDefItem);
|
|
||||||
|
|
||||||
//write the disassembly
|
|
||||||
Writer writer = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File smaliParent = smaliFile.getParentFile();
|
|
||||||
if (!smaliParent.exists()) {
|
|
||||||
if (!smaliParent.mkdirs()) {
|
|
||||||
System.err.println("Unable to create directory " + smaliParent.toString() + " - skipping class");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!smaliFile.exists()){
|
|
||||||
if (!smaliFile.createNewFile()) {
|
|
||||||
System.err.println("Unable to create file " + smaliFile.toString() + " - skipping class");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedWriter bufWriter = new BufferedWriter(new OutputStreamWriter(
|
|
||||||
new FileOutputStream(smaliFile), "UTF8"));
|
|
||||||
|
|
||||||
writer = new IndentingWriter(bufWriter);
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
TypeName name = TypeName.fromInternalName(
|
|
||||||
classDefItem.getClassType().getTypeDescriptor());
|
|
||||||
writer.write("package " + name.package_ + "; class "
|
|
||||||
+ name.getName(true, true) + " {/*\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
classDefinition.writeTo((IndentingWriter)writer);
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
writer.write("\n*/}\n");
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
System.err.println("\n\nError occured while disassembling class " + classDescriptor.replace('/', '.') + " - skipping class");
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (writer != null) {
|
|
||||||
try {
|
|
||||||
writer.close();
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
System.err.println("\n\nError occured while closing file " + smaliFile.toString());
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ignoreErrors && classDefinition.hadValidationErrors()) {
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Pattern extJarPattern = Pattern.compile("(?:^|\\\\|/)ext.(?:jar|odex)$");
|
|
||||||
private static boolean isExtJar(String dexFilePath) {
|
|
||||||
Matcher m = extJarPattern.matcher(dexFilePath);
|
|
||||||
return m.find();
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,10 +17,10 @@
|
|||||||
package brut.androlib.src;
|
package brut.androlib.src;
|
||||||
|
|
||||||
import brut.androlib.AndrolibException;
|
import brut.androlib.AndrolibException;
|
||||||
import brut.androlib.mod.BaksmaliMod;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.jf.dexlib.Code.Analysis.ClassPath;
|
import org.jf.baksmali.baksmali;
|
||||||
|
import org.jf.baksmali.main;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,15 +40,11 @@ public class SmaliDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void decode() throws AndrolibException {
|
private void decode() throws AndrolibException {
|
||||||
if (mDebug) {
|
|
||||||
ClassPath.dontLoadClassPath = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BaksmaliMod.disassembleDexFile(mDebug, mApkFile.getAbsolutePath(),
|
baksmali.disassembleDexFile(mApkFile.getAbsolutePath(),
|
||||||
new DexFile(mApkFile), false, mOutDir.getAbsolutePath(),
|
new DexFile(mApkFile), false, mOutDir.getAbsolutePath(), null,
|
||||||
null, null, null, false, true, true, true, false,
|
null, null, false, true, true, true, false, false,
|
||||||
mDebug ? org.jf.baksmali.main.DIFFPRE : 0, false, false);
|
mDebug ? main.DIFFPRE : 0, false, false, null);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw new AndrolibException(ex);
|
throw new AndrolibException(ex);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user