use of org.jf.dexlib2.iface.ClassDef in project atlas by alibaba.
the class PatchMethodTool method modifyMethod.
public static void modifyMethod(String srcDexFile, String outDexFile, boolean isAndFix) throws IOException {
DexFile dexFile = DexFileFactory.loadDexFile(srcDexFile, 15, true);
final Set<ClassDef> classes = Sets.newConcurrentHashSet();
for (ClassDef classDef : dexFile.getClasses()) {
Set<Method> methods = Sets.newConcurrentHashSet();
boolean modifiedMethod = false;
for (Method method : classDef.getMethods()) {
MethodImplementation implementation = method.getImplementation();
if (implementation != null && (methodNeedsModification(classDef, method, isAndFix))) {
modifiedMethod = true;
methods.add(new ImmutableMethod(method.getDefiningClass(), method.getName(), method.getParameters(), method.getReturnType(), method.getAccessFlags(), method.getAnnotations(), isAndFix ? modifyMethodAndFix(implementation, method) : modifyMethodTpatch(implementation, method)));
} else {
methods.add(method);
}
}
if (!modifiedMethod) {
classes.add(classDef);
} else {
classes.add(new ImmutableClassDef(classDef.getType(), classDef.getAccessFlags(), classDef.getSuperclass(), classDef.getInterfaces(), classDef.getSourceFile(), classDef.getAnnotations(), classDef.getFields(), methods));
}
}
DexFileFactory.writeDexFile(outDexFile, new DexFile() {
@Nonnull
@Override
public Set<? extends ClassDef> getClasses() {
return new AbstractSet<ClassDef>() {
@Nonnull
@Override
public Iterator<ClassDef> iterator() {
return classes.iterator();
}
@Override
public int size() {
return classes.size();
}
};
}
});
}
use of org.jf.dexlib2.iface.ClassDef in project atlas by alibaba.
the class TPatchDexTool method createTPatchDex.
/**
* 生成淘宝的动态部署的patch的Dex文件
*
* @param outDexFile
*/
public DexDiffInfo createTPatchDex(File outDexFile) throws IOException, RecognitionException, PatchException {
outDexFile.getParentFile().mkdirs();
DexDiffInfo dexDiffInfo = dexDiffer.doDiff();
// 将有变动的类写入到diff.dex
final Set<ClassDef> modifyClasses = new HashSet<ClassDef>();
for (ClassDiffInfo classDiffInfo : dexDiffInfo.getClassDiffInfoMap().values()) {
if (DiffType.MODIFY.equals(classDiffInfo.getType()) || DiffType.ADD.equals(classDiffInfo.getType()) || DiffType.OVERRIDE.equals(classDiffInfo.getType())) {
modifyClasses.add(classDiffInfo.getClassDef());
}
}
if (modifyClasses.size() > 0) {
DexFileFactory.writeDexFile(outDexFile.getAbsolutePath(), new DexFile() {
@Nonnull
@Override
public Set<? extends ClassDef> getClasses() {
return new AbstractSet<ClassDef>() {
@Nonnull
@Override
public Iterator<ClassDef> iterator() {
return modifyClasses.iterator();
}
@Override
public int size() {
return modifyClasses.size();
}
};
}
});
}
return dexDiffInfo;
}
use of org.jf.dexlib2.iface.ClassDef in project atlas by alibaba.
the class BakSmali method disassembleDexFile.
public static boolean disassembleDexFile(DexFile dexFile, final baksmaliOptions options) {
if (options.registerInfo != 0 || options.deodex) {
try {
Iterable<String> extraClassPathEntries;
if (options.extraClassPathEntries != null) {
extraClassPathEntries = options.extraClassPathEntries;
} else {
extraClassPathEntries = ImmutableList.of();
}
options.classPath = ClassPath.fromClassPath(options.bootClassPathDirs, Iterables.concat(options.bootClassPathEntries, extraClassPathEntries), dexFile, options.apiLevel, options.checkPackagePrivateAccess, options.experimental);
if (options.customInlineDefinitions != null) {
options.inlineResolver = new CustomInlineMethodResolver(options.classPath, options.customInlineDefinitions);
}
} catch (Exception ex) {
System.err.println("\n\nError occurred while loading boot class path files. Aborting.");
ex.printStackTrace(System.err);
return false;
}
}
if (options.resourceIdFileEntries != null) {
class PublicHandler extends DefaultHandler {
String prefix = null;
public PublicHandler(String prefix) {
super();
this.prefix = prefix;
}
public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException {
if (qName.equals("public")) {
String type = attr.getValue("type");
String name = attr.getValue("name").replace('.', '_');
Integer public_key = Integer.decode(attr.getValue("id"));
String public_val = new StringBuffer().append(prefix).append(".").append(type).append(".").append(name).toString();
options.resourceIds.put(public_key, public_val);
}
}
}
;
for (Map.Entry<String, String> entry : options.resourceIdFileEntries.entrySet()) {
try {
SAXParser saxp = SAXParserFactory.newInstance().newSAXParser();
String prefix = entry.getValue();
saxp.parse(entry.getKey(), new PublicHandler(prefix));
} catch (ParserConfigurationException e) {
continue;
} catch (SAXException e) {
continue;
} catch (IOException e) {
continue;
}
}
}
File outputDirectoryFile = new File(options.outputDirectory);
if (!outputDirectoryFile.exists()) {
if (!outputDirectoryFile.mkdirs()) {
System.err.println("Can't create the output directory " + options.outputDirectory);
return false;
}
}
//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
List<? extends ClassDef> classDefs = Ordering.natural().sortedCopy(dexFile.getClasses());
if (!options.noAccessorComments) {
options.syntheticAccessorResolver = new SyntheticAccessorResolver(classDefs);
}
final ClassFileNameHandler fileNameHandler = new ClassFileNameHandler(outputDirectoryFile, ".smali");
ExecutorService executor = Executors.newFixedThreadPool(options.jobs);
List<Future<Boolean>> tasks = Lists.newArrayList();
for (final ClassDef classDef : classDefs) {
tasks.add(executor.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return disassembleClass(classDef, fileNameHandler, options);
}
}));
}
boolean errorOccurred = false;
try {
for (Future<Boolean> task : tasks) {
while (true) {
try {
if (!task.get()) {
errorOccurred = true;
}
} catch (InterruptedException ex) {
continue;
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
break;
}
}
} finally {
executor.shutdown();
}
return !errorOccurred;
}
use of org.jf.dexlib2.iface.ClassDef in project atlas by alibaba.
the class SmaliUtils method disassembleDexFile.
/**
* 将dex文件转换为smali文件
* @param dex
* @param outputDir
* @param includeClasses 需要做过滤的文件
*/
public static boolean disassembleDexFile(File dex, File outputDir, final Set<String> includeClasses) throws IOException {
final baksmaliOptions options = createBaksmaliOptions();
if (!outputDir.exists()) {
outputDir.mkdirs();
}
DexFile dexFile = DexFileFactory.loadDexFile(dex, DEFAULT_API_LEVEL, true);
options.outputDirectory = outputDir.getAbsolutePath();
//1. 设置线程数
options.jobs = 3;
if (options.registerInfo != 0 || options.deodex) {
try {
Iterable<String> extraClassPathEntries;
if (options.extraClassPathEntries != null) {
extraClassPathEntries = options.extraClassPathEntries;
} else {
extraClassPathEntries = ImmutableList.of();
}
options.classPath = ClassPath.fromClassPath(options.bootClassPathDirs, Iterables.concat(options.bootClassPathEntries, extraClassPathEntries), dexFile, options.apiLevel, options.checkPackagePrivateAccess, options.experimental);
if (options.customInlineDefinitions != null) {
options.inlineResolver = new CustomInlineMethodResolver(options.classPath, options.customInlineDefinitions);
}
} catch (Exception ex) {
System.err.println("\n\nError occurred while loading boot class path files. Aborting.");
ex.printStackTrace(System.err);
return false;
}
}
if (options.resourceIdFileEntries != null) {
class PublicHandler extends DefaultHandler {
String prefix = null;
public PublicHandler(String prefix) {
super();
this.prefix = prefix;
}
public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException {
if (qName.equals("public")) {
String type = attr.getValue("type");
String name = attr.getValue("name").replace('.', '_');
Integer public_key = Integer.decode(attr.getValue("id"));
String public_val = new StringBuffer().append(prefix).append(".").append(type).append(".").append(name).toString();
options.resourceIds.put(public_key, public_val);
}
}
}
;
for (Map.Entry<String, String> entry : options.resourceIdFileEntries.entrySet()) {
try {
SAXParser saxp = SAXParserFactory.newInstance().newSAXParser();
String prefix = entry.getValue();
saxp.parse(entry.getKey(), new PublicHandler(prefix));
} catch (ParserConfigurationException e) {
continue;
} catch (SAXException e) {
continue;
} catch (IOException e) {
continue;
}
}
}
File outputDirectoryFile = new File(options.outputDirectory);
if (!outputDirectoryFile.exists()) {
if (!outputDirectoryFile.mkdirs()) {
System.err.println("Can't create the output directory " + options.outputDirectory);
return false;
}
}
// 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
List<? extends ClassDef> classDefs = Ordering.natural().sortedCopy(dexFile.getClasses());
if (!options.noAccessorComments) {
options.syntheticAccessorResolver = new SyntheticAccessorResolver(classDefs);
}
final ClassFileNameHandler fileNameHandler = new ClassFileNameHandler(outputDirectoryFile, ".smali");
ExecutorService executor = Executors.newFixedThreadPool(options.jobs);
List<Future<Boolean>> tasks = Lists.newArrayList();
for (final ClassDef classDef : classDefs) {
tasks.add(executor.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
String className = getDalvikClassName(classDef.getType());
if (null != includeClasses) {
if (includeClasses.contains(className)) {
BakSmali.disassembleClass(classDef, fileNameHandler, options);
}
return true;
} else {
return BakSmali.disassembleClass(classDef, fileNameHandler, options);
}
}
}));
}
boolean errorOccurred = false;
try {
for (Future<Boolean> task : tasks) {
while (true) {
try {
if (!task.get()) {
errorOccurred = true;
}
} catch (InterruptedException ex) {
continue;
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
break;
}
}
} finally {
executor.shutdown();
}
return !errorOccurred;
}
use of org.jf.dexlib2.iface.ClassDef in project atlas by alibaba.
the class SmaliDiffUtils method buildCode.
public static Set<String> buildCode(File smaliDir, File dexFile, DexDiffInfo info) throws IOException, RecognitionException {
Set<String> classes = new HashSet<String>();
Set<DexBackedClassDef> classDefs = new HashSet<DexBackedClassDef>();
classDefs.addAll(info.getModifiedClasses());
classDefs.addAll(info.getAddedClasses());
final ClassFileNameHandler outFileNameHandler = new ClassFileNameHandler(smaliDir, ".smali");
final ClassFileNameHandler inFileNameHandler = new ClassFileNameHandler(smaliDir, ".smali");
DexBuilder dexBuilder = DexBuilder.makeDexBuilder();
File smaliFile;
String className;
for (DexBackedClassDef classDef : classDefs) {
ApkPatch.currentClassType = classDef.getType();
className = TypeGenUtil.newType(classDef.getType());
AfBakSmali.disassembleClass(classDef, outFileNameHandler, getBuildOption(classDefs, 19), false, false);
smaliFile = inFileNameHandler.getUniqueFilenameForClass(className);
classes.add(className.substring(1, className.length() - 1).replace('/', '.'));
SmaliMod.assembleSmaliFile(smaliFile, dexBuilder, true, true);
}
dexBuilder.writeTo(new FileDataStore(dexFile));
return classes;
}
Aggregations