Add ability to store invocation information in an external file.
It is sometimes useful to save the invocation that generated an odex
file seprately from the file itself. This adds a
--write-invocation-to=<file> flag to dex2oat that lets one do this.
Test: m droid
Test: ./test.py --host -j72
Bug: 119332327
Change-Id: I3fe07e7daba3d27b49fd5b5aed7621e5cc62ab46
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 872fab3..97abde2 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -382,6 +382,9 @@
UsageError(" --avoid-storing-invocation: Avoid storing the invocation args in the key value");
UsageError(" store. Used to test determinism with different args.");
UsageError("");
+ UsageError(" --write-invocation-to=<file>: Write the invocation commandline to the given file");
+ UsageError(" for later use. Used to test determinism with different host architectures.");
+ UsageError("");
UsageError(" --runtime-arg <argument>: used to specify various arguments for the runtime,");
UsageError(" such as initial heap size, maximum heap size, and verbose output.");
UsageError(" Use a separate --runtime-arg switch for each argument.");
@@ -1003,6 +1006,21 @@
CompilerFilter::NameOfFilter(compiler_options_->GetCompilerFilter()));
key_value_store_->Put(OatHeader::kConcurrentCopying,
kUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+ if (invocation_file_.get() != -1) {
+ std::ostringstream oss;
+ for (int i = 0; i < argc; ++i) {
+ if (i > 0) {
+ oss << std::endl;
+ }
+ oss << argv[i];
+ }
+ std::string invocation(oss.str());
+ if (TEMP_FAILURE_RETRY(write(invocation_file_.get(),
+ invocation.c_str(),
+ invocation.size())) == -1) {
+ Usage("Unable to write invocation file");
+ }
+ }
}
// This simple forward is here so the string specializations below don't look out of place.
@@ -1118,6 +1136,16 @@
AssignTrueIfExists(args, M::Host, &is_host_);
AssignTrueIfExists(args, M::AvoidStoringInvocation, &avoid_storing_invocation_);
+ if (args.Exists(M::InvocationFile)) {
+ invocation_file_.reset(open(args.Get(M::InvocationFile)->c_str(),
+ O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC,
+ S_IRUSR|S_IWUSR));
+ if (invocation_file_.get() == -1) {
+ int err = errno;
+ Usage("Unable to open invocation file '%s' for writing due to %s.",
+ args.Get(M::InvocationFile)->c_str(), strerror(err));
+ }
+ }
AssignIfExists(args, M::CopyDexFiles, ©_dex_files_);
if (args.Exists(M::ForceDeterminism)) {
@@ -2714,6 +2742,7 @@
std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
bool avoid_storing_invocation_;
+ android::base::unique_fd invocation_file_;
std::string swap_file_name_;
int swap_fd_;
size_t min_dex_files_for_swap_ = kDefaultMinDexFilesForSwap;
diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc
index 236c1fc..783b326 100644
--- a/dex2oat/dex2oat_options.cc
+++ b/dex2oat/dex2oat_options.cc
@@ -229,6 +229,9 @@
{"false", linker::CopyOption::kNever},
{"always", linker::CopyOption::kAlways}})
.IntoKey(M::CopyDexFiles)
+ .Define("--write-invocation-to=_")
+ .WithType<std::string>()
+ .IntoKey(M::InvocationFile)
.Define("--classpath-dir=_")
.WithType<std::string>()
.IntoKey(M::ClasspathDir)
diff --git a/dex2oat/dex2oat_options.def b/dex2oat/dex2oat_options.def
index c8cb7e7..0b77859 100644
--- a/dex2oat/dex2oat_options.def
+++ b/dex2oat/dex2oat_options.def
@@ -84,6 +84,7 @@
DEX2OAT_OPTIONS_KEY (std::string, NoInlineFrom)
DEX2OAT_OPTIONS_KEY (Unit, ForceDeterminism)
DEX2OAT_OPTIONS_KEY (std::string, ClasspathDir)
+DEX2OAT_OPTIONS_KEY (std::string, InvocationFile)
DEX2OAT_OPTIONS_KEY (std::string, ClassLoaderContext)
DEX2OAT_OPTIONS_KEY (std::string, StoredClassLoaderContext)
DEX2OAT_OPTIONS_KEY (std::string, DirtyImageObjects)