Merge "Force _start to be the top frame for the linker."
diff --git a/docs/status.md b/docs/status.md
index 54d4c92..e6fb7a4 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -8,6 +8,7 @@
 
 New libc functions in P:
   * `__freading`/`__fwriting` (completing <stdio_ext.h>)
+  * `endhostent`/endnetent`/`endprotoent`/`getnetent`/`getprotoent`/`sethostent`/`setnetent`/`setprotoent` (completing <netdb.h>)
   * `getentropy`/`getrandom` (adding <sys/random.h>)
   * `getlogin_r`
   * `glob`/`globfree` (adding <glob.h>)
@@ -69,15 +70,10 @@
 aio_return
 aio_suspend
 aio_write
-endhostent
-endnetent
-endprotoent
 fexecve
 fmtmsg
 getdate
 getdate_err
-getnetent
-getprotoent
 lio_listio
 pthread_attr_getinheritsched
 pthread_attr_setinheritsched
@@ -95,9 +91,6 @@
 pthread_setcanceltype
 pthread_setschedprio
 pthread_testcancel
-sethostent
-setnetent
-setprotoent
 sockatmark
 swab
 wordexp
diff --git a/libc/Android.bp b/libc/Android.bp
index e37ae08..81135ea 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -21,7 +21,6 @@
     "stdio/stdio_ext.cpp",
     "stdio/vfscanf.c",
     "stdio/vfwscanf.c",
-    "stdlib/atexit.c",
     "stdlib/exit.c",
 ]
 
@@ -887,11 +886,6 @@
 cc_library_static {
     defaults: ["libc_defaults"],
     srcs: [
-        // The following implementations depend on pthread data, so we can't
-        // include them in libc_ndk.a.
-        "bionic/__cxa_thread_atexit_impl.cpp",
-        "bionic/fork.cpp",
-
         // The data that backs getauxval is initialized in the libc init
         // functions which are invoked by the linker. If this file is included
         // in libc_ndk.a, only one of the copies of the global data will be
@@ -1396,7 +1390,6 @@
         "bionic/__gnu_basename.cpp",
         "bionic/__libc_current_sigrtmax.cpp",
         "bionic/__libc_current_sigrtmin.cpp",
-        "bionic/__set_errno.cpp",
         "bionic/abort.cpp",
         "bionic/accept.cpp",
         "bionic/accept4.cpp",
@@ -1565,6 +1558,10 @@
         "bionic/wctype.cpp",
         "bionic/wcwidth.cpp",
         "bionic/wmempcpy.cpp",
+
+        // This contains a weak stub implementation of __find_icu_symbol for wctype.cpp,
+        // which will be overridden by the actual one in libc.so.
+        "bionic/icu_static.cpp",
     ],
 
     multilib: {
@@ -1619,6 +1616,12 @@
         "bionic/pthread_setschedparam.cpp",
         "bionic/pthread_sigmask.cpp",
         "bionic/pthread_spinlock.cpp",
+
+        // The following implementations depend on pthread data or implementation,
+        // so we can't include them in libc_ndk.a.
+        "bionic/__cxa_thread_atexit_impl.cpp",
+        "stdlib/atexit.c",
+        "bionic/fork.cpp",
     ],
 
     cppflags: ["-Wold-style-cast"],
@@ -1632,6 +1635,7 @@
 
 cc_library_static {
     defaults: ["libc_defaults"],
+    srcs: ["bionic/__set_errno.cpp"],
     arch: {
         arm: {
             srcs: ["arch-arm/syscalls/**/*.S"],
@@ -1731,9 +1735,8 @@
 }
 
 // ========================================================
-// libc_common.a
+// libc_nopthread.a
 // ========================================================
-
 cc_library_static {
     defaults: ["libc_defaults"],
     srcs: libc_common_src_files,
@@ -1742,7 +1745,7 @@
             srcs: libc_common_src_files_32,
         },
     },
-    name: "libc_common",
+    name: "libc_nopthread",
 
     whole_static_libs: [
         "libc_bionic",
@@ -1757,7 +1760,6 @@
         "libc_openbsd",
         "libc_openbsd_large_stack",
         "libc_openbsd_ndk",
-        "libc_pthread",
         "libc_stack_protector",
         "libc_syscalls",
         "libc_tzcode",
@@ -1772,6 +1774,20 @@
 }
 
 // ========================================================
+// libc_common.a
+// ========================================================
+
+cc_library_static {
+    defaults: ["libc_defaults"],
+    name: "libc_common",
+
+    whole_static_libs: [
+        "libc_nopthread",
+        "libc_pthread",
+    ],
+}
+
+// ========================================================
 // libc_nomalloc.a
 // ========================================================
 //
@@ -1825,7 +1841,6 @@
     static: {
         srcs: [
             "bionic/dl_iterate_phdr_static.cpp",
-            "bionic/icu_static.cpp",
             "bionic/malloc_common.cpp",
         ],
         cflags: ["-DLIBC_STATIC"],
diff --git a/libc/NOTICE b/libc/NOTICE
index 9b461ee..c0e6265 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -4014,42 +4014,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2004 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Christos Zoulas.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-       This product includes software developed by the NetBSD
-       Foundation, Inc. and its contributors.
-4. Neither the name of The NetBSD Foundation nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
--------------------------------------------------------------------
-
 Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
 Copyright (c) 1995,1999 by Internet Software Consortium.
 
diff --git a/libc/arch-mips64/include b/libc/arch-mips64/include
deleted file mode 120000
index fabbe8a..0000000
--- a/libc/arch-mips64/include
+++ /dev/null
@@ -1 +0,0 @@
-../arch-mips/include
\ No newline at end of file
diff --git a/libc/async_safe/include/async_safe/log.h b/libc/async_safe/include/async_safe/log.h
index 2f54742..10833e4 100644
--- a/libc/async_safe/include/async_safe/log.h
+++ b/libc/async_safe/include/async_safe/log.h
@@ -92,7 +92,7 @@
 
 int async_safe_format_fd(int fd, const char* format , ...) __printflike(2, 3);
 int async_safe_format_log(int pri, const char* tag, const char* fmt, ...) __printflike(3, 4);
-int async_safe_format_log_va_list( int pri, const char* tag, const char* fmt, va_list ap);
+int async_safe_format_log_va_list(int pri, const char* tag, const char* fmt, va_list ap);
 int async_safe_write_log(int pri, const char* tag, const char* msg);
 
 #define CHECK(predicate) \
diff --git a/libc/bionic/icu_static.cpp b/libc/bionic/icu_static.cpp
index cf24a38..e81e291 100644
--- a/libc/bionic/icu_static.cpp
+++ b/libc/bionic/icu_static.cpp
@@ -29,6 +29,6 @@
 #include "private/icu.h"
 
 // We don't have dlopen/dlsym for static binaries yet.
-void* __find_icu_symbol(const char*) {
+__attribute__((weak)) void* __find_icu_symbol(const char*) {
   return nullptr;
 }
diff --git a/libc/bionic/netdb.cpp b/libc/bionic/netdb.cpp
index da61f98..dc2a037 100644
--- a/libc/bionic/netdb.cpp
+++ b/libc/bionic/netdb.cpp
@@ -28,22 +28,40 @@
 
 #include <netdb.h>
 
-// We don't have an /etc/networks, so all inputs return NULL.
-netent* getnetbyname(const char* /*name*/) {
-  return NULL;
+// We don't have an /etc/networks or /etc/protocols, so these are just dummies.
+
+void endnetent() {
 }
 
-// We don't have an /etc/networks, so all inputs return NULL.
+void endprotoent() {
+}
+
 netent* getnetbyaddr(uint32_t /*net*/, int /*type*/) {
-  return NULL;
+  return nullptr;
 }
 
-// We don't have an /etc/protocols, so all inputs return NULL.
+netent* getnetbyname(const char* /*name*/) {
+  return nullptr;
+}
+
+netent* getnetent() {
+  return nullptr;
+}
+
 protoent* getprotobyname(const char* /*name*/) {
-  return NULL;
+  return nullptr;
 }
 
-// We don't have an /etc/protocols, so all inputs return NULL.
 protoent* getprotobynumber(int /*proto*/) {
-  return NULL;
+  return nullptr;
+}
+
+protoent* getprotoent() {
+  return nullptr;
+}
+
+void setnetent(int /*stayopen*/) {
+}
+
+void setprotoent(int /*stayopen*/) {
 }
diff --git a/libc/dns/net/getservbyname.c b/libc/dns/net/getservbyname.c
deleted file mode 100644
index c32416c..0000000
--- a/libc/dns/net/getservbyname.c
+++ /dev/null
@@ -1,43 +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.
- */
-
-#include <netdb.h>
-
-#include "servent.h"
-
-struct servent* getservbyname(const char* name, const char* proto) {
-  res_static rs = __res_get_static();
-  rs->servent_ptr = NULL;
-  struct servent* s;
-  while ((s = getservent_r(rs)) != NULL) {
-    if (strcmp(s->s_name, name) == 0 && (proto == NULL || strcmp(s->s_proto, proto) == 0)) {
-      return s;
-    }
-  }
-  return NULL;
-}
diff --git a/libc/dns/net/getservbyport.c b/libc/dns/net/getservbyport.c
deleted file mode 100644
index 7dcaafb..0000000
--- a/libc/dns/net/getservbyport.c
+++ /dev/null
@@ -1,52 +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.
- */
-#include <sys/cdefs.h>
-#include <netdb.h>
-#include "servent.h"
-
-struct servent *
-getservbyport(int port, const char *proto)
-{
-    res_static       rs = __res_get_static();
-
-    if (rs == NULL || proto == NULL) {
-        errno = EINVAL;
-        return NULL;
-    }
-
-    rs->servent_ptr = NULL;
-    while (1) {
-        struct servent*  s = getservent_r(rs);
-        if (s == NULL)
-            break;
-        if ( s->s_port == port && !strcmp( s->s_proto, proto ) )
-            return s;
-    }
-
-    return NULL;
-}
diff --git a/libc/dns/net/getservent.c b/libc/dns/net/getservent.c
index 0a727c7..03add59 100644
--- a/libc/dns/net/getservent.c
+++ b/libc/dns/net/getservent.c
@@ -25,32 +25,17 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <sys/cdefs.h>
-#include <sys/types.h>
-#include <endian.h>
-#include <malloc.h>
+
 #include <netdb.h>
-#include "servent.h"
+
+#include <endian.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "resolv_static.h"
 #include "services.h"
 
-void
-setservent(int f)
-{
-    res_static  rs = __res_get_static();
-    if (rs) {
-        rs->servent_ptr = NULL;
-    }
-}
-
-void
-endservent(void)
-{
-    /* nothing to do */
-}
-
-struct servent *
-getservent_r( res_static  rs )
-{
+struct servent* getservent_r(res_static rs) {
     const char*  p;
     const char*  q;
     int          namelen;
@@ -119,12 +104,48 @@
     return &rs->servent;
 }
 
-struct servent *
-getservent(void)
-{
-    res_static   rs = __res_get_static();
+void setservent(int stayopen) {
+  endservent();
+}
 
-    if (rs == NULL) return NULL;
+void endservent(void) {
+  res_static rs = __res_get_static();
+  if (rs) rs->servent_ptr = NULL;
+}
 
-    return getservent_r(rs);
+struct servent* getservent(void) {
+  res_static rs = __res_get_static();
+  return rs ? getservent_r(rs) : NULL;
+}
+
+struct servent* getservbyname(const char* name, const char* proto) {
+  res_static rs = __res_get_static();
+  if (rs == NULL) return NULL;
+
+  const char* old_servent_ptr = rs->servent_ptr;
+  rs->servent_ptr = NULL;
+  struct servent* s;
+  while ((s = getservent_r(rs)) != NULL) {
+    if (strcmp(s->s_name, name) == 0 && (proto == NULL || strcmp(s->s_proto, proto) == 0)) {
+      break;
+    }
+  }
+  rs->servent_ptr = old_servent_ptr;
+  return s;
+}
+
+struct servent* getservbyport(int port, const char* proto) {
+  res_static rs = __res_get_static();
+  if (rs == NULL) return NULL;
+
+  const char* old_servent_ptr = rs->servent_ptr;
+  rs->servent_ptr = NULL;
+  struct servent* s;
+  while ((s = getservent_r(rs)) != NULL) {
+    if (s->s_port == port && (proto == NULL || strcmp(s->s_proto, proto) == 0)) {
+      break;
+    }
+  }
+  rs->servent_ptr = old_servent_ptr;
+  return s;
 }
diff --git a/libc/dns/net/servent.h b/libc/dns/net/servent.h
deleted file mode 100644
index 822b375..0000000
--- a/libc/dns/net/servent.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*	$NetBSD: servent.h,v 1.1 2005/04/18 19:39:45 kleink Exp $	*/
-
-/*-
- * Copyright (c) 2004 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Christos Zoulas.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include "resolv_static.h"
-
-struct servent*  getservent_r(res_static rs);
diff --git a/libc/dns/net/sethostent.c b/libc/dns/net/sethostent.c
index 916421e..66c305f 100644
--- a/libc/dns/net/sethostent.c
+++ b/libc/dns/net/sethostent.c
@@ -64,13 +64,26 @@
 
 static struct hostent *_hf_gethtbyname2(const char *, int, struct getnamaddr *);
 
-static const char *_h_hosts = _PATH_HOSTS;
+void
+/*ARGSUSED*/
+sethostent(int stayopen)
+{
+	res_static rs = __res_get_static();
+	if (rs) sethostent_r(&rs->hostf);
+}
+
+void
+endhostent(void)
+{
+	res_static rs = __res_get_static();
+	if (rs) endhostent_r(&rs->hostf);
+}
 
 void
 sethostent_r(FILE **hf)
 {
 	if (!*hf)
-		*hf = fopen(_h_hosts, "re");
+		*hf = fopen(_PATH_HOSTS, "re");
 	else
 		rewind(*hf);
 }
@@ -116,15 +129,13 @@
 	hp = _hf_gethtbyname2(name, af, info);
 #endif
 	if (hp == NULL) {
-		if (*info->he == NETDB_INTERNAL && errno == ENOSPC) {
-			return NS_UNAVAIL;
-		}
+		*info->he = HOST_NOT_FOUND;
 		return NS_NOTFOUND;
 	}
 	return NS_SUCCESS;
 }
 
-static struct hostent *
+struct hostent *
 _hf_gethtbyname2(const char *name, int af, struct getnamaddr *info)
 {
 	struct hostent *hp, hent;
@@ -145,7 +156,6 @@
 	}
 
 	if ((ptr = buf = malloc(len = info->buflen)) == NULL) {
-		endhostent_r(&hf);
 		*info->he = NETDB_INTERNAL;
 		return NULL;
 	}
@@ -161,12 +171,8 @@
 
 		hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen,
 		    info->he);
-		if (hp == NULL) {
-			if (*info->he == NETDB_INTERNAL && errno == ENOSPC) {
-				goto nospc;
-			}
+		if (hp == NULL)
 			break;
-		}
 
 		if (strcasecmp(hp->h_name, name) != 0) {
 			char **cp;
@@ -230,7 +236,6 @@
 	free(buf);
 	return hp;
 nospc:
-	endhostent_r(&hf);
 	*info->he = NETDB_INTERNAL;
 	free(buf);
 	errno = ENOSPC;
@@ -265,9 +270,6 @@
 	endhostent_r(&hf);
 
 	if (hp == NULL) {
-		if (errno == ENOSPC) {
-			return NS_UNAVAIL;
-		}
 		*info->he = HOST_NOT_FOUND;
 		return NS_NOTFOUND;
 	}
diff --git a/libc/include/netdb.h b/libc/include/netdb.h
index 66ec8e3..4ee0ce2 100644
--- a/libc/include/netdb.h
+++ b/libc/include/netdb.h
@@ -196,31 +196,47 @@
 
 __BEGIN_DECLS
 
+int getaddrinfo(const char* __node, const char* __service, const struct addrinfo* __hints, struct addrinfo** __result);
+void freeaddrinfo(struct addrinfo* __ptr);
+
+/* Android ABI error: POSIX getnameinfo(3) uses socklen_t rather than size_t. */
+int getnameinfo(const struct sockaddr* __sa, socklen_t __sa_length, char* __host, size_t __host_length, char* __service, size_t __service_length, int __flags);
+const char* gai_strerror(int __error);
+
+/* These functions are obsolete. Use getaddrinfo/getnameinfo instead. */
 #define h_errno (*__get_h_errno())
 int* __get_h_errno(void);
-void endservent(void);
+void herror(const char* __s);
+const char* hstrerror(int __error);
 struct hostent* gethostbyaddr(const void* __addr, socklen_t __length, int __type);
 int gethostbyaddr_r(const void* __addr, socklen_t __length, int __type, struct hostent* __ret, char* __buf, size_t __buf_size, struct hostent** __result, int* __h_errno_ptr) __INTRODUCED_IN(23);
 struct hostent* gethostbyname(const char* __name);
 int gethostbyname_r(const char* __name, struct hostent* __ret, char* __buf, size_t __buf_size, struct hostent** __result, int* __h_errno_ptr);
 struct hostent* gethostbyname2(const char* __name, int __af);
 int gethostbyname2_r(const char* __name, int __af, struct hostent* __ret, char* __buf, size_t __buf_size, struct hostent** __result, int* __h_errno_ptr) __INTRODUCED_IN(23);
+void endhostent(void) __INTRODUCED_IN_FUTURE;
 struct hostent* gethostent(void);
+void sethostent(int __stay_open) __INTRODUCED_IN_FUTURE;
+
+/* These functions are obsolete. None of these functions return anything but nullptr. */
+void endnetent(void) __INTRODUCED_IN_FUTURE;
 struct netent* getnetbyaddr(uint32_t __net, int __type);
 struct netent* getnetbyname(const char* __name);
+struct netent* getnetent(void) __INTRODUCED_IN_FUTURE;
+void setnetent(int __stay_open) __INTRODUCED_IN_FUTURE;
+
+/* None of these functions return anything but nullptr. */
+void endprotoent(void) __INTRODUCED_IN_FUTURE;
 struct protoent* getprotobyname(const char* __name);
 struct protoent* getprotobynumber(int __proto);
-struct servent* getservbyname(const char* __name, const char* __proto);
-struct servent* getservbyport(int __port, const char* __proto);
-struct servent* getservent(void);
-void herror(const char* __s);
-const char* hstrerror(int __error);
+struct protoent* getprotoent(void) __INTRODUCED_IN_FUTURE;
+void setprotoent(int __stay_open) __INTRODUCED_IN_FUTURE;
 
-int getaddrinfo(const char* __node, const char* __service, const struct addrinfo* __hints, struct addrinfo** __result);
-/* POSIX getnameinfo uses socklen_t, not size_t, but LP64 sizeof(socklen_t) != sizeof(size_t). */
-int getnameinfo(const struct sockaddr* __sa, socklen_t __sa_length, char* __host, size_t __host_length, char* __service, size_t __service_length, int __flags);
-void freeaddrinfo(struct addrinfo* __ptr);
-const char* gai_strerror(int __error);
+/* These functions return entries from a built-in database. */
+void endservent(void);
+struct servent* getservbyname(const char* __name, const char* __proto);
+struct servent* getservbyport(int __port_in_network_order, const char* __proto);
+struct servent* getservent(void);
 void setservent(int __stay_open);
 
 __END_DECLS
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 08ba59f..82d6872 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1322,7 +1322,12 @@
   global:
     __freading;
     __fwriting;
+    endhostent;
+    endnetent;
+    endprotoent;
     getentropy;
+    getnetent;
+    getprotoent;
     getrandom;
     getlogin_r;
     glob;
@@ -1357,6 +1362,9 @@
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    sethostent;
+    setnetent;
+    setprotoent;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 400c95f..5dfe93b 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1242,7 +1242,12 @@
   global:
     __freading;
     __fwriting;
+    endhostent;
+    endnetent;
+    endprotoent;
     getentropy;
+    getnetent;
+    getprotoent;
     getrandom;
     getlogin_r;
     glob;
@@ -1277,6 +1282,9 @@
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    sethostent;
+    setnetent;
+    setprotoent;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index eb5c1e4..8f7b599 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1347,7 +1347,12 @@
   global:
     __freading;
     __fwriting;
+    endhostent;
+    endnetent;
+    endprotoent;
     getentropy;
+    getnetent;
+    getprotoent;
     getrandom;
     getlogin_r;
     glob;
@@ -1382,6 +1387,9 @@
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    sethostent;
+    setnetent;
+    setprotoent;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 16f1209..3a039c5 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1306,7 +1306,12 @@
   global:
     __freading;
     __fwriting;
+    endhostent;
+    endnetent;
+    endprotoent;
     getentropy;
+    getnetent;
+    getprotoent;
     getrandom;
     getlogin_r;
     glob;
@@ -1341,6 +1346,9 @@
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    sethostent;
+    setnetent;
+    setprotoent;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 400c95f..5dfe93b 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1242,7 +1242,12 @@
   global:
     __freading;
     __fwriting;
+    endhostent;
+    endnetent;
+    endprotoent;
     getentropy;
+    getnetent;
+    getprotoent;
     getrandom;
     getlogin_r;
     glob;
@@ -1277,6 +1282,9 @@
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    sethostent;
+    setnetent;
+    setprotoent;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 94ee319..2b165cc 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1304,7 +1304,12 @@
   global:
     __freading;
     __fwriting;
+    endhostent;
+    endnetent;
+    endprotoent;
     getentropy;
+    getnetent;
+    getprotoent;
     getrandom;
     getlogin_r;
     glob;
@@ -1339,6 +1344,9 @@
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    sethostent;
+    setnetent;
+    setprotoent;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 400c95f..5dfe93b 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1242,7 +1242,12 @@
   global:
     __freading;
     __fwriting;
+    endhostent;
+    endnetent;
+    endprotoent;
     getentropy;
+    getnetent;
+    getprotoent;
     getrandom;
     getlogin_r;
     glob;
@@ -1277,6 +1282,9 @@
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    sethostent;
+    setnetent;
+    setprotoent;
     syncfs;
 } LIBC_O;
 
diff --git a/tests/BionicDeathTest.h b/tests/BionicDeathTest.h
index 31d2d6e..3e8d7b2 100644
--- a/tests/BionicDeathTest.h
+++ b/tests/BionicDeathTest.h
@@ -17,25 +17,29 @@
 #ifndef BIONIC_TESTS_BIONIC_DEATH_TEST_H_
 #define BIONIC_TESTS_BIONIC_DEATH_TEST_H_
 
-#include <gtest/gtest.h>
+#include <signal.h>
 
-#include <sys/prctl.h>
+#include <gtest/gtest.h>
 
 class BionicDeathTest : public testing::Test {
  protected:
   virtual void SetUp() {
     // Suppress debuggerd stack traces. Too slow.
-    old_dumpable_ = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
-    prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
-    ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+    for (int signo : { SIGABRT, SIGBUS, SIGSEGV, SIGSYS }) {
+      struct sigaction action = {};
+      action.sa_handler = SIG_DFL;
+      sigaction(signo, &action, &previous_);
+    }
   }
 
   virtual void TearDown() {
-    prctl(PR_SET_DUMPABLE, old_dumpable_, 0, 0, 0, 0);
+    for (int signo : { SIGABRT, SIGBUS, SIGSEGV, SIGSYS }) {
+      sigaction(signo, &previous_, nullptr);
+    }
   }
 
  private:
-  int old_dumpable_;
+  struct sigaction previous_;
 };
 
 #endif // BIONIC_TESTS_BIONIC_DEATH_TEST_H_
diff --git a/tests/netdb_test.cpp b/tests/netdb_test.cpp
index a35f703..e699701 100644
--- a/tests/netdb_test.cpp
+++ b/tests/netdb_test.cpp
@@ -298,24 +298,152 @@
 
 TEST(netdb, getservbyname) {
   // smtp is TCP-only, so we know we'll get 25/tcp back.
-  servent* s = getservbyname("smtp", NULL);
-  ASSERT_TRUE(s != NULL);
+  servent* s = getservbyname("smtp", nullptr);
+  ASSERT_TRUE(s != nullptr);
+  ASSERT_STREQ("smtp", s->s_name);
   ASSERT_EQ(25, ntohs(s->s_port));
   ASSERT_STREQ("tcp", s->s_proto);
 
   // We get the same result by explicitly asking for tcp.
   s = getservbyname("smtp", "tcp");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_TRUE(s != nullptr);
+  ASSERT_STREQ("smtp", s->s_name);
   ASSERT_EQ(25, ntohs(s->s_port));
   ASSERT_STREQ("tcp", s->s_proto);
 
   // And we get a failure if we explicitly ask for udp.
   s = getservbyname("smtp", "udp");
-  ASSERT_TRUE(s == NULL);
+  ASSERT_TRUE(s == nullptr);
 
   // But there are actually udp services.
   s = getservbyname("echo", "udp");
-  ASSERT_TRUE(s != NULL);
+  ASSERT_TRUE(s != nullptr);
+  ASSERT_STREQ("echo", s->s_name);
   ASSERT_EQ(7, ntohs(s->s_port));
   ASSERT_STREQ("udp", s->s_proto);
 }
+
+TEST(netdb, getservbyport) {
+  // smtp is TCP-only, so we know we'll get 25/tcp back.
+  servent* s = getservbyport(htons(25), nullptr);
+  ASSERT_TRUE(s != nullptr);
+  ASSERT_STREQ("smtp", s->s_name);
+  ASSERT_EQ(25, ntohs(s->s_port));
+  ASSERT_STREQ("tcp", s->s_proto);
+
+  // We get the same result by explicitly asking for tcp.
+  s = getservbyport(htons(25), "tcp");
+  ASSERT_TRUE(s != nullptr);
+  ASSERT_STREQ("smtp", s->s_name);
+  ASSERT_EQ(25, ntohs(s->s_port));
+  ASSERT_STREQ("tcp", s->s_proto);
+
+  // And we get a failure if we explicitly ask for udp.
+  s = getservbyport(htons(25), "udp");
+  ASSERT_TRUE(s == nullptr);
+
+  // But there are actually udp services.
+  s = getservbyport(htons(7), "udp");
+  ASSERT_TRUE(s != nullptr);
+  ASSERT_STREQ("echo", s->s_name);
+  ASSERT_EQ(7, ntohs(s->s_port));
+  ASSERT_STREQ("udp", s->s_proto);
+}
+
+TEST(netdb, endnetent_getnetent_setnetent) {
+  setnetent(0);
+  setnetent(1);
+  endnetent();
+  while (getnetent() != nullptr) {
+  }
+}
+
+TEST(netdb, getnetbyaddr) {
+  getnetbyaddr(0, 0);
+}
+
+TEST(netdb, getnetbyname) {
+  getnetbyname("x");
+}
+
+TEST(netdb, endprotoent_getprotoent_setprotoent) {
+  setprotoent(0);
+  setprotoent(1);
+  endprotoent();
+  while (getprotoent() != nullptr) {
+  }
+}
+
+TEST(netdb, getprotobyname) {
+  getprotobyname("tcp");
+}
+
+TEST(netdb, getprotobynumber) {
+  getprotobynumber(6);
+}
+
+TEST(netdb, endservent_getservent_setservent) {
+  setservent(0);
+  setservent(1);
+  endservent();
+  size_t service_count = 0;
+  while (getservent() != nullptr) {
+    ++service_count;
+  }
+  ASSERT_GT(service_count, 0U);
+}
+
+TEST(netdb, getservbyname_getservent_conflicts) {
+  // Calling getservbyname shouldn't affect getservent's iteration order.
+  endservent();
+  while (getservent() != nullptr) {
+    ASSERT_TRUE(getservbyname("smtp", "tcp") != nullptr);
+  }
+}
+
+TEST(netdb, getservbyport_getservent_conflicts) {
+  // Calling getservbyport shouldn't affect getservent's iteration order.
+  endservent();
+  while (getservent() != nullptr) {
+    ASSERT_TRUE(getservbyport(htons(25), "tcp") != nullptr);
+  }
+}
+
+TEST(netdb, endservent_resets) {
+  endservent();
+  std::string first_service(getservent()->s_name);
+  endservent();
+  ASSERT_EQ(first_service, std::string(getservent()->s_name));
+}
+
+TEST(netdb, setservent_resets) {
+  endservent();
+  std::string first_service(getservent()->s_name);
+  setservent(0);
+  ASSERT_EQ(first_service, std::string(getservent()->s_name));
+}
+
+TEST(netdb, endhostent_gethostent_sethostent) {
+  sethostent(0);
+  sethostent(1);
+  endhostent();
+  size_t host_count = 0;
+  while (gethostent() != nullptr) {
+    ++host_count;
+  }
+  ASSERT_GT(host_count, 0U);
+}
+
+TEST(netdb, endhostent_resets) {
+  endhostent();
+  std::string first_host(gethostent()->h_name);
+  endhostent();
+  ASSERT_EQ(first_host, std::string(gethostent()->h_name));
+}
+
+TEST(netdb, sethostent_resets) {
+  endhostent();
+  std::string first_host(gethostent()->h_name);
+  sethostent(0);
+  ASSERT_EQ(first_host, std::string(gethostent()->h_name));
+}