diff options
37 files changed, 478 insertions, 366 deletions
diff --git a/cmdline/cmdline.h b/cmdline/cmdline.h index c5d3a6b454..2929f36d2e 100644 --- a/cmdline/cmdline.h +++ b/cmdline/cmdline.h @@ -26,6 +26,7 @@ #include "android-base/stringprintf.h" +#include "base/file_utils.h" #include "base/logging.h" #include "base/stringpiece.h" #include "noop_compiler_callbacks.h" diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index affe639f8d..1cd9142464 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -43,6 +43,7 @@ #include "art_method-inl.h" #include "base/callee_save_type.h" #include "base/dumpable.h" +#include "base/file_utils.h" #include "base/macros.h" #include "base/scoped_flock.h" #include "base/stl_util.h" diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc index 0a5068112f..a02fbf862f 100644 --- a/dex2oat/dex2oat_image_test.cc +++ b/dex2oat/dex2oat_image_test.cc @@ -24,6 +24,7 @@ #include "common_runtime_test.h" +#include "base/file_utils.h" #include "base/logging.h" #include "base/macros.h" #include "base/unix_file/fd_file.h" diff --git a/dex2oat/linker/elf_writer_test.cc b/dex2oat/linker/elf_writer_test.cc index 9f8ed77526..8427e7b8ce 100644 --- a/dex2oat/linker/elf_writer_test.cc +++ b/dex2oat/linker/elf_writer_test.cc @@ -16,6 +16,7 @@ #include "elf_file.h" +#include "base/file_utils.h" #include "base/unix_file/fd_file.h" #include "common_compiler_test.h" #include "elf_file.h" diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h index dc570da832..d3d42b98bb 100644 --- a/dex2oat/linker/image_test.h +++ b/dex2oat/linker/image_test.h @@ -26,6 +26,7 @@ #include "android-base/stringprintf.h" #include "art_method-inl.h" +#include "base/file_utils.h" #include "base/unix_file/fd_file.h" #include "class_linker-inl.h" #include "common_compiler_test.h" diff --git a/dexlayout/dexdiag_test.cc b/dexlayout/dexdiag_test.cc index 6fcd6ffe9f..9927576400 100644 --- a/dexlayout/dexdiag_test.cc +++ b/dexlayout/dexdiag_test.cc @@ -19,6 +19,7 @@ #include "common_runtime_test.h" +#include "base/file_utils.h" #include "exec_utils.h" #include "oat_file.h" #include "os.h" diff --git a/dexoptanalyzer/dexoptanalyzer.cc b/dexoptanalyzer/dexoptanalyzer.cc index 08d38d5925..b16bbb6209 100644 --- a/dexoptanalyzer/dexoptanalyzer.cc +++ b/dexoptanalyzer/dexoptanalyzer.cc @@ -18,6 +18,7 @@ #include "android-base/stringprintf.h" #include "android-base/strings.h" +#include "base/file_utils.h" #include "compiler_filter.h" #include "dex_file.h" #include "noop_compiler_callbacks.h" diff --git a/oatdump/oatdump_test.h b/oatdump/oatdump_test.h index 52fe973c1b..d0f05d9e66 100644 --- a/oatdump/oatdump_test.h +++ b/oatdump/oatdump_test.h @@ -24,6 +24,7 @@ #include "android-base/strings.h" #include "arch/instruction_set.h" +#include "base/file_utils.h" #include "base/unix_file/fd_file.h" #include "common_runtime_test.h" #include "exec_utils.h" diff --git a/runtime/Android.bp b/runtime/Android.bp index 3258aaee2a..4c4ea58f0d 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -35,6 +35,7 @@ cc_defaults { "base/arena_bit_vector.cc", "base/bit_vector.cc", "base/file_magic.cc", + "base/file_utils.cc", "base/hex_dump.cc", "base/logging.cc", "base/mutex.cc", diff --git a/runtime/base/file_utils.cc b/runtime/base/file_utils.cc new file mode 100644 index 0000000000..323a06519d --- /dev/null +++ b/runtime/base/file_utils.cc @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2011 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. + */ + +#include "file_utils.h" + +#include <inttypes.h> +#include <pthread.h> +#include <sys/mman.h> // For madvise +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +// We need dladdr. +#ifndef __APPLE__ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#define DEFINED_GNU_SOURCE +#endif +#include <dlfcn.h> +#include <libgen.h> +#ifdef DEFINED_GNU_SOURCE +#undef _GNU_SOURCE +#undef DEFINED_GNU_SOURCE +#endif +#endif + + +#include <memory> + +#include "android-base/stringprintf.h" +#include "android-base/strings.h" + +#include "base/stl_util.h" +#include "base/unix_file/fd_file.h" +#include "dex_file-inl.h" +#include "dex_file_loader.h" +#include "dex_instruction.h" +#include "oat_quick_method_header.h" +#include "os.h" +#include "scoped_thread_state_change-inl.h" +#include "utf-inl.h" + +#if defined(__APPLE__) +#include <crt_externs.h> +#include <sys/syscall.h> +#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED +#endif + +#if defined(__linux__) +#include <linux/unistd.h> +#endif + +namespace art { + +using android::base::StringAppendF; +using android::base::StringPrintf; + +bool ReadFileToString(const std::string& file_name, std::string* result) { + File file(file_name, O_RDONLY, false); + if (!file.IsOpened()) { + return false; + } + + std::vector<char> buf(8 * KB); + while (true) { + int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[0], buf.size())); + if (n == -1) { + return false; + } + if (n == 0) { + return true; + } + result->append(&buf[0], n); + } +} + +bool PrintFileToLog(const std::string& file_name, LogSeverity level) { + File file(file_name, O_RDONLY, false); + if (!file.IsOpened()) { + return false; + } + + constexpr size_t kBufSize = 256; // Small buffer. Avoid stack overflow and stack size warnings. + char buf[kBufSize + 1]; // +1 for terminator. + size_t filled_to = 0; + while (true) { + DCHECK_LT(filled_to, kBufSize); + int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[filled_to], kBufSize - filled_to)); + if (n <= 0) { + // Print the rest of the buffer, if it exists. + if (filled_to > 0) { + buf[filled_to] = 0; + LOG(level) << buf; + } + return n == 0; + } + // Scan for '\n'. + size_t i = filled_to; + bool found_newline = false; + for (; i < filled_to + n; ++i) { + if (buf[i] == '\n') { + // Found a line break, that's something to print now. + buf[i] = 0; + LOG(level) << buf; + // Copy the rest to the front. + if (i + 1 < filled_to + n) { + memmove(&buf[0], &buf[i + 1], filled_to + n - i - 1); + filled_to = filled_to + n - i - 1; + } else { + filled_to = 0; + } + found_newline = true; + break; + } + } + if (found_newline) { + continue; + } else { + filled_to += n; + // Check if we must flush now. + if (filled_to == kBufSize) { + buf[kBufSize] = 0; + LOG(level) << buf; + filled_to = 0; + } + } + } +} + +std::string GetAndroidRootSafe(std::string* error_msg) { + // Prefer ANDROID_ROOT if it's set. + const char* android_dir = getenv("ANDROID_ROOT"); + if (android_dir != nullptr) { + if (!OS::DirectoryExists(android_dir)) { + *error_msg = StringPrintf("Failed to find ANDROID_ROOT directory %s", android_dir); + return ""; + } + return android_dir; + } + + // Check where libart is from, and derive from there. Only do this for non-Mac. +#ifndef __APPLE__ + { + Dl_info info; + if (dladdr(reinterpret_cast<const void*>(&GetAndroidRootSafe), /* out */ &info) != 0) { + // Make a duplicate of the fname so dirname can modify it. + UniqueCPtr<char> fname(strdup(info.dli_fname)); + + char* dir1 = dirname(fname.get()); // This is the lib directory. + char* dir2 = dirname(dir1); // This is the "system" directory. + if (OS::DirectoryExists(dir2)) { + std::string tmp = dir2; // Make a copy here so that fname can be released. + return tmp; + } + } + } +#endif + + // Try "/system". + if (!OS::DirectoryExists("/system")) { + *error_msg = "Failed to find ANDROID_ROOT directory /system"; + return ""; + } + return "/system"; +} + +std::string GetAndroidRoot() { + std::string error_msg; + std::string ret = GetAndroidRootSafe(&error_msg); + if (ret.empty()) { + LOG(FATAL) << error_msg; + UNREACHABLE(); + } + return ret; +} + + +static const char* GetAndroidDirSafe(const char* env_var, + const char* default_dir, + std::string* error_msg) { + const char* android_dir = getenv(env_var); + if (android_dir == nullptr) { + if (OS::DirectoryExists(default_dir)) { + android_dir = default_dir; + } else { + *error_msg = StringPrintf("%s not set and %s does not exist", env_var, default_dir); + return nullptr; + } + } + if (!OS::DirectoryExists(android_dir)) { + *error_msg = StringPrintf("Failed to find %s directory %s", env_var, android_dir); + return nullptr; + } + return android_dir; +} + +static const char* GetAndroidDir(const char* env_var, const char* default_dir) { + std::string error_msg; + const char* dir = GetAndroidDirSafe(env_var, default_dir, &error_msg); + if (dir != nullptr) { + return dir; + } else { + LOG(FATAL) << error_msg; + return nullptr; + } +} + +const char* GetAndroidData() { + return GetAndroidDir("ANDROID_DATA", "/data"); +} + +const char* GetAndroidDataSafe(std::string* error_msg) { + return GetAndroidDirSafe("ANDROID_DATA", "/data", error_msg); +} + +std::string GetDefaultBootImageLocation(std::string* error_msg) { + std::string android_root = GetAndroidRootSafe(error_msg); + if (android_root.empty()) { + return ""; + } + return StringPrintf("%s/framework/boot.art", android_root.c_str()); +} + +void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache, + bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache) { + CHECK(subdir != nullptr); + std::string error_msg; + const char* android_data = GetAndroidDataSafe(&error_msg); + if (android_data == nullptr) { + *have_android_data = false; + *dalvik_cache_exists = false; + *is_global_cache = false; + return; + } else { + *have_android_data = true; + } + const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data)); + *dalvik_cache = dalvik_cache_root + subdir; + *dalvik_cache_exists = OS::DirectoryExists(dalvik_cache->c_str()); + *is_global_cache = strcmp(android_data, "/data") == 0; + if (create_if_absent && !*dalvik_cache_exists && !*is_global_cache) { + // Don't create the system's /data/dalvik-cache/... because it needs special permissions. + *dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) && + (mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST)); + } +} + +std::string GetDalvikCache(const char* subdir) { + CHECK(subdir != nullptr); + const char* android_data = GetAndroidData(); + const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data)); + const std::string dalvik_cache = dalvik_cache_root + subdir; + if (!OS::DirectoryExists(dalvik_cache.c_str())) { + // TODO: Check callers. Traditional behavior is to not abort. + return ""; + } + return dalvik_cache; +} + +bool GetDalvikCacheFilename(const char* location, const char* cache_location, + std::string* filename, std::string* error_msg) { + if (location[0] != '/') { + *error_msg = StringPrintf("Expected path in location to be absolute: %s", location); + return false; + } + std::string cache_file(&location[1]); // skip leading slash + if (!android::base::EndsWith(location, ".dex") && + !android::base::EndsWith(location, ".art") && + !android::base::EndsWith(location, ".oat")) { + cache_file += "/"; + cache_file += DexFileLoader::kClassesDex; + } + std::replace(cache_file.begin(), cache_file.end(), '/', '@'); + *filename = StringPrintf("%s/%s", cache_location, cache_file.c_str()); + return true; +} + +std::string GetVdexFilename(const std::string& oat_location) { + return ReplaceFileExtension(oat_location, "vdex"); +} + +static void InsertIsaDirectory(const InstructionSet isa, std::string* filename) { + // in = /foo/bar/baz + // out = /foo/bar/<isa>/baz + size_t pos = filename->rfind('/'); + CHECK_NE(pos, std::string::npos) << *filename << " " << isa; + filename->insert(pos, "/", 1); + filename->insert(pos + 1, GetInstructionSetString(isa)); +} + +std::string GetSystemImageFilename(const char* location, const InstructionSet isa) { + // location = /system/framework/boot.art + // filename = /system/framework/<isa>/boot.art + std::string filename(location); + InsertIsaDirectory(isa, &filename); + return filename; +} + +bool FileExists(const std::string& filename) { + struct stat buffer; + return stat(filename.c_str(), &buffer) == 0; +} + +bool FileExistsAndNotEmpty(const std::string& filename) { + struct stat buffer; + if (stat(filename.c_str(), &buffer) != 0) { + return false; + } + return buffer.st_size > 0; +} + +std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension) { + const size_t last_ext = filename.find_last_of('.'); + if (last_ext == std::string::npos) { + return filename + "." + new_extension; + } else { + return filename.substr(0, last_ext + 1) + new_extension; + } +} + +int64_t GetFileSizeBytes(const std::string& filename) { + struct stat stat_buf; + int rc = stat(filename.c_str(), &stat_buf); + return rc == 0 ? stat_buf.st_size : -1; +} + +int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice) { + DCHECK_LE(begin, end); + begin = AlignUp(begin, kPageSize); + end = AlignDown(end, kPageSize); + if (begin < end) { + int result = madvise(const_cast<uint8_t*>(begin), end - begin, advice); + if (result != 0) { + PLOG(WARNING) << "madvise failed " << result; + } + return result; + } + return 0; +} + +} // namespace art diff --git a/runtime/base/file_utils.h b/runtime/base/file_utils.h new file mode 100644 index 0000000000..007f3b443d --- /dev/null +++ b/runtime/base/file_utils.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef ART_RUNTIME_BASE_FILE_UTILS_H_ +#define ART_RUNTIME_BASE_FILE_UTILS_H_ + +#include <stdlib.h> + +#include <string> + +#include "arch/instruction_set.h" +#include "base/logging.h" + +namespace art { + +bool ReadFileToString(const std::string& file_name, std::string* result); +bool PrintFileToLog(const std::string& file_name, LogSeverity level); + +// Find $ANDROID_ROOT, /system, or abort. +std::string GetAndroidRoot(); +// Find $ANDROID_ROOT, /system, or return an empty string. +std::string GetAndroidRootSafe(std::string* error_msg); + +// Find $ANDROID_DATA, /data, or abort. +const char* GetAndroidData(); +// Find $ANDROID_DATA, /data, or return null. +const char* GetAndroidDataSafe(std::string* error_msg); + +// Returns the default boot image location (ANDROID_ROOT/framework/boot.art). +// Returns an empty string if ANDROID_ROOT is not set. +std::string GetDefaultBootImageLocation(std::string* error_msg); + +// Returns the dalvik-cache location, with subdir appended. Returns the empty string if the cache +// could not be found. +std::string GetDalvikCache(const char* subdir); +// Return true if we found the dalvik cache and stored it in the dalvik_cache argument. +// have_android_data will be set to true if we have an ANDROID_DATA that exists, +// dalvik_cache_exists will be true if there is a dalvik-cache directory that is present. +// The flag is_global_cache tells whether this cache is /data/dalvik-cache. +void GetDalvikCache(const char* subdir, bool create_if_absent, std::string* dalvik_cache, + bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache); + +// Returns the absolute dalvik-cache path for a DexFile or OatFile. The path returned will be +// rooted at cache_location. +bool GetDalvikCacheFilename(const char* file_location, const char* cache_location, + std::string* filename, std::string* error_msg); + +// Returns the system location for an image +std::string GetSystemImageFilename(const char* location, InstructionSet isa); + +// Returns the vdex filename for the given oat filename. +std::string GetVdexFilename(const std::string& oat_filename); + +// Returns true if the file exists. +bool FileExists(const std::string& filename); +bool FileExistsAndNotEmpty(const std::string& filename); + +// Returns `filename` with the text after the last occurrence of '.' replaced with +// `extension`. If `filename` does not contain a period, returns a string containing `filename`, +// a period, and `new_extension`. +// Example: ReplaceFileExtension("foo.bar", "abc") == "foo.abc" +// ReplaceFileExtension("foo", "abc") == "foo.abc" +std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension); + +// Return the file size in bytes or -1 if the file does not exists. +int64_t GetFileSizeBytes(const std::string& filename); + +// Madvise the largest page aligned region within begin and end. +int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice); + +} // namespace art + +#endif // ART_RUNTIME_BASE_FILE_UTILS_H_ diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index 149c33fa87..f15acf980a 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -27,6 +27,7 @@ #include "android-base/stringprintf.h" #include "art_field-inl.h" +#include "base/file_utils.h" #include "base/logging.h" #include "base/macros.h" #include "base/stl_util.h" diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h index 57cef3de47..5f9b3cf6c4 100644 --- a/runtime/dex2oat_environment_test.h +++ b/runtime/dex2oat_environment_test.h @@ -23,6 +23,7 @@ #include <gtest/gtest.h> +#include "base/file_utils.h" #include "base/stl_util.h" #include "common_runtime_test.h" #include "compiler_callbacks.h" diff --git a/runtime/dex_file_layout.cc b/runtime/dex_file_layout.cc index 4375d7f799..c3fae15b14 100644 --- a/runtime/dex_file_layout.cc +++ b/runtime/dex_file_layout.cc @@ -18,6 +18,7 @@ #include <sys/mman.h> +#include "base/file_utils.h" #include "dex_file.h" #include "utils.h" diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc index 4d4d8ffb58..7beff960cc 100644 --- a/runtime/gc/collector/concurrent_copying.cc +++ b/runtime/gc/collector/concurrent_copying.cc @@ -18,6 +18,7 @@ #include "art_field-inl.h" #include "base/enums.h" +#include "base/file_utils.h" #include "base/histogram-inl.h" #include "base/stl_util.h" #include "base/systrace.h" diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc index 2dc5acc14b..c6caf4b08e 100644 --- a/runtime/gc/collector/mark_sweep.cc +++ b/runtime/gc/collector/mark_sweep.cc @@ -24,6 +24,7 @@ #include "base/bounded_fifo.h" #include "base/enums.h" +#include "base/file_utils.h" #include "base/logging.h" #include "base/macros.h" #include "base/mutex-inl.h" diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 4f5458212c..9f6266612a 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -28,6 +28,7 @@ #include "base/allocator.h" #include "base/arena_allocator.h" #include "base/dumpable.h" +#include "base/file_utils.h" #include "base/histogram-inl.h" #include "base/memory_tool.h" #include "base/stl_util.h" diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index f0eada3cb4..74813b4dd1 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -30,6 +30,7 @@ #include "art_method-inl.h" #include "base/callee_save_type.h" #include "base/enums.h" +#include "base/file_utils.h" #include "base/macros.h" #include "base/scoped_flock.h" #include "base/stl_util.h" diff --git a/runtime/gc/space/image_space_fs.h b/runtime/gc/space/image_space_fs.h index 5999548d2b..bdb2edad35 100644 --- a/runtime/gc/space/image_space_fs.h +++ b/runtime/gc/space/image_space_fs.h @@ -22,6 +22,7 @@ #include "android-base/stringprintf.h" +#include "base/file_utils.h" #include "base/logging.h" #include "base/macros.h" #include "base/unix_file/fd_file.h" diff --git a/runtime/gc/verification.cc b/runtime/gc/verification.cc index beb43dfcf5..3cd04a61e9 100644 --- a/runtime/gc/verification.cc +++ b/runtime/gc/verification.cc @@ -20,6 +20,7 @@ #include <sstream> #include "art_field-inl.h" +#include "base/file_utils.h" #include "mirror/class-inl.h" #include "mirror/object-refvisitor-inl.h" diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc index 19501de81b..805b9c185a 100644 --- a/runtime/jit/profile_compilation_info.cc +++ b/runtime/jit/profile_compilation_info.cc @@ -34,6 +34,7 @@ #include "base/arena_allocator.h" #include "base/dumpable.h" +#include "base/file_utils.h" #include "base/mutex.h" #include "base/scoped_flock.h" #include "base/stl_util.h" diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc index 743604cc47..7f68d2faa0 100644 --- a/runtime/mem_map.cc +++ b/runtime/mem_map.cc @@ -34,6 +34,7 @@ #include "base/allocator.h" #include "base/bit_utils.h" +#include "base/file_utils.h" #include "base/memory_tool.h" #include "globals.h" #include "utils.h" diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index 4ab8908ff3..6059b89a76 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -20,6 +20,7 @@ #include "android-base/stringprintf.h" +#include "base/file_utils.h" #include "base/logging.h" #include "base/stl_util.h" #include "class_linker.h" diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc index dd98e25932..f5057b013a 100644 --- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc +++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc @@ -16,6 +16,7 @@ #include "org_apache_harmony_dalvik_ddmc_DdmVmInternal.h" +#include "base/file_utils.h" #include "base/logging.h" #include "base/mutex.h" #include "debugger.h" diff --git a/runtime/native_stack_dump.cc b/runtime/native_stack_dump.cc index 7e16357376..f166714b79 100644 --- a/runtime/native_stack_dump.cc +++ b/runtime/native_stack_dump.cc @@ -40,6 +40,7 @@ #include "android-base/stringprintf.h" #include "arch/instruction_set.h" +#include "base/file_utils.h" #include "base/memory_tool.h" #include "base/mutex.h" #include "base/unix_file/fd_file.h" diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 1269dcad93..d64986e76d 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -38,6 +38,7 @@ #include "art_method.h" #include "base/bit_vector.h" #include "base/enums.h" +#include "base/file_utils.h" #include "base/stl_util.h" #include "base/systrace.h" #include "base/unix_file/fd_file.h" diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index a7fe9b1205..fbb312eff4 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -23,6 +23,7 @@ #include "android-base/stringprintf.h" #include "android-base/strings.h" +#include "base/file_utils.h" #include "base/logging.h" #include "base/stl_util.h" #include "class_linker.h" diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc index 940195c0f4..ee35d9cd12 100644 --- a/runtime/oat_file_manager.cc +++ b/runtime/oat_file_manager.cc @@ -25,6 +25,7 @@ #include "art_field-inl.h" #include "base/bit_vector-inl.h" +#include "base/file_utils.h" #include "base/logging.h" #include "base/stl_util.h" #include "base/systrace.h" diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index 71d7b6c34d..526f6d147a 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -18,6 +18,7 @@ #include <sstream> +#include "base/file_utils.h" #include "base/logging.h" #include "base/stringpiece.h" #include "debugger.h" diff --git a/runtime/runtime.cc b/runtime/runtime.cc index ec210d0aef..139de2b1f3 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -60,6 +60,7 @@ #include "base/arena_allocator.h" #include "base/dumpable.h" #include "base/enums.h" +#include "base/file_utils.h" #include "base/memory_tool.h" #include "base/stl_util.h" #include "base/systrace.h" diff --git a/runtime/runtime_common.cc b/runtime/runtime_common.cc index 940e4611f6..eb69d91dad 100644 --- a/runtime/runtime_common.cc +++ b/runtime/runtime_common.cc @@ -25,6 +25,7 @@ #include "android-base/stringprintf.h" +#include "base/file_utils.h" #include "base/logging.h" #include "base/macros.h" #include "base/mutex.h" diff --git a/runtime/signal_catcher.cc b/runtime/signal_catcher.cc index a1f14be0f1..bf5d718113 100644 --- a/runtime/signal_catcher.cc +++ b/runtime/signal_catcher.cc @@ -34,6 +34,7 @@ #endif #include "arch/instruction_set.h" +#include "base/file_utils.h" #include "base/time_utils.h" #include "base/unix_file/fd_file.h" #include "class_linker.h" diff --git a/runtime/thread.cc b/runtime/thread.cc index 47ffb4e13f..cb3e8de36e 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -39,6 +39,7 @@ #include "art_field-inl.h" #include "art_method-inl.h" #include "base/bit_utils.h" +#include "base/file_utils.h" #include "base/memory_tool.h" #include "base/mutex.h" #include "base/systrace.h" diff --git a/runtime/utils.cc b/runtime/utils.cc index 1f6bd742b6..f6533a7130 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -18,41 +18,20 @@ #include <inttypes.h> #include <pthread.h> -#include <sys/mman.h> // For madvise #include <sys/stat.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> -// We need dladdr. -#ifndef __APPLE__ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#define DEFINED_GNU_SOURCE -#endif -#include <dlfcn.h> -#include <libgen.h> -#ifdef DEFINED_GNU_SOURCE -#undef _GNU_SOURCE -#undef DEFINED_GNU_SOURCE -#endif -#endif - - #include <memory> #include "android-base/stringprintf.h" #include "android-base/strings.h" -#include "base/stl_util.h" -#include "base/unix_file/fd_file.h" +#include "base/file_utils.h" #include "dex_file-inl.h" -#include "dex_file_loader.h" -#include "dex_instruction.h" -#include "oat_quick_method_header.h" #include "os.h" -#include "scoped_thread_state_change-inl.h" #include "utf-inl.h" #if defined(__APPLE__) @@ -92,78 +71,6 @@ std::string GetThreadName(pid_t tid) { return result; } -bool ReadFileToString(const std::string& file_name, std::string* result) { - File file(file_name, O_RDONLY, false); - if (!file.IsOpened()) { - return false; - } - - std::vector<char> buf(8 * KB); - while (true) { - int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[0], buf.size())); - if (n == -1) { - return false; - } - if (n == 0) { - return true; - } - result->append(&buf[0], n); - } -} - -bool PrintFileToLog(const std::string& file_name, LogSeverity level) { - File file(file_name, O_RDONLY, false); - if (!file.IsOpened()) { - return false; - } - - constexpr size_t kBufSize = 256; // Small buffer. Avoid stack overflow and stack size warnings. - char buf[kBufSize + 1]; // +1 for terminator. - size_t filled_to = 0; - while (true) { - DCHECK_LT(filled_to, kBufSize); - int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[filled_to], kBufSize - filled_to)); - if (n <= 0) { - // Print the rest of the buffer, if it exists. - if (filled_to > 0) { - buf[filled_to] = 0; - LOG(level) << buf; - } - return n == 0; - } - // Scan for '\n'. - size_t i = filled_to; - bool found_newline = false; - for (; i < filled_to + n; ++i) { - if (buf[i] == '\n') { - // Found a line break, that's something to print now. - buf[i] = 0; - LOG(level) << buf; - // Copy the rest to the front. - if (i + 1 < filled_to + n) { - memmove(&buf[0], &buf[i + 1], filled_to + n - i - 1); - filled_to = filled_to + n - i - 1; - } else { - filled_to = 0; - } - found_newline = true; - break; - } - } - if (found_newline) { - continue; - } else { - filled_to += n; - // Check if we must flush now. - if (filled_to == kBufSize) { - buf[kBufSize] = 0; - LOG(level) << buf; - filled_to = 0; - } - } - } -} - void AppendPrettyDescriptor(const char* descriptor, std::string* result) { // Count the number of '['s to get the dimensionality. const char* c = descriptor; @@ -718,197 +625,6 @@ void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) *task_cpu = strtoull(fields[36].c_str(), nullptr, 10); } -std::string GetAndroidRootSafe(std::string* error_msg) { - // Prefer ANDROID_ROOT if it's set. - const char* android_dir = getenv("ANDROID_ROOT"); - if (android_dir != nullptr) { - if (!OS::DirectoryExists(android_dir)) { - *error_msg = StringPrintf("Failed to find ANDROID_ROOT directory %s", android_dir); - return ""; - } - return android_dir; - } - - // Check where libart is from, and derive from there. Only do this for non-Mac. -#ifndef __APPLE__ - { - Dl_info info; - if (dladdr(reinterpret_cast<const void*>(&GetAndroidRootSafe), /* out */ &info) != 0) { - // Make a duplicate of the fname so dirname can modify it. - UniqueCPtr<char> fname(strdup(info.dli_fname)); - - char* dir1 = dirname(fname.get()); // This is the lib directory. - char* dir2 = dirname(dir1); // This is the "system" directory. - if (OS::DirectoryExists(dir2)) { - std::string tmp = dir2; // Make a copy here so that fname can be released. - return tmp; - } - } - } -#endif - - // Try "/system". - if (!OS::DirectoryExists("/system")) { - *error_msg = "Failed to find ANDROID_ROOT directory /system"; - return ""; - } - return "/system"; -} - -std::string GetAndroidRoot() { - std::string error_msg; - std::string ret = GetAndroidRootSafe(&error_msg); - if (ret.empty()) { - LOG(FATAL) << error_msg; - UNREACHABLE(); - } - return ret; -} - - -static const char* GetAndroidDirSafe(const char* env_var, - const char* default_dir, - std::string* error_msg) { - const char* android_dir = getenv(env_var); - if (android_dir == nullptr) { - if (OS::DirectoryExists(default_dir)) { - android_dir = default_dir; - } else { - *error_msg = StringPrintf("%s not set and %s does not exist", env_var, default_dir); - return nullptr; - } - } - if (!OS::DirectoryExists(android_dir)) { - *error_msg = StringPrintf("Failed to find %s directory %s", env_var, android_dir); - return nullptr; - } - return android_dir; -} - -static const char* GetAndroidDir(const char* env_var, const char* default_dir) { - std::string error_msg; - const char* dir = GetAndroidDirSafe(env_var, default_dir, &error_msg); - if (dir != nullptr) { - return dir; - } else { - LOG(FATAL) << error_msg; - return nullptr; - } -} - -const char* GetAndroidData() { - return GetAndroidDir("ANDROID_DATA", "/data"); -} - -const char* GetAndroidDataSafe(std::string* error_msg) { - return GetAndroidDirSafe("ANDROID_DATA", "/data", error_msg); -} - -std::string GetDefaultBootImageLocation(std::string* error_msg) { - std::string android_root = GetAndroidRootSafe(error_msg); - if (android_root.empty()) { - return ""; - } - return StringPrintf("%s/framework/boot.art", android_root.c_str()); -} - -void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache, - bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache) { - CHECK(subdir != nullptr); - std::string error_msg; - const char* android_data = GetAndroidDataSafe(&error_msg); - if (android_data == nullptr) { - *have_android_data = false; - *dalvik_cache_exists = false; - *is_global_cache = false; - return; - } else { - *have_android_data = true; - } - const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data)); - *dalvik_cache = dalvik_cache_root + subdir; - *dalvik_cache_exists = OS::DirectoryExists(dalvik_cache->c_str()); - *is_global_cache = strcmp(android_data, "/data") == 0; - if (create_if_absent && !*dalvik_cache_exists && !*is_global_cache) { - // Don't create the system's /data/dalvik-cache/... because it needs special permissions. - *dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) && - (mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST)); - } -} - -std::string GetDalvikCache(const char* subdir) { - CHECK(subdir != nullptr); - const char* android_data = GetAndroidData(); - const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data)); - const std::string dalvik_cache = dalvik_cache_root + subdir; - if (!OS::DirectoryExists(dalvik_cache.c_str())) { - // TODO: Check callers. Traditional behavior is to not abort. - return ""; - } - return dalvik_cache; -} - -bool GetDalvikCacheFilename(const char* location, const char* cache_location, - std::string* filename, std::string* error_msg) { - if (location[0] != '/') { - *error_msg = StringPrintf("Expected path in location to be absolute: %s", location); - return false; - } - std::string cache_file(&location[1]); // skip leading slash - if (!android::base::EndsWith(location, ".dex") && - !android::base::EndsWith(location, ".art") && - !android::base::EndsWith(location, ".oat")) { - cache_file += "/"; - cache_file += DexFileLoader::kClassesDex; - } - std::replace(cache_file.begin(), cache_file.end(), '/', '@'); - *filename = StringPrintf("%s/%s", cache_location, cache_file.c_str()); - return true; -} - -std::string GetVdexFilename(const std::string& oat_location) { - return ReplaceFileExtension(oat_location, "vdex"); -} - -static void InsertIsaDirectory(const InstructionSet isa, std::string* filename) { - // in = /foo/bar/baz - // out = /foo/bar/<isa>/baz - size_t pos = filename->rfind('/'); - CHECK_NE(pos, std::string::npos) << *filename << " " << isa; - filename->insert(pos, "/", 1); - filename->insert(pos + 1, GetInstructionSetString(isa)); -} - -std::string GetSystemImageFilename(const char* location, const InstructionSet isa) { - // location = /system/framework/boot.art - // filename = /system/framework/<isa>/boot.art - std::string filename(location); - InsertIsaDirectory(isa, &filename); - return filename; -} - -bool FileExists(const std::string& filename) { - struct stat buffer; - return stat(filename.c_str(), &buffer) == 0; -} - -bool FileExistsAndNotEmpty(const std::string& filename) { - struct stat buffer; - if (stat(filename.c_str(), &buffer) != 0) { - return false; - } - return buffer.st_size > 0; -} - -std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension) { - const size_t last_ext = filename.find_last_of('.'); - if (last_ext == std::string::npos) { - return filename + "." + new_extension; - } else { - return filename.substr(0, last_ext + 1) + new_extension; - } -} - std::string PrettyDescriptor(Primitive::Type type) { return PrettyDescriptor(Primitive::Descriptor(type)); } @@ -952,30 +668,10 @@ void ParseDouble(const std::string& option, *parsed_value = value; } -int64_t GetFileSizeBytes(const std::string& filename) { - struct stat stat_buf; - int rc = stat(filename.c_str(), &stat_buf); - return rc == 0 ? stat_buf.st_size : -1; -} - void SleepForever() { while (true) { usleep(1000000); } } -int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice) { - DCHECK_LE(begin, end); - begin = AlignUp(begin, kPageSize); - end = AlignDown(end, kPageSize); - if (begin < end) { - int result = madvise(const_cast<uint8_t*>(begin), end - begin, advice); - if (result != 0) { - PLOG(WARNING) << "madvise failed " << result; - } - return result; - } - return 0; -} - } // namespace art diff --git a/runtime/utils.h b/runtime/utils.h index fbf812a6b3..ede32dc57a 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -20,12 +20,8 @@ #include <pthread.h> #include <stdlib.h> -#include <limits> -#include <memory> #include <random> #include <string> -#include <type_traits> -#include <vector> #include "arch/instruction_set.h" #include "base/casts.h" @@ -118,9 +114,6 @@ bool IsValidDescriptor(const char* s); // "Ljava/lang/String;" // additionally allowing names that begin with '<' and end with '>'. bool IsValidMemberName(const char* s); -bool ReadFileToString(const std::string& file_name, std::string* result); -bool PrintFileToLog(const std::string& file_name, LogSeverity level); - // Splits a string using the given separator character into a vector of // strings. Empty strings will be omitted. void Split(const std::string& s, char separator, std::vector<std::string>* result); @@ -131,58 +124,12 @@ pid_t GetTid(); // Returns the given thread's name. std::string GetThreadName(pid_t tid); -// Reads data from "/proc/self/task/${tid}/stat". -void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu); - // Sets the name of the current thread. The name may be truncated to an // implementation-defined limit. void SetThreadName(const char* thread_name); -// Find $ANDROID_ROOT, /system, or abort. -std::string GetAndroidRoot(); -// Find $ANDROID_ROOT, /system, or return an empty string. -std::string GetAndroidRootSafe(std::string* error_msg); - -// Find $ANDROID_DATA, /data, or abort. -const char* GetAndroidData(); -// Find $ANDROID_DATA, /data, or return null. -const char* GetAndroidDataSafe(std::string* error_msg); - -// Returns the default boot image location (ANDROID_ROOT/framework/boot.art). -// Returns an empty string if ANDROID_ROOT is not set. -std::string GetDefaultBootImageLocation(std::string* error_msg); - -// Returns the dalvik-cache location, with subdir appended. Returns the empty string if the cache -// could not be found. -std::string GetDalvikCache(const char* subdir); -// Return true if we found the dalvik cache and stored it in the dalvik_cache argument. -// have_android_data will be set to true if we have an ANDROID_DATA that exists, -// dalvik_cache_exists will be true if there is a dalvik-cache directory that is present. -// The flag is_global_cache tells whether this cache is /data/dalvik-cache. -void GetDalvikCache(const char* subdir, bool create_if_absent, std::string* dalvik_cache, - bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache); - -// Returns the absolute dalvik-cache path for a DexFile or OatFile. The path returned will be -// rooted at cache_location. -bool GetDalvikCacheFilename(const char* file_location, const char* cache_location, - std::string* filename, std::string* error_msg); - -// Returns the system location for an image -std::string GetSystemImageFilename(const char* location, InstructionSet isa); - -// Returns the vdex filename for the given oat filename. -std::string GetVdexFilename(const std::string& oat_filename); - -// Returns true if the file exists. -bool FileExists(const std::string& filename); -bool FileExistsAndNotEmpty(const std::string& filename); - -// Returns `filename` with the text after the last occurrence of '.' replaced with -// `extension`. If `filename` does not contain a period, returns a string containing `filename`, -// a period, and `new_extension`. -// Example: ReplaceFileExtension("foo.bar", "abc") == "foo.abc" -// ReplaceFileExtension("foo", "abc") == "foo.abc" -std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension); +// Reads data from "/proc/self/task/${tid}/stat". +void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu); class VoidFunctor { public: @@ -273,9 +220,6 @@ static T GetRandomNumber(T min, T max) { return dist(rng); } -// Return the file size in bytes or -1 if the file does not exists. -int64_t GetFileSizeBytes(const std::string& filename); - // Sleep forever and never come back. NO_RETURN void SleepForever(); @@ -335,9 +279,6 @@ inline static int32_t Signum(T opnd) { return (opnd < 0) ? -1 : ((opnd == 0) ? 0 : 1); } -// Madvise the largest page aligned region within begin and end. -int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice); - template <typename Func, typename... Args> static inline void CheckedCall(const Func& function, const char* what, Args... args) { int rc = function(args...); diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc index e846c983af..efb20bae9e 100644 --- a/runtime/utils_test.cc +++ b/runtime/utils_test.cc @@ -20,6 +20,7 @@ #include <stdlib.h> #include "base/enums.h" +#include "base/file_utils.h" #include "base/stl_util.h" #include "class_linker-inl.h" #include "common_runtime_test.h" diff --git a/test/137-cfi/cfi.cc b/test/137-cfi/cfi.cc index ad705c56d2..58b33be573 100644 --- a/test/137-cfi/cfi.cc +++ b/test/137-cfi/cfi.cc @@ -28,6 +28,7 @@ #include <backtrace/Backtrace.h> #include "android-base/stringprintf.h" +#include "base/file_utils.h" #include "base/logging.h" #include "base/macros.h" #include "gc/heap.h" |