Build dexlist, dexlayout, and profman for Windows
Bug: 22322814
Test: wine on linux on a large dex file.
Change-Id: I93a89253799715de54e1c52213595b0749a5f47f
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index 24ee5f8..e914738 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -26,9 +26,33 @@
"dex_writer.cc",
],
export_include_dirs: ["."],
- shared_libs: [
- "libbase",
- ],
+ target: {
+ android: {
+ shared_libs: [
+ "libdexfile",
+ "libartbase",
+ "libprofile",
+ "libbase",
+ ],
+ },
+ not_windows: {
+ shared_libs: [
+ "libdexfile",
+ "libartbase",
+ "libprofile",
+ "libbase",
+ ],
+ },
+ windows: {
+ cflags: ["-Wno-thread-safety"],
+ static_libs: [
+ "libdexfile",
+ "libartbase",
+ "libprofile",
+ "libbase",
+ ],
+ },
+ },
static_libs: ["libz"],
}
@@ -46,18 +70,18 @@
"libart-dexlayout-defaults",
"dex2oat-pgo-defaults",
],
- shared_libs: [
- "libdexfile",
- "libartbase",
- "libprofile",
- ],
-
target: {
android: {
lto: {
thin: true,
},
},
+ windows: {
+ enabled: true,
+ shared: {
+ enabled: false,
+ },
+ },
},
}
@@ -118,6 +142,29 @@
}
art_cc_binary {
+ name: "dexlayouts",
+ defaults: [
+ "dexlayout-defaults",
+ "libart-dexlayout_static_defaults",
+ "libprofile_static_defaults",
+ "libdexfile_static_defaults",
+ "libartbase_static_defaults",
+ ],
+ srcs: ["dexlayout_main.cc"],
+ host_supported: true,
+ device_supported: false,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ windows: {
+ enabled: true,
+ cflags: ["-Wno-thread-safety"],
+ },
+ },
+}
+
+art_cc_binary {
name: "dexlayoutd",
defaults: [
"art_debug_defaults",
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 32122eb..ef2c9e4 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -24,7 +24,6 @@
#include <inttypes.h>
#include <stdio.h>
-#include <sys/mman.h> // For the PROT_* and MAP_* constants.
#include <iostream>
#include <memory>
@@ -36,6 +35,7 @@
#include "base/logging.h" // For VLOG_IS_ON.
#include "base/hiddenapi_flags.h"
#include "base/mem_map.h"
+#include "base/mman.h" // For the PROT_* and MAP_* constants.
#include "base/os.h"
#include "base/utils.h"
#include "dex/art_dex_file_loader.h"
diff --git a/dexlayout/dexlayout_main.cc b/dexlayout/dexlayout_main.cc
index 41b60da..2163f89 100644
--- a/dexlayout/dexlayout_main.cc
+++ b/dexlayout/dexlayout_main.cc
@@ -190,7 +190,12 @@
// Open profile file.
std::unique_ptr<ProfileCompilationInfo> profile_info;
if (options.profile_file_name_) {
- int profile_fd = open(options.profile_file_name_, O_RDONLY | O_CLOEXEC);
+#ifdef _WIN32
+ int flags = O_RDONLY;
+#else
+ int flags = O_RDONLY | O_CLOEXEC;
+#endif
+ int profile_fd = open(options.profile_file_name_, flags);
if (profile_fd < 0) {
PLOG(ERROR) << "Can't open " << options.profile_file_name_;
return 1;
@@ -201,6 +206,7 @@
return 1;
}
}
+ PLOG(INFO) << "After opening profile file";
// Create DexLayout instance.
DexLayout dex_layout(options, profile_info.get(), out_file, /*header=*/ nullptr);
diff --git a/dexlist/Android.bp b/dexlist/Android.bp
index 217a024..356791c 100644
--- a/dexlist/Android.bp
+++ b/dexlist/Android.bp
@@ -24,6 +24,26 @@
],
}
+art_cc_binary {
+ name: "dexlists",
+ defaults: [
+ "art_defaults",
+ "libartbase_static_defaults",
+ "libdexfile_static_defaults",
+ ],
+ host_supported: true,
+ srcs: ["dexlist.cc"],
+ device_supported: false,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ windows: {
+ enabled: true,
+ },
+ },
+}
+
art_cc_test {
name: "art_dexlist_tests",
defaults: [
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index 0fcd6a5..109853c 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -64,6 +64,7 @@
// For common macros.
"libbase",
],
+ export_shared_lib_headers: ["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.
@@ -82,12 +83,16 @@
// For common macros.
"libbase",
],
+ export_shared_lib_headers: ["libbase"],
},
linux_glibc: {
version_script: "libartbase.map",
},
windows: {
version_script: "libartbase.map",
+ srcs: [
+ "base/mem_map_windows.cc",
+ ],
static_libs: [
"libziparchive",
"libz",
@@ -97,6 +102,7 @@
// For common macros.
"libbase",
],
+ export_static_lib_headers: ["libbase"],
cflags: ["-Wno-thread-safety"],
},
},
@@ -115,7 +121,6 @@
// ART's macros.h depends on libbase's macros.h.
// Note: runtime_options.h depends on cmdline. But we don't really want to export this
// generically. dex2oat takes care of it itself.
- export_shared_lib_headers: ["libbase"],
}
cc_defaults {
diff --git a/libartbase/base/mem_map_windows.cc b/libartbase/base/mem_map_windows.cc
new file mode 100644
index 0000000..84e14ea
--- /dev/null
+++ b/libartbase/base/mem_map_windows.cc
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+#include "mem_map.h"
+
+#include <windows.h>
+
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+#include "android-base/mapped_file.h"
+#ifdef PROT_READ
+#undef PROT_READ
+#endif
+#ifdef PROT_WRITE
+#undef PROT_WRITE
+#endif
+#include "mman.h"
+
+namespace art {
+
+using android::base::MappedFile;
+using android::base::StringPrintf;
+
+static off_t allocation_granularity;
+
+void MemMap::TargetMMapInit() {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ allocation_granularity = si.dwAllocationGranularity;
+}
+
+void* MemMap::TargetMMap(void* start, size_t len, int prot, int flags, int fd, off_t fd_off) {
+ UNUSED(start);
+ size_t padding = fd_off % allocation_granularity;
+ off_t file_offset = fd_off - padding;
+ off_t map_length = len + padding;
+
+ // Only read and write permissions are supported.
+ if ((prot != PROT_READ) && (prot != (PROT_READ | PROT_WRITE))) {
+ PLOG(ERROR) << "Protection or flag error was not supported.";
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+ // Fixed is not currently supported either.
+ // TODO(sehr): add MAP_FIXED support.
+ if ((flags & MAP_FIXED) != 0) {
+ PLOG(ERROR) << "MAP_FIXED not supported.";
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+
+ // Compute the Windows access flags for the two APIs from the PROTs and MAPs.
+ DWORD map_access = 0;
+ DWORD view_access = 0;
+ if ((prot & PROT_WRITE) != 0) {
+ map_access = PAGE_READWRITE;
+ if (((flags & MAP_SHARED) != 0) && ((flags & MAP_PRIVATE) == 0)) {
+ view_access = FILE_MAP_ALL_ACCESS;
+ } else if (((flags & MAP_SHARED) == 0) && ((flags & MAP_PRIVATE) != 0)) {
+ view_access = FILE_MAP_COPY | FILE_MAP_READ;
+ } else {
+ PLOG(ERROR) << "MAP_PRIVATE and MAP_SHARED inconsistently set.";
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+ } else {
+ map_access = PAGE_READONLY;
+ view_access = FILE_MAP_READ;
+ }
+
+ // MapViewOfFile does not like to see a size greater than the file size of the
+ // underlying file object, unless the underlying file object is writable. If
+ // the mapped region would go beyond the end of the underlying file, use zero,
+ // as this indicates the physical size.
+ HANDLE file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+ LARGE_INTEGER file_length;
+ if (!::GetFileSizeEx(file_handle, &file_length)) {
+ PLOG(ERROR) << "Couldn't get file size.";
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+ if (((map_access & PAGE_READONLY) != 0) &&
+ file_offset + map_length > file_length.QuadPart) {
+ map_length = 0;
+ }
+
+ // Create a file mapping object that will be used to access the file.
+ HANDLE handle = ::CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd)),
+ nullptr,
+ map_access,
+ 0,
+ 0,
+ nullptr);
+ if (handle == nullptr) {
+ DWORD error = ::GetLastError();
+ PLOG(ERROR) << StringPrintf("Couldn't create file mapping %lx.", error);
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+
+ // Map the file into the process address space.
+ DWORD offset_low = static_cast<DWORD>(file_offset & 0xffffffffU);
+#ifdef _WIN64
+ DWORD offset_high = static_cast<DWORD>(file_offset >> 32);
+#else
+ DWORD offset_high = static_cast<DWORD>(0);
+#endif
+ void* view_address = MapViewOfFile(handle, view_access, offset_high, offset_low, map_length);
+ if (view_address == nullptr) {
+ DWORD error = ::GetLastError();
+ PLOG(ERROR) << StringPrintf("Couldn't create file view %lx.", error);
+ ::CloseHandle(handle);
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+
+ return view_address;
+}
+
+int MemMap::TargetMUnmap(void* start, size_t len) {
+ // TODO(sehr): implement unmap.
+ UNUSED(start);
+ UNUSED(len);
+ return 0;
+}
+
+} // namespace art
diff --git a/libartbase/base/mman.h b/libartbase/base/mman.h
index bd63f65..b56edfc 100644
--- a/libartbase/base/mman.h
+++ b/libartbase/base/mman.h
@@ -20,19 +20,18 @@
#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 PROT_READ 0x1
+#define PROT_WRITE 0x2
+#define PROT_EXEC 0x4
+#define PROT_NONE 0x0
-#define MAP_SHARED 0 // 0x01
-#define MAP_PRIVATE 0 // 0x02
+#define MAP_SHARED 0x01
+#define MAP_PRIVATE 0x02
-#define MAP_FAILED nullptr // ((void*) -1)
-#define MAP_FIXED 0 // 0x10
-#define MAP_ANONYMOUS 0 // 0x20
+#define MAP_FAILED ((void*) -1)
+#define MAP_FIXED 0x10
+#define MAP_ANONYMOUS 0x20
#else
diff --git a/libprofile/Android.bp b/libprofile/Android.bp
index a8d8b2f..fd32c5f 100644
--- a/libprofile/Android.bp
+++ b/libprofile/Android.bp
@@ -23,33 +23,55 @@
],
target: {
android: {
+ shared_libs: [
+ "libartbase",
+ "libdexfile",
+ "libartbase",
+ // For atrace.
+ "libcutils",
+ "libbase",
+ ],
static_libs: [
// ZipArchive support, the order matters here to get all symbols.
"libziparchive",
"libz",
],
+ export_shared_lib_headers: ["libbase"],
},
- host: {
+ not_windows: {
shared_libs: [
+ "libartbase",
+ "libdexfile",
+ "libartbase",
+ // For atrace.
+ "libcutils",
"libziparchive",
"libz",
+ "libbase",
],
+ export_shared_lib_headers: ["libbase"],
+ },
+ windows: {
+ cflags: ["-Wno-thread-safety"],
+ static_libs: [
+ "libartbase",
+ "libdexfile",
+ "libartbase",
+ // For atrace.
+ "libcutils",
+ "libziparchive",
+ "libz",
+ "libbase",
+ ],
+ export_static_lib_headers: ["libbase"],
},
},
//generated_sources: ["art_libartbase_operator_srcs"],
cflags: ["-DBUILDING_LIBART=1"],
- shared_libs: [
- "libartbase",
- "libdexfile",
- "libartbase",
- // For atrace.
- "libcutils",
- ],
export_include_dirs: ["."],
// ART's macros.h depends on libbase's macros.h.
// Note: runtime_options.h depends on cmdline. But we don't really want to export this
// generically. dex2oat takes care of it itself.
- export_shared_lib_headers: ["libbase"],
}
cc_defaults {
@@ -95,6 +117,14 @@
"libziparchive",
],
export_shared_lib_headers: ["libbase"],
+ target: {
+ windows: {
+ enabled: true,
+ shared: {
+ enabled: false,
+ },
+ },
+ }
}
art_cc_library {
diff --git a/libprofile/profile/profile_compilation_info.cc b/libprofile/profile/profile_compilation_info.cc
index 8b8569d..47b17ae 100644
--- a/libprofile/profile/profile_compilation_info.cc
+++ b/libprofile/profile/profile_compilation_info.cc
@@ -19,7 +19,6 @@
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <sys/uio.h>
#include <unistd.h>
#include <zlib.h>
@@ -208,7 +207,11 @@
bool ProfileCompilationInfo::MergeWith(const std::string& filename) {
std::string error;
+#ifdef _WIN32
+ int flags = O_RDONLY;
+#else
int flags = O_RDONLY | O_NOFOLLOW | O_CLOEXEC;
+#endif
ScopedFlock profile_file =
LockedFile::Open(filename.c_str(), flags, /*block=*/false, &error);
@@ -236,7 +239,11 @@
return kProfileLoadWouldOverwiteData;
}
+#ifdef _WIN32
+ int flags = O_RDWR;
+#else
int flags = O_RDWR | O_NOFOLLOW | O_CLOEXEC;
+#endif
// There's no need to fsync profile data right away. We get many chances
// to write it again in case something goes wrong. We can rely on a simple
// close(), no sync, and let to the kernel decide when to write to disk.
@@ -274,7 +281,11 @@
bool ProfileCompilationInfo::Save(const std::string& filename, uint64_t* bytes_written) {
ScopedTrace trace(__PRETTY_FUNCTION__);
std::string error;
+#ifdef _WIN32
+ int flags = O_WRONLY;
+#else
int flags = O_WRONLY | O_NOFOLLOW | O_CLOEXEC;
+#endif
// There's no need to fsync profile data right away. We get many chances
// to write it again in case something goes wrong. We can rely on a simple
// close(), no sync, and let to the kernel decide when to write to disk.
diff --git a/profman/Android.bp b/profman/Android.bp
index 89e1f7e..33cca02 100644
--- a/profman/Android.bp
+++ b/profman/Android.bp
@@ -40,7 +40,6 @@
name: "profman",
defaults: ["profman-defaults"],
shared_libs: [
- "libart",
"libprofile",
"libdexfile",
"libartbase",
@@ -54,13 +53,33 @@
"profman-defaults",
],
shared_libs: [
- "libartd",
"libprofiled",
"libdexfiled",
"libartbased",
],
}
+art_cc_binary {
+ name: "profmans",
+ defaults: [
+ "profman-defaults",
+ "libprofile_static_defaults",
+ "libdexfile_static_defaults",
+ "libartbase_static_defaults",
+ ],
+ host_supported: true,
+ device_supported: false,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ windows: {
+ enabled: true,
+ cflags: ["-Wno-thread-safety"],
+ },
+ },
+}
+
art_cc_test {
name: "art_profman_tests",
defaults: [
diff --git a/profman/profman.cc b/profman/profman.cc
index 88c5c4e..82d9df0 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -467,6 +467,10 @@
// The methods reads the links from /proc/self/fd/ to find the original apk paths
// and puts them in the dex_locations_ vector.
bool ComputeDexLocationsFromApkFds() {
+#ifdef _WIN32
+ PLOG(ERROR) << "ComputeDexLocationsFromApkFds is unsupported on Windows.";
+ return false;
+#else
// We can't use a char array of PATH_MAX size without exceeding the frame size.
// So we use a vector as the buffer for the path.
std::vector<char> buffer(PATH_MAX, 0);
@@ -482,11 +486,17 @@
dex_locations_.push_back(buffer.data());
}
return true;
+#endif
}
std::unique_ptr<const ProfileCompilationInfo> LoadProfile(const std::string& filename, int fd) {
if (!filename.empty()) {
- fd = open(filename.c_str(), O_RDWR | O_CLOEXEC);
+#ifdef _WIN32
+ int flags = O_RDWR;
+#else
+ int flags = O_RDWR | O_CLOEXEC;
+#endif
+ fd = open(filename.c_str(), flags);
if (fd < 0) {
LOG(ERROR) << "Cannot open " << filename << strerror(errno);
return nullptr;
@@ -650,7 +660,12 @@
bool GetClassNamesAndMethods(const std::string& profile_file,
std::vector<std::unique_ptr<const DexFile>>* dex_files,
std::set<std::string>* out_lines) {
- int fd = open(profile_file.c_str(), O_RDONLY | O_CLOEXEC);
+#ifdef _WIN32
+ int flags = O_RDONLY;
+#else
+ int flags = O_RDONLY | O_CLOEXEC;
+#endif
+ int fd = open(profile_file.c_str(), flags);
if (!FdIsValid(fd)) {
LOG(ERROR) << "Cannot open " << profile_file << strerror(errno);
return false;
@@ -1031,7 +1046,12 @@
int fd = reference_profile_file_fd_;
if (!FdIsValid(fd)) {
CHECK(!reference_profile_file_.empty());
- fd = open(reference_profile_file_.c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
+#ifdef _WIN32
+ int flags = O_CREAT | O_TRUNC | O_WRONLY;
+#else
+ int flags = O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC;
+#endif
+ fd = open(reference_profile_file_.c_str(), flags, 0644);
if (fd < 0) {
LOG(ERROR) << "Cannot open " << reference_profile_file_ << strerror(errno);
return kInvalidFd;
@@ -1164,9 +1184,12 @@
}
}
// ShouldGenerateTestProfile confirms !test_profile_.empty().
- int profile_test_fd = open(test_profile_.c_str(),
- O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC,
- 0644);
+#ifdef _WIN32
+ int flags = O_CREAT | O_TRUNC | O_WRONLY;
+#else
+ int flags = O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC;
+#endif
+ int profile_test_fd = open(test_profile_.c_str(), flags, 0644);
if (profile_test_fd < 0) {
LOG(ERROR) << "Cannot open " << test_profile_ << strerror(errno);
return -1;