Add installd support to dex2oat
Change-Id: Id1a64403ccea7dc2c1e8b8340d33d383d4045a33
diff --git a/src/class_linker.cc b/src/class_linker.cc
index e3b30d7..01ba9af 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -584,7 +584,7 @@
dex_file_option_string += filename;
const char* dex_file_option = dex_file_option_string.c_str();
- std::string oat_file_option_string("--oat=");
+ std::string oat_file_option_string("--oat-file=");
oat_file_option_string += oat_filename;
const char* oat_file_option = oat_file_option_string.c_str();
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index a63d4ab..35494cb 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -19,6 +19,7 @@
#include "os.h"
#include "runtime.h"
#include "stringpiece.h"
+#include "zip_archive.h"
namespace art {
@@ -27,13 +28,27 @@
"Usage: dex2oat [options]...\n"
"\n");
fprintf(stderr,
- " --dex-file=<dex-file>: specifies a .dex file to compile. At least one .dex\n"
- " file must be specified. \n"
+ " --dex-file=<dex-file>: specifies a .dex file to compile.\n"
" Example: --dex-file=/system/framework/core.jar\n"
"\n");
fprintf(stderr,
- " --oat=<file.oat>: specifies the required oat filename.\n"
- " Example: --oat=/system/framework/boot.oat\n"
+ " --zip-fd=<file-descriptor>: specifies a file descriptor of a zip file\n"
+ " containing a classes.dex file to compile.\n"
+ " Example: --zip-fd=5\n"
+ "\n");
+ fprintf(stderr,
+ " --zip-name=<zip-name>: specifies a symbolic name for the file corresponding\n"
+ " to the file descriptor specified by --zip-fd.\n"
+ " Example: --zip-name=/system/app/Calculator.apk\n"
+ "\n");
+ fprintf(stderr,
+ " --oat-file=<file.oat>: specifies the required oat filename.\n"
+ " Example: --oat-file=/system/framework/boot.oat\n"
+ "\n");
+ fprintf(stderr,
+ " --oat-name=<oat-name>: specifies a symbolic name for the file corresponding\n"
+ " to the file descriptor specified by --oat-fd.\n"
+ " Example: --oat-name=/data/art-cache/system@app@Calculator.apk.oat\n"
"\n");
fprintf(stderr,
" --image=<file.art>: specifies the output image filename.\n"
@@ -146,8 +161,7 @@
}
bool CreateOatFile(const std::string& boot_image_option,
- const std::vector<const char*>& dex_filenames,
- const std::string& host_prefix,
+ const std::vector<const DexFile*>& dex_files,
File* oat_file,
bool image,
const std::set<std::string>* image_classes) {
@@ -158,18 +172,14 @@
return false;
}
- std::vector<const DexFile*> dex_files;
if (!boot_image_option.empty()) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- DexFile::OpenDexFiles(dex_filenames, dex_files, host_prefix);
std::vector<const DexFile*> class_path_files(dex_files);
OpenClassPathFiles(runtime_->GetClassPath(), class_path_files);
for (size_t i = 0; i < class_path_files.size(); i++) {
class_linker->RegisterDexFile(*class_path_files[i]);
}
class_loader.get()->reset(PathClassLoader::AllocCompileTime(class_path_files));
- } else {
- dex_files = runtime_->GetClassLinker()->GetBootClassPath();
}
Compiler compiler(instruction_set_, image, image_classes);
@@ -333,6 +343,16 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
};
+bool parse_int(const char* in, int* out) {
+ char* end;
+ int result = strtol(in, &end, 10);
+ if (in == end || *end != '\0') {
+ return false;
+ }
+ *out = result;
+ return true;
+}
+
int dex2oat(int argc, char** argv) {
// Skip over argv[0].
argv++;
@@ -344,7 +364,11 @@
}
std::vector<const char*> dex_filenames;
+ int zip_fd = -1;
+ std::string zip_name;
std::string oat_filename;
+ int oat_fd = -1;
+ std::string oat_name;
const char* image_filename = NULL;
const char* image_classes_filename = NULL;
std::string boot_image_filename;
@@ -354,13 +378,30 @@
for (int i = 0; i < argc; i++) {
const StringPiece option(argv[i]);
- if (false) {
+ bool log_options = false;
+ if (log_options) {
LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i];
}
if (option.starts_with("--dex-file=")) {
dex_filenames.push_back(option.substr(strlen("--dex-file=")).data());
- } else if (option.starts_with("--oat=")) {
- oat_filename = option.substr(strlen("--oat=")).data();
+ } else if (option.starts_with("--zip-fd=")) {
+ const char* zip_fd_str = option.substr(strlen("--zip-fd=")).data();
+ if (!parse_int(zip_fd_str, &zip_fd)) {
+ fprintf(stderr, "could not parse --zip-fd argument %s as integer\n", zip_fd_str);
+ usage();
+ }
+ } else if (option.starts_with("--zip-name=")) {
+ zip_name = option.substr(strlen("--zip-name=")).data();
+ } else if (option.starts_with("--oat-file=")) {
+ oat_filename = option.substr(strlen("--oat-file=")).data();
+ } else if (option.starts_with("--oat-fd=")) {
+ const char* oat_fd_str = option.substr(strlen("--oat-fd=")).data();
+ if (!parse_int(oat_fd_str, &oat_fd)) {
+ fprintf(stderr, "could not parse --oat-fd argument %s as integer\n", oat_fd_str);
+ usage();
+ }
+ } else if (option.starts_with("--oat-name=")) {
+ oat_name = option.substr(strlen("--oat-name=")).data();
} else if (option.starts_with("--image=")) {
image_filename = option.substr(strlen("--image=")).data();
} else if (option.starts_with("--image-classes=")) {
@@ -382,6 +423,9 @@
fprintf(stderr, "Missing required argument for --runtime-arg\n");
usage();
}
+ if (log_options) {
+ LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i];
+ }
runtime_args.push_back(argv[i]);
} else {
fprintf(stderr, "unknown argument %s\n", option.data());
@@ -389,8 +433,33 @@
}
}
- if (oat_filename.empty()) {
- fprintf(stderr, "--oat file name not specified\n");
+ if (oat_filename.empty() && oat_fd == -1) {
+ fprintf(stderr, "Output must be supplied with either --oat-file or --oat-fd\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!oat_filename.empty() && oat_fd != -1) {
+ fprintf(stderr, "--oat-file should not be used with --oat-fd\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!oat_filename.empty() && oat_fd != -1) {
+ fprintf(stderr, "--oat-file should not be used with --oat-fd\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!oat_filename.empty() && !oat_name.empty()) {
+ fprintf(stderr, "--oat-file should not be used with --oat-name\n");
+ return EXIT_FAILURE;
+ }
+
+ if (oat_fd != -1 && oat_name.empty()) {
+ fprintf(stderr, "--oat-name should be supplied with --oat-fd\n");
+ return EXIT_FAILURE;
+ }
+
+ if (oat_fd != -1 && image_filename != NULL) {
+ fprintf(stderr, "--oat-fd should not be used with --image\n");
return EXIT_FAILURE;
}
@@ -404,7 +473,7 @@
bool image = (image_filename != NULL);
if (!image && boot_image_filename.empty()) {
boot_image_filename += host_prefix;
- boot_image_filename += "/data/art-cache/boot.art";
+ boot_image_filename += "/system/framework/boot.art";
}
std::string boot_image_option;
if (boot_image_filename != NULL) {
@@ -422,6 +491,26 @@
return EXIT_FAILURE;
}
+ if (dex_filenames.empty() && zip_fd == -1) {
+ fprintf(stderr, "Input must be supplied with either --dex-file or --zip-fd\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!dex_filenames.empty() && zip_fd != -1) {
+ fprintf(stderr, "--dex-file should not be used with --zip-fd\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!dex_filenames.empty() && !zip_name.empty()) {
+ fprintf(stderr, "--dex-file should not be used with --zip-name\n");
+ return EXIT_FAILURE;
+ }
+
+ if (zip_fd != -1 && zip_name.empty()) {
+ fprintf(stderr, "--zip-name should be supplied with --zip-fd\n");
+ return EXIT_FAILURE;
+ }
+
if (boot_image_option.empty()) {
if (image_base == 0) {
fprintf(stderr, "non-zero --base not specified\n");
@@ -430,12 +519,19 @@
}
// Check early that the result of compilation can be written
- UniquePtr<File> oat_file(OS::OpenFile(oat_filename.c_str(), true));
+ UniquePtr<File> oat_file;
+ if (!oat_filename.empty()) {
+ oat_file.reset(OS::OpenFile(oat_filename.c_str(), true));
+ oat_name = oat_filename;
+ } else {
+ oat_file.reset(OS::FileFromFd(oat_name.c_str(), oat_fd));
+ }
if (oat_file.get() == NULL) {
- PLOG(ERROR) << "Unable to create oat file " << oat_filename;
+ PLOG(ERROR) << "Unable to create oat file " << oat_name;
return EXIT_FAILURE;
}
- LOG(INFO) << "dex2oat: " << oat_filename;
+
+ LOG(INFO) << "dex2oat: " << oat_name;
Runtime::Options options;
options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL)));
@@ -470,13 +566,33 @@
}
}
+ std::vector<const DexFile*> dex_files;
+ if (boot_image_option.empty()) {
+ dex_files = Runtime::Current()->GetClassLinker()->GetBootClassPath();
+ } else {
+ if (dex_filenames.empty()) {
+ UniquePtr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(zip_fd));
+ if (zip_archive.get() == NULL) {
+ LOG(ERROR) << "Failed to zip from file descriptor for " << zip_name;
+ return NULL;
+ }
+ const DexFile* dex_file = DexFile::Open(*zip_archive.get(), zip_name);
+ if (dex_file == NULL) {
+ LOG(ERROR) << "Failed to open dex from file descriptor for zip file " << zip_name;
+ return EXIT_FAILURE;
+ }
+ dex_files.push_back(dex_file);
+ } else {
+ DexFile::OpenDexFiles(dex_filenames, dex_files, host_prefix);
+ }
+ }
+
if (!dex2oat->CreateOatFile(boot_image_option,
- dex_filenames,
- host_prefix,
+ dex_files,
oat_file.get(),
image,
image_classes.get())) {
- LOG(ERROR) << "Failed to create oat file" << oat_filename;
+ LOG(ERROR) << "Failed to create oat file" << oat_name;
return EXIT_FAILURE;
}
diff --git a/src/dex_file.cc b/src/dex_file.cc
index a45455d..81a60fc 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -187,9 +187,13 @@
LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex";
return NULL;
}
- UniquePtr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex));
+ return DexFile::Open(*zip_archive.get(), location);
+}
+
+const DexFile* DexFile::Open(const ZipArchive& zip_archive, const std::string& location) {
+ UniquePtr<ZipEntry> zip_entry(zip_archive.Find(kClassesDex));
if (zip_entry.get() == NULL) {
- LOG(ERROR) << "Failed to find classes.dex within " << filename;
+ LOG(ERROR) << "Failed to find classes.dex within " << location;
return NULL;
}
@@ -199,14 +203,14 @@
length,
PROT_READ | PROT_WRITE));
if (map.get() == NULL) {
- LOG(ERROR) << "mmap classes.dex for \"" << filename << "\" failed";
+ LOG(ERROR) << "mmap classes.dex for \"" << location << "\" failed";
return NULL;
}
// Extract classes.dex
bool success = zip_entry->ExtractToMemory(*map.get());
if (!success) {
- LOG(ERROR) << "Failed to extract classes.dex from '" << filename << "' to memory";
+ LOG(ERROR) << "Failed to extract classes.dex from '" << location << "' to memory";
return NULL;
}
diff --git a/src/dex_file.h b/src/dex_file.h
index a0363b0..2ca4308 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -18,6 +18,8 @@
namespace art {
+class ZipArchive;
+
// TODO: move all of the macro functionality into the DexCache class.
class DexFile {
public:
@@ -189,6 +191,9 @@
return OpenMemory(base, length, location, NULL);
}
+ // Opens .dex file from the classes.dex in a zip archive
+ static const DexFile* Open(const ZipArchive& zip_archive, const std::string& location);
+
// Closes a .dex file.
virtual ~DexFile();
diff --git a/src/oat_file.cc b/src/oat_file.cc
index c37c7a6..58dd984 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -12,8 +12,8 @@
std::string OatFile::DexFilenameToOatFilename(const std::string& location) {
CHECK(IsValidDexFilename(location) || IsValidZipFilename(location));
- std::string oat_location(location.substr(0, location.size() - 3));
- oat_location += "oat";
+ std::string oat_location(location);
+ oat_location += ".oat";
return oat_location;
}
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 3b204c0..a664852 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -27,7 +27,7 @@
" Example: adb shell oatdump --image=/system/framework/boot.art\n"
"\n");
fprintf(stderr,
- " --oat=<file.oat>: specifies an input oat filename.\n"
+ " --oat-file=<file.oat>: specifies an input oat filename.\n"
" Example: --image=/system/framework/boot.oat\n"
"\n");
fprintf(stderr,
@@ -505,8 +505,8 @@
for (int i = 0; i < argc; i++) {
const StringPiece option(argv[i]);
- if (option.starts_with("--oat=")) {
- oat_filename = option.substr(strlen("--oat=")).data();
+ if (option.starts_with("--oat-file=")) {
+ oat_filename = option.substr(strlen("--oat-file=")).data();
} else if (option.starts_with("--image=")) {
image_filename = option.substr(strlen("--image=")).data();
} else if (option.starts_with("--boot-image=")) {
diff --git a/src/oatopt.cc b/src/oatopt.cc
deleted file mode 100644
index 5862431..0000000
--- a/src/oatopt.cc
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "dex_file.h"
-#include "file.h"
-#include "logging.h"
-#include "oat_file.h"
-#include "os.h"
-#include "UniquePtr.h"
-#include "zip_archive.h"
-
-namespace art {
-
-int ProcessZipFile(int zip_fd, int cache_fd, const char* zip_name, const char* flags) {
- // TODO: need to read/write to installd opened file descriptors
- if (false) {
- UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(zip_fd));
- if (zip_archive.get() == NULL) {
- LOG(ERROR) << "Failed to open " << zip_name << " when looking for classes.dex";
- return -1;
- }
-
- UniquePtr<ZipEntry> zip_entry(zip_archive->Find(DexFile::kClassesDex));
- if (zip_entry.get() == NULL) {
- LOG(ERROR) << "Failed to find classes.dex within " << zip_name;
- return -1;
- }
-
- UniquePtr<File> file(OS::FileFromFd("oatopt cache file descriptor", cache_fd));
- bool success = zip_entry->ExtractToFile(*file);
- if (!success) {
- LOG(ERROR) << "Failed to extract classes.dex from " << zip_name;
- return -1;
- }
- }
-
- // Opening a zip file for a dex will extract to art-cache
- UniquePtr<const DexFile> dex_file(DexFile::Open(zip_name, ""));
- if (dex_file.get() == NULL) {
- LOG(ERROR) << "Failed to open " << zip_name;
- return -1;
- }
-
- std::string dex_file_option("--dex-file=");
- dex_file_option += zip_name;
-
- std::string oat_file_option("--oat=");
- oat_file_option += GetArtCacheFilenameOrDie(OatFile::DexFilenameToOatFilename(dex_file.get()->GetLocation()));
-
- std::string dex2oat("/system/bin/dex2oat");
-#ifndef NDEBUG
- dex2oat += 'd';
-#endif
-
- execl(dex2oat.c_str(), dex2oat.c_str(),
- "--runtime-arg", "-Xms64m",
- "--runtime-arg", "-Xmx64m",
- "--boot-image=/data/art-cache/boot.art",
- dex_file_option.c_str(),
- oat_file_option.c_str(),
- NULL);
- PLOG(FATAL) << "execl(dex2oatd) failed";
- return -1;
-}
-
-// Parse arguments. We want:
-// 0. (name of command -- ignored)
-// 1. "--zip"
-// 2. zip fd (input, read-only)
-// 3. cache fd (output, read-write, locked with flock)
-// 4. filename of zipfile
-// 5. flags
-int FromZip(const int argc, const char* const argv[]) {
- if (argc != 6) {
- LOG(ERROR) << "Wrong number of args for --zip (found " << argc << ")";
- return -1;
- }
-
- // ignore program name
-
- // verify --zip
- CHECK_STREQ(argv[1], "--zip");
-
- char* zip_end;
- int zip_fd = strtol(argv[2], &zip_end, 0);
- if (*zip_end != '\0') {
- LOG(ERROR) << "bad zip fd: " << argv[2];
- return -1;
- }
-#ifndef NDEBUG
- LOG(INFO) << "zip_fd=" << zip_fd;
-#endif
-
- char* cache_end;
- int cache_fd = strtol(argv[3], &cache_end, 0);
- if (*cache_end != '\0') {
- LOG(ERROR) << "bad cache fd: " << argv[3];
- return -1;
- }
-#ifndef NDEBUG
- LOG(INFO) << "cache_fd=" << cache_fd;
-#endif
-
- const char* zip_name = argv[4];
-#ifndef NDEBUG
- LOG(INFO) << "zip_name=" << zip_name;
-#endif
-
- const char* flags = argv[5];
-#ifndef NDEBUG
- LOG(INFO) << "flags=" << flags;
-#endif
-
- return ProcessZipFile(zip_fd, cache_fd, zip_name, flags);
-}
-
-int oatopt(int argc, char** argv) {
- setvbuf(stdout, NULL, _IONBF, 0);
-
- if (true) {
- for (int i = 0; i < argc; ++i) {
- LOG(INFO) << "oatopt: option[" << i << "]=" << argv[i];
- }
- }
-
- if (argc > 1) {
- if (strcmp(argv[1], "--zip") == 0) {
- return FromZip(argc, argv);
- }
- }
-
- fprintf(stderr,
- "Usage:\n\n"
- "Short version: Don't use this.\n\n"
- "Slightly longer version: This system-internal tool is used to extract\n"
- "dex files and produce oat files. See the source code for details.\n");
-
- return 1;
-}
-
-} // namespace art
-
-int main(int argc, char** argv) {
- return art::oatopt(argc, argv);
-}
diff --git a/src/zip_archive.cc b/src/zip_archive.cc
index 666da23..6105c21 100644
--- a/src/zip_archive.cc
+++ b/src/zip_archive.cc
@@ -287,10 +287,10 @@
PLOG(WARNING) << "Unable to open '" << filename << "'";
return NULL;
}
- return Open(fd);
+ return OpenFromFd(fd);
}
-ZipArchive* ZipArchive::Open(int fd) {
+ZipArchive* ZipArchive::OpenFromFd(int fd) {
UniquePtr<ZipArchive> zip_archive(new ZipArchive(fd));
if (zip_archive.get() == NULL) {
return NULL;
@@ -306,7 +306,7 @@
return zip_archive.release();
}
-ZipEntry* ZipArchive::Find(const char* name) {
+ZipEntry* ZipArchive::Find(const char* name) const {
DCHECK(name != NULL);
DirEntries::const_iterator it = dir_entries_.find(name);
if (it == dir_entries_.end()) {
diff --git a/src/zip_archive.h b/src/zip_archive.h
index e367773..6427da9 100644
--- a/src/zip_archive.h
+++ b/src/zip_archive.h
@@ -46,7 +46,7 @@
private:
- ZipEntry(ZipArchive* zip_archive, const byte* ptr) : zip_archive_(zip_archive), ptr_(ptr) {}
+ ZipEntry(const ZipArchive* zip_archive, const byte* ptr) : zip_archive_(zip_archive), ptr_(ptr) {}
// Zip compression methods
enum {
@@ -62,7 +62,7 @@
// returns -1 on error
off_t GetDataOffset();
- ZipArchive* zip_archive_;
+ const ZipArchive* zip_archive_;
// pointer to zip entry within central directory
const byte* ptr_;
@@ -102,9 +102,9 @@
// return new ZipArchive instance on success, NULL on error.
static ZipArchive* Open(const std::string& filename);
- static ZipArchive* Open(int fd);
+ static ZipArchive* OpenFromFd(int fd);
- ZipEntry* Find(const char* name);
+ ZipEntry* Find(const char* name) const;
~ZipArchive() {
Close();