Пример #1
0
  private static void convertToDex(
      Oat oat, File outputFolder, String bootClassPath, boolean addSelfToBcp) throws IOException {
    final Opcodes opcodes = new Opcodes(oat.guessApiLevel());
    LLog.i("Preparing bootclasspath from " + bootClassPath);
    if (bootClassPath == null || !new File(bootClassPath).exists()) {
      LLog.e("Invalid bootclasspath: " + bootClassPath);
    }
    final OatDexRewriterModule odr = new OatDexRewriterModule(bootClassPath, opcodes);
    final DexRewriter deOpt = odr.getRewriter();

    DexFile[] dexFiles = getOdexFromOat(oat, opcodes);
    if (addSelfToBcp) {
      for (DexFile d : dexFiles) {
        odr.mBootClassPath.addDex(d);
      }
    }
    for (int i = 0; i < oat.mOatDexFiles.length; i++) {
      Oat.OatDexFile odf = oat.mOatDexFiles[i];
      String dexLoc = new String(odf.dex_file_location_data_);
      String opath = getOuputNameForSubDex(dexLoc);
      if ("base.apk".equals(opath)) {
        opath = MiscUtil.getFilenamePrefix(oat.mSrcFile.getName());
      }
      File outputFile = MiscUtil.changeExt(new File(outputFolder, opath), "dex");
      LLog.i("De-optimizing " + dexLoc);
      DexFile d = deOpt.rewriteDexFile(dexFiles[i]);
      if (!OatDexRewriter.isValid(d)) {
        LLog.i("convertToDex: skip " + dexLoc);
        continue;
      }

      if (outputFile.exists()) {
        File old = outputFile;
        outputFile = MiscUtil.appendTail(outputFile, "-deodex");
        LLog.i(old + " already existed, use name " + outputFile.getName());
      }
      DexPool.writeTo(outputFile.getAbsolutePath(), d);
      LLog.i("Output to " + outputFile);
    }
  }
Пример #2
0
  public static void convertToDexJar(
      Oat oat, File outputFolder, String bootClassPath, String noClassJarFolder, boolean isBoot)
      throws IOException {
    final Opcodes opcodes = new Opcodes(oat.guessApiLevel());
    LLog.i("Preparing bootclasspath from " + bootClassPath);
    final OatDexRewriterModule odr = new OatDexRewriterModule(bootClassPath, opcodes);
    HashMap<String, ArrayList<Oat.DexFile>> dexFileGroup = new HashMap<>();
    for (int i = 0; i < oat.mOatDexFiles.length; i++) {
      Oat.OatDexFile odf = oat.mOatDexFiles[i];
      String opath = new String(odf.dex_file_location_data_);
      int spos = opath.indexOf(':');
      if (spos > 0) {
        // .../framework.jar:classes2.dex
        opath = opath.substring(0, spos);
      }
      opath = opath.substring(opath.lastIndexOf('/') + 1);
      ArrayList<Oat.DexFile> dfiles = dexFileGroup.get(opath);
      if (dfiles == null) {
        dfiles = new ArrayList<>();
        dexFileGroup.put(opath, dfiles);
      }
      dfiles.add(oat.mDexFiles[i]);
      if (!isBoot) {
        Oat.DexFile dex = oat.mDexFiles[i];
        odr.mBootClassPath.addDex(readDex(dex, dex.mHeader.file_size_, opcodes, null));
      }
    }

    final int BSIZE = 8192;
    final byte[] buf = new byte[BSIZE];
    final DexRewriter deOpt = odr.getRewriter();

    for (String jarName : dexFileGroup.keySet()) {
      File outputFile = MiscUtil.changeExt(new File(outputFolder, jarName), "jar");
      String classesIdx = "";
      int i = 1;
      int readSize;
      try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(outputFile))) {
        for (Oat.DexFile dex : dexFileGroup.get(jarName)) {
          jos.putNextEntry(new ZipEntry("classes" + classesIdx + ".dex"));
          final int dexSize = dex.mHeader.file_size_;
          ByteBuffer dexBytes = ByteBuffer.allocateDirect(dexSize);
          dex.mReader.seek(dex.mDexPosition);
          int remain = dexSize;
          int read = BSIZE > dexSize ? dexSize : BSIZE;
          while ((readSize = dex.mReader.readRaw(buf, 0, read)) != -1 && remain > 0) {
            dexBytes.put(buf, 0, readSize);
            remain -= readSize;
            if (remain < BSIZE) {
              read = remain;
            }
          }

          LLog.i("De-optimizing " + jarName + (i > 1 ? (" part-" + classesIdx) : ""));
          int length = dexBytes.position();
          dexBytes.flip();
          byte[] data = new byte[length];
          dexBytes.get(data);
          DexFile d = new DexBackedDexFile(opcodes, data);
          d = deOpt.rewriteDexFile(d);
          if (!OatDexRewriter.isValid(d)) {
            LLog.i("convertToDexJar: skip " + jarName);
            continue;
          }

          MemoryDataStore m = new MemoryDataStore(dexSize + 512);
          DexPool.writeTo(m, d);

          jos.write(m.mBuffer.mData, 0, m.mBuffer.mMaxDataPosition);
          classesIdx = String.valueOf(++i);
          jos.closeEntry();
        }

        // Copy files from original jar
        try (JarFile jarFile = new JarFile(new File(noClassJarFolder, jarName))) {
          final Enumeration<JarEntry> entries = jarFile.entries();
          while (entries.hasMoreElements()) {
            final JarEntry e = entries.nextElement();
            String name = e.getName();
            if (name.startsWith("classes") && name.endsWith(".dex")) {
              continue;
            }
            jos.putNextEntry(new ZipEntry(name));
            try (InputStream is = jarFile.getInputStream(e)) {
              int bytesRead;
              while ((bytesRead = is.read(buf)) != -1) {
                jos.write(buf, 0, bytesRead);
              }
            }
            jos.closeEntry();
          }
        }
        LLog.i("Output " + outputFile);
      } catch (IOException e) {
        LLog.ex(e);
      }
    }
  }