diff options
-rw-r--r-- | dex2oat/dex2oat_test.cc | 108 | ||||
-rw-r--r-- | dex2oat/linker/oat_writer.cc | 26 | ||||
-rw-r--r-- | dexlayout/compact_dex_writer.cc | 59 | ||||
-rw-r--r-- | dexlayout/compact_dex_writer.h | 5 | ||||
-rw-r--r-- | dexlayout/dex_writer.cc | 12 | ||||
-rw-r--r-- | dexlayout/dex_writer.h | 7 | ||||
-rw-r--r-- | dexlayout/dexlayout.cc | 46 | ||||
-rw-r--r-- | dexlayout/dexlayout.h | 10 | ||||
-rw-r--r-- | dexlayout/dexlayout_test.cc | 11 | ||||
-rw-r--r-- | openjdkjvmti/fixed_up_dex_file.cc | 11 |
10 files changed, 246 insertions, 49 deletions
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc index 17a27f8567..d0b0d49a39 100644 --- a/dex2oat/dex2oat_test.cc +++ b/dex2oat/dex2oat_test.cc @@ -31,6 +31,7 @@ #include "base/mutex-inl.h" #include "bytecode_utils.h" #include "dex/art_dex_file_loader.h" +#include "dex/base64_test_util.h" #include "dex/code_item_accessors-inl.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_loader.h" @@ -1559,4 +1560,111 @@ TEST_F(Dex2oatTest, EmptyUncompressedDexTest) { ASSERT_EQ(WEXITSTATUS(status), 1) << error_msg; } +// Dex file that has duplicate methods have different code items and debug info. +static const char kDuplicateMethodInputDex[] = + "ZGV4CjAzOQDEy8VPdj4qHpgPYFWtLCtOykfFP4kB8tGYDAAAcAAAAHhWNBIAAAAAAAAAANALAABI" + "AAAAcAAAAA4AAACQAQAABQAAAMgBAAANAAAABAIAABkAAABsAgAABAAAADQDAADgCAAAuAMAADgI" + "AABCCAAASggAAE8IAABcCAAAaggAAHkIAACICAAAlggAAKQIAACyCAAAwAgAAM4IAADcCAAA6ggA" + "APgIAAD7CAAA/wgAABcJAAAuCQAARQkAAFQJAAB4CQAAmAkAALsJAADSCQAA5gkAAPoJAAAVCgAA" + "KQoAADsKAABCCgAASgoAAFIKAABbCgAAZAoAAGwKAAB0CgAAfAoAAIQKAACMCgAAlAoAAJwKAACk" + "CgAArQoAALcKAADACgAAwwoAAMcKAADcCgAA6QoAAPEKAAD3CgAA/QoAAAMLAAAJCwAAEAsAABcL" + "AAAdCwAAIwsAACkLAAAvCwAANQsAADsLAABBCwAARwsAAE0LAABSCwAAWwsAAF4LAABoCwAAbwsA" + "ABEAAAASAAAAEwAAABQAAAAVAAAAFgAAABcAAAAYAAAAGQAAABoAAAAbAAAAHAAAAC4AAAAwAAAA" + "DwAAAAkAAAAAAAAAEAAAAAoAAACoBwAALgAAAAwAAAAAAAAALwAAAAwAAACoBwAALwAAAAwAAACw" + "BwAAAgAJADUAAAACAAkANgAAAAIACQA3AAAAAgAJADgAAAACAAkAOQAAAAIACQA6AAAAAgAJADsA" + "AAACAAkAPAAAAAIACQA9AAAAAgAJAD4AAAACAAkAPwAAAAIACQBAAAAACwAHAEIAAAAAAAIAAQAA" + "AAAAAwAeAAAAAQACAAEAAAABAAMAHgAAAAIAAgAAAAAAAgACAAEAAAADAAIAAQAAAAMAAgAfAAAA" + "AwACACAAAAADAAIAIQAAAAMAAgAiAAAAAwACACMAAAADAAIAJAAAAAMAAgAlAAAAAwACACYAAAAD" + "AAIAJwAAAAMAAgAoAAAAAwACACkAAAADAAIAKgAAAAMABAA0AAAABwADAEMAAAAIAAIAAQAAAAoA" + "AgABAAAACgABADIAAAAKAAAARQAAAAAAAAAAAAAACAAAAAAAAAAdAAAAaAcAALYHAAAAAAAAAQAA" + "AAAAAAAIAAAAAAAAAB0AAAB4BwAAxAcAAAAAAAACAAAAAAAAAAgAAAAAAAAAHQAAAIgHAADSBwAA" + "AAAAAAMAAAAAAAAACAAAAAAAAAAdAAAAmAcAAPoHAAAAAAAAAAAAAAEAAAAAAAAArAYAADEAAAAa" + "AAMAaQAAABoABABpAAEAGgAHAGkABAAaAAgAaQAFABoACQBpAAYAGgAKAGkABwAaAAsAaQAIABoA" + "DABpAAkAGgANAGkACgAaAA4AaQALABoABQBpAAIAGgAGAGkAAwAOAAAAAQABAAEAAACSBgAABAAA" + "AHAQFQAAAA4ABAABAAIAAACWBgAAFwAAAGIADAAiAQoAcBAWAAEAGgICAG4gFwAhAG4gFwAxAG4Q" + "GAABAAwBbiAUABAADgAAAAEAAQABAAAAngYAAAQAAABwEBUAAAAOAAIAAQACAAAAogYAAAYAAABi" + "AAwAbiAUABAADgABAAEAAQAAAKgGAAAEAAAAcBAVAAAADgABAAEAAQAAALsGAAAEAAAAcBAVAAAA" + "DgABAAAAAQAAAL8GAAAGAAAAYgAAAHEQAwAAAA4AAQAAAAEAAADEBgAABgAAAGIAAQBxEAMAAAAO" + "AAEAAAABAAAA8QYAAAYAAABiAAIAcRABAAAADgABAAAAAQAAAPYGAAAGAAAAYgADAHEQAwAAAA4A" + "AQAAAAEAAADJBgAABgAAAGIABABxEAMAAAAOAAEAAAABAAAAzgYAAAYAAABiAAEAcRADAAAADgAB" + "AAAAAQAAANMGAAAGAAAAYgAGAHEQAwAAAA4AAQAAAAEAAADYBgAABgAAAGIABwBxEAMAAAAOAAEA" + "AAABAAAA3QYAAAYAAABiAAgAcRABAAAADgABAAAAAQAAAOIGAAAGAAAAYgAJAHEQAwAAAA4AAQAA" + "AAEAAADnBgAABgAAAGIACgBxEAMAAAAOAAEAAAABAAAA7AYAAAYAAABiAAsAcRABAAAADgABAAEA" + "AAAAAPsGAAAlAAAAcQAHAAAAcQAIAAAAcQALAAAAcQAMAAAAcQANAAAAcQAOAAAAcQAPAAAAcQAQ" + "AAAAcQARAAAAcQASAAAAcQAJAAAAcQAKAAAADgAnAA4AKQFFDgEWDwAhAA4AIwFFDloAEgAOABMA" + "DktLS0tLS0tLS0tLABEADgAuAA5aADIADloANgAOWgA6AA5aAD4ADloAQgAOWgBGAA5aAEoADloA" + "TgAOWgBSAA5aAFYADloAWgAOWgBeATQOPDw8PDw8PDw8PDw8AAIEAUYYAwIFAjEECEEXLAIFAjEE" + "CEEXKwIFAjEECEEXLQIGAUYcAxgAGAEYAgAAAAIAAAAMBwAAEgcAAAIAAAAMBwAAGwcAAAIAAAAM" + "BwAAJAcAAAEAAAAtBwAAPAcAAAAAAAAAAAAAAAAAAEgHAAAAAAAAAAAAAAAAAABUBwAAAAAAAAAA" + "AAAAAAAAYAcAAAAAAAAAAAAAAAAAAAEAAAAJAAAAAQAAAA0AAAACAACAgASsCAEIxAgAAAIAAoCA" + "BIQJAQicCQwAAgAACQEJAQkBCQEJAQkBCQEJAQkBCQEJAQkEiIAEuAcBgIAEuAkAAA4ABoCABNAJ" + "AQnoCQAJhAoACaAKAAm8CgAJ2AoACfQKAAmQCwAJrAsACcgLAAnkCwAJgAwACZwMAAm4DAg8Y2xp" + "bml0PgAGPGluaXQ+AANBQUEAC0hlbGxvIFdvcmxkAAxIZWxsbyBXb3JsZDEADUhlbGxvIFdvcmxk" + "MTAADUhlbGxvIFdvcmxkMTEADEhlbGxvIFdvcmxkMgAMSGVsbG8gV29ybGQzAAxIZWxsbyBXb3Js" + "ZDQADEhlbGxvIFdvcmxkNQAMSGVsbG8gV29ybGQ2AAxIZWxsbyBXb3JsZDcADEhlbGxvIFdvcmxk" + "OAAMSGVsbG8gV29ybGQ5AAFMAAJMTAAWTE1hbnlNZXRob2RzJFByaW50ZXIyOwAVTE1hbnlNZXRo" + "b2RzJFByaW50ZXI7ABVMTWFueU1ldGhvZHMkU3RyaW5nczsADUxNYW55TWV0aG9kczsAIkxkYWx2" + "aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNs" + "YXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNzZXM7ABVMamF2YS9pby9QcmludFN0" + "cmVhbTsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABlMamF2YS9sYW5n" + "L1N0cmluZ0J1aWxkZXI7ABJMamF2YS9sYW5nL1N5c3RlbTsAEE1hbnlNZXRob2RzLmphdmEABVBy" + "aW50AAZQcmludDAABlByaW50MQAHUHJpbnQxMAAHUHJpbnQxMQAGUHJpbnQyAAZQcmludDMABlBy" + "aW50NAAGUHJpbnQ1AAZQcmludDYABlByaW50NwAGUHJpbnQ4AAZQcmludDkAB1ByaW50ZXIACFBy" + "aW50ZXIyAAdTdHJpbmdzAAFWAAJWTAATW0xqYXZhL2xhbmcvU3RyaW5nOwALYWNjZXNzRmxhZ3MA" + "BmFwcGVuZAAEYXJncwAEbWFpbgAEbXNnMAAEbXNnMQAFbXNnMTAABW1zZzExAARtc2cyAARtc2cz" + "AARtc2c0AARtc2c1AARtc2c2AARtc2c3AARtc2c4AARtc2c5AARuYW1lAANvdXQAB3ByaW50bG4A" + "AXMACHRvU3RyaW5nAAV2YWx1ZQBffn5EOHsibWluLWFwaSI6MTAwMDAsInNoYS0xIjoiZmViODZj" + "MDA2ZWZhY2YxZDc5ODRiODVlMTc5MGZlZjdhNzY3YWViYyIsInZlcnNpb24iOiJ2MS4xLjUtZGV2" + "In0AEAAAAAAAAAABAAAAAAAAAAEAAABIAAAAcAAAAAIAAAAOAAAAkAEAAAMAAAAFAAAAyAEAAAQA" + "AAANAAAABAIAAAUAAAAZAAAAbAIAAAYAAAAEAAAANAMAAAEgAAAUAAAAuAMAAAMgAAAUAAAAkgYA" + "AAQgAAAFAAAADAcAAAMQAAAEAAAAOQcAAAYgAAAEAAAAaAcAAAEQAAACAAAAqAcAAAAgAAAEAAAA" + "tgcAAAIgAABIAAAAOAgAAAAQAAABAAAA0AsAAAAAAAA="; + +static void WriteBase64ToFile(const char* base64, File* file) { + // Decode base64. + CHECK(base64 != nullptr); + size_t length; + std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length)); + CHECK(bytes != nullptr); + if (!file->WriteFully(bytes.get(), length)) { + PLOG(FATAL) << "Failed to write base64 as file"; + } +} + +TEST_F(Dex2oatTest, CompactDexGenerationFailure) { + ScratchFile temp_dex; + WriteBase64ToFile(kDuplicateMethodInputDex, temp_dex.GetFile()); + std::string out_dir = GetScratchDir(); + const std::string oat_filename = out_dir + "/base.oat"; + // The dex won't pass the method verifier, only use the verify filter. + GenerateOdexForTest(temp_dex.GetFilename(), + oat_filename, + CompilerFilter::Filter::kVerify, + { }, + true, // expect_success + false, // use_fd + [](const OatFile& o) { + CHECK(o.ContainsDexCode()); + }); + // Open our generated oat file. + std::string error_msg; + std::unique_ptr<OatFile> odex_file(OatFile::Open(oat_filename.c_str(), + oat_filename.c_str(), + nullptr, + nullptr, + false, + /*low_4gb*/false, + temp_dex.GetFilename().c_str(), + &error_msg)); + ASSERT_TRUE(odex_file != nullptr); + std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles(); + ASSERT_EQ(oat_dex_files.size(), 1u); + // The dexes should have failed to convert to compact dex. + for (const OatDexFile* oat_dex : oat_dex_files) { + std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg)); + ASSERT_TRUE(dex_file != nullptr) << error_msg; + ASSERT_TRUE(!dex_file->IsCompactDexFile()); + } +} + } // namespace art diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index 0953e0813f..01125a178e 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -3597,17 +3597,21 @@ bool OatWriter::LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_fil options.compact_dex_level_ = compact_dex_level_; options.update_checksum_ = true; DexLayout dex_layout(options, profile_compilation_info_, /*file*/ nullptr, /*header*/ nullptr); - dex_layout.ProcessDexFile(location.c_str(), dex_file.get(), 0, &dex_container_); - oat_dex_file->dex_sections_layout_ = dex_layout.GetSections(); - // Dex layout can affect the size of the dex file, so we update here what we have set - // when adding the dex file as a source. - const UnalignedDexFileHeader* header = - AsUnalignedDexFileHeader(dex_container_->GetMainSection()->Begin()); - oat_dex_file->dex_file_size_ = header->file_size_; - if (!WriteDexFile(out, - oat_dex_file, - dex_container_->GetMainSection()->Begin(), - /* update_input_vdex */ false)) { + const uint8_t* dex_src = nullptr; + if (dex_layout.ProcessDexFile(location.c_str(), dex_file.get(), 0, &dex_container_, &error_msg)) { + oat_dex_file->dex_sections_layout_ = dex_layout.GetSections(); + // Dex layout can affect the size of the dex file, so we update here what we have set + // when adding the dex file as a source. + const UnalignedDexFileHeader* header = + AsUnalignedDexFileHeader(dex_container_->GetMainSection()->Begin()); + oat_dex_file->dex_file_size_ = header->file_size_; + dex_src = dex_container_->GetMainSection()->Begin(); + } else { + LOG(WARNING) << "Failed to run dex layout, reason:" << error_msg; + // Since we failed to convert the dex, just copy the input dex. + dex_src = dex_file->Begin(); + } + if (!WriteDexFile(out, oat_dex_file, dex_src, /* update_input_vdex */ false)) { return false; } if (dex_container_ != nullptr) { diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc index ca13f7588b..39cf86d4b2 100644 --- a/dexlayout/compact_dex_writer.cc +++ b/dexlayout/compact_dex_writer.cc @@ -16,6 +16,7 @@ #include "compact_dex_writer.h" +#include "android-base/stringprintf.h" #include "base/logging.h" #include "base/time_utils.h" #include "dex/compact_dex_debug_info.h" @@ -328,9 +329,63 @@ void CompactDexWriter::WriteStringData(Stream* stream, dex_ir::StringData* strin stream->Skip(1); } -void CompactDexWriter::Write(DexContainer* output) { +bool CompactDexWriter::CanGenerateCompactDex(std::string* error_msg) { + dex_ir::Collections& collections = header_->GetCollections(); + static constexpr InvokeType invoke_types[] = { + kDirect, + kVirtual + }; + std::vector<bool> saw_method_id(collections.MethodIdsSize(), false); + std::vector<dex_ir::CodeItem*> method_id_code_item(collections.MethodIdsSize(), nullptr); + std::vector<dex_ir::DebugInfoItem*> method_id_debug_info(collections.MethodIdsSize(), nullptr); + for (InvokeType invoke_type : invoke_types) { + for (std::unique_ptr<dex_ir::ClassDef>& class_def : collections.ClassDefs()) { + // Skip classes that are not defined in this dex file. + dex_ir::ClassData* class_data = class_def->GetClassData(); + if (class_data == nullptr) { + continue; + } + for (auto& method : *(invoke_type == InvokeType::kDirect + ? class_data->DirectMethods() + : class_data->VirtualMethods())) { + const uint32_t idx = method->GetMethodId()->GetIndex(); + dex_ir::CodeItem* code_item = method->GetCodeItem(); + dex_ir:: DebugInfoItem* debug_info_item = nullptr; + if (code_item != nullptr) { + debug_info_item = code_item->DebugInfo(); + } + if (saw_method_id[idx]) { + if (method_id_code_item[idx] != code_item) { + *error_msg = android::base::StringPrintf("Conflicting code item for method id %u", + idx); + // Conflicting info, abort generation. + return false; + } + if (method_id_debug_info[idx] != debug_info_item) { + *error_msg = android::base::StringPrintf("Conflicting debug info for method id %u", + idx); + // Conflicting info, abort generation. + return false; + } + } + method_id_code_item[idx] = code_item; + method_id_debug_info[idx] = debug_info_item; + saw_method_id[idx] = true; + } + } + } + return true; +} + +bool CompactDexWriter::Write(DexContainer* output, std::string* error_msg) { + DCHECK(error_msg != nullptr); CHECK(compute_offsets_); CHECK(output->IsCompactDexContainer()); + + if (!CanGenerateCompactDex(error_msg)) { + return false; + } + Container* const container = down_cast<Container*>(output); // For now, use the same stream for both data and metadata. Stream temp_main_stream(output->GetMainSection()); @@ -472,6 +527,8 @@ void CompactDexWriter::Write(DexContainer* output) { // dex2oat's class unloading. The issue is that verification encounters quickened opcodes after // the first dex gets unloaded. code_item_dedupe_->Clear(); + + return true; } std::unique_ptr<DexContainer> CompactDexWriter::CreateDexContainer() const { diff --git a/dexlayout/compact_dex_writer.h b/dexlayout/compact_dex_writer.h index ea9f7d13db..0e7d65f9e4 100644 --- a/dexlayout/compact_dex_writer.h +++ b/dexlayout/compact_dex_writer.h @@ -136,7 +136,10 @@ class CompactDexWriter : public DexWriter { }; protected: - void Write(DexContainer* output) OVERRIDE; + // Return true if we can generate compact dex for the IR. + bool CanGenerateCompactDex(std::string* error_msg); + + bool Write(DexContainer* output, std::string* error_msg) OVERRIDE; std::unique_ptr<DexContainer> CreateDexContainer() const OVERRIDE; diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc index 808bfad029..eead13f69a 100644 --- a/dexlayout/dex_writer.cc +++ b/dexlayout/dex_writer.cc @@ -788,7 +788,9 @@ size_t DexWriter::GetHeaderSize() const { return sizeof(StandardDexFile::Header); } -void DexWriter::Write(DexContainer* output) { +bool DexWriter::Write(DexContainer* output, std::string* error_msg) { + DCHECK(error_msg != nullptr); + Stream stream_storage(output->GetMainSection()); Stream* stream = &stream_storage; @@ -905,11 +907,13 @@ void DexWriter::Write(DexContainer* output) { // Trim the map to make it sized as large as the dex file. output->GetMainSection()->Resize(header_->FileSize()); + return true; } -void DexWriter::Output(DexLayout* dex_layout, +bool DexWriter::Output(DexLayout* dex_layout, std::unique_ptr<DexContainer>* container, - bool compute_offsets) { + bool compute_offsets, + std::string* error_msg) { CHECK(dex_layout != nullptr); std::unique_ptr<DexWriter> writer; if (dex_layout->GetOptions().compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone) { @@ -922,7 +926,7 @@ void DexWriter::Output(DexLayout* dex_layout, if (*container == nullptr) { *container = writer->CreateDexContainer(); } - writer->Write(container->get()); + return writer->Write(container->get(), error_msg); } void MapItemQueue::AddIfNotEmpty(const MapItem& item) { diff --git a/dexlayout/dex_writer.h b/dexlayout/dex_writer.h index 5df11116ee..df098c0f6f 100644 --- a/dexlayout/dex_writer.h +++ b/dexlayout/dex_writer.h @@ -214,14 +214,15 @@ class DexWriter { DexWriter(DexLayout* dex_layout, bool compute_offsets); - static void Output(DexLayout* dex_layout, + static bool Output(DexLayout* dex_layout, std::unique_ptr<DexContainer>* container, - bool compute_offsets); + bool compute_offsets, + std::string* error_msg) WARN_UNUSED; virtual ~DexWriter() {} protected: - virtual void Write(DexContainer* output); + virtual bool Write(DexContainer* output, std::string* error_msg); virtual std::unique_ptr<DexContainer> CreateDexContainer() const; void WriteEncodedValue(Stream* stream, dex_ir::EncodedValue* encoded_value); diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc index 91d35ff6d7..e841811861 100644 --- a/dexlayout/dexlayout.cc +++ b/dexlayout/dexlayout.cc @@ -1813,11 +1813,11 @@ void DexLayout::LayoutOutputFile(const DexFile* dex_file) { LayoutCodeItems(dex_file); } -void DexLayout::OutputDexFile(const DexFile* input_dex_file, +bool DexLayout::OutputDexFile(const DexFile* input_dex_file, bool compute_offsets, - std::unique_ptr<DexContainer>* dex_container) { + std::unique_ptr<DexContainer>* dex_container, + std::string* error_msg) { const std::string& dex_file_location = input_dex_file->GetLocation(); - std::string error_msg; std::unique_ptr<File> new_file; // If options_.output_dex_directory_ is non null, we are outputting to a file. if (options_.output_dex_directory_ != nullptr) { @@ -1834,35 +1834,39 @@ void DexLayout::OutputDexFile(const DexFile* input_dex_file, new_file.reset(OS::CreateEmptyFile(output_location.c_str())); if (new_file == nullptr) { LOG(ERROR) << "Could not create dex writer output file: " << output_location; - return; + return false; } } - DexWriter::Output(this, dex_container, compute_offsets); + if (!DexWriter::Output(this, dex_container, compute_offsets, error_msg)) { + return false; + } if (new_file != nullptr) { DexContainer* const container = dex_container->get(); DexContainer::Section* const main_section = container->GetMainSection(); if (!new_file->WriteFully(main_section->Begin(), main_section->Size())) { LOG(ERROR) << "Failed to write main section for dex file " << dex_file_location; new_file->Erase(); - return; + return false; } DexContainer::Section* const data_section = container->GetDataSection(); if (!new_file->WriteFully(data_section->Begin(), data_section->Size())) { LOG(ERROR) << "Failed to write data section for dex file " << dex_file_location; new_file->Erase(); - return; + return false; } UNUSED(new_file->FlushCloseOrErase()); } + return true; } /* * Dumps the requested sections of the file. */ -void DexLayout::ProcessDexFile(const char* file_name, +bool DexLayout::ProcessDexFile(const char* file_name, const DexFile* dex_file, size_t dex_file_index, - std::unique_ptr<DexContainer>* dex_container) { + std::unique_ptr<DexContainer>* dex_container, + std::string* error_msg) { const bool has_output_container = dex_container != nullptr; const bool output = options_.output_dex_directory_ != nullptr || has_output_container; @@ -1885,12 +1889,12 @@ void DexLayout::ProcessDexFile(const char* file_name, if (options_.visualize_pattern_) { VisualizeDexLayout(header_, dex_file, dex_file_index, info_); - return; + return true; } if (options_.show_section_statistics_) { ShowDexSectionStatistics(header_, dex_file_index); - return; + return true; } // Dump dex file. @@ -1912,7 +1916,9 @@ void DexLayout::ProcessDexFile(const char* file_name, dex_container = &temp_container; } // If we didn't set the offsets eagerly, we definitely need to compute them here. - OutputDexFile(dex_file, do_layout || !eagerly_assign_offsets, dex_container); + if (!OutputDexFile(dex_file, do_layout || !eagerly_assign_offsets, dex_container, error_msg)) { + return false; + } // Clear header before verifying to reduce peak RAM usage. const size_t file_size = header_->FileSize(); @@ -1920,7 +1926,6 @@ void DexLayout::ProcessDexFile(const char* file_name, // Verify the output dex file's structure, only enabled by default for debug builds. if (options_.verify_output_ && has_output_container) { - std::string error_msg; std::string location = "memory mapped file for " + std::string(file_name); // Dex file verifier cannot handle compact dex. bool verify = options_.compact_dex_level_ == CompactDexLevel::kCompactDexLevelNone; @@ -1940,8 +1945,8 @@ void DexLayout::ProcessDexFile(const char* file_name, /*oat_dex_file*/ nullptr, verify, /*verify_checksum*/ false, - &error_msg)); - CHECK(output_dex_file != nullptr) << "Failed to re-open output file:" << error_msg; + 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 @@ -1956,9 +1961,10 @@ void DexLayout::ProcessDexFile(const char* file_name, dex_ir::DexIrBuilder(*dex_file, /*eagerly_assign_offsets*/ true, GetOptions())); - CHECK(VerifyOutputDexFile(output_header.get(), orig_header.get(), &error_msg)) << error_msg; + CHECK(VerifyOutputDexFile(output_header.get(), orig_header.get(), error_msg)) << *error_msg; } } + return true; } /* @@ -1990,7 +1996,13 @@ int DexLayout::ProcessFile(const char* file_name) { } else { for (size_t i = 0; i < dex_files.size(); i++) { // Pass in a null container to avoid output by default. - ProcessDexFile(file_name, dex_files[i].get(), i, /*dex_container*/ nullptr); + if (!ProcessDexFile(file_name, + dex_files[i].get(), + i, + /*dex_container*/ nullptr, + &error_msg)) { + LOG(WARNING) << "Failed to run dex file " << i << " in " << file_name << " : " << error_msg; + } } } return 0; diff --git a/dexlayout/dexlayout.h b/dexlayout/dexlayout.h index 5635271dc1..b79a59209d 100644 --- a/dexlayout/dexlayout.h +++ b/dexlayout/dexlayout.h @@ -111,10 +111,11 @@ class DexLayout { header_(header) { } int ProcessFile(const char* file_name); - void ProcessDexFile(const char* file_name, + bool ProcessDexFile(const char* file_name, const DexFile* dex_file, size_t dex_file_index, - std::unique_ptr<DexContainer>* dex_container); + std::unique_ptr<DexContainer>* dex_container, + std::string* error_msg); dex_ir::Header* GetHeader() const { return header_; } void SetHeader(dex_ir::Header* header) { header_ = header; } @@ -168,9 +169,10 @@ class DexLayout { // Creates a new layout for the dex file based on profile info. // Currently reorders ClassDefs, ClassDataItems, and CodeItems. void LayoutOutputFile(const DexFile* dex_file); - void OutputDexFile(const DexFile* input_dex_file, + bool OutputDexFile(const DexFile* input_dex_file, bool compute_offsets, - std::unique_ptr<DexContainer>* dex_container); + std::unique_ptr<DexContainer>* dex_container, + std::string* error_msg); void DumpCFG(const DexFile* dex_file, int idx); void DumpCFG(const DexFile* dex_file, uint32_t dex_method_idx, const DexFile::CodeItem* code); diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc index a1901f08f3..d9a93ddf36 100644 --- a/dexlayout/dexlayout_test.cc +++ b/dexlayout/dexlayout_test.cc @@ -834,10 +834,13 @@ TEST_F(DexLayoutTest, ClassFilter) { /*out_file*/ nullptr, /*header*/ nullptr); std::unique_ptr<DexContainer> out; - dexlayout.ProcessDexFile(dex_file->GetLocation().c_str(), - dex_file.get(), - /*dex_file_index*/ 0, - &out); + bool result = dexlayout.ProcessDexFile( + dex_file->GetLocation().c_str(), + dex_file.get(), + /*dex_file_index*/ 0, + &out, + &error_msg); + ASSERT_TRUE(result) << "Failed to run dexlayout " << error_msg; std::unique_ptr<const DexFile> output_dex_file( dex_file_loader.OpenWithDataSection( out->GetMainSection()->Begin(), diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc index e9522b3984..427d87eedf 100644 --- a/openjdkjvmti/fixed_up_dex_file.cc +++ b/openjdkjvmti/fixed_up_dex_file.cc @@ -104,10 +104,13 @@ std::unique_ptr<FixedUpDexFile> FixedUpDexFile::Create(const art::DexFile& origi /*out_file*/ nullptr, /*header*/ nullptr); std::unique_ptr<art::DexContainer> dex_container; - dex_layout.ProcessDexFile(original.GetLocation().c_str(), - &original, - 0, - &dex_container); + bool result = dex_layout.ProcessDexFile( + original.GetLocation().c_str(), + &original, + 0, + &dex_container, + &error); + CHECK(result) << "Failed to generate dex file " << error; art::DexContainer::Section* main_section = dex_container->GetMainSection(); CHECK_EQ(dex_container->GetDataSection()->Size(), 0u); data.insert(data.end(), main_section->Begin(), main_section->End()); |