路径
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);
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);