From 2d036e98d8527ad02f1e6a3715a57d406266d7da Mon Sep 17 00:00:00 2001 From: sn-o-w Date: Fri, 18 Dec 2020 02:22:01 +0200 Subject: [PATCH] Sync with dexmaker This commit contains changes from linkedin/dexmaker@1bb921e, linkedin/dexmaker@a863767, linkedin/dexmaker@7929d11, linkedin/dexmaker@53339f9, linkedin/dexmaker@4b7c28b --- .../com/android/dx/AppDataDirGuesser.java | 23 ++++++++---- .../java/external/com/android/dx/Code.java | 20 ++++++++--- .../external/com/android/dx/DexMaker.java | 36 ++++++++++++------- 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/dexmaker/src/main/java/external/com/android/dx/AppDataDirGuesser.java b/dexmaker/src/main/java/external/com/android/dx/AppDataDirGuesser.java index eb3549f1..a4465ac5 100644 --- a/dexmaker/src/main/java/external/com/android/dx/AppDataDirGuesser.java +++ b/dexmaker/src/main/java/external/com/android/dx/AppDataDirGuesser.java @@ -136,20 +136,31 @@ class AppDataDirGuesser { File[] guessPath(String input) { List results = new ArrayList<>(); + String apkPathRoot = "/data/app/"; for (String potential : splitPathList(input)) { - if (!potential.startsWith("/data/app/")) { + if (!potential.startsWith(apkPathRoot)) { continue; } - int start = "/data/app/".length(); int end = potential.lastIndexOf(".apk"); if (end != potential.length() - 4) { continue; } - int dash = potential.indexOf("-"); - if (dash != -1) { - end = dash; + int endSlash = potential.lastIndexOf("/", end); + if (endSlash == apkPathRoot.length() - 1) { + // Apks cannot be directly under /data/app + continue; } - String packageName = potential.substring(start, end); + int startSlash = potential.lastIndexOf("/", endSlash - 1); + if (startSlash == -1) { + continue; + } + // Look for the first dash after the package name + int dash = potential.indexOf("-", startSlash); + if (dash == -1) { + continue; + } + end = dash; + String packageName = potential.substring(startSlash + 1, end); File dataDir = getWriteableDirectory("/data/data/" + packageName); if (dataDir == null) { diff --git a/dexmaker/src/main/java/external/com/android/dx/Code.java b/dexmaker/src/main/java/external/com/android/dx/Code.java index e63f7acc..e8d8aab6 100644 --- a/dexmaker/src/main/java/external/com/android/dx/Code.java +++ b/dexmaker/src/main/java/external/com/android/dx/Code.java @@ -484,15 +484,27 @@ public final class Code { * must be a primitive, String, Class, TypeId, or null. */ public void loadConstant(Local target, T value) { + loadConstantInternal(target, value); + } + + /** + * Copies a class type in {@code target}. The benefit to using this method vs {@link Code#loadConstant(Local, Object)} + * is that the {@code value} can itself be a generated type - {@link TypeId} allows for deferred referencing of class types. + */ + public void loadDeferredClassConstant(Local target, TypeId value) { + loadConstantInternal(target, value); + } + + private void loadConstantInternal(Local target, Object value) { Rop rop = value == null - ? Rops.CONST_OBJECT_NOTHROW - : Rops.opConst(target.type.ropType); + ? Rops.CONST_OBJECT_NOTHROW + : Rops.opConst(target.type.ropType); if (rop.getBranchingness() == BRANCH_NONE) { addInstruction(new PlainCstInsn(rop, sourcePosition, target.spec(), - RegisterSpecList.EMPTY, Constants.getConstant(value))); + RegisterSpecList.EMPTY, Constants.getConstant(value))); } else { addInstruction(new ThrowingCstInsn(rop, sourcePosition, - RegisterSpecList.EMPTY, catches, Constants.getConstant(value))); + RegisterSpecList.EMPTY, catches, Constants.getConstant(value))); moveResult(target, true); } } diff --git a/dexmaker/src/main/java/external/com/android/dx/DexMaker.java b/dexmaker/src/main/java/external/com/android/dx/DexMaker.java index 62efd845..9cd467d7 100644 --- a/dexmaker/src/main/java/external/com/android/dx/DexMaker.java +++ b/dexmaker/src/main/java/external/com/android/dx/DexMaker.java @@ -32,6 +32,7 @@ import external.com.android.dx.rop.cst.CstString; import external.com.android.dx.rop.cst.CstType; import external.com.android.dx.rop.type.StdTypeList; +import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -46,8 +47,7 @@ import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import static external.com.android.dx.rop.code.AccessFlags.ACC_CONSTRUCTOR; -import static java.lang.reflect.Modifier.PRIVATE; -import static java.lang.reflect.Modifier.STATIC; +import static java.lang.reflect.Modifier.*; /** * Generates a Dalvik EXecutable (dex) @@ -265,8 +265,8 @@ public final class DexMaker { throw new IllegalStateException("already declared: " + method); } - int supportedFlags = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED - | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED + int supportedFlags = Modifier.ABSTRACT | Modifier.NATIVE | Modifier.PUBLIC | Modifier.PRIVATE + | Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED | Modifier.TRANSIENT | AccessFlags.ACC_SYNTHETIC | AccessFlags.ACC_BRIDGE; if ((flags & ~supportedFlags) != 0) { throw new IllegalArgumentException("Unexpected flag: " @@ -558,14 +558,22 @@ public final class DexMaker { result.createNewFile(); - JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(result)); - JarEntry entry = new JarEntry(DexFormat.DEX_IN_JAR_NAME); - byte[] dex = generate(); - entry.setSize(dex.length); - jarOut.putNextEntry(entry); - jarOut.write(dex); - jarOut.closeEntry(); - jarOut.close(); + JarOutputStream jarOut = + new JarOutputStream(new BufferedOutputStream(new FileOutputStream(result))); + try { + JarEntry entry = new JarEntry(DexFormat.DEX_IN_JAR_NAME); + byte[] dex = generate(); + entry.setSize(dex.length); + jarOut.putNextEntry(entry); + try { + jarOut.write(dex); + } finally { + jarOut.closeEntry(); + } + } finally { + jarOut.close(); + } + return generateClassLoader(result, dexCache, parent); } @@ -702,6 +710,10 @@ public final class DexMaker { } EncodedMethod toEncodedMethod(DexOptions dexOptions) { + if ((flags & ABSTRACT) != 0 || (flags & NATIVE) != 0) { + return new EncodedMethod(method.constant, flags, null, StdTypeList.EMPTY); + } + RopMethod ropMethod = new RopMethod(code.toBasicBlocks(), 0); LocalVariableInfo locals = null; DalvCode dalvCode = RopTranslator.translate(