Merge "[mips] Add missing linker shdr tests"
diff --git a/libc/Android.bp b/libc/Android.bp
index c706935..5bfc930 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -7,7 +7,6 @@
     "bionic/getpriority.c",
     "bionic/initgroups.c",
     "bionic/isatty.c",
-    "bionic/memmem.c",
     "bionic/pututline.c",
     "bionic/sched_cpualloc.c",
     "bionic/sched_cpucount.c",
@@ -40,6 +39,7 @@
     "-Wextra",
     "-Wunused",
     "-Wno-deprecated-declarations",
+    "-Wframe-larger-than=2048",
 
     // Try to catch typical 32-bit assumptions that break with 64-bit pointers.
     "-Werror=pointer-to-int-cast",
@@ -176,6 +176,7 @@
         "-DINET6",
         "-Wno-unused-parameter",
         "-include netbsd-compat.h",
+        "-Wframe-larger-than=66000",
     ],
 
     local_include_dirs: [
@@ -204,7 +205,6 @@
         "upstream-freebsd/lib/libc/stdlib/getopt_long.c",
         "upstream-freebsd/lib/libc/stdlib/qsort.c",
         "upstream-freebsd/lib/libc/stdlib/quick_exit.c",
-        "upstream-freebsd/lib/libc/stdlib/realpath.c",
         "upstream-freebsd/lib/libc/string/wcpcpy.c",
         "upstream-freebsd/lib/libc/string/wcpncpy.c",
         "upstream-freebsd/lib/libc/string/wcscasecmp.c",
@@ -275,6 +275,25 @@
     name: "libc_freebsd",
 }
 
+cc_library_static {
+    defaults: ["libc_defaults"],
+    srcs: [
+        "upstream-freebsd/lib/libc/stdlib/realpath.c",
+    ],
+
+    cflags: [
+        "-Wno-sign-compare",
+        "-include freebsd-compat.h",
+        "-Wframe-larger-than=15000",
+    ],
+
+    local_include_dirs: [
+        "upstream-freebsd/android/include",
+    ],
+
+    name: "libc_freebsd_large_stack",
+}
+
 // ========================================================
 // libc_netbsd.a - upstream NetBSD C library code
 // ========================================================
@@ -359,7 +378,6 @@
         "upstream-openbsd/lib/libc/gen/daemon.c",
         "upstream-openbsd/lib/libc/gen/err.c",
         "upstream-openbsd/lib/libc/gen/errx.c",
-        "upstream-openbsd/lib/libc/gen/exec.c",
         "upstream-openbsd/lib/libc/gen/fnmatch.c",
         "upstream-openbsd/lib/libc/gen/ftok.c",
         "upstream-openbsd/lib/libc/gen/getprogname.c",
@@ -435,10 +453,7 @@
         "upstream-openbsd/lib/libc/stdio/ungetwc.c",
         "upstream-openbsd/lib/libc/stdio/vasprintf.c",
         "upstream-openbsd/lib/libc/stdio/vdprintf.c",
-        "upstream-openbsd/lib/libc/stdio/vfprintf.c",
         "upstream-openbsd/lib/libc/stdio/vfscanf.c",
-        "upstream-openbsd/lib/libc/stdio/vfwprintf.c",
-        "upstream-openbsd/lib/libc/stdio/vfwscanf.c",
         "upstream-openbsd/lib/libc/stdio/vsscanf.c",
         "upstream-openbsd/lib/libc/stdio/vswprintf.c",
         "upstream-openbsd/lib/libc/stdio/vswscanf.c",
@@ -499,6 +514,29 @@
     ],
 }
 
+cc_library_static {
+    name: "libc_openbsd_large_stack",
+    defaults: ["libc_defaults"],
+    srcs: [
+        "upstream-openbsd/lib/libc/gen/exec.c",
+        "upstream-openbsd/lib/libc/stdio/vfprintf.c",
+        "upstream-openbsd/lib/libc/stdio/vfwprintf.c",
+        "upstream-openbsd/lib/libc/stdio/vfwscanf.c",
+    ],
+    cflags: [
+        "-include openbsd-compat.h",
+        "-Wno-sign-compare",
+        "-Wframe-larger-than=5000",
+    ],
+
+    local_include_dirs: [
+        "stdio",
+        "upstream-openbsd/android/include",
+        "upstream-openbsd/lib/libc/include",
+        "upstream-openbsd/lib/libc/gdtoa/",
+    ],
+}
+
 // ========================================================
 // libc_openbsd.a - upstream OpenBSD C library code
 // ========================================================
@@ -645,10 +683,7 @@
 
     local_include_dirs: [
         "private",
-        "stdio",
         "upstream-openbsd/android/include",
-        "upstream-openbsd/lib/libc/include",
-        "upstream-openbsd/lib/libc/gdtoa/",
     ],
 
     name: "libc_openbsd",
@@ -736,7 +771,6 @@
         "bionic/strnlen.c",
         "bionic/strrchr.cpp",
     ],
-    cflags: ["-Wframe-larger-than=2048"],
 
     arch: {
         arm: {
@@ -1245,6 +1279,7 @@
         "bionic/mbrtoc16.cpp",
         "bionic/mbrtoc32.cpp",
         "bionic/mbstate.cpp",
+        "bionic/memmem.cpp",
         "bionic/mempcpy.cpp",
         "bionic/mkdir.cpp",
         "bionic/mkfifo.cpp",
@@ -1330,7 +1365,6 @@
         "bionic/wctype.cpp",
         "bionic/wmempcpy.cpp",
     ],
-    cflags: ["-Wframe-larger-than=2048"],
 
     multilib: {
         lib32: {
@@ -1380,7 +1414,6 @@
         "bionic/pthread_sigmask.cpp",
         "bionic/pthread_spinlock.cpp",
     ],
-    cflags: ["-Wframe-larger-than=2048"],
 
     cppflags: ["-Wold-style-cast"],
     include_dirs: ["bionic/libstdc++/include"],
@@ -1475,9 +1508,11 @@
     whole_static_libs: [
         "libc_bionic_ndk",
         "libc_freebsd",
+        "libc_freebsd_large_stack",
         "libc_gdtoa",
         "libc_malloc",
         "libc_netbsd",
+        "libc_openbsd_large_stack",
         "libc_openbsd_ndk",
         "libc_stack_protector",
         "libc_syscalls",
@@ -1507,10 +1542,12 @@
         "libc_bionic_ndk",
         "libc_dns",
         "libc_freebsd",
+        "libc_freebsd_large_stack",
         "libc_gdtoa",
         "libc_malloc",
         "libc_netbsd",
         "libc_openbsd",
+        "libc_openbsd_large_stack",
         "libc_openbsd_ndk",
         "libc_pthread",
         "libc_stack_protector",
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 5188b6d..42c8f01 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -239,7 +239,7 @@
 # sockets
 int           __socket:socket(int, int, int)              arm,arm64,mips,mips64,x86_64
 int           socketpair(int, int, int, int*)    arm,arm64,mips,mips64,x86_64
-int           bind(int, struct sockaddr*, int)  arm,arm64,mips,mips64,x86_64
+int           bind(int, struct sockaddr*, socklen_t)  arm,arm64,mips,mips64,x86_64
 int           __connect:connect(int, struct sockaddr*, socklen_t)   arm,arm64,mips,mips64,x86_64
 int           listen(int, int)                   arm,arm64,mips,mips64,x86_64
 int           __accept4:accept4(int, struct sockaddr*, socklen_t*, int)  arm,arm64,mips,mips64,x86_64
@@ -250,8 +250,8 @@
 int           shutdown(int, int)  arm,arm64,mips,mips64,x86_64
 int           setsockopt(int, int, int, const void*, socklen_t)  arm,arm64,mips,mips64,x86_64
 int           getsockopt(int, int, int, void*, socklen_t*)    arm,arm64,mips,mips64,x86_64
-int           sendmsg(int, const struct msghdr*, unsigned int)  arm,arm64,mips,mips64,x86_64
-int           recvmsg(int, struct msghdr*, unsigned int)   arm,arm64,mips,mips64,x86_64
+ssize_t       recvmsg(int, struct msghdr*, unsigned int)   arm,arm64,mips,mips64,x86_64
+ssize_t       sendmsg(int, const struct msghdr*, unsigned int)  arm,arm64,mips,mips64,x86_64
 int           recvmmsg(int, struct mmsghdr*, unsigned int, int, const struct timespec*)   arm,arm64,mips,mips64,x86_64
 int           sendmmsg(int, struct mmsghdr*, unsigned int, int)   arm,arm64,mips,mips64,x86_64
 
diff --git a/libc/bionic/memmem.c b/libc/bionic/memmem.c
deleted file mode 100644
index e72501b..0000000
--- a/libc/bionic/memmem.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-/*
- * This uses the "Not So Naive" algorithm, a very simple but
- * usually effective algorithm, see:
- * http://www-igm.univ-mlv.fr/~lecroq/string/
- */
-#include <string.h>
-
-void *memmem(const void *haystack, size_t n, const void *needle, size_t m)
-{
-    if (m > n || !m || !n)
-        return NULL;
-
-    if (__builtin_expect((m > 1), 1)) {
-        const unsigned char*  y = (const unsigned char*) haystack;
-        const unsigned char*  x = (const unsigned char*) needle;
-        size_t                j = 0;
-        size_t                k = 1, l = 2;
-
-        if (x[0] == x[1]) {
-            k = 2;
-            l = 1;
-        }
-        while (j <= n-m) {
-            if (x[1] != y[j+1]) {
-                j += k;
-            } else {
-                if (!memcmp(x+2, y+j+2, m-2) && x[0] == y[j])
-                    return (void*) &y[j];
-                j += l;
-            }
-        }
-    } else {
-        /* degenerate case */
-        return memchr(haystack, ((unsigned char*)needle)[0], n);
-    }
-    return NULL;
-}
diff --git a/libc/bionic/memmem.cpp b/libc/bionic/memmem.cpp
new file mode 100644
index 0000000..61d681f
--- /dev/null
+++ b/libc/bionic/memmem.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+void* memmem(const void* void_haystack, size_t n, const void* void_needle, size_t m) {
+  const unsigned char* haystack = reinterpret_cast<const unsigned char*>(void_haystack);
+  const unsigned char* needle = reinterpret_cast<const unsigned char*>(void_needle);
+
+  if (n < m) return nullptr;
+
+  if (m == 0) return const_cast<void*>(void_haystack);
+  if (m == 1) return memchr(haystack, needle[0], n);
+
+  // This uses the "Not So Naive" algorithm, a very simple but usually effective algorithm.
+  // http://www-igm.univ-mlv.fr/~lecroq/string/
+  const unsigned char* y = haystack;
+  const unsigned char* x = needle;
+  size_t j = 0;
+  size_t k = 1, l = 2;
+
+  if (x[0] == x[1]) {
+    k = 2;
+    l = 1;
+  }
+  while (j <= n-m) {
+    if (x[1] != y[j+1]) {
+      j += k;
+    } else {
+      if (!memcmp(x+2, y+j+2, m-2) && x[0] == y[j]) return const_cast<unsigned char*>(&y[j]);
+      j += l;
+    }
+  }
+  return nullptr;
+}
diff --git a/libc/include/netdb.h b/libc/include/netdb.h
index 95f0986..816acc5 100644
--- a/libc/include/netdb.h
+++ b/libc/include/netdb.h
@@ -220,10 +220,11 @@
 void herror(const char*);
 const char* hstrerror(int);
 
-int getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **);
-int getnameinfo(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int);
-void freeaddrinfo(struct addrinfo *);
-const char	*gai_strerror(int);
+int getaddrinfo(const char*, const char*, const struct addrinfo*, struct addrinfo**);
+/* POSIX getnameinfo uses socklen_t, not size_t, but LP64 sizeof(socklen_t) != sizeof(size_t). */
+int getnameinfo(const struct sockaddr*, socklen_t, char*, size_t, char*, size_t, int);
+void freeaddrinfo(struct addrinfo*);
+const char* gai_strerror(int);
 void setservent(int);
 
 __END_DECLS
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index 934963f..79f1faf 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -57,8 +57,8 @@
 void* mmap64(void*, size_t, int, int, int, off64_t) __INTRODUCED_IN(21);
 
 int munmap(void*, size_t);
-int msync(const void*, size_t, int);
-int mprotect(const void*, size_t, int);
+int msync(void*, size_t, int);
+int mprotect(void*, size_t, int);
 void* mremap(void*, size_t, size_t, int, ...);
 
 int mlockall(int) __INTRODUCED_IN(17);
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index 6a275e4..910fee1 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -271,7 +271,7 @@
 
 __socketcall int accept(int, struct sockaddr*, socklen_t*);
 __socketcall int accept4(int, struct sockaddr*, socklen_t*, int) __INTRODUCED_IN(21);
-__socketcall int bind(int, const struct sockaddr*, int);
+__socketcall int bind(int, const struct sockaddr*, socklen_t);
 __socketcall int connect(int, const struct sockaddr*, socklen_t);
 __socketcall int getpeername(int, struct sockaddr*, socklen_t*);
 __socketcall int getsockname(int, struct sockaddr*, socklen_t*);
@@ -279,16 +279,16 @@
 __socketcall int listen(int, int);
 __socketcall int recvmmsg(int, struct mmsghdr*, unsigned int, int, const struct timespec*)
   __INTRODUCED_IN(21);
-__socketcall int recvmsg(int, struct msghdr*, int);
+__socketcall ssize_t recvmsg(int, struct msghdr*, int);
 __socketcall int sendmmsg(int, const struct mmsghdr*, unsigned int, int) __INTRODUCED_IN(21);
-__socketcall int sendmsg(int, const struct msghdr*, int);
+__socketcall ssize_t sendmsg(int, const struct msghdr*, int);
 __socketcall int setsockopt(int, int, int, const void*, socklen_t);
 __socketcall int shutdown(int, int);
 __socketcall int socket(int, int, int);
 __socketcall int socketpair(int, int, int, int*);
 
-ssize_t send(int, const void*, size_t, int);
 ssize_t recv(int, void*, size_t, int);
+ssize_t send(int, const void*, size_t, int);
 
 __socketcall ssize_t sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t);
 __socketcall ssize_t recvfrom(int, void*, size_t, int, struct sockaddr*, socklen_t*);
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index 775fb08..cc9dd91 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -141,6 +141,12 @@
 #define S_IEXEC S_IXUSR
 #endif
 
+/* POSIX mandates these, but Linux doesn't implement them as distinct file types. */
+#define S_TYPEISMQ(__sb) 0
+#define S_TYPEISSEM(__sb) 0
+#define S_TYPEISSHM(__sb) 0
+#define S_TYPEISTMO(__sb) 0
+
 int chmod(const char*, mode_t);
 int fchmod(int, mode_t);
 int mkdir(const char*, mode_t);
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 763d65c..385fe33 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -1455,3 +1455,32 @@
   }
   RunSingleBufferAlignTest(MEDIUM, DoMemcpySameTest);
 }
+
+TEST(STRING_TEST, memmem_strstr_empty_needle) {
+  const char* some_haystack = "haystack";
+  const char* empty_haystack = "";
+
+  ASSERT_EQ(some_haystack, memmem(some_haystack, 8, "", 0));
+  ASSERT_EQ(empty_haystack, memmem(empty_haystack, 0, "", 0));
+
+  ASSERT_EQ(some_haystack, strstr(some_haystack, ""));
+  ASSERT_EQ(empty_haystack, strstr(empty_haystack, ""));
+}
+
+TEST(STRING_TEST, memmem_smoke) {
+  const char haystack[] = "big\0daddy\0giant\0haystacks";
+  ASSERT_EQ(haystack, memmem(haystack, sizeof(haystack), "", 0));
+  ASSERT_EQ(haystack + 3, memmem(haystack, sizeof(haystack), "", 1));
+  ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "b", 1));
+  ASSERT_EQ(haystack + 1, memmem(haystack, sizeof(haystack), "i", 1));
+  ASSERT_EQ(haystack + 4, memmem(haystack, sizeof(haystack), "da", 2));
+  ASSERT_EQ(haystack + 8, memmem(haystack, sizeof(haystack), "y\0g", 3));
+}
+
+TEST(STRING_TEST, strstr_smoke) {
+  const char* haystack = "big daddy/giant haystacks";
+  ASSERT_EQ(haystack, strstr(haystack, ""));
+  ASSERT_EQ(haystack + 0, strstr(haystack, "b"));
+  ASSERT_EQ(haystack + 1, strstr(haystack, "i"));
+  ASSERT_EQ(haystack + 4, strstr(haystack, "da"));
+}