InMemoryDexClassLoader源码阅读

安卓10

Java层

路径
libcore\dalvik\src\main\java\dalvik\system\InMemoryDexClassLoader.java

public final class InMemoryDexClassLoader extends BaseDexClassLoader {
    /**
     * Create an in-memory DEX class loader with the given dex buffers.
     *
     * @param dexBuffers array of buffers containing DEX files between
     *                       buffer.position() and buffer.limit().
     * @param librarySearchPath the list of directories containing native
     *   libraries, delimited by {@code File.pathSeparator}; may be {@code null}
     * @param parent the parent class loader for delegation.
     */
    public InMemoryDexClassLoader(@NonNull ByteBuffer @NonNull [] dexBuffers,
            @Nullable String librarySearchPath, @Nullable ClassLoader parent) {
        super(dexBuffers, librarySearchPath, parent);
    }

libcore\dalvik\src\main\java\dalvik\system\BaseDexClassLoader.java

public class BaseDexClassLoader extends ClassLoader {


    /**
     * Constructs an instance.
     *
     * dexFile must be an in-memory representation of a full dexFile.
     *
     * @param dexFiles the array of in-memory dex files containing classes.
     * @param librarySearchPath the list of directories containing native
     *   libraries, delimited by {@code File.pathSeparator}; may be {@code null}
     * @param parent the parent class loader
     *
     * @hide
     */
    public BaseDexClassLoader(ByteBuffer[] dexFiles, String librarySearchPath, ClassLoader parent) {
        super(parent);
        this.sharedLibraryLoaders = null;
        this.pathList = new DexPathList(this, librarySearchPath);
        this.pathList.initByteBufferDexPath(dexFiles);
    }
 }

libcore\dalvik\src\main\java\dalvik\system\DexPathList.java

/**
 * For InMemoryDexClassLoader. Initializes {@code dexElements} with dex files
 * loaded from {@code dexFiles} buffers.
 *
 * @param dexFiles ByteBuffers containing raw dex data. Apks are not supported.
 */
/* package */ void initByteBufferDexPath(ByteBuffer[] dexFiles) 

    final List<IOException> suppressedExceptions = new ArrayList<IOException>();

    try {
        Element[] null_elements = null;
        DexFile dex = new DexFile(dexFiles, definingContext, null_elements);
        // Capture class loader context from *before* `dexElements` is set (see comment below).
        String classLoaderContext = dex.isBackedByOatFile()
                ? null : DexFile.getClassLoaderContext(definingContext, null_elements);
        dexElements = new Element[] { new Element(dex) };
        // Spawn background thread to verify all classes and cache verification results.
        // Must be called *after* `dexElements` has been initialized for ART to find
        // its classes (the field is hardcoded in ART and dex files iterated over in
        // the order of the array), but with class loader context from *before*
        // `dexElements` was set because that is what it will be compared against next
        // time the same bytecode is loaded.
        // We only spawn the background thread if the bytecode is not backed by an oat
        // file, i.e. this is the first time this bytecode is being loaded and/or
        // verification results have not been cached yet. Skip spawning the thread on
        // all subsequent loads of the same bytecode in the same class loader context.
        if (classLoaderContext != null) {
            dex.verifyInBackground(definingContext, classLoaderContext);
        }
    } catch (IOException suppressed) {
        System.logE("Unable to load dex files", suppressed);
        suppressedExceptions.add(suppressed);
        dexElements = new Element[0];
    }

    if (suppressedExceptions.size() > 0) {
        dexElementsSuppressedExceptions = suppressedExceptions.toArray(
                new IOException[suppressedExceptions.size()]);
    }
}

libcore\dalvik\src\main\java\dalvik\system\DexFile.java

DexFile(ByteBuffer[] bufs, ClassLoader loader, DexPathList.Element[] elements)
        throws IOException {
    mCookie = openInMemoryDexFiles(bufs, loader, elements);
    mInternalCookie = mCookie;
    mFileName = null;
}

libcore\dalvik\src\main\java\dalvik\system\DexFile.java

private static Object openInMemoryDexFiles(ByteBuffer[] bufs, ClassLoader loader,
        DexPathList.Element[] elements) throws IOException {
    // Preprocess the ByteBuffers for openInMemoryDexFilesNative. We extract
    // the backing array (non-direct buffers only) and start/end positions
    // so that the native method does not have to call Java methods anymore.
    byte[][] arrays = new byte[bufs.length][];
    int[] starts = new int[bufs.length];
    int[] ends = new int[bufs.length];
    for (int i = 0; i < bufs.length; ++i) {
        arrays[i] = bufs[i].isDirect() ? null : bufs[i].array();
        starts[i] = bufs[i].position();
        ends[i] = bufs[i].limit();
    }
    return openInMemoryDexFilesNative(bufs, arrays, starts, ends, loader, elements);
}

private static native Object openInMemoryDexFilesNative(ByteBuffer[] bufs, byte[][] arrays,
        int[] starts, int[] ends, ClassLoader loader, DexPathList.Element[] elements);

Native层

art\runtime\native\dalvik_system_DexFile.cc

static jobject DexFile_openInMemoryDexFilesNative(JNIEnv* env,
                                                  jclass,
                                                  jobjectArray buffers,
                                                  jobjectArray arrays,
                                                  jintArray jstarts,
                                                  jintArray jends,
                                                  jobject class_loader, jobjectArray dex_elements) {
  // Hand MemMaps over to OatFileManager to open the dex files and potentially
  // create a backing OatFile instance from an anonymous vdex.
  std::vector<std::string> error_msgs;
  const OatFile* oat_file = nullptr;
  std::vector<std::unique_ptr<const DexFile>> dex_files =
      Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(std::move(dex_mem_maps),
                                                                  class_loader,
                                                                  dex_elements,
                                                                  /*out*/ &oat_file,
                                                                  /*out*/ &error_msgs);
  return CreateCookieFromOatFileManagerResult(env, dex_files, oat_file, error_msgs);
}

art\runtime\oat_file_manager.cc
重点:dex_file 构造函数和dex_file_loader.Open

std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
    std::vector<MemMap>&& dex_mem_maps,
    jobject class_loader,
    jobjectArray dex_elements,
    const OatFile** out_oat_file,
    std::vector<std::string>* error_msgs) {
  std::vector<std::unique_ptr<const DexFile>> dex_files = OpenDexFilesFromOat_Impl(
      std::move(dex_mem_maps),
      class_loader,
      dex_elements,
      out_oat_file,
      error_msgs);

  return dex_files;
}

std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat_Impl(
    std::vector<MemMap>&& dex_mem_maps,
    jobject class_loader,
    jobjectArray dex_elements,
    const OatFile** out_oat_file,
    std::vector<std::string>* error_msgs) {

  // Load dex files. Skip structural dex file verification if vdex was found
  // and dex checksums matched.
  std::vector<std::unique_ptr<const DexFile>> dex_files;
  for (size_t i = 0; i < dex_mem_maps.size(); ++i) {
    static constexpr bool kVerifyChecksum = true;
    const ArtDexFileLoader dex_file_loader;
    std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(
        DexFileLoader::GetMultiDexLocation(i, dex_location.c_str()),
        location_checksum,
        std::move(dex_mem_maps[i]),
        /* verify= */ (vdex_file == nullptr) && Runtime::Current()->IsVerificationEnabled(),
        kVerifyChecksum,
        &error_msg));
    if (dex_file != nullptr) {
      dex::tracking::RegisterDexFile(dex_file.get());  // Register for tracking.
      dex_files.push_back(std::move(dex_file));
    } else {
      error_msgs->push_back("Failed to open dex files from memory: " + error_msg);
    }
  }

  return dex_files;
}

art\libdexfile\dex\art_dex_file_loader.cc


std::unique_ptr<const DexFile> ArtDexFileLoader::Open(const std::string& location,
                                                      uint32_t location_checksum,
                                                      MemMap&& map,
                                                      bool verify,
                                                      bool verify_checksum,
                                                      std::string* error_msg) const {
  ScopedTrace trace(std::string("Open dex file from mapped-memory ") + location);
  CHECK(map.IsValid());

  size_t size = map.Size();
  if (size < sizeof(DexFile::Header)) {
    *error_msg = StringPrintf(
        "DexFile: failed to open dex file '%s' that is too short to have a header",
        location.c_str());
    return nullptr;
  }

  uint8_t* begin = map.Begin();
  std::unique_ptr<DexFile> dex_file = OpenCommon(begin,
                                                 size,
                                                 /*data_base=*/ nullptr,
                                                 /*data_size=*/ 0u,
                                                 location,
                                                 location_checksum,
                                                 kNoOatDexFile,
                                                 verify,
                                                 verify_checksum,
                                                 error_msg,
                                                 std::make_unique<MemMapContainer>(std::move(map)),
                                                 /*verify_result=*/ nullptr);
  // Opening CompactDex is only supported from vdex files.
  if (dex_file != nullptr && dex_file->IsCompactDexFile()) {
    *error_msg = StringPrintf("Opening CompactDex file '%s' is only supported from vdex files",
                              location.c_str());
    return nullptr;
  }
  return dex_file;
}
std::unique_ptr<DexFile> ArtDexFileLoader::OpenCommon(const uint8_t* base,
                                                      size_t size,
                                                      const uint8_t* data_base,
                                                      size_t data_size,
                                                      const std::string& location,
                                                      uint32_t location_checksum,
                                                      const OatDexFile* oat_dex_file,
                                                      bool verify,
                                                      bool verify_checksum,
                                                      std::string* error_msg,
                                                      std::unique_ptr<DexFileContainer> container,
                                                      VerifyResult* verify_result) {
  return DexFileLoader::OpenCommon(base,
                                   size,
                                   data_base,
                                   data_size,
                                   location,
                                   location_checksum,
                                   oat_dex_file,
                                   verify,
                                   verify_checksum,
                                   error_msg,
                                   std::move(container),
                                   verify_result);
}

得到常用脱壳点 OpenCommon

  static std::unique_ptr<DexFile> OpenCommon(const uint8_t* base,
                                             size_t size,
                                             const uint8_t* data_base,
                                             size_t data_size,
                                             const std::string& location,
                                             uint32_t location_checksum,
                                             const OatDexFile* oat_dex_file,
                                             bool verify,
                                             bool verify_checksum,
                                             std::string* error_msg,
                                             std::unique_ptr<DexFileContainer> container,
                                             VerifyResult* verify_result);

你可能感兴趣的:(逆向工程,逆向,源码,dex加载)