Re-generate dex IR to verify dex file
Instead of using the existing IR, re-generate it to catch possible
bugs writing the output dex.
Test: test-art-host
Bug: 63756964
Change-Id: Ib63f3137f5807ee5de1b05f8278137a3b3a3aee0
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 1c966c1..9a2ab66 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -2022,25 +2022,6 @@
if (new_file != nullptr) {
UNUSED(new_file->FlushCloseOrErase());
}
- // Verify the output dex file's structure for debug builds.
- if (kIsDebugBuild) {
- std::string location = "memory mapped file for " + dex_file_location;
- std::unique_ptr<const DexFile> output_dex_file(DexFileLoader::Open(mem_map_->Begin(),
- mem_map_->Size(),
- location,
- header_->Checksum(),
- /*oat_dex_file*/ nullptr,
- /*verify*/ true,
- /*verify_checksum*/ false,
- &error_msg));
- DCHECK(output_dex_file != nullptr) << " Failed to re-open output file:" << error_msg;
- }
- // Do IR-level comparison between input and output. This check ignores potential differences
- // due to layout, so offsets are not checked. Instead, it checks the data contents of each item.
- if (kIsDebugBuild || options_.verify_output_) {
- std::unique_ptr<dex_ir::Header> orig_header(dex_ir::DexIrBuilder(*dex_file));
- CHECK(VerifyOutputDexFile(orig_header.get(), header_, &error_msg)) << error_msg;
- }
}
/*
@@ -2072,12 +2053,38 @@
DumpDexFile();
}
- // Output dex file as file or memmap.
+ // In case we are outputting to a file, keep it open so we can verify.
if (options_.output_dex_directory_ != nullptr || options_.output_to_memmap_) {
if (info_ != nullptr) {
LayoutOutputFile(dex_file);
}
OutputDexFile(dex_file);
+
+ // Clear header before verifying to reduce peak RAM usage.
+ header.reset();
+
+ // Verify the output dex file's structure, only enabled by default for debug builds.
+ if (options_.verify_output_) {
+ std::string error_msg;
+ std::string location = "memory mapped file for " + std::string(file_name);
+ std::unique_ptr<const DexFile> output_dex_file(DexFileLoader::Open(mem_map_->Begin(),
+ mem_map_->Size(),
+ location,
+ /* checksum */ 0,
+ /*oat_dex_file*/ nullptr,
+ /*verify*/ true,
+ /*verify_checksum*/ false,
+ &error_msg));
+ CHECK(output_dex_file != nullptr) << "Failed to re-open output file:" << error_msg;
+
+ // Do IR-level comparison between input and output. This check ignores potential differences
+ // due to layout, so offsets are not checked. Instead, it checks the data contents of each item.
+ //
+ // Regenerate output IR to catch any bugs that might happen during writing.
+ std::unique_ptr<dex_ir::Header> output_header(dex_ir::DexIrBuilder(*output_dex_file));
+ std::unique_ptr<dex_ir::Header> orig_header(dex_ir::DexIrBuilder(*dex_file));
+ CHECK(VerifyOutputDexFile(output_header.get(), orig_header.get(), &error_msg)) << error_msg;
+ }
}
}
diff --git a/dexlayout/dexlayout.h b/dexlayout/dexlayout.h
index 57d273e..2e89773 100644
--- a/dexlayout/dexlayout.h
+++ b/dexlayout/dexlayout.h
@@ -60,7 +60,7 @@
bool show_section_headers_ = false;
bool show_section_statistics_ = false;
bool verbose_ = false;
- bool verify_output_ = false;
+ bool verify_output_ = kIsDebugBuild;
bool visualize_pattern_ = false;
CompactDexLevel compact_dex_level_ = CompactDexLevel::kCompactDexLevelNone;
OutputFormat output_format_ = kOutputPlain;