Merge "Create PTHREAD_COND_INITIALIZER_MONOTONIC_NP"
diff --git a/libc/bionic/fortify.cpp b/libc/bionic/fortify.cpp
index 985d47f..944cfca 100644
--- a/libc/bionic/fortify.cpp
+++ b/libc/bionic/fortify.cpp
@@ -169,6 +169,12 @@
   return ppoll(fds, fd_count, timeout, mask);
 }
 
+int __ppoll64_chk(pollfd* fds, nfds_t fd_count, const timespec* timeout,
+                  const sigset64_t* mask, size_t fds_size) {
+  __check_pollfd_array("ppoll64", fds_size, fd_count);
+  return ppoll64(fds, fd_count, timeout, mask);
+}
+
 ssize_t __pread64_chk(int fd, void* buf, size_t count, off64_t offset, size_t buf_size) {
   __check_count("pread64", "count", count);
   __check_buffer_access("pread64", "write into", count, buf_size);
diff --git a/libc/include/bits/fortify/poll.h b/libc/include/bits/fortify/poll.h
index 8363e35..c3ae31d 100644
--- a/libc/include/bits/fortify/poll.h
+++ b/libc/include/bits/fortify/poll.h
@@ -31,8 +31,8 @@
 #endif
 
 int __poll_chk(struct pollfd*, nfds_t, int, size_t) __INTRODUCED_IN(23);
-int __ppoll_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*, size_t)
-  __INTRODUCED_IN(23);
+int __ppoll_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*, size_t) __INTRODUCED_IN(23);
+int __ppoll64_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset64_t*, size_t) __INTRODUCED_IN(28);
 
 #if defined(__BIONIC_FORTIFY)
 #if __ANDROID_API__ >= __ANDROID_API_M__
@@ -64,7 +64,24 @@
   }
   return __ppoll_chk(fds, fd_count, timeout, mask, bos_fds);
 }
-#else /* defined(__clang__) */
+
+#if __ANDROID_API__ >= __ANDROID_API_P__
+__BIONIC_FORTIFY_INLINE
+int ppoll64(struct pollfd* const fds __pass_object_size, nfds_t fd_count, const struct timespec* timeout, const sigset64_t* mask)
+    __overloadable
+    __clang_error_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                       __bos(fds) < sizeof(*fds) * fd_count,
+                     "in call to 'ppoll64', fd_count is larger than the given buffer") {
+  size_t bos_fds = __bos(fds);
+
+  if (bos_fds == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+    return __call_bypassing_fortify(ppoll64)(fds, fd_count, timeout, mask);
+  }
+  return __ppoll64_chk(fds, fd_count, timeout, mask, bos_fds);
+}
+#endif
+
+#else /* !defined(__clang__) */
 int __poll_real(struct pollfd*, nfds_t, int) __RENAME(poll);
 __errordecl(__poll_too_small_error, "poll: pollfd array smaller than fd count");
 
diff --git a/libc/include/bits/ioctl.h b/libc/include/bits/ioctl.h
index 0cf87d2..3357c1b 100644
--- a/libc/include/bits/ioctl.h
+++ b/libc/include/bits/ioctl.h
@@ -35,6 +35,28 @@
 
 int ioctl(int __fd, int __request, ...);
 
+/*
+ * Work around unsigned -> signed conversion warnings: many common ioctl
+ * constants are unsigned.
+ *
+ * Since this workaround introduces an overload to ioctl, it's possible that it
+ * will break existing code that takes the address of ioctl. If such a breakage
+ * occurs, you can work around it by either:
+ * - specifying a concrete, correct type for ioctl (whether it be through a cast
+ *   in `(int (*)(int, int, ...))ioctl`, creating a temporary variable with the
+ *   type of the ioctl you prefer, ...), or
+ * - defining BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD, which will make the
+ *   overloading go away.
+ *
+ * FIXME: __has_extension is more or less a clang version check. Remove it when
+ * we don't need to support old clang code.
+ */
+#if defined(__clang__) && __has_extension(overloadable_unmarked) && \
+  !defined(BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD)
+/* enable_if(1) just exists to break overloading ties. */
+int ioctl(int __fd, unsigned __request, ...) __overloadable __enable_if(1, "") __RENAME(ioctl);
+#endif
+
 __END_DECLS
 
 #endif
diff --git a/libc/include/elf.h b/libc/include/elf.h
index a8d62db..f5b2091 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -260,6 +260,8 @@
 #define DT_ANDROID_RELASZ (DT_LOOS + 5)
 
 #define DT_GNU_HASH 0x6ffffef5
+#define DT_TLSDESC_PLT 0x6ffffef6
+#define DT_TLSDESC_GOT 0x6ffffef7
 
 /* http://www.sco.com/developers/gabi/latest/ch4.eheader.html */
 #define EI_ABIVERSION 8
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index c270bb5..5760689 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -343,21 +343,7 @@
 #  define __BIONIC_INCLUDE_FORTIFY_HEADERS 1
 #endif
 
-/*
- * Used to support clangisms with FORTIFY. Because these change how symbols are
- * emitted, we need to ensure that bionic itself is built fortified. But lots
- * of external code (especially stuff using configure) likes to declare
- * functions directly, and they can't know that the overloadable attribute
- * exists. This leads to errors like:
- *
- * dcigettext.c:151:7: error: redeclaration of 'getcwd' must have the 'overloadable' attribute
- * char *getcwd ();
- *       ^
- *
- * To avoid this and keep such software building, don't use overloadable if
- * we're not using fortify.
- */
-#if defined(__clang__) && defined(__BIONIC_FORTIFY)
+#if defined(__clang__)
 #  define __overloadable __attribute__((overloadable))
 #else
 #  define __overloadable
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index b0f96a9..56e4189 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -115,6 +115,7 @@
     __poll_chk; # introduced=23
     __ppoll; # arm x86 mips introduced=21
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 6b0e415..880ed80 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -74,6 +74,7 @@
     __p_type_syms; # var
     __poll_chk; # introduced=23
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 85c9a58..b787ea5 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -115,6 +115,7 @@
     __poll_chk; # introduced=23
     __ppoll; # arm x86 mips introduced=21
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 9e760c2..ec3fe3a 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -112,6 +112,7 @@
     __poll_chk; # introduced=23
     __ppoll; # arm x86 mips introduced=21
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 6b0e415..880ed80 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -74,6 +74,7 @@
     __p_type_syms; # var
     __poll_chk; # introduced=23
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 2855f9e..9407b58 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -112,6 +112,7 @@
     __poll_chk; # introduced=23
     __ppoll; # arm x86 mips introduced=21
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 6b0e415..880ed80 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -74,6 +74,7 @@
     __p_type_syms; # var
     __poll_chk; # introduced=23
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/linker/linker.cpp b/linker/linker.cpp
index dd700fe..32df911 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -2784,6 +2784,11 @@
           }
         }
 #endif
+        if (ELF_ST_TYPE(s->st_info) == STT_TLS) {
+          DL_ERR("unsupported ELF TLS symbol \"%s\" referenced by \"%s\"",
+                 sym_name, get_realpath());
+          return false;
+        }
         sym_addr = lsi->resolve_symbol_address(s);
 #if !defined(__LP64__)
         if (protect_segments) {
@@ -3437,6 +3442,11 @@
 
       default:
         if (!relocating_linker) {
+          if (d->d_tag == DT_TLSDESC_GOT || d->d_tag == DT_TLSDESC_PLT) {
+            DL_ERR("unsupported ELF TLS DT entry in \"%s\"", get_realpath());
+            return false;
+          }
+
           const char* tag_name;
           if (d->d_tag == DT_RPATH) {
             tag_name = "DT_RPATH";
diff --git a/tests/Android.bp b/tests/Android.bp
index ec90296..eb3b5f4 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -48,6 +48,18 @@
 // All standard tests.
 // -----------------------------------------------------------------------------
 
+// Test diagnostics emitted by clang. The library that results is useless; we
+// just want to run '-Xclang -verify', which will fail if the diagnostics don't
+// match up with what the source file says they should be.
+cc_test_library {
+    name: "clang_diagnostic_tests",
+    cflags: [
+      "-Xclang",
+      "-verify",
+    ],
+    srcs: ["sys_ioctl_diag_test.cpp"],
+}
+
 cc_test_library {
     name: "libBionicStandardTests",
     defaults: ["bionic_tests_defaults"],
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 46f5097..84f525d 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1080,6 +1080,13 @@
   ASSERT_SUBSTR("libsysv-hash-table-library.so", dlinfo.dli_fname);
 }
 
+TEST(dlfcn, dlopen_library_with_ELF_TLS) {
+  dlerror(); // Clear any pending errors.
+  void* handle = dlopen("libelf-tls-library.so", RTLD_NOW);
+  ASSERT_TRUE(handle == nullptr);
+  ASSERT_SUBSTR("unsupported ELF TLS", dlerror());
+}
+
 TEST(dlfcn, dlopen_bad_flags) {
   dlerror(); // Clear any pending errors.
   void* handle;
diff --git a/tests/fortify_filecheck_diagnostics_test.cpp b/tests/fortify_filecheck_diagnostics_test.cpp
index c6198c6..375a156 100644
--- a/tests/fortify_filecheck_diagnostics_test.cpp
+++ b/tests/fortify_filecheck_diagnostics_test.cpp
@@ -278,7 +278,15 @@
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__ppoll_too_small_error' declared with attribute error: ppoll: pollfd array smaller than fd count
   // CLANG: error: in call to 'ppoll', fd_count is larger than the given buffer
-  ppoll(fds, 2, &timeout, NULL);
+  ppoll(fds, 2, &timeout, nullptr);
+}
+
+void test_ppoll64() {
+  pollfd fds[1];
+  timespec timeout;
+  // NOLINTNEXTLINE(whitespace/line_length)
+  // CLANG: error: in call to 'ppoll64', fd_count is larger than the given buffer
+  ppoll64(fds, 2, &timeout, nullptr);
 }
 
 void test_fread_overflow() {
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 67c124d..b5b858f 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -995,7 +995,18 @@
   // Set timeout to zero to prevent waiting in ppoll when fortify test fails.
   timespec timeout;
   timeout.tv_sec = timeout.tv_nsec = 0;
-  ASSERT_FORTIFY(ppoll(buf, fd_count, &timeout, NULL));
+  ASSERT_FORTIFY(ppoll(buf, fd_count, &timeout, nullptr));
+}
+
+TEST_F(DEATHTEST, ppoll64_fortified) {
+#if __BIONIC__ // glibc doesn't have ppoll64.
+  nfds_t fd_count = atoi("2"); // suppress compiler optimizations
+  pollfd buf[1] = {{0, POLLIN, 0}};
+  // Set timeout to zero to prevent waiting in ppoll when fortify test fails.
+  timespec timeout;
+  timeout.tv_sec = timeout.tv_nsec = 0;
+  ASSERT_FORTIFY(ppoll64(buf, fd_count, &timeout, nullptr));
+#endif
 }
 
 TEST_F(DEATHTEST, open_O_CREAT_without_mode_fortified) {
diff --git a/tests/gtest_main.cpp b/tests/gtest_main.cpp
index 6b20094..6f8c403 100644
--- a/tests/gtest_main.cpp
+++ b/tests/gtest_main.cpp
@@ -317,6 +317,12 @@
       line.pop_back();
       testcase_list.push_back(TestCase(line.c_str()));
     } else {
+      if (testcase_list.empty()) {
+        // Invalid response from gtest - likely it has been upset by an invalid --gtest_* flag.
+        // Relay the message to user.
+        fprintf(stderr, "%s", content.c_str());
+        return false;
+      }
       testcase_list.back().AppendTest(line.c_str());
     }
   }
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 3afda67..ae5f78a 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -40,6 +40,16 @@
 }
 
 // -----------------------------------------------------------------------------
+// Library to test ELF TLS
+// -----------------------------------------------------------------------------
+cc_test_library {
+    name: "libelf-tls-library",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["elf_tls_test_library.cpp"],
+    cflags: ["-fno-emulated-tls"],
+}
+
+// -----------------------------------------------------------------------------
 // Library to test gnu-styled hash
 // -----------------------------------------------------------------------------
 cc_test_library {
diff --git a/tests/libs/elf_tls_test_library.cpp b/tests/libs/elf_tls_test_library.cpp
new file mode 100644
index 0000000..56d0171
--- /dev/null
+++ b/tests/libs/elf_tls_test_library.cpp
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+thread_local int elf_tls_variable;
+
+extern "C" int* get() { return &elf_tls_variable; }
diff --git a/tests/sys_ioctl_diag_test.cpp b/tests/sys_ioctl_diag_test.cpp
new file mode 100644
index 0000000..e271e6c
--- /dev/null
+++ b/tests/sys_ioctl_diag_test.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+// This file makes uses of clang's built-in diagnostic checker.
+// While not officially supported by clang, it's used by clang for all of its
+// own diagnostic tests. Please see
+// https://clang.llvm.org/doxygen/classclang_1_1VerifyDiagnosticConsumer.html#details
+// for details.
+
+// expected-no-diagnostics
+
+#include <sys/ioctl.h>
+
+#pragma clang diagnostic warning "-Wsign-conversion"
+
+void check_no_signedness_warnings(int i, unsigned x) {
+  ioctl(i, i);
+  ioctl(i, x);
+
+  ioctl(i, i, nullptr);
+  ioctl(i, x, nullptr);
+}