diff options
-rw-r--r-- | compiler/compiler.h | 6 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 7 | ||||
-rw-r--r-- | dex2oat/dex2oat_options.cc | 7 | ||||
-rw-r--r-- | dex2oat/dex2oat_options.def | 2 | ||||
-rw-r--r-- | dex2oat/linker/image_test.h | 2 | ||||
-rw-r--r-- | dex2oat/linker/oat_writer.cc | 9 | ||||
-rw-r--r-- | dex2oat/linker/oat_writer.h | 6 | ||||
-rw-r--r-- | dex2oat/linker/oat_writer_test.cc | 2 | ||||
-rw-r--r-- | libdexfile/dex/dex_file_loader.cc | 10 | ||||
-rw-r--r-- | libdexfile/dex/dex_file_loader.h | 3 | ||||
-rw-r--r-- | runtime/dex/art_dex_file_loader.cc | 13 | ||||
-rw-r--r-- | runtime/dex/art_dex_file_loader.h | 3 | ||||
-rw-r--r-- | runtime/oat_file_assistant.cc | 15 | ||||
-rw-r--r-- | runtime/oat_file_assistant.h | 3 | ||||
-rw-r--r-- | runtime/parsed_options.cc | 2 | ||||
-rw-r--r-- | runtime/runtime.cc | 5 | ||||
-rw-r--r-- | runtime/runtime_options.def | 2 | ||||
-rwxr-xr-x | test/677-fsi/build | 17 | ||||
-rw-r--r-- | test/677-fsi/check | 23 | ||||
-rw-r--r-- | test/677-fsi/expected.txt | 3 | ||||
-rw-r--r-- | test/677-fsi/info.txt | 0 | ||||
-rw-r--r-- | test/677-fsi/run | 19 | ||||
-rw-r--r-- | test/677-fsi/src/Main.java | 21 | ||||
-rw-r--r-- | test/knownfailures.json | 7 |
24 files changed, 162 insertions, 25 deletions
diff --git a/compiler/compiler.h b/compiler/compiler.h index b92bff61a9..a17e2b5875 100644 --- a/compiler/compiler.h +++ b/compiler/compiler.h @@ -39,6 +39,12 @@ template<class T> class Handle; class OatWriter; class Thread; +enum class CopyOption { + kNever, + kAlways, + kOnlyIfCompressed +}; + class Compiler { public: enum Kind { diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 3732b17de5..1578656362 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -457,7 +457,7 @@ NO_RETURN static void Usage(const char* fmt, ...) { UsageError(" --deduplicate-code=true|false: enable|disable code deduplication. Deduplicated"); UsageError(" code will have an arbitrary symbol tagged with [DEDUPED]."); UsageError(""); - UsageError(" --copying-dex-files=true|false: enable|disable copying the dex files into the"); + UsageError(" --copy-dex-files=true|false: enable|disable copying the dex files into the"); UsageError(" output vdex."); UsageError(""); UsageError(" --compilation-reason=<string>: optional metadata specifying the reason for"); @@ -2921,8 +2921,9 @@ class Dex2Oat FINAL { // Whether the given input vdex is also the output. bool update_input_vdex_ = false; - // By default, copy the dex to the vdex file. - bool copy_dex_files_ = true; + // By default, copy the dex to the vdex file only if dex files are + // compressed in APK. + CopyOption copy_dex_files_ = CopyOption::kOnlyIfCompressed; // The reason for invoking the compiler. std::string compilation_reason_; diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc index 1ef100df08..0d68f4fab6 100644 --- a/dex2oat/dex2oat_options.cc +++ b/dex2oat/dex2oat_options.cc @@ -234,9 +234,10 @@ static Parser CreateArgumentParser() { .Define("--force-determinism") .IntoKey(M::ForceDeterminism) .Define("--copy-dex-files=_") - .WithType<bool>() - .WithValueMap({{"true", false}, - {"false", false}}) + .WithType<CopyOption>() + .WithValueMap({{"true", CopyOption::kOnlyIfCompressed}, + {"false", CopyOption::kNever}, + {"always", CopyOption::kAlways}}) .IntoKey(M::CopyDexFiles) .Define("--classpath-dir=_") .WithType<std::string>() diff --git a/dex2oat/dex2oat_options.def b/dex2oat/dex2oat_options.def index a9d349bd08..01f9d9425f 100644 --- a/dex2oat/dex2oat_options.def +++ b/dex2oat/dex2oat_options.def @@ -74,7 +74,7 @@ DEX2OAT_OPTIONS_KEY (Unit, Host) DEX2OAT_OPTIONS_KEY (Unit, DumpTiming) DEX2OAT_OPTIONS_KEY (Unit, DumpPasses) DEX2OAT_OPTIONS_KEY (Unit, DumpStats) -DEX2OAT_OPTIONS_KEY (bool, CopyDexFiles) +DEX2OAT_OPTIONS_KEY (CopyOption, CopyDexFiles) DEX2OAT_OPTIONS_KEY (Unit, AvoidStoringInvocation) DEX2OAT_OPTIONS_KEY (std::string, SwapFile) DEX2OAT_OPTIONS_KEY (int, SwapFileFd) diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h index 303c873349..c6ce951506 100644 --- a/dex2oat/linker/image_test.h +++ b/dex2oat/linker/image_test.h @@ -276,7 +276,7 @@ inline void CompilationHelper::Compile(CompilerDriver* driver, &key_value_store, /* verify */ false, // Dex files may be dex-to-dex-ed, don't verify. /* update_input_vdex */ false, - /* extract_dex_files */ true, + /* copy_dex_files */ CopyOption::kOnlyIfCompressed, &cur_opened_dex_files_maps, &cur_opened_dex_files); ASSERT_TRUE(dex_files_ok); diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index ff0729f6e3..e22936c12a 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -643,7 +643,7 @@ bool OatWriter::WriteAndOpenDexFiles( SafeMap<std::string, std::string>* key_value_store, bool verify, bool update_input_vdex, - bool copy_dex_files, + CopyOption copy_dex_files, /*out*/ std::vector<std::unique_ptr<MemMap>>* opened_dex_files_map, /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) { CHECK(write_state_ == WriteState::kAddingDexFileSources); @@ -3330,13 +3330,13 @@ bool OatWriter::RecordOatDataOffset(OutputStream* out) { bool OatWriter::WriteDexFiles(OutputStream* out, File* file, bool update_input_vdex, - bool copy_dex_files) { + CopyOption copy_dex_files) { TimingLogger::ScopedTiming split("Write Dex files", timings_); vdex_dex_files_offset_ = vdex_size_; // If extraction is enabled, only do it if not all the dex files are aligned and uncompressed. - if (copy_dex_files) { + if (copy_dex_files == CopyOption::kOnlyIfCompressed) { extract_dex_files_into_vdex_ = false; for (OatDexFile& oat_dex_file : oat_dex_files_) { if (!oat_dex_file.source_.IsZipEntry()) { @@ -3349,7 +3349,10 @@ bool OatWriter::WriteDexFiles(OutputStream* out, break; } } + } else if (copy_dex_files == CopyOption::kAlways) { + extract_dex_files_into_vdex_ = true; } else { + DCHECK(copy_dex_files == CopyOption::kNever); extract_dex_files_into_vdex_ = false; } diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h index 6a7e1e4fbf..2bc56c68a7 100644 --- a/dex2oat/linker/oat_writer.h +++ b/dex2oat/linker/oat_writer.h @@ -24,6 +24,7 @@ #include "base/array_ref.h" #include "base/dchecked_vector.h" +#include "compiler.h" #include "dex/compact_dex_level.h" #include "debug/debug_info.h" #include "linker/relative_patcher.h" // For RelativePatcherTargetProvider. @@ -168,7 +169,6 @@ class OatWriter { // This is generally the case, and should only be false for tests. // If `update_input_vdex` is true, then this method won't actually write the dex files, // and the compiler will just re-use the existing vdex file. - // If `copy_dex_files` is true, copy the input dex files into the vdex file. bool WriteAndOpenDexFiles(File* vdex_file, OutputStream* oat_rodata, InstructionSet instruction_set, @@ -176,7 +176,7 @@ class OatWriter { SafeMap<std::string, std::string>* key_value_store, bool verify, bool update_input_vdex, - bool copy_dex_files, + CopyOption copy_dex_files, /*out*/ std::vector<std::unique_ptr<MemMap>>* opened_dex_files_map, /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files); bool WriteQuickeningInfo(OutputStream* vdex_out); @@ -288,7 +288,7 @@ class OatWriter { bool WriteDexFiles(OutputStream* out, File* file, bool update_input_vdex, - bool copy_dex_files); + CopyOption copy_dex_files); bool WriteDexFile(OutputStream* out, File* file, OatDexFile* oat_dex_file, diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc index 6dd8e1988e..00b9abe69b 100644 --- a/dex2oat/linker/oat_writer_test.cc +++ b/dex2oat/linker/oat_writer_test.cc @@ -198,7 +198,7 @@ class OatTest : public CommonCompilerTest { &key_value_store, verify, /* update_input_vdex */ false, - compiler_driver_->GetCompilerOptions().GetCompilerFilter(), + CopyOption::kOnlyIfCompressed, &opened_dex_files_maps, &opened_dex_files)) { return false; diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc index f0e54eab27..758a2f0599 100644 --- a/libdexfile/dex/dex_file_loader.cc +++ b/libdexfile/dex/dex_file_loader.cc @@ -204,10 +204,12 @@ std::string DexFileLoader::GetDexCanonicalLocation(const char* dex_location) { // All of the implementations here should be independent of the runtime. // TODO: implement all the virtual methods. -bool DexFileLoader::GetMultiDexChecksums(const char* filename ATTRIBUTE_UNUSED, - std::vector<uint32_t>* checksums ATTRIBUTE_UNUSED, - std::string* error_msg, - int zip_fd ATTRIBUTE_UNUSED) const { +bool DexFileLoader::GetMultiDexChecksums( + const char* filename ATTRIBUTE_UNUSED, + std::vector<uint32_t>* checksums ATTRIBUTE_UNUSED, + std::string* error_msg, + int zip_fd ATTRIBUTE_UNUSED, + bool* zip_file_only_contains_uncompress_dex ATTRIBUTE_UNUSED) const { *error_msg = "UNIMPLEMENTED"; return false; } diff --git a/libdexfile/dex/dex_file_loader.h b/libdexfile/dex/dex_file_loader.h index 8d1cfaedb1..28cdfc13ce 100644 --- a/libdexfile/dex/dex_file_loader.h +++ b/libdexfile/dex/dex_file_loader.h @@ -108,7 +108,8 @@ class DexFileLoader { virtual bool GetMultiDexChecksums(const char* filename, std::vector<uint32_t>* checksums, std::string* error_msg, - int zip_fd = -1) const; + int zip_fd = -1, + bool* zip_file_only_contains_uncompress_dex = nullptr) const; // Opens .dex file, backed by existing memory virtual std::unique_ptr<const DexFile> Open(const uint8_t* base, diff --git a/runtime/dex/art_dex_file_loader.cc b/runtime/dex/art_dex_file_loader.cc index 14386a3423..c456764834 100644 --- a/runtime/dex/art_dex_file_loader.cc +++ b/runtime/dex/art_dex_file_loader.cc @@ -85,7 +85,8 @@ static constexpr OatDexFile* kNoOatDexFile = nullptr; bool ArtDexFileLoader::GetMultiDexChecksums(const char* filename, std::vector<uint32_t>* checksums, std::string* error_msg, - int zip_fd) const { + int zip_fd, + bool* zip_file_only_contains_uncompressed_dex) const { CHECK(checksums != nullptr); uint32_t magic; @@ -119,7 +120,17 @@ bool ArtDexFileLoader::GetMultiDexChecksums(const char* filename, return false; } + if (zip_file_only_contains_uncompressed_dex != nullptr) { + // Start by assuming everything is uncompressed. + *zip_file_only_contains_uncompressed_dex = true; + } + do { + if (zip_file_only_contains_uncompressed_dex != nullptr) { + if (!(zip_entry->IsUncompressed() && zip_entry->IsAlignedToDexHeader())) { + *zip_file_only_contains_uncompressed_dex = false; + } + } checksums->push_back(zip_entry->GetCrc32()); zip_entry_name = GetMultiDexClassesDexName(i++); zip_entry.reset(zip_archive->Find(zip_entry_name.c_str(), error_msg)); diff --git a/runtime/dex/art_dex_file_loader.h b/runtime/dex/art_dex_file_loader.h index 3585381f9b..7c7a59b37f 100644 --- a/runtime/dex/art_dex_file_loader.h +++ b/runtime/dex/art_dex_file_loader.h @@ -50,7 +50,8 @@ class ArtDexFileLoader : public DexFileLoader { bool GetMultiDexChecksums(const char* filename, std::vector<uint32_t>* checksums, std::string* error_msg, - int zip_fd = -1) const OVERRIDE; + int zip_fd = -1, + bool* only_contains_uncompressed_dex = nullptr) const OVERRIDE; // Opens .dex file, backed by existing memory std::unique_ptr<const DexFile> Open(const uint8_t* base, diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index 0170073e29..6bf05b77a8 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -515,6 +515,18 @@ OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& VLOG(oat) << "Image checksum test skipped for compiler filter " << current_compiler_filter; } + // zip_file_only_contains_uncompressed_dex_ is only set during fetching the dex checksums. + DCHECK(required_dex_checksums_attempted_); + if (only_load_system_executable_ && + !LocationIsOnSystem(file.GetLocation().c_str()) && + file.ContainsDexCode() && + zip_file_only_contains_uncompressed_dex_) { + LOG(ERROR) << "Not loading " + << dex_location_ + << ": oat file has dex code, but APK has uncompressed dex code"; + return kOatDexOutOfDate; + } + if (CompilerFilter::IsAotCompilationEnabled(current_compiler_filter)) { if (!file.IsPic()) { const ImageInfo* image_info = GetImageInfo(); @@ -879,7 +891,8 @@ const std::vector<uint32_t>* OatFileAssistant::GetRequiredDexChecksums() { if (dex_file_loader.GetMultiDexChecksums(dex_location_.c_str(), &cached_required_dex_checksums_, &error_msg, - zip_fd_)) { + zip_fd_, + &zip_file_only_contains_uncompressed_dex_)) { required_dex_checksums_found_ = true; has_original_dex_files_ = true; } else { diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h index a184807b73..6da49a9c29 100644 --- a/runtime/oat_file_assistant.h +++ b/runtime/oat_file_assistant.h @@ -508,6 +508,9 @@ class OatFileAssistant { // Whether only oat files on /system are loaded executable. const bool only_load_system_executable_ = false; + // Whether the potential zip file only contains uncompressed dex. + // Will be set during GetRequiredDexChecksums. + bool zip_file_only_contains_uncompressed_dex_ = true; // Cached value of the required dex checksums. // This should be accessed only by the GetRequiredDexChecksums() method. diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index c7f73d14db..c61ecc880b 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -334,6 +334,8 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize .IntoKey(M::HiddenApiChecks) .Define("-Xuse-stderr-logger") .IntoKey(M::UseStderrLogger) + .Define("-Xonly-use-system-oat-files") + .IntoKey(M::OnlyUseSystemOatFiles) .Ignore({ "-ea", "-da", "-enableassertions", "-disableassertions", "--runtime-arg", "-esa", "-dsa", "-enablesystemassertions", "-disablesystemassertions", "-Xrs", "-Xint:_", diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 2074f1e5f5..4442fc6a54 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -1593,6 +1593,11 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { VLOG(startup) << "Runtime::Init exiting"; + // Set OnlyUseSystemOatFiles only after boot classpath has been set up. + if (runtime_options.Exists(Opt::OnlyUseSystemOatFiles)) { + oat_file_manager_->SetOnlyUseSystemOatFiles(); + } + return true; } diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def index dba648e785..4121ad69ed 100644 --- a/runtime/runtime_options.def +++ b/runtime/runtime_options.def @@ -152,4 +152,6 @@ RUNTIME_OPTIONS_KEY (bool, SlowDebug, false) RUNTIME_OPTIONS_KEY (unsigned int, GlobalRefAllocStackTraceLimit, 0) // 0 = off RUNTIME_OPTIONS_KEY (Unit, UseStderrLogger) +RUNTIME_OPTIONS_KEY (Unit, OnlyUseSystemOatFiles) + #undef RUNTIME_OPTIONS_KEY diff --git a/test/677-fsi/build b/test/677-fsi/build new file mode 100755 index 0000000000..b90b408d9c --- /dev/null +++ b/test/677-fsi/build @@ -0,0 +1,17 @@ +#!/bin/bash +# +# Copyright 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +./default-build "$@" --zip-compression-method store --zip-align 4 diff --git a/test/677-fsi/check b/test/677-fsi/check new file mode 100644 index 0000000000..a84cf65434 --- /dev/null +++ b/test/677-fsi/check @@ -0,0 +1,23 @@ +#!/bin/bash +# +# Copyright (C) 2014 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Remove part of message containing the JDWP log (only on target) +sed -s '/^.*JDWP support\./d' "$2" > "$2.tmp" + +# Remove part of message containing filename. +sed -s 's/^.*: //' "$2.tmp" > "$2.tmp2" + +diff --strip-trailing-cr -q "$1" "$2.tmp2" >/dev/null diff --git a/test/677-fsi/expected.txt b/test/677-fsi/expected.txt new file mode 100644 index 0000000000..c7fb8fed77 --- /dev/null +++ b/test/677-fsi/expected.txt @@ -0,0 +1,3 @@ +oat file has dex code, but APK has uncompressed dex code +oat file has dex code, but APK has uncompressed dex code +Hello World diff --git a/test/677-fsi/info.txt b/test/677-fsi/info.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/677-fsi/info.txt diff --git a/test/677-fsi/run b/test/677-fsi/run new file mode 100644 index 0000000000..30d925ecd9 --- /dev/null +++ b/test/677-fsi/run @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Redirect logger to stderr, as the test relies on error +# messages being printed there. +exec ${RUN} $@ -Xcompiler-option --copy-dex-files=always --runtime-option -Xonly-use-system-oat-files --runtime-option -Xuse-stderr-logger diff --git a/test/677-fsi/src/Main.java b/test/677-fsi/src/Main.java new file mode 100644 index 0000000000..834075f67a --- /dev/null +++ b/test/677-fsi/src/Main.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +public class Main { + public static void main(String[] args) { + System.out.println("Hello World"); + } +} diff --git a/test/knownfailures.json b/test/knownfailures.json index cc3d200ed1..8426a14ecf 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -970,7 +970,10 @@ "variant": "jvm", "bug": "b/73888836", "description": ["Failing on JVM. Needs further investigating."] + }, + { + "tests": "677-fsi", + "variant": "no-dex2oat | no-image | no-prebuild | relocate-npatchoat", + "description": ["Test requires a successful dex2oat invocation"] } - - ] |