Last active
April 14, 2024 17:36
-
-
Save anestisb/71d6b0496912f801533dec9d264aa409 to your computer and use it in GitHub Desktop.
oatdump vdex unquicken
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
project art/ | |
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc | |
index a8ab7c6..2bb04a2 100644 | |
--- a/compiler/driver/compiler_driver.cc | |
+++ b/compiler/driver/compiler_driver.cc | |
@@ -442,7 +442,7 @@ void CompilerDriver::CompileAll(jobject class_loader, | |
// We do not decompile a RETURN_VOID_NO_BARRIER into a RETURN_VOID, as the quickening | |
// optimization does not depend on the boot image (the optimization relies on not | |
// having final fields in a class, which does not change for an app). | |
- VdexFile::Unquicken(dex_files, vdex_file->GetQuickeningInfo()); | |
+ VdexFile::Unquicken(dex_files, vdex_file->GetQuickeningInfo(), /* decompile_return_instruction */ false); | |
Runtime::Current()->GetCompilerCallbacks()->SetVerifierDeps( | |
new verifier::VerifierDeps(dex_files, vdex_file->GetVerifierDepsData())); | |
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc | |
index d8d3cda..6e186ae 100644 | |
--- a/dex2oat/dex2oat.cc | |
+++ b/dex2oat/dex2oat.cc | |
@@ -1294,6 +1294,7 @@ class Dex2Oat FINAL { | |
/* writable */ false, | |
/* low_4gb */ false, | |
eagerly_unquicken_vdex, | |
+ /* decompile_return_instruction */ false, | |
&error_msg); | |
} | |
@@ -1344,6 +1345,7 @@ class Dex2Oat FINAL { | |
/* writable */ false, | |
/* low_4gb */ false, | |
eagerly_unquicken_vdex, | |
+ /* decompile_return_instruction */ false, | |
&error_msg); | |
// If there's any problem with the passed vdex, just warn and proceed | |
// without it. | |
diff --git a/dexlayout/dexdiag.cc b/dexlayout/dexdiag.cc | |
index 7e0a1be..8aacb50 100644 | |
--- a/dexlayout/dexdiag.cc | |
+++ b/dexlayout/dexdiag.cc | |
@@ -314,10 +314,11 @@ static bool DisplayMappingIfFromVdexFile(pm_map_t* map, Printer* printer) { | |
// Extract all the dex files from the vdex file. | |
std::string error_msg; | |
std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_name, | |
- false /*writeable*/, | |
- false /*low_4gb*/, | |
- false /*unquicken */, | |
- &error_msg /*out*/)); | |
+ false /* writeable */, | |
+ false /* low_4gb */, | |
+ false /* unquicken */, | |
+ false /* decompile_return_instruction */, | |
+ &error_msg /* out */)); | |
if (vdex == nullptr) { | |
std::cerr << "Could not open vdex file " | |
<< vdex_name | |
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc | |
index 878d0f2..5cd50e1 100644 | |
--- a/oatdump/oatdump.cc | |
+++ b/oatdump/oatdump.cc | |
@@ -515,14 +515,58 @@ class OatDumper { | |
for (size_t i = 0; i < oat_dex_files_.size(); i++) { | |
const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i]; | |
CHECK(oat_dex_file != nullptr); | |
+ if (!DumpOatDexFile(os, *oat_dex_file)) { | |
+ success = false; | |
+ } | |
+ } | |
+ } | |
+ | |
+ if (options_.export_dex_location_) { | |
+ if (kIsVdexEnabled) { | |
+ std::string error_msg; | |
+ std::string vdex_filename = GetVdexFilename(oat_file_.GetLocation()); | |
+ if (!OS::FileExists(vdex_filename.c_str())) { | |
+ os << "File " << vdex_filename.c_str() << " does not exist\n"; | |
+ return false; | |
+ } | |
+ | |
+ std::unique_ptr<VdexFile> vdex = VdexFile::Open(vdex_filename, | |
+ /* writable */ false, | |
+ /* low_4gb */ false, | |
+ /* unquicken */ true, | |
+ /* decompile_return_instruction */ true, | |
+ &error_msg); | |
+ if (vdex.get() == nullptr) { | |
+ os << "Failed to load vdex file '" << vdex_filename.c_str() << "': " | |
+ << error_msg << "\n"; | |
+ return false; | |
+ } | |
+ | |
+ std::vector<std::unique_ptr<const DexFile>> unique_ptr_dex_files; | |
+ if (!vdex->OpenAllDexFiles(&unique_ptr_dex_files, &error_msg)) { | |
+ os << "Failed to open dex files from vdex: " << error_msg << "\n"; | |
+ return false; | |
+ } | |
+ if (oat_dex_files_.size() != unique_ptr_dex_files.size()) { | |
+ os << "Unexpected number of dex files\n"; | |
+ return false; | |
+ } | |
- // If file export selected skip file analysis | |
- if (options_.export_dex_location_) { | |
- if (!ExportDexFile(os, *oat_dex_file)) { | |
+ size_t i = 0; | |
+ for (const auto& dex_file : unique_ptr_dex_files) { | |
+ const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i]; | |
+ CHECK(oat_dex_file != nullptr); | |
+ CHECK(dex_file != nullptr); | |
+ if (!ExportDexFile(os, *oat_dex_file, dex_file.get())) { | |
success = false; | |
} | |
- } else { | |
- if (!DumpOatDexFile(os, *oat_dex_file)) { | |
+ i++; | |
+ } | |
+ } else { | |
+ for (size_t i = 0; i < oat_dex_files_.size(); i++) { | |
+ const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i]; | |
+ CHECK(oat_dex_file != nullptr); | |
+ if (!ExportDexFile(os, *oat_dex_file, nullptr)) { | |
success = false; | |
} | |
} | |
@@ -981,15 +1025,9 @@ class OatDumper { | |
return success; | |
} | |
- bool ExportDexFile(std::ostream& os, const OatFile::OatDexFile& oat_dex_file) { | |
+ bool ExportDexFile(std::ostream& os, const OatFile::OatDexFile& oat_dex_file, const DexFile* dex_file) { | |
std::string error_msg; | |
std::string dex_file_location = oat_dex_file.GetDexFileLocation(); | |
- | |
- const DexFile* const dex_file = OpenDexFile(&oat_dex_file, &error_msg); | |
- if (dex_file == nullptr) { | |
- os << "Failed to open dex file '" << dex_file_location << "': " << error_msg; | |
- return false; | |
- } | |
size_t fsize = oat_dex_file.FileSize(); | |
// Some quick checks just in case | |
@@ -998,6 +1036,26 @@ class OatDumper { | |
return false; | |
} | |
+ if (dex_file == nullptr) { | |
+ // Exported bytecode is quickened (dex-to-dex transformations present) | |
+ dex_file = OpenDexFile(&oat_dex_file, &error_msg); | |
+ if (dex_file == nullptr) { | |
+ os << "Failed to open dex file '" << dex_file_location << "': " << error_msg; | |
+ return false; | |
+ } | |
+ | |
+ // Recompute checksum | |
+ reinterpret_cast<art::DexFile::Header*>(const_cast<uint8_t*>(dex_file->Begin()))->checksum_ = | |
+ dex_file->CalculateChecksum(); | |
+ } else { | |
+ // Vdex unquicken output should match original input bytecode | |
+ uint32_t orig_checksum = reinterpret_cast<art::DexFile::Header*>(const_cast<uint8_t*>(dex_file->Begin()))->checksum_; | |
+ if (orig_checksum != dex_file->CalculateChecksum()) { | |
+ os << "Unexpected checksum from unquicken dex file '" << dex_file_location << "'\n"; | |
+ return false; | |
+ } | |
+ } | |
+ | |
// Verify output directory exists | |
if (!OS::DirectoryExists(options_.export_dex_location_)) { | |
// TODO: Extend OS::DirectoryExists if symlink support is required | |
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc | |
index a816522..73e0fef 100644 | |
--- a/runtime/oat_file.cc | |
+++ b/runtime/oat_file.cc | |
@@ -193,7 +193,12 @@ bool OatFileBase::LoadVdex(const std::string& vdex_filename, | |
bool writable, | |
bool low_4gb, | |
std::string* error_msg) { | |
- vdex_ = VdexFile::Open(vdex_filename, writable, low_4gb, /* unquicken*/ false, error_msg); | |
+ vdex_ = VdexFile::Open(vdex_filename, | |
+ writable, | |
+ low_4gb, | |
+ /* unquicken*/ false, | |
+ /* decompile_return_instruction */ false, | |
+ error_msg); | |
if (vdex_.get() == nullptr) { | |
*error_msg = StringPrintf("Failed to load vdex file '%s' %s", | |
vdex_filename.c_str(), | |
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc | |
index f0912cf..36ee77c 100644 | |
--- a/runtime/oat_file_assistant.cc | |
+++ b/runtime/oat_file_assistant.cc | |
@@ -968,6 +968,7 @@ OatFileAssistant::OatStatus OatFileAssistant::OatFileInfo::Status() { | |
/*writeable*/false, | |
/*low_4gb*/false, | |
/*unquicken*/false, | |
+ /*decompile_return_instruction*/false, | |
&error_msg); | |
if (vdex == nullptr) { | |
status_ = kOatCannotOpen; | |
diff --git a/runtime/runtime.cc b/runtime/runtime.cc | |
index 8667310..477f3d6 100644 | |
--- a/runtime/runtime.cc | |
+++ b/runtime/runtime.cc | |
@@ -908,7 +908,8 @@ static bool OpenDexFilesFromImage(const std::string& image_location, | |
std::unique_ptr<VdexFile> vdex_file(VdexFile::Open(vdex_filename, | |
false /* writable */, | |
false /* low_4gb */, | |
- false, /* unquicken */ | |
+ false /* unquicken */, | |
+ false /* decompile_return_instruction */, | |
&error_msg)); | |
if (vdex_file.get() == nullptr) { | |
return false; | |
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc | |
index 842aa04..de96951 100644 | |
--- a/runtime/vdex_file.cc | |
+++ b/runtime/vdex_file.cc | |
@@ -58,6 +58,7 @@ std::unique_ptr<VdexFile> VdexFile::Open(const std::string& vdex_filename, | |
bool writable, | |
bool low_4gb, | |
bool unquicken, | |
+ bool decompile_return_instruction, | |
std::string* error_msg) { | |
if (!OS::FileExists(vdex_filename.c_str())) { | |
*error_msg = "File " + vdex_filename + " does not exist."; | |
@@ -82,7 +83,7 @@ std::unique_ptr<VdexFile> VdexFile::Open(const std::string& vdex_filename, | |
return nullptr; | |
} | |
- return Open(vdex_file->Fd(), vdex_length, vdex_filename, writable, low_4gb, unquicken, error_msg); | |
+ return Open(vdex_file->Fd(), vdex_length, vdex_filename, writable, low_4gb, unquicken, decompile_return_instruction, error_msg); | |
} | |
std::unique_ptr<VdexFile> VdexFile::Open(int file_fd, | |
@@ -91,6 +92,7 @@ std::unique_ptr<VdexFile> VdexFile::Open(int file_fd, | |
bool writable, | |
bool low_4gb, | |
bool unquicken, | |
+ bool decompile_return_instruction, | |
std::string* error_msg) { | |
std::unique_ptr<MemMap> mmap(MemMap::MapFile( | |
vdex_length, | |
@@ -117,7 +119,9 @@ std::unique_ptr<VdexFile> VdexFile::Open(int file_fd, | |
if (!vdex->OpenAllDexFiles(&unique_ptr_dex_files, error_msg)) { | |
return nullptr; | |
} | |
- Unquicken(MakeNonOwningPointerVector(unique_ptr_dex_files), vdex->GetQuickeningInfo()); | |
+ Unquicken(MakeNonOwningPointerVector(unique_ptr_dex_files), | |
+ vdex->GetQuickeningInfo(), | |
+ decompile_return_instruction); | |
// Update the quickening info size to pretend there isn't any. | |
reinterpret_cast<Header*>(vdex->mmap_->Begin())->quickening_info_size_ = 0; | |
} | |
@@ -165,7 +169,8 @@ bool VdexFile::OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_ | |
} | |
void VdexFile::Unquicken(const std::vector<const DexFile*>& dex_files, | |
- const ArrayRef<const uint8_t>& quickening_info) { | |
+ const ArrayRef<const uint8_t>& quickening_info, | |
+ bool decompile_return_instruction) { | |
if (quickening_info.size() == 0) { | |
// If there is no quickening info, we bail early, as the code below expects at | |
// least the size of quickening data for each method that has a code item. | |
@@ -196,7 +201,7 @@ void VdexFile::Unquicken(const std::vector<const DexFile*>& dex_files, | |
quickening_info_ptr += sizeof(uint32_t); | |
optimizer::ArtDecompileDEX(*code_item, | |
ArrayRef<const uint8_t>(quickening_info_ptr, quickening_size), | |
- /* decompile_return_instruction */ false); | |
+ decompile_return_instruction); | |
quickening_info_ptr += quickening_size; | |
} | |
it.Next(); | |
@@ -209,7 +214,7 @@ void VdexFile::Unquicken(const std::vector<const DexFile*>& dex_files, | |
quickening_info_ptr += sizeof(uint32_t); | |
optimizer::ArtDecompileDEX(*code_item, | |
ArrayRef<const uint8_t>(quickening_info_ptr, quickening_size), | |
- /* decompile_return_instruction */ false); | |
+ decompile_return_instruction); | |
quickening_info_ptr += quickening_size; | |
} | |
it.Next(); | |
diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h | |
index 93d282b..78bcb88 100644 | |
--- a/runtime/vdex_file.h | |
+++ b/runtime/vdex_file.h | |
@@ -85,6 +85,7 @@ class VdexFile { | |
bool writable, | |
bool low_4gb, | |
bool unquicken, | |
+ bool decompile_return_instruction, | |
std::string* error_msg); | |
// Returns nullptr if the vdex file cannot be opened or is not valid. | |
@@ -94,6 +95,7 @@ class VdexFile { | |
bool writable, | |
bool low_4gb, | |
bool unquicken, | |
+ bool decompile_return_instruction, | |
std::string* error_msg); | |
const uint8_t* Begin() const { return mmap_->Begin(); } | |
@@ -137,7 +139,8 @@ class VdexFile { | |
// In-place unquicken the given `dex_files` based on `quickening_info`. | |
static void Unquicken(const std::vector<const DexFile*>& dex_files, | |
- const ArrayRef<const uint8_t>& quickening_info); | |
+ const ArrayRef<const uint8_t>& quickening_info, | |
+ bool decompile_return_instruction); | |
private: | |
explicit VdexFile(MemMap* mmap) : mmap_(mmap) {} | |
diff --git a/runtime/vdex_file_test.cc b/runtime/vdex_file_test.cc | |
index ced6e28..bf73430 100644 | |
--- a/runtime/vdex_file_test.cc | |
+++ b/runtime/vdex_file_test.cc | |
@@ -37,11 +37,16 @@ TEST_F(VdexFileTest, OpenEmptyVdex) { | |
/*writable*/false, | |
/*low_4gb*/false, | |
/*quicken*/false, | |
+ /*decompile_return_instruction*/false, | |
&error_msg); | |
EXPECT_TRUE(vdex == nullptr); | |
- vdex = VdexFile::Open( | |
- tmp.GetFilename(), /*writable*/false, /*low_4gb*/false, /*quicken*/ false, &error_msg); | |
+ vdex = VdexFile::Open(tmp.GetFilename(), | |
+ /*writable*/false, | |
+ /*low_4gb*/false, | |
+ /*quicken*/false, | |
+ /*decompile_return_instruction*/false, | |
+ &error_msg); | |
EXPECT_TRUE(vdex == nullptr); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
True