summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dex2oat/dex2oat_test.cc108
-rw-r--r--dex2oat/linker/oat_writer.cc26
-rw-r--r--dexlayout/compact_dex_writer.cc59
-rw-r--r--dexlayout/compact_dex_writer.h5
-rw-r--r--dexlayout/dex_writer.cc12
-rw-r--r--dexlayout/dex_writer.h7
-rw-r--r--dexlayout/dexlayout.cc46
-rw-r--r--dexlayout/dexlayout.h10
-rw-r--r--dexlayout/dexlayout_test.cc11
-rw-r--r--openjdkjvmti/fixed_up_dex_file.cc11
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());