Skip to content

Commit

Permalink
Use internal dex library
Browse files Browse the repository at this point in the history
  • Loading branch information
REAndroid committed Jan 21, 2025
1 parent 270d9e8 commit 6145aad
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 37 deletions.
3 changes: 3 additions & 0 deletions src/main/java/com/reandroid/apkeditor/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,7 @@ public static String getHelp(Class<?> optionClass){
public static final String TYPE_RAW = "raw";
public static final String TYPE_XML = "xml";
public static final String TYPE_TEXT = "text";

public static final String DEX_LIB_INTERNAL = "internal";
public static final String DEX_LIB_JF = "jf";
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ public class BuildOptions extends OptionsWithFramework {
@OptionArg(name = "-no-cache", description = "build_no_cache", flag = true)
public boolean noCache;

@ChoiceArg(name = "-dex-lib",
values = {
DEX_LIB_INTERNAL,
DEX_LIB_JF
},
description = "dex_lib"
)
public String dexLib = DEX_LIB_JF;

@OptionArg(name = "-sig", description = "signatures_path")
public File signaturesDirectory;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
"decode_example_3",
"decode_example_4",
"decode_example_5"
},
notes = {
"decode_note_1",
"decode_note_2"
})
public class DecompileOptions extends OptionsWithFramework {

Expand Down Expand Up @@ -68,6 +72,18 @@ public class DecompileOptions extends OptionsWithFramework {
@OptionArg(name = "-dex-markers", flag = true, description = "dump_dex_markers")
public boolean dexMarkers;

@OptionArg(name = "-load-dex", description = "decode_load_dex")
public int loadDex = 3;

@ChoiceArg(name = "-dex-lib",
values = {
DEX_LIB_INTERNAL,
DEX_LIB_JF
},
description = "dex_lib"
)
public String dexLib = DEX_LIB_INTERNAL;

@OptionArg(name = "-sig", description = "signatures_path")
public File signaturesDirectory;

Expand Down
21 changes: 9 additions & 12 deletions src/main/java/com/reandroid/apkeditor/smali/SmaliCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
import com.reandroid.apk.APKLogger;
import com.reandroid.apk.ApkModuleEncoder;
import com.reandroid.apk.DexEncoder;
import com.reandroid.apkeditor.APKEditor;
import com.reandroid.apkeditor.compile.BuildOptions;
import com.reandroid.archive.FileInputSource;
import com.reandroid.archive.InputSource;
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
import com.reandroid.dex.model.DexFile;
import com.reandroid.utils.StringsUtil;
import com.reandroid.utils.io.FileUtil;
import org.jf.dexlib2.extra.DexMarker;
import org.jf.smali.Smali;
import org.jf.smali.SmaliOptions;
Expand Down Expand Up @@ -79,18 +79,15 @@ private InputSource build(String progress, File classesDir) throws IOException {
}
}
private InputSource build(String progress, File classesDir, File dexCacheFile) throws IOException {
if(APKEditor.isExperimental()) {
return buildExperimental(progress, classesDir, dexCacheFile);
if(BuildOptions.DEX_LIB_INTERNAL.equals(buildOptions.dexLib)) {
return buildWithInternalLib(progress, classesDir, dexCacheFile);
}
return buildJesusFreke(progress, classesDir, dexCacheFile);
return buildWithJesusFreke(progress, classesDir, dexCacheFile);
}
private InputSource buildJesusFreke(String progress, File classesDir, File dexCacheFile) throws IOException {
logMessage(progress + "Smali: " + dexCacheFile.getName());
private InputSource buildWithJesusFreke(String progress, File classesDir, File dexCacheFile) throws IOException {
logMessage(progress + "Smali<JF>: " + dexCacheFile.getName());
SmaliOptions smaliOptions = new SmaliOptions();
File dir = dexCacheFile.getParentFile();
if(dir != null && !dir.exists()){
dir.mkdirs();
}
FileUtil.ensureParentDirectory(dexCacheFile);
smaliOptions.outputDexFile = dexCacheFile.getAbsolutePath();
File marker = new File(classesDir, DexMarker.FILE_NAME);
if(marker.isFile()){
Expand All @@ -108,8 +105,8 @@ private InputSource buildJesusFreke(String progress, File classesDir, File dexCa
}
return new FileInputSource(dexCacheFile, dexCacheFile.getName());
}
private InputSource buildExperimental(String progress, File classesDir, File dexCacheFile) throws IOException {
logMessage(progress + "Smali: " + dexCacheFile.getName());
private InputSource buildWithInternalLib(String progress, File classesDir, File dexCacheFile) throws IOException {
logMessage(progress + "Smali<INTERNAL>: " + dexCacheFile.getName());
DexFile dexFile = DexFile.createDefault();
int version = 0;
if (this.minSdkVersion != null) {
Expand Down
34 changes: 9 additions & 25 deletions src/main/java/com/reandroid/apkeditor/smali/SmaliDecompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.reandroid.apk.ApkModule;
import com.reandroid.apk.DexDecoder;
import com.reandroid.apk.DexFileInputSource;
import com.reandroid.apkeditor.APKEditor;
import com.reandroid.apkeditor.decompile.DecompileOptions;
import com.reandroid.arsc.chunk.TableBlock;
import com.reandroid.dex.model.DexDirectory;
Expand Down Expand Up @@ -59,26 +58,26 @@ public SmaliDecompiler(TableBlock tableBlock){
@Override
public void decodeDex(DexFileInputSource inputSource, File mainDir) throws IOException {
logMessage("Baksmali: " + inputSource.getAlias());
if(APKEditor.isExperimental()) {
disassembleDexFileExperimental(inputSource, mainDir);
if(DecompileOptions.DEX_LIB_INTERNAL.equals(decompileOptions.dexLib)) {
disassembleWithInternalDexLib(inputSource, mainDir);
}else {
disassembleJesusFreke(inputSource, mainDir);
disassembleWithJesusFrekeLib(inputSource, mainDir);
}
writeDexCache(inputSource, mainDir);
}
@Override
public void decodeDex(ApkModule apkModule, File mainDirectory) throws IOException {
if(!APKEditor.isExperimental()) {
if(!DecompileOptions.DEX_LIB_INTERNAL.equals(decompileOptions.dexLib)) {
DexDecoder.super.decodeDex(apkModule, mainDirectory);
return;
}
DexDirectory directory = (DexDirectory) apkModule.getTag(DexDirectory.class);
if(directory == null) {
if(!canLoadFullDex(apkModule)) {
if (directory == null) {
if (apkModule.listDexFiles().size() > decompileOptions.loadDex) {
DexDecoder.super.decodeDex(apkModule, mainDirectory);
return;
}
logMessage("Loading full dex ...");
logMessage("Loading full dex files: " + apkModule.listDexFiles().size());
Predicate<SectionType<?>> filter;
if (decompileOptions.noDexDebug) {
filter = sectionType -> sectionType != SectionType.DEBUG_INFO;
Expand All @@ -88,7 +87,6 @@ public void decodeDex(ApkModule apkModule, File mainDirectory) throws IOExceptio
directory = DexDirectory.fromZip(apkModule.getZipEntryMap(), filter);
}

logMessage("Dumping smali ...");
File smali = toSmaliRoot(mainDirectory);
SmaliWriterSetting setting = new SmaliWriterSetting();
if (tableBlock != null) {
Expand All @@ -108,22 +106,8 @@ public void decodeDex(ApkModule apkModule, File mainDirectory) throws IOExceptio
writeDexCache(inputSource, mainDirectory);
}
}
private boolean canLoadFullDex(ApkModule apkModule) {
int CLASSES_LIMIT = 4;
if (decompileOptions.noDexDebug) {
CLASSES_LIMIT += 3;
}
int size = apkModule.listDexFiles().size();
logMessage("Total dex files: " + size);
if(size > CLASSES_LIMIT) {
logMessage("Huge classes your memory might not handle it, decoding separately without advanced features." +
" You can disable this restrictions by increasing \"CLASSES_LIMIT\" variable here on source code");
return false;
}
return true;
}

private void disassembleJesusFreke(DexFileInputSource inputSource, File mainDir) throws IOException {
private void disassembleWithJesusFrekeLib(DexFileInputSource inputSource, File mainDir) throws IOException {
File dir = toOutDir(inputSource, mainDir);
BaksmaliOptions options = new BaksmaliOptions();
options.localsDirective = true;
Expand All @@ -135,7 +119,7 @@ private void disassembleJesusFreke(DexFileInputSource inputSource, File mainDir)
DexBackedDexFile dexFile = getInputDexFile(inputSource, options);
Baksmali.disassembleDexFile(dexFile, dir, 1, options);
}
private void disassembleDexFileExperimental(DexFileInputSource inputSource, File mainDir) throws IOException {
private void disassembleWithInternalDexLib(DexFileInputSource inputSource, File mainDir) throws IOException {
Predicate<SectionType<?>> filter;
if (decompileOptions.noDexDebug) {
filter = sectionType -> sectionType != SectionType.DEBUG_INFO;
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/strings/strings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,14 @@ decode_example_2=[Specify output]\njava -jar APKEditor.jar d -i path/input.apk -
decode_example_3=[Specify decode type]\njava -jar APKEditor.jar d -t xml -i path/input.apk
decode_example_4=[Specify framework file(s)]\njava -jar APKEditor.jar d -i path/input.apk -framework framework-res.apk -framework platforms/android-32/android.jar
decode_example_5=[Decode apk signature block]\njava -jar APKEditor.jar d -t sig -i path/input.apk -sig path/signatures_dir
decode_load_dex=Number of dex files to load at a time.\nIf the apk dex files count greater than this value, then the decoder loads one dex at a time.\n *Applies only when -dex-lib set to internal.\n *Default = 3\n *See<Notes> below.
decode_note_1=[internal] Dex builder\:\n* Fully supports dex files up to 042.\n* Highest dex file compression.\n* Builds with similar dex-section order as r8/dx.\n* Convenient dex markers editing, see file smali/classes/dex-file.json \n* Additional helpful smali comments: e.g class/method hierarchy.\n* Supports whitespaces on class simple name as introduced on dex 041+
decode_note_2=[-load-dex] To print correct class/method hierarchy, it is necessary to load all dex files at once. This may result high memory consumption and could fail with "OutOfMemoryError" thus you are required to limit the number of dex files to load at a time. You can overcome this problem with -Xmx memory arg e.g java -Xmx8g -jar APKEditor.jar ...
decode_types=Decode types\:
decode_usage=d [Options, flags]
dump_dex_markers=Dumps dex markers (applies only when smali mode).
duplicate_option_exception=Duplicate option '%s'
dex_lib=Dex library to use\:\n 1) internal : Use internal library, supports dex versions up to 042.\n 2) jf : Use library by JesusFreke/smali, supports dex versions 035 and below.\n *Default = jf\n **WARN: The default value will be replaced by "internal" on coming versions.\n *See <Notes> below.
empty_command_args_exception=Empty command, run with -h to get help
empty_command_option_exception=Empty options, run with <command> -h to get help
force_delete=Force delete output path.
Expand Down Expand Up @@ -121,6 +125,7 @@ title_example=Examples\:
title_flags=Flags\:
title_options=Options\:
title_other_options=Other options\:
title_notes=Notes\:
title_usage=Usage\:
unknown_command_exception=Unknown command\: '%s'
unknown_option_exception=Unknown option\: '%s'
Expand Down

0 comments on commit 6145aad

Please sign in to comment.