diff options
26 files changed, 412 insertions, 49 deletions
diff --git a/dexdump/Android.bp b/dexdump/Android.bp index d15bbda4f4..434cb3553f 100644 --- a/dexdump/Android.bp +++ b/dexdump/Android.bp @@ -49,6 +49,9 @@ art_cc_binary { darwin: { enabled: false, }, + windows: { + enabled: true, + }, }, } diff --git a/libartbase/Android.bp b/libartbase/Android.bp index c3fb5fd407..0fcd6a5d25 100644 --- a/libartbase/Android.bp +++ b/libartbase/Android.bp @@ -35,7 +35,6 @@ cc_defaults { "base/memory_region.cc", "base/mem_map.cc", // "base/mem_map_fuchsia.cc", put in target when fuchsia supported by soong - "base/mem_map_unix.cc", "base/os_linux.cc", "base/runtime_debug.cc", "base/safe_copy.cc", @@ -50,20 +49,38 @@ cc_defaults { ], target: { android: { + srcs: [ + "base/mem_map_unix.cc", + ], static_libs: [ // ZipArchive support, the order matters here to get all symbols. "libziparchive", "libz", ], + shared_libs: [ + "liblog", + // For ashmem. + "libcutils", + // For common macros. + "libbase", + ], // Exclude the version script from Darwin host since it's not // supported by the linker there. That means ASan checks on Darwin // might trigger ODR violations. version_script: "libartbase.map", }, - host: { + not_windows: { + srcs: [ + "base/mem_map_unix.cc", + ], shared_libs: [ "libziparchive", "libz", + "liblog", + // For ashmem. + "libcutils", + // For common macros. + "libbase", ], }, linux_glibc: { @@ -71,17 +88,20 @@ cc_defaults { }, windows: { version_script: "libartbase.map", + static_libs: [ + "libziparchive", + "libz", + "liblog", + // For ashmem. + "libcutils", + // For common macros. + "libbase", + ], + cflags: ["-Wno-thread-safety"], }, }, generated_sources: ["art_libartbase_operator_srcs"], cflags: ["-DBUILDING_LIBART=1"], - shared_libs: [ - "liblog", - // For ashmem. - "libcutils", - // For common macros. - "libbase", - ], // Utilities used by various ART libs and tools are linked in statically // here to avoid shared lib dependencies outside the ART APEX. No target @@ -147,6 +167,14 @@ art_cc_library { "libziparchive", ], export_shared_lib_headers: ["libbase"], + target: { + windows: { + enabled: true, + shared: { + enabled: false, + }, + }, + }, } art_cc_library { @@ -160,6 +188,14 @@ art_cc_library { "libziparchive", ], export_shared_lib_headers: ["libbase"], + target: { + windows: { + enabled: true, + shared: { + enabled: false, + }, + }, + }, } art_cc_library { diff --git a/libartbase/base/arena_allocator.cc b/libartbase/base/arena_allocator.cc index df3deba178..0e7f6cceb3 100644 --- a/libartbase/base/arena_allocator.cc +++ b/libartbase/base/arena_allocator.cc @@ -16,7 +16,6 @@ #include "arena_allocator-inl.h" -#include <sys/mman.h> #include <algorithm> #include <cstddef> @@ -25,6 +24,8 @@ #include <android-base/logging.h> +#include "mman.h" + namespace art { constexpr size_t kMemoryToolRedZoneBytes = 8; diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc index f8d6016315..9490798552 100644 --- a/libartbase/base/file_utils.cc +++ b/libartbase/base/file_utils.cc @@ -19,11 +19,13 @@ #include <inttypes.h> #include <sys/stat.h> #include <sys/types.h> +#ifndef _WIN32 #include <sys/wait.h> +#endif #include <unistd.h> // We need dladdr. -#ifndef __APPLE__ +#if !defined(__APPLE__) && !defined(_WIN32) #ifndef _GNU_SOURCE #define _GNU_SOURCE #define DEFINED_GNU_SOURCE @@ -84,6 +86,10 @@ bool ReadFileToString(const std::string& file_name, std::string* result) { } std::string GetAndroidRootSafe(std::string* error_msg) { +#ifdef _WIN32 + *error_msg = "GetAndroidRootSafe unsupported for Windows."; + return ""; +#else // Prefer ANDROID_ROOT if it's set. const char* android_dir = getenv("ANDROID_ROOT"); if (android_dir != nullptr) { @@ -118,6 +124,7 @@ std::string GetAndroidRootSafe(std::string* error_msg) { return ""; } return "/system"; +#endif } std::string GetAndroidRoot() { @@ -179,6 +186,15 @@ std::string GetDefaultBootImageLocation(std::string* error_msg) { 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) { +#ifdef _WIN32 + UNUSED(subdir); + UNUSED(create_if_absent); + UNUSED(dalvik_cache); + UNUSED(have_android_data); + UNUSED(dalvik_cache_exists); + UNUSED(is_global_cache); + LOG(FATAL) << "GetDalvikCache unsupported on Windows."; +#else CHECK(subdir != nullptr); std::string error_msg; const char* android_data = GetAndroidDataSafe(&error_msg); @@ -199,6 +215,7 @@ void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string *dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) && (mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST)); } +#endif } std::string GetDalvikCache(const char* subdir) { @@ -262,9 +279,15 @@ std::string ReplaceFileExtension(const std::string& filename, const std::string& } bool LocationIsOnSystem(const char* path) { +#ifdef _WIN32 + UNUSED(path); + LOG(FATAL) << "LocationIsOnSystem is unsupported on Windows."; + return false; +#else UniqueCPtr<const char[]> full_path(realpath(path, nullptr)); return full_path != nullptr && android::base::StartsWith(full_path.get(), GetAndroidRoot().c_str()); +#endif } bool LocationIsOnSystemFramework(const char* full_path) { diff --git a/libartbase/base/malloc_arena_pool.cc b/libartbase/base/malloc_arena_pool.cc index 02e29f1d21..4de34b5707 100644 --- a/libartbase/base/malloc_arena_pool.cc +++ b/libartbase/base/malloc_arena_pool.cc @@ -16,7 +16,6 @@ #include "malloc_arena_pool.h" -#include <sys/mman.h> #include <algorithm> #include <cstddef> @@ -25,6 +24,7 @@ #include <android-base/logging.h> #include "arena_allocator-inl.h" +#include "mman.h" namespace art { diff --git a/libartbase/base/mem_map.cc b/libartbase/base/mem_map.cc index 532ca28b50..28337507d8 100644 --- a/libartbase/base/mem_map.cc +++ b/libartbase/base/mem_map.cc @@ -18,8 +18,7 @@ #include <inttypes.h> #include <stdlib.h> -#include <sys/mman.h> // For the PROT_* and MAP_* constants. -#if !defined(ANDROID_OS) && !defined(__Fuchsia__) +#if !defined(ANDROID_OS) && !defined(__Fuchsia__) && !defined(_WIN32) #include <sys/resource.h> #endif @@ -39,6 +38,7 @@ #include "globals.h" #include "logging.h" // For VLOG_IS_ON. #include "memory_tool.h" +#include "mman.h" // For the PROT_* and MAP_* constants. #include "utils.h" #ifndef MAP_ANONYMOUS @@ -811,19 +811,30 @@ void MemMap::MadviseDontNeedAndZero() { if (!kMadviseZeroes) { memset(base_begin_, 0, base_size_); } +#ifdef _WIN32 + // It is benign not to madvise away the pages here. + PLOG(WARNING) << "MemMap::MadviseDontNeedAndZero does not madvise on Windows."; +#else int result = madvise(base_begin_, base_size_, MADV_DONTNEED); if (result == -1) { PLOG(WARNING) << "madvise failed"; } +#endif } } bool MemMap::Sync() { +#ifdef _WIN32 + // TODO: add FlushViewOfFile support. + PLOG(ERROR) << "MemMap::Sync unsupported on Windows."; + return false; +#else // Historical note: To avoid Valgrind errors, we temporarily lifted the lower-end noaccess // protection before passing it to msync() when `redzone_size_` was non-null, as Valgrind // only accepts page-aligned base address, and excludes the higher-end noaccess protection // from the msync range. b/27552451. return msync(BaseBegin(), BaseSize(), MS_SYNC) == 0; +#endif } bool MemMap::Protect(int prot) { @@ -832,10 +843,12 @@ bool MemMap::Protect(int prot) { return true; } +#ifndef _WIN32 if (mprotect(base_begin_, base_size_, prot) == 0) { prot_ = prot; return true; } +#endif PLOG(ERROR) << "mprotect(" << reinterpret_cast<void*>(base_begin_) << ", " << base_size_ << ", " << prot << ") failed"; @@ -1206,7 +1219,11 @@ void ZeroAndReleasePages(void* address, size_t length) { DCHECK_LE(page_begin, page_end); DCHECK_LE(page_end, mem_end); std::fill(mem_begin, page_begin, 0); +#ifdef _WIN32 + LOG(WARNING) << "ZeroAndReleasePages does not madvise on Windows."; +#else CHECK_NE(madvise(page_begin, page_end - page_begin, MADV_DONTNEED), -1) << "madvise failed"; +#endif std::fill(page_end, mem_end, 0); } } diff --git a/libartbase/base/mem_map_fuchsia.cc b/libartbase/base/mem_map_fuchsia.cc index d1c92ce4d6..6b0e06c268 100644 --- a/libartbase/base/mem_map_fuchsia.cc +++ b/libartbase/base/mem_map_fuchsia.cc @@ -15,8 +15,8 @@ */ #include "mem_map.h" -#include <sys/mman.h> #include "logging.h" +#include "mman.h" #include <zircon/process.h> #include <zircon/syscalls.h> diff --git a/libartbase/base/mem_map_test.cc b/libartbase/base/mem_map_test.cc index 074d4c2890..bf39fd1562 100644 --- a/libartbase/base/mem_map_test.cc +++ b/libartbase/base/mem_map_test.cc @@ -16,8 +16,6 @@ #include "mem_map.h" -#include <sys/mman.h> - #include <memory> #include <random> @@ -25,6 +23,7 @@ #include "common_runtime_test.h" // For TEST_DISABLED_FOR_MIPS #include "logging.h" #include "memory_tool.h" +#include "mman.h" #include "unix_file/fd_file.h" namespace art { diff --git a/libartbase/base/mem_map_unix.cc b/libartbase/base/mem_map_unix.cc index 601b049525..ac854dfd52 100644 --- a/libartbase/base/mem_map_unix.cc +++ b/libartbase/base/mem_map_unix.cc @@ -16,7 +16,7 @@ #include "mem_map.h" -#include <sys/mman.h> +#include "mman.h" namespace art { diff --git a/libartbase/base/membarrier.cc b/libartbase/base/membarrier.cc index 4c86b6b0f6..abb36bcaa9 100644 --- a/libartbase/base/membarrier.cc +++ b/libartbase/base/membarrier.cc @@ -18,8 +18,10 @@ #include <errno.h> +#if !defined(_WIN32) #include <sys/syscall.h> #include <unistd.h> +#endif #include "macros.h" #if defined(__BIONIC__) diff --git a/libartbase/base/memfd.cc b/libartbase/base/memfd.cc index 7c2040147e..780be328af 100644 --- a/libartbase/base/memfd.cc +++ b/libartbase/base/memfd.cc @@ -18,9 +18,11 @@ #include <errno.h> #include <stdio.h> +#if !defined(_WIN32) #include <sys/syscall.h> #include <sys/utsname.h> #include <unistd.h> +#endif #include "macros.h" diff --git a/libartbase/base/mman.h b/libartbase/base/mman.h new file mode 100644 index 0000000000..bd63f6506f --- /dev/null +++ b/libartbase/base/mman.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef ART_LIBARTBASE_BASE_MMAN_H_ +#define ART_LIBARTBASE_BASE_MMAN_H_ + +#ifdef _WIN32 + +// There is no sys/mman.h in mingw. +// As these are just placeholders for the APIs, all values are stubbed out. + +#define PROT_READ 0 // 0x1 +#define PROT_WRITE 0 // 0x2 +#define PROT_EXEC 0 // 0x4 +#define PROT_NONE 0 // 0x0 + +#define MAP_SHARED 0 // 0x01 +#define MAP_PRIVATE 0 // 0x02 + +#define MAP_FAILED nullptr // ((void*) -1) +#define MAP_FIXED 0 // 0x10 +#define MAP_ANONYMOUS 0 // 0x20 + +#else + +#include <sys/mman.h> + +#endif + + +#endif // ART_LIBARTBASE_BASE_MMAN_H_ diff --git a/libartbase/base/os_linux.cc b/libartbase/base/os_linux.cc index f8b31cf0d8..a00779eb48 100644 --- a/libartbase/base/os_linux.cc +++ b/libartbase/base/os_linux.cc @@ -50,7 +50,12 @@ File* OS::CreateEmptyFile(const char* name) { } File* OS::CreateEmptyFileWriteOnly(const char* name) { - return art::CreateEmptyFile(name, O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC); +#ifdef _WIN32 + int flags = O_WRONLY | O_TRUNC; +#else + int flags = O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC; +#endif + return art::CreateEmptyFile(name, flags); } File* OS::OpenFileWithFlags(const char* name, int flags, bool auto_flush) { diff --git a/libartbase/base/safe_copy.cc b/libartbase/base/safe_copy.cc index b46b921307..ad75aa7b28 100644 --- a/libartbase/base/safe_copy.cc +++ b/libartbase/base/safe_copy.cc @@ -16,8 +16,10 @@ #include "safe_copy.h" +#ifdef __linux__ #include <sys/uio.h> #include <sys/user.h> +#endif #include <unistd.h> #include <algorithm> diff --git a/libartbase/base/safe_copy_test.cc b/libartbase/base/safe_copy_test.cc index c23651f7a7..9f7d40964b 100644 --- a/libartbase/base/safe_copy_test.cc +++ b/libartbase/base/safe_copy_test.cc @@ -18,12 +18,12 @@ #include <errno.h> #include <string.h> -#include <sys/mman.h> #include <sys/user.h> #include "android-base/logging.h" #include "globals.h" #include "gtest/gtest.h" +#include "mman.h" namespace art { diff --git a/libartbase/base/scoped_flock.cc b/libartbase/base/scoped_flock.cc index 2f16fb2820..b16a45aaec 100644 --- a/libartbase/base/scoped_flock.cc +++ b/libartbase/base/scoped_flock.cc @@ -35,6 +35,14 @@ using android::base::StringPrintf; /* static */ ScopedFlock LockedFile::Open(const char* filename, int flags, bool block, std::string* error_msg) { +#ifdef _WIN32 + // TODO: implement file locking for Windows. + UNUSED(filename); + UNUSED(flags); + UNUSED(block); + *error_msg = "flock is unsupported on Windows"; + return nullptr; +#else while (true) { // NOTE: We don't check usage here because the ScopedFlock should *never* be // responsible for flushing its underlying FD. Its only purpose should be @@ -89,10 +97,19 @@ using android::base::StringPrintf; return ScopedFlock(new LockedFile(std::move((*file.get())))); } +#endif } ScopedFlock LockedFile::DupOf(const int fd, const std::string& path, const bool read_only_mode, std::string* error_msg) { +#ifdef _WIN32 + // TODO: implement file locking for Windows. + UNUSED(fd); + UNUSED(path); + UNUSED(read_only_mode); + *error_msg = "flock is unsupported on Windows."; + return nullptr; +#else // NOTE: We don't check usage here because the ScopedFlock should *never* be // responsible for flushing its underlying FD. Its only purpose should be // to acquire a lock, and the unlock / close in the corresponding @@ -112,9 +129,11 @@ ScopedFlock LockedFile::DupOf(const int fd, const std::string& path, } return locked_file; +#endif } void LockedFile::ReleaseLock() { +#ifndef _WIN32 if (this->Fd() != -1) { int flock_result = TEMP_FAILURE_RETRY(flock(this->Fd(), LOCK_UN)); if (flock_result != 0) { @@ -126,6 +145,7 @@ void LockedFile::ReleaseLock() { PLOG(WARNING) << "Unable to unlock file " << this->GetPath(); } } +#endif } } // namespace art diff --git a/libartbase/base/socket_peer_is_trusted.cc b/libartbase/base/socket_peer_is_trusted.cc index 440054eac6..3996d90b8b 100644 --- a/libartbase/base/socket_peer_is_trusted.cc +++ b/libartbase/base/socket_peer_is_trusted.cc @@ -16,8 +16,10 @@ #include "socket_peer_is_trusted.h" +#if !defined(_WIN32) #include <pwd.h> #include <sys/socket.h> +#endif #include <android-base/logging.h> diff --git a/libartbase/base/time_utils.cc b/libartbase/base/time_utils.cc index cb3024664b..aa6c987669 100644 --- a/libartbase/base/time_utils.cc +++ b/libartbase/base/time_utils.cc @@ -14,12 +14,14 @@ * limitations under the License. */ +#include "time_utils.h" + #include <inttypes.h> +#include <stdio.h> + #include <limits> #include <sstream> -#include "time_utils.h" - #include "android-base/stringprintf.h" #include "logging.h" @@ -30,6 +32,20 @@ namespace art { +namespace { + +#if !defined(__linux__) +int GetTimeOfDay(struct timeval* tv, struct timezone* tz) { +#ifdef _WIN32 + return mingw_gettimeofday(tv, tz); +#else + return gettimeofday(tv, tz); +#endif +} +#endif + +} // namespace + using android::base::StringPrintf; std::string PrettyDuration(uint64_t nano_duration, size_t max_fraction_digits) { @@ -117,7 +133,12 @@ std::string FormatDuration(uint64_t nano_duration, TimeUnit time_unit, std::string GetIsoDate() { time_t now = time(nullptr); tm tmbuf; +#ifdef _WIN32 + localtime_s(&tmbuf, &now); + tm* ptm = &tmbuf; +#else tm* ptm = localtime_r(&now, &tmbuf); +#endif return StringPrintf("%04d-%02d-%02d %02d:%02d:%02d", ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); @@ -130,7 +151,7 @@ uint64_t MilliTime() { return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_nsec / UINT64_C(1000000); #else timeval now; - gettimeofday(&now, nullptr); + GetTimeOfDay(&now, nullptr); return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_usec / UINT64_C(1000); #endif } @@ -142,7 +163,7 @@ uint64_t MicroTime() { return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000) + now.tv_nsec / UINT64_C(1000); #else timeval now; - gettimeofday(&now, nullptr); + GetTimeOfDay(&now, nullptr); return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000) + now.tv_usec; #endif } @@ -154,7 +175,7 @@ uint64_t NanoTime() { return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_nsec; #else timeval now; - gettimeofday(&now, nullptr); + GetTimeOfDay(&now, nullptr); return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_usec * UINT64_C(1000); #endif } @@ -195,12 +216,12 @@ void NanoSleep(uint64_t ns) { void InitTimeSpec(bool absolute, int clock, int64_t ms, int32_t ns, timespec* ts) { if (absolute) { -#if !defined(__APPLE__) +#if defined(__linux__) clock_gettime(clock, ts); #else UNUSED(clock); timeval tv; - gettimeofday(&tv, nullptr); + GetTimeOfDay(&tv, nullptr); ts->tv_sec = tv.tv_sec; ts->tv_nsec = tv.tv_usec * 1000; #endif diff --git a/libartbase/base/time_utils.h b/libartbase/base/time_utils.h index 431d3e19ac..15805f3f63 100644 --- a/libartbase/base/time_utils.h +++ b/libartbase/base/time_utils.h @@ -18,6 +18,7 @@ #define ART_LIBARTBASE_BASE_TIME_UTILS_H_ #include <stdint.h> +#include <stdio.h> // Needed for correct _WIN32 build. #include <time.h> #include <string> diff --git a/libartbase/base/unix_file/fd_file.cc b/libartbase/base/unix_file/fd_file.cc index 76894c6a8a..8831b9c6b7 100644 --- a/libartbase/base/unix_file/fd_file.cc +++ b/libartbase/base/unix_file/fd_file.cc @@ -25,8 +25,13 @@ #include <android/fdsan.h> #endif +#if defined(_WIN32) +#include <windows.h> +#endif + #include <limits> +#include <android-base/file.h> #include <android-base/logging.h> // Includes needed for FdFile::Copy(). @@ -40,6 +45,96 @@ namespace unix_file { +#if defined(_WIN32) +// RAII wrapper for an event object to allow asynchronous I/O to correctly signal completion. +class ScopedEvent { + public: + ScopedEvent() { + handle_ = CreateEventA(/*lpEventAttributes*/ nullptr, + /*bManualReset*/ true, + /*bInitialState*/ false, + /*lpName*/ nullptr); + } + + ~ScopedEvent() { CloseHandle(handle_); } + + HANDLE handle() { return handle_; } + + private: + HANDLE handle_; + DISALLOW_COPY_AND_ASSIGN(ScopedEvent); +}; + +// Windows implementation of pread/pwrite. Note that these DO move the file descriptor's read/write +// position, but do so atomically. +static ssize_t pread(int fd, void* data, size_t byte_count, off64_t offset) { + ScopedEvent event; + if (event.handle() == INVALID_HANDLE_VALUE) { + PLOG(ERROR) << "Could not create event handle."; + errno = EIO; + return static_cast<ssize_t>(-1); + } + + auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); + DWORD bytes_read = 0; + OVERLAPPED overlapped = {}; + overlapped.Offset = static_cast<DWORD>(offset); + overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32); + overlapped.hEvent = event.handle(); + if (!ReadFile(handle, data, static_cast<DWORD>(byte_count), &bytes_read, &overlapped)) { + // If the read failed with other than ERROR_IO_PENDING, return an error. + // ERROR_IO_PENDING signals the write was begun asynchronously. + // Block until the asynchronous operation has finished or fails, and return + // result accordingly. + if (::GetLastError() != ERROR_IO_PENDING || + !::GetOverlappedResult(handle, &overlapped, &bytes_read, TRUE)) { + // In case someone tries to read errno (since this is masquerading as a POSIX call). + errno = EIO; + return static_cast<ssize_t>(-1); + } + } + return static_cast<ssize_t>(bytes_read); +} + +static ssize_t pwrite(int fd, const void* buf, size_t count, off64_t offset) { + ScopedEvent event; + if (event.handle() == INVALID_HANDLE_VALUE) { + PLOG(ERROR) << "Could not create event handle."; + errno = EIO; + return static_cast<ssize_t>(-1); + } + + auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); + DWORD bytes_written = 0; + OVERLAPPED overlapped = {}; + overlapped.Offset = static_cast<DWORD>(offset); + overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32); + overlapped.hEvent = event.handle(); + if (!::WriteFile(handle, buf, count, &bytes_written, &overlapped)) { + // If the write failed with other than ERROR_IO_PENDING, return an error. + // ERROR_IO_PENDING signals the write was begun asynchronously. + // Block until the asynchronous operation has finished or fails, and return + // result accordingly. + if (::GetLastError() != ERROR_IO_PENDING || + !::GetOverlappedResult(handle, &overlapped, &bytes_written, TRUE)) { + // In case someone tries to read errno (since this is masquerading as a POSIX call). + errno = EIO; + return static_cast<ssize_t>(-1); + } + } + return static_cast<ssize_t>(bytes_written); +} + +static int fsync(int fd) { + auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); + if (handle != INVALID_HANDLE_VALUE && ::FlushFileBuffers(handle)) { + return 0; + } + errno = EINVAL; + return -1; +} +#endif + #if defined(__BIONIC__) static uint64_t GetFdFileOwnerTag(FdFile* fd_file) { return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_ART_FDFILE, diff --git a/libartbase/base/utils.cc b/libartbase/base/utils.cc index 0f172fdcfb..58d8575ea8 100644 --- a/libartbase/base/utils.cc +++ b/libartbase/base/utils.cc @@ -19,9 +19,7 @@ #include <inttypes.h> #include <pthread.h> #include <sys/stat.h> -#include <sys/syscall.h> #include <sys/types.h> -#include <sys/wait.h> #include <unistd.h> #include <fstream> @@ -47,6 +45,16 @@ #if defined(__linux__) #include <linux/unistd.h> +#include <sys/syscall.h> +#endif + +#if defined(_WIN32) +#include <windows.h> +// This include needs to be here due to our coding conventions. Unfortunately +// it drags in the definition of the dread ERROR macro. +#ifdef ERROR +#undef ERROR +#endif #endif namespace art { @@ -61,6 +69,8 @@ pid_t GetTid() { return owner; #elif defined(__BIONIC__) return gettid(); +#elif defined(_WIN32) + return static_cast<pid_t>(::GetCurrentThreadId()); #else return syscall(__NR_gettid); #endif @@ -68,12 +78,17 @@ pid_t GetTid() { std::string GetThreadName(pid_t tid) { std::string result; +#ifdef _WIN32 + UNUSED(tid); + result = "<unknown>"; +#else // TODO: make this less Linux-specific. if (ReadFileToString(StringPrintf("/proc/self/task/%d/comm", tid), &result)) { result.resize(result.size() - 1); // Lose the trailing '\n'. } else { result = "<unknown>"; } +#endif return result; } @@ -137,7 +152,7 @@ void SetThreadName(const char* thread_name) { } else { s = thread_name + len - 15; } -#if defined(__linux__) +#if defined(__linux__) || defined(_WIN32) // pthread_setname_np fails rather than truncating long strings. char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded in the kernel. strncpy(buf, s, sizeof(buf)-1); @@ -153,6 +168,11 @@ void SetThreadName(const char* thread_name) { void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) { *utime = *stime = *task_cpu = 0; +#ifdef _WIN32 + // TODO: implement this. + UNUSED(tid); + *state = 'S'; +#else std::string stats; // TODO: make this less Linux-specific. if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) { @@ -167,6 +187,7 @@ void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) *utime = strtoull(fields[11].c_str(), nullptr, 10); *stime = strtoull(fields[12].c_str(), nullptr, 10); *task_cpu = strtoull(fields[36].c_str(), nullptr, 10); +#endif } static void ParseStringAfterChar(const std::string& s, diff --git a/libartbase/base/zip_archive.cc b/libartbase/base/zip_archive.cc index a7f4b28c84..5056edc607 100644 --- a/libartbase/base/zip_archive.cc +++ b/libartbase/base/zip_archive.cc @@ -18,7 +18,6 @@ #include <fcntl.h> #include <stdio.h> -#include <sys/mman.h> // For the PROT_* and MAP_* constants. #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -27,6 +26,7 @@ #include "android-base/stringprintf.h" #include "ziparchive/zip_archive.h" +#include "base/mman.h" #include "bit_utils.h" #include "unix_file/fd_file.h" @@ -203,6 +203,11 @@ MemMap ZipEntry::MapDirectlyOrExtract(const char* zip_filename, } static void SetCloseOnExec(int fd) { +#ifdef _WIN32 + // Exec is not supported on Windows. + UNUSED(fd); + PLOG(ERROR) << "SetCloseOnExec is not supported on Windows."; +#else // This dance is more portable than Linux's O_CLOEXEC open(2) flag. int flags = fcntl(fd, F_GETFD); if (flags == -1) { @@ -214,6 +219,7 @@ static void SetCloseOnExec(int fd) { PLOG(WARNING) << "fcntl(" << fd << ", F_SETFD, " << flags << ") failed"; return; } +#endif } ZipArchive* ZipArchive::Open(const char* filename, std::string* error_msg) { diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp index 4d6aa5c8ac..a4f7e25128 100644 --- a/libdexfile/Android.bp +++ b/libdexfile/Android.bp @@ -43,30 +43,58 @@ cc_defaults { "libziparchive", "libz", ], + shared_libs: [ + // For MemMap. + "libartbase", + "liblog", + // For atrace. + "libcutils", + // For common macros. + "libbase", + ], + export_shared_lib_headers: [ + "libartbase", + "libbase", + ], }, - host: { + not_windows: { shared_libs: [ "libziparchive", "libz", + // For MemMap. + "libartbase", + "liblog", + // For atrace. + "libcutils", + // For common macros. + "libbase", + ], + export_shared_lib_headers: [ + "libartbase", + "libbase", ], }, + windows: { + static_libs: [ + "libziparchive", + "libz", + // For MemMap. + "libartbase", + "liblog", + // For atrace. + "libcutils", + // For common macros. + "libbase", + ], + export_static_lib_headers: [ + "libartbase", + "libbase", + ], + cflags: ["-Wno-thread-safety"], + }, }, generated_sources: ["dexfile_operator_srcs"], - shared_libs: [ - // For MemMap. - "libartbase", - "liblog", - // For atrace. - "libcutils", - // For common macros. - "libbase", - "libz", - ], export_include_dirs: ["."], - export_shared_lib_headers: [ - "libartbase", - "libbase", - ], } cc_defaults { @@ -121,6 +149,14 @@ art_cc_library { strip: { keep_symbols: true, }, + target: { + windows: { + enabled: true, + shared: { + enabled: false, + }, + }, + }, } art_cc_library { @@ -129,6 +165,14 @@ art_cc_library { "art_debug_defaults", "libdexfile_defaults", ], + target: { + windows: { + enabled: true, + shared: { + enabled: false, + }, + }, + }, } cc_library_headers { diff --git a/libdexfile/dex/art_dex_file_loader.cc b/libdexfile/dex/art_dex_file_loader.cc index ae1322d059..57e838fe5d 100644 --- a/libdexfile/dex/art_dex_file_loader.cc +++ b/libdexfile/dex/art_dex_file_loader.cc @@ -16,7 +16,6 @@ #include "art_dex_file_loader.h" -#include <sys/mman.h> // For the PROT_* and MAP_* constants. #include <sys/stat.h> #include "android-base/stringprintf.h" @@ -24,6 +23,7 @@ #include "base/file_magic.h" #include "base/file_utils.h" #include "base/mem_map.h" +#include "base/mman.h" // For the PROT_* and MAP_* constants. #include "base/stl_util.h" #include "base/systrace.h" #include "base/unix_file/fd_file.h" diff --git a/libdexfile/dex/dex_file_layout.cc b/libdexfile/dex/dex_file_layout.cc index 75a31112bb..929025a253 100644 --- a/libdexfile/dex/dex_file_layout.cc +++ b/libdexfile/dex/dex_file_layout.cc @@ -16,9 +16,9 @@ #include "dex_file_layout.h" -#include <sys/mman.h> #include "base/bit_utils.h" +#include "base/mman.h" #include "dex_file.h" namespace art { @@ -26,6 +26,12 @@ namespace art { int DexLayoutSection::MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice) { +#ifdef _WIN32 + UNUSED(begin); + UNUSED(end); + UNUSED(advice); + PLOG(WARNING) << "madvise is unsupported on Windows."; +#else DCHECK_LE(begin, end); begin = AlignUp(begin, kPageSize); end = AlignDown(end, kPageSize); @@ -37,6 +43,7 @@ int DexLayoutSection::MadviseLargestPageAlignedRegion(const uint8_t* begin, } return result; } +#endif return 0; } @@ -50,6 +57,11 @@ void DexLayoutSection::Subsection::Madvise(const DexFile* dex_file, int advice) } void DexLayoutSections::Madvise(const DexFile* dex_file, MadviseState state) const { +#ifdef _WIN32 + UNUSED(dex_file); + UNUSED(state); + PLOG(WARNING) << "madvise is unsupported on Windows."; +#else // The dex file is already defaulted to random access everywhere. for (const DexLayoutSection& section : sections_) { switch (state) { @@ -79,6 +91,7 @@ void DexLayoutSections::Madvise(const DexFile* dex_file, MadviseState state) con } } } +#endif } std::ostream& operator<<(std::ostream& os, const DexLayoutSection& section) { diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc index 1884bcf3f8..a719d4176b 100644 --- a/libdexfile/dex/dex_file_loader.cc +++ b/libdexfile/dex/dex_file_loader.cc @@ -187,12 +187,18 @@ std::string DexFileLoader::GetDexCanonicalLocation(const char* dex_location) { std::string base_location = GetBaseLocation(dex_location); const char* suffix = dex_location + base_location.size(); DCHECK(suffix[0] == 0 || suffix[0] == kMultiDexSeparator); +#ifdef _WIN32 + // Warning: No symbolic link processing here. + PLOG(WARNING) << "realpath is unsupported on Windows."; +#else // Warning: Bionic implementation of realpath() allocates > 12KB on the stack. // Do not run this code on a small stack, e.g. in signal handler. UniqueCPtr<const char[]> path(realpath(base_location.c_str(), nullptr)); if (path != nullptr && path.get() != base_location) { return std::string(path.get()) + suffix; - } else if (suffix[0] == 0) { + } +#endif + if (suffix[0] == 0) { return base_location; } else { return dex_location; |