diff options
| author | 2011-10-13 14:58:47 -0700 | |
|---|---|---|
| committer | 2011-10-14 00:24:28 -0700 | |
| commit | b7bbba49d88eae58223d9878da4069bf6d7140bf (patch) | |
| tree | 00d1a0758d762903e648bb550434320822228c46 | |
| parent | 30646836b4a1c6e5e80ddaea246cf9669eaa0628 (diff) | |
Add oatopt drop in replacement for dexopt
Change-Id: I094375230af2d9a88e30245b390cac71be7b50f4
| -rw-r--r-- | Android.mk | 7 | ||||
| -rw-r--r-- | build/Android.common.mk | 3 | ||||
| -rw-r--r-- | build/Android.executable.mk | 4 | ||||
| -rw-r--r-- | build/Android.oat.mk | 2 | ||||
| -rw-r--r-- | src/class_linker.cc | 15 | ||||
| -rw-r--r-- | src/dex2oat.cc | 5 | ||||
| -rw-r--r-- | src/dex_file.cc | 14 | ||||
| -rw-r--r-- | src/dex_file.h | 3 | ||||
| -rw-r--r-- | src/oat_file.cc | 11 | ||||
| -rw-r--r-- | src/oat_file.h | 3 | ||||
| -rw-r--r-- | src/oatdump.cc | 6 | ||||
| -rw-r--r-- | src/oatopt.cc | 144 | ||||
| -rw-r--r-- | src/utils.cc | 8 | ||||
| -rw-r--r-- | src/utils.h | 5 | ||||
| -rw-r--r-- | src/zip_archive.cc | 5 | ||||
| -rw-r--r-- | src/zip_archive.h | 3 |
16 files changed, 211 insertions, 27 deletions
diff --git a/Android.mk b/Android.mk index 06b7ebe346..5b1d13b79b 100644 --- a/Android.mk +++ b/Android.mk @@ -186,12 +186,15 @@ test-art-target-oat-process-Calculator: $(call art-cache-oat,system/app/Calculat zygote-artd-target-sync: $(ART_TARGET_DEPENDENCIES) $(TARGET_BOOT_OAT) $(ART_CACHE_OATS) cp $(TARGET_OUT_SHARED_LIBRARIES)/libartd.so $(TARGET_OUT_SHARED_LIBRARIES)/libdvm.so cp $(TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED)/libartd.so $(TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED)/libdvm.so + cp $(TARGET_OUT_EXECUTABLES)/oatoptd $(TARGET_OUT_EXECUTABLES)/dexopt + cp $(TARGET_OUT_EXECUTABLES_UNSTRIPPED)/oatoptd $(TARGET_OUT_EXECUTABLES_UNSTRIPPED)/dexopt adb remount adb sync .PHONY: zygote-artd zygote-artd: zygote-artd-target-sync - sed 's/--start-system-server/--start-system-server --no-preload/' < system/core/rootdir/init.rc > $(ANDROID_PRODUCT_OUT)/root/init.rc + sed -e 's/--start-system-server/--start-system-server --no-preload/' -e 's/art-cache 0771/art-cache 0777/' < system/core/rootdir/init.rc > $(ANDROID_PRODUCT_OUT)/root/init.rc + adb shell rm -f $(ART_CACHE_DIR) rm -f $(ANDROID_PRODUCT_OUT)/boot.img unset ONE_SHOT_MAKEFILE && $(MAKE) showcommands bootimage adb reboot bootloader @@ -202,6 +205,8 @@ zygote-artd: zygote-artd-target-sync zygote-dalvik: cp $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/libdvm.so $(TARGET_OUT_SHARED_LIBRARIES)/libdvm.so cp $(call intermediates-dir-for,SHARED_LIBRARIES,libdvm)/LINKED/libdvm.so $(TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED)/libdvm.so + cp $(call intermediates-dir-for,EXECUTABLES,dexopt)/dexopt $(TARGET_OUT_EXECUTABLES)/dexopt + cp $(call intermediates-dir-for,EXECUTABLES,dexopt)/LINKED/dexopt $(TARGET_OUT_EXECUTABLES_UNSTRIPPED)/dexopt adb remount adb sync cp system/core/rootdir/init.rc $(ANDROID_PRODUCT_OUT)/root/init.rc diff --git a/build/Android.common.mk b/build/Android.common.mk index 7875ee97c0..319d673e20 100644 --- a/build/Android.common.mk +++ b/build/Android.common.mk @@ -67,6 +67,9 @@ OATDUMP_SRC_FILES := \ OATEXEC_SRC_FILES := \ src/oatexec.cc +OATOPT_SRC_FILES := \ + src/oatopt.cc + LIBART_COMMON_SRC_FILES := \ src/assembler.cc \ src/assembler_arm.cc \ diff --git a/build/Android.executable.mk b/build/Android.executable.mk index 7619f74b15..d00002af42 100644 --- a/build/Android.executable.mk +++ b/build/Android.executable.mk @@ -91,20 +91,24 @@ ifeq ($(ART_BUILD_TARGET_NDEBUG),true) $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),target,ndebug)) $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),target,ndebug)) $(eval $(call build-art-executable,oatexec,$(OATEXEC_SRC_FILES),target,ndebug)) + $(eval $(call build-art-executable,oatopt,$(OATOPT_SRC_FILES),target,ndebug)) endif ifeq ($(ART_BUILD_TARGET_DEBUG),true) $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),target,debug)) $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),target,debug)) $(eval $(call build-art-executable,oatexec,$(OATEXEC_SRC_FILES),target,debug)) + $(eval $(call build-art-executable,oatopt,$(OATOPT_SRC_FILES),target,debug)) endif ifeq ($(ART_BUILD_HOST_NDEBUG),true) $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),host,ndebug)) $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),host,ndebug)) $(eval $(call build-art-executable,oatexec,$(OATEXEC_SRC_FILES),host,ndebug)) + $(eval $(call build-art-executable,oatopt,$(OATOPT_SRC_FILES),host,ndebug)) endif ifeq ($(ART_BUILD_HOST_DEBUG),true) $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),host,debug)) $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),host,debug)) $(eval $(call build-art-executable,oatexec,$(OATEXEC_SRC_FILES),host,debug)) + $(eval $(call build-art-executable,oatopt,$(OATOPT_SRC_FILES),host,debug)) endif diff --git a/build/Android.oat.mk b/build/Android.oat.mk index 59bb77169a..846cda3e58 100644 --- a/build/Android.oat.mk +++ b/build/Android.oat.mk @@ -20,8 +20,8 @@ DEX2OATD := $(HOST_OUT_EXECUTABLES)/dex2oatd$(HOST_EXECUTABLE_SUFFIX) DEX2OAT := $(DEX2OATD) # TODO: change DEX2OAT_DEPENDENCY to order-only prerequisite when output is stable +# DEX2OAT_DEPENDENCY := | $(DEX2OAT) # only build dex2oat if needed to build oat files DEX2OAT_DEPENDENCY := $(DEX2OAT) # when dex2oat changes, rebuild all oat files -DEX2OAT_DEPENDENCY := | $(DEX2OAT) # only build dex2oat if needed to build oat files OATDUMP := $(HOST_OUT_EXECUTABLES)/oatdump$(HOST_EXECUTABLE_SUFFIX) OATDUMPD := $(HOST_OUT_EXECUTABLES)/oatdumpd$(HOST_EXECUTABLE_SUFFIX) diff --git a/src/class_linker.cc b/src/class_linker.cc index f610f31e55..9fd8f0b249 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -573,16 +573,8 @@ OatFile* ClassLinker::OpenOat(const Space* space) { const OatFile* ClassLinker::FindOatFile(const DexFile& dex_file) { MutexLock mu(lock_); - std::string dex_file_location = dex_file.GetLocation(); - std::string location(dex_file_location); - CHECK(StringPiece(location).ends_with(".dex") - || StringPiece(location).ends_with(".zip") - || StringPiece(location).ends_with(".jar") - || StringPiece(location).ends_with(".apk")); - location.erase(location.size()-3); - location += "oat"; // TODO: check if dex_file matches an OatDexFile location and checksum - return FindOatFile(location); + return FindOatFile(OatFile::DexFileToOatFilename(dex_file)); } const OatFile* ClassLinker::FindOatFile(const std::string& location) { @@ -601,10 +593,7 @@ const OatFile* ClassLinker::FindOatFile(const std::string& location) { return NULL; } // not found in /foo/bar/baz.oat? try /data/art-cache/foo@bar@baz.oat - std::string art_cache = GetArtCacheOrDie(); - std::string cache_file(location, 1); // skip leading slash - std::replace(cache_file.begin(), cache_file.end(), '/', '@'); - std::string cache_location = art_cache + "/" + cache_file; + std::string cache_location = GetArtCacheOatFilenameOrDie(location); oat_file = OatFile::Open(cache_location, "", NULL); if (oat_file == NULL) { LOG(ERROR) << "Failed to open oat file from " << location << " or " << cache_location << "."; diff --git a/src/dex2oat.cc b/src/dex2oat.cc index e8cd26d7b8..a4d7449574 100644 --- a/src/dex2oat.cc +++ b/src/dex2oat.cc @@ -86,6 +86,9 @@ int dex2oat(int argc, char** argv) { for (int i = 0; i < argc; i++) { const StringPiece option(argv[i]); + if (false) { + 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("--method=")) { @@ -142,7 +145,7 @@ int dex2oat(int argc, char** argv) { } Runtime::Options options; - std::string boot_class_path_string; + std::string boot_class_path_string; if (boot_image_option.empty()) { boot_class_path_string += "-Xbootclasspath:"; for (size_t i = 0; i < dex_filenames.size()-1; i++) { diff --git a/src/dex_file.cc b/src/dex_file.cc index 235c734aa7..a11744d232 100644 --- a/src/dex_file.cc +++ b/src/dex_file.cc @@ -107,7 +107,7 @@ const DexFile* DexFile::OpenFile(const std::string& filename, return OpenMemory(dex_file, length, location.ToString(), map.release()); } -static const char* kClassesDex = "classes.dex"; +const char* DexFile::kClassesDex = "classes.dex"; class LockedFd { public: @@ -643,7 +643,7 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* ParameterIterator* it = GetParameterIterator(GetProtoId(method->GetProtoIdx())); for (uint32_t i = 0; i < parameters_size && it->HasNext(); ++i, it->Next()) { if (arg_reg >= code_item->registers_size_) { - LOG(FATAL) << "invalid stream"; + LOG(ERROR) << "invalid stream"; return; } int32_t id = DecodeUnsignedLeb128P1(&stream); @@ -669,7 +669,7 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* } if (it->HasNext()) { - LOG(FATAL) << "invalid stream"; + LOG(ERROR) << "invalid stream"; return; } @@ -695,7 +695,7 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* case DBG_START_LOCAL_EXTENDED: reg = DecodeUnsignedLeb128(&stream); if (reg > code_item->registers_size_) { - LOG(FATAL) << "invalid stream"; + LOG(ERROR) << "invalid stream"; return; } @@ -718,7 +718,7 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* case DBG_END_LOCAL: reg = DecodeUnsignedLeb128(&stream); if (reg > code_item->registers_size_) { - LOG(FATAL) << "invalid stream"; + LOG(ERROR) << "invalid stream"; return; } @@ -731,13 +731,13 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method* case DBG_RESTART_LOCAL: reg = DecodeUnsignedLeb128(&stream); if (reg > code_item->registers_size_) { - LOG(FATAL) << "invalid stream"; + LOG(ERROR) << "invalid stream"; return; } if (need_locals) { if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) { - LOG(FATAL) << "invalid stream"; + LOG(ERROR) << "invalid stream"; return; } diff --git a/src/dex_file.h b/src/dex_file.h index 77189f8617..7d9e6f998f 100644 --- a/src/dex_file.h +++ b/src/dex_file.h @@ -31,6 +31,9 @@ class DexFile { static const byte kDexMagicVersion[]; static const size_t kSha1DigestSize = 20; + // name of the DexFile entry within a zip archive + static const char* kClassesDex; + static const byte kEncodedValueTypeMask = 0x1f; // 0b11111 static const byte kEncodedValueArgShift = 5; diff --git a/src/oat_file.cc b/src/oat_file.cc index 8a4aa9a6be..23eae7cbe7 100644 --- a/src/oat_file.cc +++ b/src/oat_file.cc @@ -10,6 +10,17 @@ namespace art { +std::string OatFile::DexFileToOatFilename(const DexFile& dex_file) { + std::string location(dex_file.GetLocation()); + CHECK(StringPiece(location).ends_with(".dex") + || StringPiece(location).ends_with(".zip") + || StringPiece(location).ends_with(".jar") + || StringPiece(location).ends_with(".apk")); + location.erase(location.size()-3); + location += "oat"; + return location; +} + OatFile* OatFile::Open(const std::string& filename, const std::string& strip_location_prefix, byte* requested_base) { diff --git a/src/oat_file.h b/src/oat_file.h index 9f95b3b72e..1d3367cdad 100644 --- a/src/oat_file.h +++ b/src/oat_file.h @@ -16,6 +16,9 @@ namespace art { class OatFile { public: + // Returns an OatFile name based on a DexFile location + static std::string DexFileToOatFilename(const DexFile& dex_file); + // Open an oat file. Returns NULL on failure. Requested base can // optionally be used to request where the file should be loaded. static OatFile* Open(const std::string& filename, diff --git a/src/oatdump.cc b/src/oatdump.cc index 46f6c24968..a5c8c7be59 100644 --- a/src/oatdump.cc +++ b/src/oatdump.cc @@ -109,8 +109,9 @@ class OatDump { os << "location: " << dex_file_location; if (!host_prefix.empty()) { dex_file_location = host_prefix + dex_file_location; - os << " (" << dex_file_location << ")\n"; + os << " (" << dex_file_location << ")"; } + os << "\n"; os << StringPrintf("checksum: %08x\n", oat_dex_file.GetDexFileChecksum()); const DexFile* dex_file = DexFile::Open(dex_file_location, ""); if (dex_file == NULL) { @@ -282,8 +283,9 @@ class ImageDump { os << oat_location; if (!host_prefix.empty()) { oat_location = host_prefix + oat_location; - os << " (" << oat_location << ")\n"; + os << " (" << oat_location << ")"; } + os << "\n"; const OatFile* oat_file = class_linker->FindOatFile(oat_location); if (oat_file == NULL) { os << "NOT FOUND\n"; diff --git a/src/oatopt.cc b/src/oatopt.cc new file mode 100644 index 0000000000..367e5bfc4d --- /dev/null +++ b/src/oatopt.cc @@ -0,0 +1,144 @@ +// 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->Extract(*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 += GetArtCacheOatFilenameOrDie(OatFile::DexFileToOatFilename(*dex_file.get())); + + execl("/system/bin/dex2oatd", + "/system/bin/dex2oatd", + "-Xms64m", + "-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/utils.cc b/src/utils.cc index bc51c2a254..4f4cd8fc44 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -514,6 +514,14 @@ std::string GetArtCacheOrDie() { return art_cache; } +std::string GetArtCacheOatFilenameOrDie(const std::string& location) { + std::string art_cache = GetArtCacheOrDie(); + CHECK_EQ(location[0], '/'); + std::string cache_file(location, 1); // skip leading slash + std::replace(cache_file.begin(), cache_file.end(), '/', '@'); + return art_cache + "/" + cache_file; +} + } // namespace art // Neither bionic nor glibc exposes gettid(2). diff --git a/src/utils.h b/src/utils.h index 7778918bc7..35b350be4e 100644 --- a/src/utils.h +++ b/src/utils.h @@ -212,9 +212,12 @@ pid_t GetTid(); // implementation-defined limit. void SetThreadName(const char* name); -// Returns the art-cache location or dies trying +// Returns the art-cache location, or dies trying. std::string GetArtCacheOrDie(); +// Returns the art-cache location for an OatFile, or dies trying. +std::string GetArtCacheOatFilenameOrDie(const std::string& location); + } // namespace art #endif // ART_SRC_UTILS_H_ diff --git a/src/zip_archive.cc b/src/zip_archive.cc index 82d97ec387..41a25deb19 100644 --- a/src/zip_archive.cc +++ b/src/zip_archive.cc @@ -257,7 +257,6 @@ bool ZipEntry::Extract(File& file) { } } -// return new ZipArchive instance on success, NULL on error. ZipArchive* ZipArchive::Open(const std::string& filename) { DCHECK(!filename.empty()); int fd = open(filename.c_str(), O_RDONLY | O_CLOEXEC, 0); @@ -265,6 +264,10 @@ ZipArchive* ZipArchive::Open(const std::string& filename) { PLOG(WARNING) << "Unable to open '" << filename << "'"; return NULL; } + return Open(fd); +} + +ZipArchive* ZipArchive::Open(int fd) { UniquePtr<ZipArchive> zip_archive(new ZipArchive(fd)); if (zip_archive.get() == NULL) { return NULL; diff --git a/src/zip_archive.h b/src/zip_archive.h index 0c9e6c27e8..13a22cc1a5 100644 --- a/src/zip_archive.h +++ b/src/zip_archive.h @@ -102,7 +102,10 @@ class ZipArchive { static const int32_t kCDECommentLen = 32; // offset to comment length static const int32_t kCDELocalOffset = 42; // offset to local hdr + // return new ZipArchive instance on success, NULL on error. static ZipArchive* Open(const std::string& filename); + static ZipArchive* Open(int fd); + ZipEntry* Find(const char * name); ~ZipArchive() { |