Merge "Add malloc debug documentation."
diff --git a/libc/Android.bp b/libc/Android.bp
index 3ec5e96..8024912 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -307,8 +307,6 @@
defaults: ["libc_defaults"],
srcs: [
"upstream-netbsd/common/lib/libc/stdlib/random.c",
- "upstream-netbsd/lib/libc/gen/ftw.c",
- "upstream-netbsd/lib/libc/gen/nftw.c",
"upstream-netbsd/lib/libc/gen/nice.c",
"upstream-netbsd/lib/libc/gen/popen.c",
"upstream-netbsd/lib/libc/gen/psignal.c",
@@ -508,6 +506,7 @@
"upstream-openbsd/lib/libc/stdlib/atol.c",
"upstream-openbsd/lib/libc/stdlib/atoll.c",
"upstream-openbsd/lib/libc/stdlib/getenv.c",
+ "upstream-openbsd/lib/libc/stdlib/getsubopt.c",
"upstream-openbsd/lib/libc/stdlib/insque.c",
"upstream-openbsd/lib/libc/stdlib/imaxabs.c",
"upstream-openbsd/lib/libc/stdlib/imaxdiv.c",
@@ -1279,6 +1278,7 @@
"bionic/fpclassify.cpp",
"bionic/fsetxattr.cpp",
"bionic/ftruncate.cpp",
+ "bionic/ftw.cpp",
"bionic/futimens.cpp",
"bionic/getcwd.cpp",
"bionic/getdomainname.cpp",
@@ -1350,12 +1350,17 @@
"bionic/sigdelset.cpp",
"bionic/sigemptyset.cpp",
"bionic/sigfillset.cpp",
+ "bionic/sighold.cpp",
+ "bionic/sigignore.cpp",
"bionic/sigismember.cpp",
"bionic/signal.cpp",
"bionic/signalfd.cpp",
+ "bionic/sigpause.cpp",
"bionic/sigpending.cpp",
"bionic/sigprocmask.cpp",
"bionic/sigqueue.cpp",
+ "bionic/sigrelse.cpp",
+ "bionic/sigset.cpp",
"bionic/sigsuspend.cpp",
"bionic/sigtimedwait.cpp",
"bionic/sigwait.cpp",
@@ -1369,6 +1374,7 @@
"bionic/strsignal.cpp",
"bionic/strtold.cpp",
"bionic/symlink.cpp",
+ "bionic/sync_file_range.cpp",
"bionic/sysinfo.cpp",
"bionic/syslog.cpp",
"bionic/sys_siglist.c",
@@ -1914,7 +1920,7 @@
"crt_defaults",
"crt_so_defaults",
],
- deps: [
+ objs: [
"crtbegin_so1",
"crtbrand",
],
@@ -1972,7 +1978,7 @@
cc_object {
name: "crtbegin_static",
- deps: [
+ objs: [
"crtbegin_static1",
"crtbrand",
],
@@ -2018,7 +2024,7 @@
cc_object {
name: "crtbegin_dynamic",
- deps: [
+ objs: [
"crtbegin_dynamic1",
"crtbrand",
],
diff --git a/libc/Android.mk b/libc/Android.mk
index fa392d1..02682af 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -107,6 +107,7 @@
bionic/fpclassify.cpp \
bionic/fsetxattr.cpp \
bionic/ftruncate.cpp \
+ bionic/ftw.cpp \
bionic/futimens.cpp \
bionic/getcwd.cpp \
bionic/getdomainname.cpp \
@@ -288,8 +289,6 @@
libc_upstream_netbsd_src_files := \
upstream-netbsd/common/lib/libc/stdlib/random.c \
- upstream-netbsd/lib/libc/gen/ftw.c \
- upstream-netbsd/lib/libc/gen/nftw.c \
upstream-netbsd/lib/libc/gen/nice.c \
upstream-netbsd/lib/libc/gen/popen.c \
upstream-netbsd/lib/libc/gen/psignal.c \
diff --git a/libc/bionic/clock.cpp b/libc/bionic/clock.cpp
index 053e9e7..fda0708 100644
--- a/libc/bionic/clock.cpp
+++ b/libc/bionic/clock.cpp
@@ -26,9 +26,9 @@
* SUCH DAMAGE.
*/
-#include <time.h>
-#include <sys/sysconf.h>
#include <sys/times.h>
+#include <time.h>
+#include <unistd.h>
#include "private/bionic_constants.h"
diff --git a/libc/bionic/ftw.cpp b/libc/bionic/ftw.cpp
new file mode 100644
index 0000000..2123619
--- /dev/null
+++ b/libc/bionic/ftw.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include <errno.h>
+#include <fts.h>
+#include <ftw.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+static int do_nftw(const char *path,
+ int (*ftw_fn)(const char*, const struct stat*, int),
+ int (*nftw_fn)(const char*, const struct stat*, int, FTW*),
+ int nfds,
+ int nftw_flags) {
+ // TODO: nfds is currently unused.
+ if (nfds < 1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ // Translate to fts_open options.
+ int fts_options = FTS_LOGICAL | FTS_COMFOLLOW | FTS_NOCHDIR;
+ if (nftw_fn) {
+ fts_options = FTS_COMFOLLOW | ((nftw_flags & FTW_PHYS) ? FTS_PHYSICAL : FTS_LOGICAL);
+ if (!(nftw_flags & FTW_CHDIR)) fts_options |= FTS_NOCHDIR;
+ if (nftw_flags & FTW_MOUNT) fts_options |= FTS_XDEV;
+ }
+ bool postorder = (nftw_flags & FTW_DEPTH) != 0;
+
+ // Call fts_open.
+ char* const paths[2] = { const_cast<char*>(path), nullptr };
+ FTS* fts = fts_open(paths, fts_options, nullptr);
+ if (fts == nullptr) {
+ return -1;
+ }
+
+ // Translate fts_read results into ftw/nftw callbacks.
+ int error = 0;
+ FTSENT* cur;
+ while (error == 0 && (cur = fts_read(fts)) != nullptr) {
+ int fn_flag;
+ switch (cur->fts_info) {
+ case FTS_D:
+ // In the postorder case, we'll translate FTS_DP to FTW_DP later.
+ // In the can't-access case, we'll translate FTS_DNR to FTW_DNR later.
+ if (postorder || access(cur->fts_path, R_OK) == -1) continue;
+ fn_flag = FTW_D;
+ break;
+ case FTS_DNR:
+ fn_flag = FTW_DNR;
+ break;
+ case FTS_DP:
+ if (!postorder) continue;
+ fn_flag = FTW_DP;
+ break;
+ case FTS_F:
+ case FTS_DEFAULT:
+ fn_flag = FTW_F;
+ break;
+ case FTS_NS:
+ case FTS_NSOK:
+ fn_flag = FTW_NS;
+ break;
+ case FTS_SL:
+ fn_flag = FTW_SL;
+ break;
+ case FTS_SLNONE:
+ fn_flag = (nftw_fn != nullptr) ? FTW_SLN : FTW_NS;
+ break;
+ case FTS_DC:
+ errno = ELOOP;
+ error = -1;
+ continue;
+ default:
+ error = -1;
+ continue;
+ }
+
+ // Call the appropriate function.
+ if (nftw_fn != nullptr) {
+ FTW ftw;
+ ftw.base = cur->fts_pathlen - cur->fts_namelen;
+ ftw.level = cur->fts_level;
+ error = nftw_fn(cur->fts_path, cur->fts_statp, fn_flag, &ftw);
+ } else {
+ error = ftw_fn(cur->fts_path, cur->fts_statp, fn_flag);
+ }
+ }
+
+ int saved_errno = errno;
+ if (fts_close(fts) != 0 && error == 0) {
+ error = -1;
+ } else {
+ errno = saved_errno;
+ }
+ return error;
+}
+
+int ftw(const char* path, int (*ftw_fn)(const char*, const struct stat*, int), int nfds) {
+ return do_nftw(path, ftw_fn, nullptr, nfds, 0);
+}
+
+int nftw(const char* path, int (*nftw_fn)(const char*, const struct stat*, int, FTW*),
+ int nfds, int nftw_flags) {
+ return do_nftw(path, nullptr, nftw_fn, nfds, nftw_flags);
+}
diff --git a/libc/bionic/strerror_r.cpp b/libc/bionic/strerror_r.cpp
index d419fb1..a0a0809 100644
--- a/libc/bionic/strerror_r.cpp
+++ b/libc/bionic/strerror_r.cpp
@@ -31,7 +31,7 @@
static const Pair _sys_error_strings[] = {
#define __BIONIC_ERRDEF(x,y,z) { x, z },
-#include <sys/_errdefs.h>
+#include "private/bionic_errdefs.h"
{ 0, NULL }
};
@@ -41,7 +41,7 @@
static const Pair _sys_signal_strings[] = {
#define __BIONIC_SIGDEF(signal_number, signal_description) { signal_number, signal_description },
-#include <sys/_sigdefs.h>
+#include "private/bionic_sigdefs.h"
{ 0, NULL }
};
diff --git a/libc/bionic/sys_siglist.c b/libc/bionic/sys_siglist.c
index 3cfddbf..8e33d64 100644
--- a/libc/bionic/sys_siglist.c
+++ b/libc/bionic/sys_siglist.c
@@ -30,5 +30,5 @@
const char* const sys_siglist[NSIG] = {
#define __BIONIC_SIGDEF(signal_number, signal_description) [ signal_number ] = signal_description,
-#include <sys/_sigdefs.h>
+#include "private/bionic_sigdefs.h"
};
diff --git a/libc/bionic/sys_signame.c b/libc/bionic/sys_signame.c
index e1286f2..5158b83 100644
--- a/libc/bionic/sys_signame.c
+++ b/libc/bionic/sys_signame.c
@@ -30,5 +30,5 @@
const char* const sys_signame[NSIG] = {
#define __BIONIC_SIGDEF(signal_number, unused) [ signal_number ] = #signal_number + 3,
-#include <sys/_sigdefs.h>
+#include "private/bionic_sigdefs.h"
};
diff --git a/libc/bionic/sysconf.cpp b/libc/bionic/sysconf.cpp
index cff6288..7be0ab7 100644
--- a/libc/bionic/sysconf.cpp
+++ b/libc/bionic/sysconf.cpp
@@ -34,7 +34,6 @@
#include <stdio.h> // For FOPEN_MAX.
#include <sys/auxv.h>
#include <sys/resource.h>
-#include <sys/sysconf.h>
#include <sys/sysinfo.h>
#include <time.h>
#include <unistd.h>
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
index 2d2f096..b230cef 100644
--- a/libc/include/android/api-level.h
+++ b/libc/include/android/api-level.h
@@ -33,6 +33,8 @@
* Magic version number for a current development build, which has
* not yet turned into an official release.
*/
+#ifndef __ANDROID_API__
#define __ANDROID_API__ 10000
+#endif
#endif /* ANDROID_API_LEVEL_H */
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index d5ec386..6e32b68 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -17,6 +17,7 @@
#ifndef __ANDROID_DLEXT_H__
#define __ANDROID_DLEXT_H__
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/cdefs.h>
diff --git a/libc/include/android/legacy_errno_inlines.h b/libc/include/android/legacy_errno_inlines.h
index 71096fc..93cba1f 100644
--- a/libc/include/android/legacy_errno_inlines.h
+++ b/libc/include/android/legacy_errno_inlines.h
@@ -29,8 +29,11 @@
#ifndef _ANDROID_LEGACY_ERRNO_INLINES_H
#define _ANDROID_LEGACY_ERRNO_INLINES_H
+#include <errno.h>
#include <sys/cdefs.h>
+#if __ANDROID_API__ < 21
+
__BEGIN_DECLS
static __inline int __attribute__((deprecated)) __set_errno(int n) {
@@ -40,4 +43,5 @@
__END_DECLS
+#endif
#endif /* _ANDROID_LEGACY_ERRNO_INLINES_H */
diff --git a/libc/include/android/legacy_signal_inlines.h b/libc/include/android/legacy_signal_inlines.h
index 1b6e687..bf895da 100644
--- a/libc/include/android/legacy_signal_inlines.h
+++ b/libc/include/android/legacy_signal_inlines.h
@@ -29,14 +29,18 @@
#ifndef _ANDROID_LEGACY_SIGNAL_INLINES_H_
#define _ANDROID_LEGACY_SIGNAL_INLINES_H_
+#include <errno.h>
+#include <signal.h>
#include <string.h>
#include <sys/cdefs.h>
+#if __ANDROID_API__ < 21
+
__BEGIN_DECLS
extern sighandler_t bsd_signal(int signum, sighandler_t handler);
-static __inline int sigismember(sigset_t *set, int signum) {
+static __inline int sigismember(const sigset_t *set, int signum) {
/* Signal numbers start at 1, but bit positions start at 0. */
int bit = signum - 1;
const unsigned long *local_set = (const unsigned long *)set;
@@ -95,4 +99,5 @@
__END_DECLS
+#endif
#endif /* _ANDROID_LEGACY_SIGNAL_INLINES_H_ */
diff --git a/libc/include/android/legacy_stdlib_inlines.h b/libc/include/android/legacy_stdlib_inlines.h
index 58a2a9e..93554e5 100644
--- a/libc/include/android/legacy_stdlib_inlines.h
+++ b/libc/include/android/legacy_stdlib_inlines.h
@@ -29,8 +29,11 @@
#ifndef _ANDROID_LEGACY_STDLIB_INLINES_H_
#define _ANDROID_LEGACY_STDLIB_INLINES_H_
+#include <stdlib.h>
#include <sys/cdefs.h>
+#if __ANDROID_API__ < 21
+
__BEGIN_DECLS
static __inline float strtof(const char *nptr, char **endptr) {
@@ -61,4 +64,5 @@
__END_DECLS
+#endif
#endif /* _ANDROID_LEGACY_STDLIB_INLINES_H_ */
diff --git a/libc/include/android/legacy_sys_atomics_inlines.h b/libc/include/android/legacy_sys_atomics_inlines.h
index 85cbade..3314e35 100644
--- a/libc/include/android/legacy_sys_atomics_inlines.h
+++ b/libc/include/android/legacy_sys_atomics_inlines.h
@@ -31,6 +31,8 @@
#include <sys/cdefs.h>
+#if __ANDROID_API__ < 21
+
__BEGIN_DECLS
/* Note: atomic operations that were exported by the C library didn't
@@ -69,4 +71,5 @@
__END_DECLS
+#endif
#endif /* _ANDROID_LEGACY_SYS_ATOMICS_INLINES_H_ */
diff --git a/libc/include/android/legacy_sys_stat_inlines.h b/libc/include/android/legacy_sys_stat_inlines.h
index f6d3c0f..c08edfa 100644
--- a/libc/include/android/legacy_sys_stat_inlines.h
+++ b/libc/include/android/legacy_sys_stat_inlines.h
@@ -30,6 +30,9 @@
#define _ANDROID_LEGACY_SYS_STAT_INLINES_H_
#include <sys/cdefs.h>
+#include <sys/stat.h>
+
+#if __ANDROID_API__ < 21
__BEGIN_DECLS
@@ -39,4 +42,5 @@
__END_DECLS
+#endif
#endif /* _ANDROID_LEGACY_SYS_STAT_INLINES_H_ */
diff --git a/libc/include/android/legacy_termios_inlines.h b/libc/include/android/legacy_termios_inlines.h
index fb61f27..41ea955 100644
--- a/libc/include/android/legacy_termios_inlines.h
+++ b/libc/include/android/legacy_termios_inlines.h
@@ -34,6 +34,8 @@
#include <sys/ioctl.h>
#include <sys/types.h>
+#if __ANDROID_API__ < 21
+
__BEGIN_DECLS
static __inline int tcgetattr(int fd, struct termios *s) {
@@ -90,4 +92,5 @@
__END_DECLS
+#endif
#endif /* _ANDROID_LEGACY_TERMIOS_INLINES_H_ */
diff --git a/libc/include/bits/fcntl.h b/libc/include/bits/fcntl.h
new file mode 100644
index 0000000..90f933c
--- /dev/null
+++ b/libc/include/bits/fcntl.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef _BITS_FCNTL_H_
+#define _BITS_FCNTL_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+extern int fcntl(int, int, ...);
+
+__END_DECLS
+
+#endif
diff --git a/libc/include/bits/getopt.h b/libc/include/bits/getopt.h
new file mode 100644
index 0000000..7153d48
--- /dev/null
+++ b/libc/include/bits/getopt.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef _BITS_GETOPT_H_
+#define _BITS_GETOPT_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+int getopt(int, char * const [], const char *);
+
+extern char *optarg; /* getopt(3) external variables */
+extern int optind, opterr, optopt;
+
+__END_DECLS
+
+#endif
diff --git a/libc/include/bits/ioctl.h b/libc/include/bits/ioctl.h
new file mode 100644
index 0000000..788a4f7
--- /dev/null
+++ b/libc/include/bits/ioctl.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef _BITS_IOCTL_H_
+#define _BITS_IOCTL_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+extern int ioctl(int, int, ...);
+
+__END_DECLS
+
+#endif
diff --git a/libc/include/bits/lockf.h b/libc/include/bits/lockf.h
index d814807..a0ba19d 100644
--- a/libc/include/bits/lockf.h
+++ b/libc/include/bits/lockf.h
@@ -30,6 +30,7 @@
#define _BITS_LOCKF_H_
#include <sys/cdefs.h>
+#include <sys/types.h>
#define F_ULOCK 0
#define F_LOCK 1
diff --git a/libc/include/bits/strcasecmp.h b/libc/include/bits/strcasecmp.h
new file mode 100644
index 0000000..124f5cd
--- /dev/null
+++ b/libc/include/bits/strcasecmp.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef _BITS_STRCASECMP_H_
+#define _BITS_STRCASECMP_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <xlocale.h>
+
+__BEGIN_DECLS
+
+int strcasecmp(const char*, const char*) __purefunc;
+int strcasecmp_l(const char*, const char*, locale_t) __purefunc;
+int strncasecmp(const char*, const char*, size_t) __purefunc;
+int strncasecmp_l(const char*, const char*, size_t, locale_t) __purefunc;
+
+__END_DECLS
+
+#endif
diff --git a/libc/include/bits/sysconf.h b/libc/include/bits/sysconf.h
new file mode 100644
index 0000000..2cbbb11
--- /dev/null
+++ b/libc/include/bits/sysconf.h
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ */
+
+#ifndef _BITS_SYSCONF_H_
+#define _BITS_SYSCONF_H_
+
+#include <sys/cdefs.h>
+
+/* as listed by Posix sysconf() description */
+/* most of these will return -1 and ENOSYS */
+
+#define _SC_ARG_MAX 0x0000
+#define _SC_BC_BASE_MAX 0x0001
+#define _SC_BC_DIM_MAX 0x0002
+#define _SC_BC_SCALE_MAX 0x0003
+#define _SC_BC_STRING_MAX 0x0004
+#define _SC_CHILD_MAX 0x0005
+#define _SC_CLK_TCK 0x0006
+#define _SC_COLL_WEIGHTS_MAX 0x0007
+#define _SC_EXPR_NEST_MAX 0x0008
+#define _SC_LINE_MAX 0x0009
+#define _SC_NGROUPS_MAX 0x000a
+#define _SC_OPEN_MAX 0x000b
+#define _SC_PASS_MAX 0x000c
+#define _SC_2_C_BIND 0x000d
+#define _SC_2_C_DEV 0x000e
+#define _SC_2_C_VERSION 0x000f /* Obsolescent in POSIX.1-2008, TODO: remove it. */
+#define _SC_2_CHAR_TERM 0x0010
+#define _SC_2_FORT_DEV 0x0011
+#define _SC_2_FORT_RUN 0x0012
+#define _SC_2_LOCALEDEF 0x0013
+#define _SC_2_SW_DEV 0x0014
+#define _SC_2_UPE 0x0015
+#define _SC_2_VERSION 0x0016
+#define _SC_JOB_CONTROL 0x0017
+#define _SC_SAVED_IDS 0x0018
+#define _SC_VERSION 0x0019
+#define _SC_RE_DUP_MAX 0x001a
+#define _SC_STREAM_MAX 0x001b
+#define _SC_TZNAME_MAX 0x001c
+#define _SC_XOPEN_CRYPT 0x001d
+#define _SC_XOPEN_ENH_I18N 0x001e
+#define _SC_XOPEN_SHM 0x001f
+#define _SC_XOPEN_VERSION 0x0020
+#define _SC_XOPEN_XCU_VERSION 0x0021 /* Obsolescent in POSIX.1-2008, TODO: remove it. */
+#define _SC_XOPEN_REALTIME 0x0022
+#define _SC_XOPEN_REALTIME_THREADS 0x0023
+#define _SC_XOPEN_LEGACY 0x0024
+#define _SC_ATEXIT_MAX 0x0025
+#define _SC_IOV_MAX 0x0026
+#define _SC_PAGESIZE 0x0027
+#define _SC_PAGE_SIZE 0x0028
+#define _SC_XOPEN_UNIX 0x0029
+#define _SC_XBS5_ILP32_OFF32 0x002a /* Obsolescent in POSIX.1-2008, TODO: remove it. */
+#define _SC_XBS5_ILP32_OFFBIG 0x002b /* Obsolescent in POSIX.1-2008, TODO: remove it. */
+#define _SC_XBS5_LP64_OFF64 0x002c /* Obsolescent in POSIX.1-2008, TODO: remove it. */
+#define _SC_XBS5_LPBIG_OFFBIG 0x002d /* Obsolescent in POSIX.1-2008, TODO: remove it. */
+#define _SC_AIO_LISTIO_MAX 0x002e
+#define _SC_AIO_MAX 0x002f
+#define _SC_AIO_PRIO_DELTA_MAX 0x0030
+#define _SC_DELAYTIMER_MAX 0x0031
+#define _SC_MQ_OPEN_MAX 0x0032
+#define _SC_MQ_PRIO_MAX 0x0033
+#define _SC_RTSIG_MAX 0x0034
+#define _SC_SEM_NSEMS_MAX 0x0035
+#define _SC_SEM_VALUE_MAX 0x0036
+#define _SC_SIGQUEUE_MAX 0x0037
+#define _SC_TIMER_MAX 0x0038
+#define _SC_ASYNCHRONOUS_IO 0x0039
+#define _SC_FSYNC 0x003a
+#define _SC_MAPPED_FILES 0x003b
+#define _SC_MEMLOCK 0x003c
+#define _SC_MEMLOCK_RANGE 0x003d
+#define _SC_MEMORY_PROTECTION 0x003e
+#define _SC_MESSAGE_PASSING 0x003f
+#define _SC_PRIORITIZED_IO 0x0040
+#define _SC_PRIORITY_SCHEDULING 0x0041
+#define _SC_REALTIME_SIGNALS 0x0042
+#define _SC_SEMAPHORES 0x0043
+#define _SC_SHARED_MEMORY_OBJECTS 0x0044
+#define _SC_SYNCHRONIZED_IO 0x0045
+#define _SC_TIMERS 0x0046
+#define _SC_GETGR_R_SIZE_MAX 0x0047
+#define _SC_GETPW_R_SIZE_MAX 0x0048
+#define _SC_LOGIN_NAME_MAX 0x0049
+#define _SC_THREAD_DESTRUCTOR_ITERATIONS 0x004a
+#define _SC_THREAD_KEYS_MAX 0x004b
+#define _SC_THREAD_STACK_MIN 0x004c
+#define _SC_THREAD_THREADS_MAX 0x004d
+#define _SC_TTY_NAME_MAX 0x004e
+
+#define _SC_THREADS 0x004f
+#define _SC_THREAD_ATTR_STACKADDR 0x0050
+#define _SC_THREAD_ATTR_STACKSIZE 0x0051
+#define _SC_THREAD_PRIORITY_SCHEDULING 0x0052
+#define _SC_THREAD_PRIO_INHERIT 0x0053
+#define _SC_THREAD_PRIO_PROTECT 0x0054
+#define _SC_THREAD_SAFE_FUNCTIONS 0x0055
+
+#define _SC_NPROCESSORS_CONF 0x0060
+#define _SC_NPROCESSORS_ONLN 0x0061
+#define _SC_PHYS_PAGES 0x0062
+#define _SC_AVPHYS_PAGES 0x0063
+#define _SC_MONOTONIC_CLOCK 0x0064
+
+#define _SC_2_PBS 0x0065
+#define _SC_2_PBS_ACCOUNTING 0x0066
+#define _SC_2_PBS_CHECKPOINT 0x0067
+#define _SC_2_PBS_LOCATE 0x0068
+#define _SC_2_PBS_MESSAGE 0x0069
+#define _SC_2_PBS_TRACK 0x006a
+#define _SC_ADVISORY_INFO 0x006b
+#define _SC_BARRIERS 0x006c
+#define _SC_CLOCK_SELECTION 0x006d
+#define _SC_CPUTIME 0x006e
+#define _SC_HOST_NAME_MAX 0x006f
+#define _SC_IPV6 0x0070
+#define _SC_RAW_SOCKETS 0x0071
+#define _SC_READER_WRITER_LOCKS 0x0072
+#define _SC_REGEXP 0x0073
+#define _SC_SHELL 0x0074
+#define _SC_SPAWN 0x0075
+#define _SC_SPIN_LOCKS 0x0076
+#define _SC_SPORADIC_SERVER 0x0077
+#define _SC_SS_REPL_MAX 0x0078
+#define _SC_SYMLOOP_MAX 0x0079
+#define _SC_THREAD_CPUTIME 0x007a
+#define _SC_THREAD_PROCESS_SHARED 0x007b
+#define _SC_THREAD_ROBUST_PRIO_INHERIT 0x007c
+#define _SC_THREAD_ROBUST_PRIO_PROTECT 0x007d
+#define _SC_THREAD_SPORADIC_SERVER 0x007e
+#define _SC_TIMEOUTS 0x007f
+#define _SC_TRACE 0x0080
+#define _SC_TRACE_EVENT_FILTER 0x0081
+#define _SC_TRACE_EVENT_NAME_MAX 0x0082
+#define _SC_TRACE_INHERIT 0x0083
+#define _SC_TRACE_LOG 0x0084
+#define _SC_TRACE_NAME_MAX 0x0085
+#define _SC_TRACE_SYS_MAX 0x0086
+#define _SC_TRACE_USER_EVENT_MAX 0x0087
+#define _SC_TYPED_MEMORY_OBJECTS 0x0088
+#define _SC_V7_ILP32_OFF32 0x0089
+#define _SC_V7_ILP32_OFFBIG 0x008a
+#define _SC_V7_LP64_OFF64 0x008b
+#define _SC_V7_LPBIG_OFFBIG 0x008c
+#define _SC_XOPEN_STREAMS 0x008d
+#define _SC_XOPEN_UUCP 0x008e
+
+#define _SC_LEVEL1_ICACHE_SIZE 0x008f
+#define _SC_LEVEL1_ICACHE_ASSOC 0x0090
+#define _SC_LEVEL1_ICACHE_LINESIZE 0x0091
+#define _SC_LEVEL1_DCACHE_SIZE 0x0092
+#define _SC_LEVEL1_DCACHE_ASSOC 0x0093
+#define _SC_LEVEL1_DCACHE_LINESIZE 0x0094
+#define _SC_LEVEL2_CACHE_SIZE 0x0095
+#define _SC_LEVEL2_CACHE_ASSOC 0x0096
+#define _SC_LEVEL2_CACHE_LINESIZE 0x0097
+#define _SC_LEVEL3_CACHE_SIZE 0x0098
+#define _SC_LEVEL3_CACHE_ASSOC 0x0099
+#define _SC_LEVEL3_CACHE_LINESIZE 0x009a
+#define _SC_LEVEL4_CACHE_SIZE 0x009b
+#define _SC_LEVEL4_CACHE_ASSOC 0x009c
+#define _SC_LEVEL4_CACHE_LINESIZE 0x009d
+
+__BEGIN_DECLS
+
+long sysconf(int __name);
+
+__END_DECLS
+
+#endif /* _SYS_SYSCONF_H_ */
diff --git a/libc/include/errno.h b/libc/include/errno.h
index 82f4b42..2ff1369 100644
--- a/libc/include/errno.h
+++ b/libc/include/errno.h
@@ -46,10 +46,8 @@
/* a macro expanding to the errno l-value */
#define errno (*__errno())
-#if __ANDROID_API__ < 21
-#include <android/legacy_errno_inlines.h>
-#endif
-
__END_DECLS
+#include <android/legacy_errno_inlines.h>
+
#endif /* _ERRNO_H */
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index 9d15e92..013d72c 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -36,6 +36,8 @@
#include <linux/stat.h>
#include <linux/uio.h>
+#include <bits/fcntl.h>
+
#if defined(__USE_GNU) || defined(__USE_BSD)
#include <bits/lockf.h>
#endif
@@ -63,14 +65,12 @@
extern int creat(const char*, mode_t);
extern int creat64(const char*, mode_t);
-extern int fcntl(int, int, ...);
extern int openat(int, const char*, int, ...);
extern int openat64(int, const char*, int, ...);
extern int open(const char*, int, ...);
extern int open64(const char*, int, ...);
extern ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int);
extern ssize_t tee(int, int, size_t, unsigned int);
-extern int unlinkat(int, const char*, int);
extern ssize_t vmsplice(int, const struct iovec*, size_t, unsigned int);
#if defined(__USE_FILE_OFFSET64)
diff --git a/libc/include/getopt.h b/libc/include/getopt.h
index 4451941..46d2eb7 100644
--- a/libc/include/getopt.h
+++ b/libc/include/getopt.h
@@ -35,9 +35,10 @@
#include <sys/cdefs.h>
+#include <bits/getopt.h>
+
/*
* GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension.
- * getopt() is declared here too for GNU programs.
*/
#define no_argument 0
#define required_argument 1
@@ -62,13 +63,7 @@
const struct option *, int *);
int getopt_long_only(int, char * const *, const char *,
const struct option *, int *);
-#ifndef _GETOPT_DECLARED
-#define _GETOPT_DECLARED
-int getopt(int, char * const [], const char *);
-extern char *optarg; /* getopt(3) external variables */
-extern int optind, opterr, optopt;
-#endif
#ifndef _OPTRESET_DECLARED
#define _OPTRESET_DECLARED
extern int optreset; /* getopt(3) external variable */
diff --git a/libc/include/math.h b/libc/include/math.h
index 8e193cb..203968a 100644
--- a/libc/include/math.h
+++ b/libc/include/math.h
@@ -20,12 +20,6 @@
#include <sys/cdefs.h>
#include <limits.h>
-#if !defined(__BIONIC_NO_MATH_INLINES)
-#define __BIONIC_MATH_INLINE(__def) extern __inline__ __always_inline __attribute__((gnu_inline)) __attribute__((__artificial__)) __def
-#else
-#define __BIONIC_MATH_INLINE(__def)
-#endif
-
__BEGIN_DECLS
#pragma GCC visibility push(default)
@@ -183,7 +177,6 @@
double ceil(double);
double fabs(double) __pure2;
-__BIONIC_MATH_INLINE(double fabs(double x) { return __builtin_fabs(x); })
double floor(double);
double fmod(double, double);
@@ -302,7 +295,6 @@
float ceilf(float);
float fabsf(float) __pure2;
-__BIONIC_MATH_INLINE(float fabsf(float x) { return __builtin_fabsf(x); })
float floorf(float);
float fmodf(float, float);
float roundf(float);
@@ -390,7 +382,6 @@
long double expl(long double);
long double expm1l(long double);
long double fabsl(long double) __pure2;
-__BIONIC_MATH_INLINE(long double fabsl(long double x) { return __builtin_fabsl(x); })
long double fdiml(long double, long double);
long double floorl(long double);
long double fmal(long double, long double, long double);
diff --git a/libc/include/net/if_ieee1394.h b/libc/include/net/if_ieee1394.h
index 5a61581..2f8a7c3 100644
--- a/libc/include/net/if_ieee1394.h
+++ b/libc/include/net/if_ieee1394.h
@@ -39,6 +39,8 @@
#ifndef _NET_IF_IEEE1394_H_
#define _NET_IF_IEEE1394_H_
+#include <sys/types.h>
+
/* hardware address information for arp / nd */
struct ieee1394_hwaddr {
u_int8_t iha_uid[8]; /* node unique ID */
diff --git a/libc/include/netinet/in_systm.h b/libc/include/netinet/in_systm.h
index ff53fb7..7e474ba 100644
--- a/libc/include/netinet/in_systm.h
+++ b/libc/include/netinet/in_systm.h
@@ -34,6 +34,8 @@
#ifndef _NETINET_IN_SYSTM_H_
#define _NETINET_IN_SYSTM_H_
+#include <sys/types.h>
+
/*
* Miscellaneous internetwork
* definitions for kernel.
diff --git a/libc/include/netinet/ip6.h b/libc/include/netinet/ip6.h
index aa816c2..aa89186 100644
--- a/libc/include/netinet/ip6.h
+++ b/libc/include/netinet/ip6.h
@@ -64,6 +64,10 @@
#ifndef _NETINET_IP6_H_
#define _NETINET_IP6_H_
+#include <sys/types.h>
+
+#include <linux/in6.h>
+
/*
* Definition for internet protocol version 6.
* RFC 2460
diff --git a/libc/include/netinet/tcp.h b/libc/include/netinet/tcp.h
index 5601645..e95cc09 100644
--- a/libc/include/netinet/tcp.h
+++ b/libc/include/netinet/tcp.h
@@ -29,6 +29,8 @@
#ifndef _NETINET_TCP_H
#define _NETINET_TCP_H
+#include <sys/cdefs.h>
+
#include <linux/tcp.h>
__BEGIN_DECLS
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 763bae9..5679402 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -110,15 +110,15 @@
extern int sigaction(int, const struct sigaction*, struct sigaction*);
-extern sighandler_t signal(int, sighandler_t) __INTRODUCED_IN(21);
+__BIONIC_LEGACY_INLINE sighandler_t signal(int, sighandler_t);
extern int siginterrupt(int, int);
-extern int sigaddset(sigset_t*, int) __INTRODUCED_IN(21);
-extern int sigdelset(sigset_t*, int) __INTRODUCED_IN(21);
-extern int sigemptyset(sigset_t*) __INTRODUCED_IN(21);
-extern int sigfillset(sigset_t*) __INTRODUCED_IN(21);
-extern int sigismember(const sigset_t*, int) __INTRODUCED_IN(21);
+__BIONIC_LEGACY_INLINE int sigaddset(sigset_t*, int);
+__BIONIC_LEGACY_INLINE int sigdelset(sigset_t*, int);
+__BIONIC_LEGACY_INLINE int sigemptyset(sigset_t*);
+__BIONIC_LEGACY_INLINE int sigfillset(sigset_t*);
+__BIONIC_LEGACY_INLINE int sigismember(const sigset_t*, int);
extern int sigpending(sigset_t*) __nonnull((1));
extern int sigprocmask(int, const sigset_t*, sigset_t*);
@@ -147,10 +147,8 @@
extern int sigtimedwait(const sigset_t*, siginfo_t*, const struct timespec*);
extern int sigwaitinfo(const sigset_t*, siginfo_t*);
-#if __ANDROID_API__ < 21
-#include <android/legacy_signal_inlines.h>
-#endif
-
__END_DECLS
+#include <android/legacy_signal_inlines.h>
+
#endif /* _SIGNAL_H_ */
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 88930b1..d0fb0e8 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -76,10 +76,10 @@
extern int posix_memalign(void **memptr, size_t alignment, size_t size);
-extern double atof(const char*) __INTRODUCED_IN(21);
+__BIONIC_LEGACY_INLINE double atof(const char*);
extern double strtod(const char*, char**) __LIBC_ABI_PUBLIC__;
-extern float strtof(const char*, char**) __LIBC_ABI_PUBLIC__ __INTRODUCED_IN(21);
+__BIONIC_LEGACY_INLINE float strtof(const char*, char**) __LIBC_ABI_PUBLIC__;
extern long double strtold(const char*, char**) __LIBC_ABI_PUBLIC__;
extern long double strtold_l(const char *, char **, locale_t) __LIBC_ABI_PUBLIC__;
@@ -90,9 +90,9 @@
extern long atol(const char*) __purefunc;
extern long long atoll(const char*) __purefunc;
-extern int abs(int) __pure2 __INTRODUCED_IN(21);
-extern long labs(long) __pure2 __INTRODUCED_IN(21);
-extern long long llabs(long long) __pure2 __INTRODUCED_IN(21);
+__BIONIC_LEGACY_INLINE int abs(int) __pure2;
+__BIONIC_LEGACY_INLINE long labs(long) __pure2;
+__BIONIC_LEGACY_INLINE long long llabs(long long) __pure2;
extern char * realpath(const char *path, char *resolved);
extern int system(const char *string);
@@ -109,9 +109,9 @@
#define RAND_MAX 0x7fffffff
-int rand(void) __INTRODUCED_IN(21);
+__BIONIC_LEGACY_INLINE int rand(void);
int rand_r(unsigned int*);
-void srand(unsigned int) __INTRODUCED_IN(21);
+__BIONIC_LEGACY_INLINE void srand(unsigned int);
double drand48(void);
double erand48(unsigned short[3]);
@@ -124,12 +124,12 @@
void srand48(long);
char* initstate(unsigned int, char*, size_t);
-long random(void) __INTRODUCED_IN(21);
+__BIONIC_LEGACY_INLINE long random(void);
char* setstate(char*);
-void srandom(unsigned int) __INTRODUCED_IN(21);
+__BIONIC_LEGACY_INLINE void srandom(unsigned int);
int getpt(void);
-int grantpt(int) __INTRODUCED_IN(21);
+__BIONIC_LEGACY_INLINE int grantpt(int);
int posix_openpt(int);
char* ptsname(int);
int ptsname_r(int, char*, size_t);
@@ -174,10 +174,6 @@
extern size_t __ctype_get_mb_cur_max(void);
#define MB_CUR_MAX __ctype_get_mb_cur_max()
-#if __ANDROID_API__ < 21
-#include <android/legacy_stdlib_inlines.h>
-#endif
-
#if defined(__BIONIC_FORTIFY)
extern char* __realpath_real(const char*, char*) __RENAME(realpath);
@@ -201,4 +197,6 @@
__END_DECLS
+#include <android/legacy_stdlib_inlines.h>
+
#endif /* _STDLIB_H */
diff --git a/libc/include/string.h b/libc/include/string.h
index 32d4a18..dada52b 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -33,6 +33,8 @@
#include <stddef.h>
#include <xlocale.h>
+#include <bits/strcasecmp.h>
+
__BEGIN_DECLS
#if defined(__USE_BSD)
@@ -72,11 +74,6 @@
extern char* strcpy(char* __restrict, const char* __restrict);
extern char* strcat(char* __restrict, const char* __restrict);
-int strcasecmp(const char*, const char*) __purefunc;
-int strcasecmp_l(const char*, const char*, locale_t) __purefunc;
-int strncasecmp(const char*, const char*, size_t) __purefunc;
-int strncasecmp_l(const char*, const char*, size_t, locale_t) __purefunc;
-
extern char* strdup(const char *);
extern char* strstr(const char *, const char *) __purefunc;
diff --git a/libc/include/strings.h b/libc/include/strings.h
index 1253006..1200e77 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -43,6 +43,8 @@
#include <sys/cdefs.h>
#include <xlocale.h>
+#include <bits/strcasecmp.h>
+
__BEGIN_DECLS
#if defined(__BIONIC_FORTIFY)
#define bcopy(b1, b2, len) (void)(__builtin___memmove_chk((b2), (b1), (len), __bos0(b2)))
@@ -54,11 +56,6 @@
int ffs(int);
-int strcasecmp(const char*, const char*) __purefunc;
-int strcasecmp_l(const char*, const char*, locale_t) __purefunc;
-int strncasecmp(const char*, const char*, size_t) __purefunc;
-int strncasecmp_l(const char*, const char*, size_t, locale_t) __purefunc;
-
__END_DECLS
#endif /* !defined(_STRINGS_H_) */
diff --git a/libc/include/sys/atomics.h b/libc/include/sys/atomics.h
index 38ab366..b9b2ba3 100644
--- a/libc/include/sys/atomics.h
+++ b/libc/include/sys/atomics.h
@@ -38,8 +38,6 @@
* sys/atomics.h header was removed, so we'll just add these somewhere we can be
* sure they will be included.
*/
-#if __ANDROID_API__ < 21
#include <android/legacy_sys_atomics_inlines.h>
-#endif
#endif /* _SYS_ATOMICS_H_ */
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index f51942b..2bd058e 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -443,6 +443,12 @@
/* Used to rename functions so that the compiler emits a call to 'x' rather than the function this was applied to. */
#define __RENAME(x) __asm__(#x)
+#if __ANDROID_API__ < 21
+#define __BIONIC_LEGACY_INLINE static __inline
+#else
+#define __BIONIC_LEGACY_INLINE extern
+#endif
+
#ifdef __clang__
#define __AVAILABILITY(...) __attribute__((availability(android,__VA_ARGS__)))
#define __INTRODUCED_IN(api_level) __AVAILABILITY(introduced=api_level)
diff --git a/libc/include/sys/ioctl.h b/libc/include/sys/ioctl.h
index a1014dc..ed261f2 100644
--- a/libc/include/sys/ioctl.h
+++ b/libc/include/sys/ioctl.h
@@ -40,10 +40,6 @@
#include <sys/ioctl_compat.h>
#include <linux/tty.h>
-__BEGIN_DECLS
-
-extern int ioctl(int, int, ...);
-
-__END_DECLS
+#include <bits/ioctl.h>
#endif /* _SYS_IOCTL_H_ */
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index a19ceb5..170300a 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -65,13 +65,10 @@
extern int munlockall(void);
extern int mlock(const void*, size_t);
extern int munlock(const void*, size_t);
-extern int madvise(void*, size_t, int);
-
-extern int mlock(const void*, size_t);
-extern int munlock(const void*, size_t);
extern int mincore(void*, size_t, unsigned char*);
+extern int madvise(void*, size_t, int);
extern int posix_madvise(void*, size_t, int);
__END_DECLS
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index 86668f6..ae85f62 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -177,7 +177,7 @@
}
#endif /* defined(__BIONIC_FORTIFY) */
-extern int mkfifo(const char*, mode_t) __INTRODUCED_IN(21);
+__BIONIC_LEGACY_INLINE int mkfifo(const char*, mode_t);
extern int mkfifoat(int, const char*, mode_t);
extern int fchmodat(int, const char*, mode_t, int);
@@ -189,10 +189,8 @@
extern int utimensat(int fd, const char *path, const struct timespec times[2], int flags);
extern int futimens(int fd, const struct timespec times[2]);
-#if __ANDROID_API__ < 21
-#include <android/legacy_sys_stat_inlines.h>
-#endif
-
__END_DECLS
+#include <android/legacy_sys_stat_inlines.h>
+
#endif /* _SYS_STAT_H_ */
diff --git a/libc/include/sys/sysconf.h b/libc/include/sys/sysconf.h
index ca32132..c9895f2 100644
--- a/libc/include/sys/sysconf.h
+++ b/libc/include/sys/sysconf.h
@@ -25,171 +25,9 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifndef _SYS_SYSCONF_H_
-#define _SYS_SYSCONF_H_
-#include <sys/cdefs.h>
+// This file used to contain the declarations of sysconf and its associated constants.
+// No standard mentions a <sys/sysconf.h>, but there are enough users in vendor (and potential ones
+// in the NDK) to warrant not breaking source compatibility.
-__BEGIN_DECLS
-
-/* as listed by Posix sysconf() description */
-/* most of these will return -1 and ENOSYS */
-
-#define _SC_ARG_MAX 0x0000
-#define _SC_BC_BASE_MAX 0x0001
-#define _SC_BC_DIM_MAX 0x0002
-#define _SC_BC_SCALE_MAX 0x0003
-#define _SC_BC_STRING_MAX 0x0004
-#define _SC_CHILD_MAX 0x0005
-#define _SC_CLK_TCK 0x0006
-#define _SC_COLL_WEIGHTS_MAX 0x0007
-#define _SC_EXPR_NEST_MAX 0x0008
-#define _SC_LINE_MAX 0x0009
-#define _SC_NGROUPS_MAX 0x000a
-#define _SC_OPEN_MAX 0x000b
-#define _SC_PASS_MAX 0x000c
-#define _SC_2_C_BIND 0x000d
-#define _SC_2_C_DEV 0x000e
-#define _SC_2_C_VERSION 0x000f /* Obsolescent in POSIX.1-2008, TODO: remove it. */
-#define _SC_2_CHAR_TERM 0x0010
-#define _SC_2_FORT_DEV 0x0011
-#define _SC_2_FORT_RUN 0x0012
-#define _SC_2_LOCALEDEF 0x0013
-#define _SC_2_SW_DEV 0x0014
-#define _SC_2_UPE 0x0015
-#define _SC_2_VERSION 0x0016
-#define _SC_JOB_CONTROL 0x0017
-#define _SC_SAVED_IDS 0x0018
-#define _SC_VERSION 0x0019
-#define _SC_RE_DUP_MAX 0x001a
-#define _SC_STREAM_MAX 0x001b
-#define _SC_TZNAME_MAX 0x001c
-#define _SC_XOPEN_CRYPT 0x001d
-#define _SC_XOPEN_ENH_I18N 0x001e
-#define _SC_XOPEN_SHM 0x001f
-#define _SC_XOPEN_VERSION 0x0020
-#define _SC_XOPEN_XCU_VERSION 0x0021 /* Obsolescent in POSIX.1-2008, TODO: remove it. */
-#define _SC_XOPEN_REALTIME 0x0022
-#define _SC_XOPEN_REALTIME_THREADS 0x0023
-#define _SC_XOPEN_LEGACY 0x0024
-#define _SC_ATEXIT_MAX 0x0025
-#define _SC_IOV_MAX 0x0026
-#define _SC_PAGESIZE 0x0027
-#define _SC_PAGE_SIZE 0x0028
-#define _SC_XOPEN_UNIX 0x0029
-#define _SC_XBS5_ILP32_OFF32 0x002a /* Obsolescent in POSIX.1-2008, TODO: remove it. */
-#define _SC_XBS5_ILP32_OFFBIG 0x002b /* Obsolescent in POSIX.1-2008, TODO: remove it. */
-#define _SC_XBS5_LP64_OFF64 0x002c /* Obsolescent in POSIX.1-2008, TODO: remove it. */
-#define _SC_XBS5_LPBIG_OFFBIG 0x002d /* Obsolescent in POSIX.1-2008, TODO: remove it. */
-#define _SC_AIO_LISTIO_MAX 0x002e
-#define _SC_AIO_MAX 0x002f
-#define _SC_AIO_PRIO_DELTA_MAX 0x0030
-#define _SC_DELAYTIMER_MAX 0x0031
-#define _SC_MQ_OPEN_MAX 0x0032
-#define _SC_MQ_PRIO_MAX 0x0033
-#define _SC_RTSIG_MAX 0x0034
-#define _SC_SEM_NSEMS_MAX 0x0035
-#define _SC_SEM_VALUE_MAX 0x0036
-#define _SC_SIGQUEUE_MAX 0x0037
-#define _SC_TIMER_MAX 0x0038
-#define _SC_ASYNCHRONOUS_IO 0x0039
-#define _SC_FSYNC 0x003a
-#define _SC_MAPPED_FILES 0x003b
-#define _SC_MEMLOCK 0x003c
-#define _SC_MEMLOCK_RANGE 0x003d
-#define _SC_MEMORY_PROTECTION 0x003e
-#define _SC_MESSAGE_PASSING 0x003f
-#define _SC_PRIORITIZED_IO 0x0040
-#define _SC_PRIORITY_SCHEDULING 0x0041
-#define _SC_REALTIME_SIGNALS 0x0042
-#define _SC_SEMAPHORES 0x0043
-#define _SC_SHARED_MEMORY_OBJECTS 0x0044
-#define _SC_SYNCHRONIZED_IO 0x0045
-#define _SC_TIMERS 0x0046
-#define _SC_GETGR_R_SIZE_MAX 0x0047
-#define _SC_GETPW_R_SIZE_MAX 0x0048
-#define _SC_LOGIN_NAME_MAX 0x0049
-#define _SC_THREAD_DESTRUCTOR_ITERATIONS 0x004a
-#define _SC_THREAD_KEYS_MAX 0x004b
-#define _SC_THREAD_STACK_MIN 0x004c
-#define _SC_THREAD_THREADS_MAX 0x004d
-#define _SC_TTY_NAME_MAX 0x004e
-
-#define _SC_THREADS 0x004f
-#define _SC_THREAD_ATTR_STACKADDR 0x0050
-#define _SC_THREAD_ATTR_STACKSIZE 0x0051
-#define _SC_THREAD_PRIORITY_SCHEDULING 0x0052
-#define _SC_THREAD_PRIO_INHERIT 0x0053
-#define _SC_THREAD_PRIO_PROTECT 0x0054
-#define _SC_THREAD_SAFE_FUNCTIONS 0x0055
-
-#define _SC_NPROCESSORS_CONF 0x0060
-#define _SC_NPROCESSORS_ONLN 0x0061
-#define _SC_PHYS_PAGES 0x0062
-#define _SC_AVPHYS_PAGES 0x0063
-#define _SC_MONOTONIC_CLOCK 0x0064
-
-#define _SC_2_PBS 0x0065
-#define _SC_2_PBS_ACCOUNTING 0x0066
-#define _SC_2_PBS_CHECKPOINT 0x0067
-#define _SC_2_PBS_LOCATE 0x0068
-#define _SC_2_PBS_MESSAGE 0x0069
-#define _SC_2_PBS_TRACK 0x006a
-#define _SC_ADVISORY_INFO 0x006b
-#define _SC_BARRIERS 0x006c
-#define _SC_CLOCK_SELECTION 0x006d
-#define _SC_CPUTIME 0x006e
-#define _SC_HOST_NAME_MAX 0x006f
-#define _SC_IPV6 0x0070
-#define _SC_RAW_SOCKETS 0x0071
-#define _SC_READER_WRITER_LOCKS 0x0072
-#define _SC_REGEXP 0x0073
-#define _SC_SHELL 0x0074
-#define _SC_SPAWN 0x0075
-#define _SC_SPIN_LOCKS 0x0076
-#define _SC_SPORADIC_SERVER 0x0077
-#define _SC_SS_REPL_MAX 0x0078
-#define _SC_SYMLOOP_MAX 0x0079
-#define _SC_THREAD_CPUTIME 0x007a
-#define _SC_THREAD_PROCESS_SHARED 0x007b
-#define _SC_THREAD_ROBUST_PRIO_INHERIT 0x007c
-#define _SC_THREAD_ROBUST_PRIO_PROTECT 0x007d
-#define _SC_THREAD_SPORADIC_SERVER 0x007e
-#define _SC_TIMEOUTS 0x007f
-#define _SC_TRACE 0x0080
-#define _SC_TRACE_EVENT_FILTER 0x0081
-#define _SC_TRACE_EVENT_NAME_MAX 0x0082
-#define _SC_TRACE_INHERIT 0x0083
-#define _SC_TRACE_LOG 0x0084
-#define _SC_TRACE_NAME_MAX 0x0085
-#define _SC_TRACE_SYS_MAX 0x0086
-#define _SC_TRACE_USER_EVENT_MAX 0x0087
-#define _SC_TYPED_MEMORY_OBJECTS 0x0088
-#define _SC_V7_ILP32_OFF32 0x0089
-#define _SC_V7_ILP32_OFFBIG 0x008a
-#define _SC_V7_LP64_OFF64 0x008b
-#define _SC_V7_LPBIG_OFFBIG 0x008c
-#define _SC_XOPEN_STREAMS 0x008d
-#define _SC_XOPEN_UUCP 0x008e
-
-#define _SC_LEVEL1_ICACHE_SIZE 0x008f
-#define _SC_LEVEL1_ICACHE_ASSOC 0x0090
-#define _SC_LEVEL1_ICACHE_LINESIZE 0x0091
-#define _SC_LEVEL1_DCACHE_SIZE 0x0092
-#define _SC_LEVEL1_DCACHE_ASSOC 0x0093
-#define _SC_LEVEL1_DCACHE_LINESIZE 0x0094
-#define _SC_LEVEL2_CACHE_SIZE 0x0095
-#define _SC_LEVEL2_CACHE_ASSOC 0x0096
-#define _SC_LEVEL2_CACHE_LINESIZE 0x0097
-#define _SC_LEVEL3_CACHE_SIZE 0x0098
-#define _SC_LEVEL3_CACHE_ASSOC 0x0099
-#define _SC_LEVEL3_CACHE_LINESIZE 0x009a
-#define _SC_LEVEL4_CACHE_SIZE 0x009b
-#define _SC_LEVEL4_CACHE_ASSOC 0x009c
-#define _SC_LEVEL4_CACHE_LINESIZE 0x009d
-
-long sysconf(int);
-
-__END_DECLS
-
-#endif /* _SYS_SYSCONF_H_ */
+#include <bits/sysconf.h>
diff --git a/libc/include/termios.h b/libc/include/termios.h
index 683fde2..e604747 100644
--- a/libc/include/termios.h
+++ b/libc/include/termios.h
@@ -35,24 +35,22 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 21
-speed_t cfgetispeed(const struct termios*);
-speed_t cfgetospeed(const struct termios*);
-void cfmakeraw(struct termios*);
-int cfsetispeed(struct termios*, speed_t);
-int cfsetospeed(struct termios*, speed_t);
-int cfsetspeed(struct termios*, speed_t);
-int tcdrain(int);
-int tcflow(int, int);
-int tcflush(int, int);
-int tcgetattr(int, struct termios*);
-pid_t tcgetsid(int);
-int tcsendbreak(int, int);
-int tcsetattr(int, int, const struct termios*);
-#else
-#include <android/legacy_termios_inlines.h>
-#endif
+__BIONIC_LEGACY_INLINE speed_t cfgetispeed(const struct termios*);
+__BIONIC_LEGACY_INLINE speed_t cfgetospeed(const struct termios*);
+__BIONIC_LEGACY_INLINE void cfmakeraw(struct termios*);
+__BIONIC_LEGACY_INLINE int cfsetispeed(struct termios*, speed_t);
+__BIONIC_LEGACY_INLINE int cfsetospeed(struct termios*, speed_t);
+__BIONIC_LEGACY_INLINE int cfsetspeed(struct termios*, speed_t);
+__BIONIC_LEGACY_INLINE int tcdrain(int);
+__BIONIC_LEGACY_INLINE int tcflow(int, int);
+__BIONIC_LEGACY_INLINE int tcflush(int, int);
+__BIONIC_LEGACY_INLINE int tcgetattr(int, struct termios*);
+__BIONIC_LEGACY_INLINE pid_t tcgetsid(int);
+__BIONIC_LEGACY_INLINE int tcsendbreak(int, int);
+__BIONIC_LEGACY_INLINE int tcsetattr(int, int, const struct termios*);
__END_DECLS
+#include <android/legacy_termios_inlines.h>
+
#endif /* _TERMIOS_H_ */
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 2d62c1f..ea6c8a1 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -33,10 +33,13 @@
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/select.h>
-#include <sys/sysconf.h>
+#include <bits/fcntl.h>
+#include <bits/getopt.h>
+#include <bits/ioctl.h>
#include <bits/lockf.h>
#include <bits/posix_limits.h>
+#include <bits/sysconf.h>
__BEGIN_DECLS
@@ -161,8 +164,6 @@
extern int dup(int __oldfd);
extern int dup2(int __oldfd, int __newfd);
extern int dup3(int __oldfd, int __newfd, int __flags) __INTRODUCED_IN(21);
-extern int fcntl(int __fd, int __cmd, ...);
-extern int ioctl(int __fd, int __request, ...);
extern int fsync(int __fd);
extern int fdatasync(int __fd) __INTRODUCED_IN(9);
@@ -207,18 +208,12 @@
extern int brk(void* __addr);
extern void* sbrk(ptrdiff_t __increment);
-extern int getopt(int __argc, char* const* __argv, const char* __argstring);
-extern char* optarg;
-extern int optind, opterr, optopt;
-
extern int isatty(int __fd);
extern char* ttyname(int __fd);
extern int ttyname_r(int __fd, char* __buf, size_t __buflen) __INTRODUCED_IN(8);
extern int acct(const char* __filepath);
-long sysconf(int __name);
-
#if __ANDROID_API__ >= 21
int getpagesize(void);
#else
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 0a94cee..fe068be 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -97,7 +97,6 @@
extern size_t mbrtowc(wchar_t *, const char *, size_t, mbstate_t *);
extern size_t mbsrtowcs(wchar_t*, const char**, size_t, mbstate_t*);
extern size_t mbsnrtowcs(wchar_t*, const char**, size_t, size_t, mbstate_t*);
-extern size_t mbstowcs(wchar_t *, const char *, size_t);
extern wint_t putwc(wchar_t, FILE *);
extern wint_t putwchar(wchar_t);
extern int swprintf(wchar_t *, size_t, const wchar_t *, ...);
diff --git a/libc/libc.arm.brillo.map b/libc/libc.arm.brillo.map
index 651fea4..541dbb2 100644
--- a/libc/libc.arm.brillo.map
+++ b/libc/libc.arm.brillo.map
@@ -1434,7 +1434,7 @@
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
__truncdfsf2; # arm
- __udivdi3; # arm mips
+ __udivdi3; # arm x86 mips
__udivsi3; # arm
__unorddf2; # arm
__unordsf2; # arm
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 1c7a0ba..1784b95 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1445,7 +1445,7 @@
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
__truncdfsf2; # arm
- __udivdi3; # arm mips
+ __udivdi3; # arm x86 mips
__udivsi3; # arm
__unorddf2; # arm
__unordsf2; # arm
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index ed20efc..f51c5d3 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -207,7 +207,6 @@
__timer_getoverrun; # arm x86 mips
__timer_gettime; # arm x86 mips
__timer_settime; # arm x86 mips
- __udivdi3; # x86
__umask_chk;
__vsnprintf_chk;
__vsprintf_chk;
@@ -1471,7 +1470,7 @@
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
__truncdfsf2; # arm
- __udivdi3; # arm mips
+ __udivdi3; # arm x86 mips
__udivsi3; # arm
__umoddi3; # x86 mips
__unorddf2; # arm
diff --git a/libc/libc.mips.brillo.map b/libc/libc.mips.brillo.map
index d96de34..953fc29 100644
--- a/libc/libc.mips.brillo.map
+++ b/libc/libc.mips.brillo.map
@@ -1294,7 +1294,7 @@
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
- __udivdi3; # arm mips
+ __udivdi3; # arm x86 mips
__umoddi3; # x86 mips
_fwalk; # arm x86 mips
android_getaddrinfofornet;
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 5fe3a51..90db79d 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1305,7 +1305,7 @@
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
- __udivdi3; # arm mips
+ __udivdi3; # arm x86 mips
__umoddi3; # x86 mips
__wait4; # arm x86 mips nobrillo
_fwalk; # arm x86 mips
diff --git a/libc/libc.x86.brillo.map b/libc/libc.x86.brillo.map
index f167183..9f6cc52 100644
--- a/libc/libc.x86.brillo.map
+++ b/libc/libc.x86.brillo.map
@@ -203,7 +203,6 @@
__timer_getoverrun; # arm x86 mips
__timer_gettime; # arm x86 mips
__timer_settime; # arm x86 mips
- __udivdi3; # x86
__umask_chk;
__vsnprintf_chk;
__vsprintf_chk;
@@ -1294,6 +1293,7 @@
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
+ __udivdi3; # arm x86 mips
__umoddi3; # x86 mips
_fwalk; # arm x86 mips
android_getaddrinfofornet;
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index d37d28a..4443731 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -203,7 +203,6 @@
__timer_getoverrun; # arm x86 mips
__timer_gettime; # arm x86 mips
__timer_settime; # arm x86 mips
- __udivdi3; # x86
__umask_chk;
__vsnprintf_chk;
__vsprintf_chk;
@@ -1305,6 +1304,7 @@
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
+ __udivdi3; # arm x86 mips
__umoddi3; # x86 mips
__wait4; # arm x86 mips nobrillo
_fwalk; # arm x86 mips
diff --git a/libc/malloc_debug/BacktraceData.cpp b/libc/malloc_debug/BacktraceData.cpp
index 400e282..3d46bf0 100644
--- a/libc/malloc_debug/BacktraceData.cpp
+++ b/libc/malloc_debug/BacktraceData.cpp
@@ -41,27 +41,24 @@
#include "debug_log.h"
#include "malloc_debug.h"
-BacktraceData::BacktraceData(const Config& config, size_t* offset) {
+static void EnableToggle(int, siginfo_t*, void*) {
+ if (g_debug->backtrace->enabled()) {
+ g_debug->backtrace->set_enabled(false);
+ } else {
+ g_debug->backtrace->set_enabled(true);
+ }
+}
+
+BacktraceData::BacktraceData(DebugData* debug_data, const Config& config, size_t* offset)
+ : OptionData(debug_data) {
size_t hdr_len = sizeof(BacktraceHeader) + sizeof(uintptr_t) * config.backtrace_frames;
alloc_offset_ = *offset;
*offset += BIONIC_ALIGN(hdr_len, MINIMUM_ALIGNMENT_BYTES);
}
-static BacktraceData* g_backtrace_data = nullptr;
-
-static void EnableToggle(int, siginfo_t*, void*) {
- if (g_backtrace_data->enabled()) {
- g_backtrace_data->set_enabled(false);
- } else {
- g_backtrace_data->set_enabled(true);
- }
-}
-
bool BacktraceData::Initialize(const Config& config) {
enabled_ = config.backtrace_enabled;
if (config.backtrace_enable_on_signal) {
- g_backtrace_data = this;
-
struct sigaction enable_act;
memset(&enable_act, 0, sizeof(enable_act));
diff --git a/libc/malloc_debug/BacktraceData.h b/libc/malloc_debug/BacktraceData.h
index 842e372..dbc3989 100644
--- a/libc/malloc_debug/BacktraceData.h
+++ b/libc/malloc_debug/BacktraceData.h
@@ -33,12 +33,14 @@
#include <private/bionic_macros.h>
+#include "OptionData.h"
+
// Forward declarations.
struct Config;
-class BacktraceData {
+class BacktraceData : public OptionData {
public:
- BacktraceData(const Config& config, size_t* offset);
+ BacktraceData(DebugData* debug_data, const Config& config, size_t* offset);
virtual ~BacktraceData() = default;
bool Initialize(const Config& config);
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index ded618c..cc60086 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -273,7 +273,7 @@
fill_free_value = DEFAULT_FILL_FREE_VALUE;
front_guard_value = DEFAULT_FRONT_GUARD_VALUE;
rear_guard_value = DEFAULT_REAR_GUARD_VALUE;
- backtrace_signal = SIGRTMIN + 10;
+ backtrace_signal = SIGRTMAX - 19;
free_track_backtrace_num_frames = 16;
// Parse the options are of the format:
diff --git a/libc/malloc_debug/Config.h b/libc/malloc_debug/Config.h
index cb1de5a..3ee93b2 100644
--- a/libc/malloc_debug/Config.h
+++ b/libc/malloc_debug/Config.h
@@ -49,8 +49,8 @@
constexpr size_t MINIMUM_ALIGNMENT_BYTES = 8;
#endif
-// If only one or more of these options is set, then no special header is needed.
-constexpr uint64_t NO_HEADER_OPTIONS = FILL_ON_ALLOC | FILL_ON_FREE | EXPAND_ALLOC;
+// If one or more of these options is set, then a special header is needed.
+constexpr uint64_t HEADER_OPTIONS = FRONT_GUARD | REAR_GUARD | BACKTRACE | FREE_TRACK | LEAK_TRACK;
struct Config {
bool SetFromProperties();
diff --git a/libc/malloc_debug/DebugData.cpp b/libc/malloc_debug/DebugData.cpp
index 0447566..58cbbcb 100644
--- a/libc/malloc_debug/DebugData.cpp
+++ b/libc/malloc_debug/DebugData.cpp
@@ -43,37 +43,37 @@
}
// Check to see if the options that require a header are enabled.
- if ((config_.options & ~(NO_HEADER_OPTIONS)) != 0) {
+ if (config_.options & HEADER_OPTIONS) {
need_header_ = true;
// Initialize all of the static header offsets.
pointer_offset_ = BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
if (config_.options & BACKTRACE) {
- backtrace.reset(new BacktraceData(config_, &pointer_offset_));
+ backtrace.reset(new BacktraceData(this, config_, &pointer_offset_));
if (!backtrace->Initialize(config_)) {
return false;
}
}
if (config_.options & FRONT_GUARD) {
- front_guard.reset(new FrontGuardData(config_, &pointer_offset_));
+ front_guard.reset(new FrontGuardData(this, config_, &pointer_offset_));
}
extra_bytes_ = pointer_offset_;
// Initialize all of the non-header data.
if (config_.options & REAR_GUARD) {
- rear_guard.reset(new RearGuardData(config_));
+ rear_guard.reset(new RearGuardData(this, config_));
extra_bytes_ += config_.rear_guard_bytes;
}
if (config_.options & FREE_TRACK) {
- free_track.reset(new FreeTrackData(config_));
+ free_track.reset(new FreeTrackData(this, config_));
}
if (config_.options & TRACK_ALLOCS) {
- track.reset(new TrackData());
+ track.reset(new TrackData(this));
}
}
diff --git a/libc/malloc_debug/DebugData.h b/libc/malloc_debug/DebugData.h
index 4600b33..7e55512 100644
--- a/libc/malloc_debug/DebugData.h
+++ b/libc/malloc_debug/DebugData.h
@@ -103,4 +103,6 @@
DISALLOW_COPY_AND_ASSIGN(DebugData);
};
+extern DebugData* g_debug;
+
#endif // MALLOC_DEBUG_DEBUGDATA_H
diff --git a/libc/malloc_debug/FreeTrackData.cpp b/libc/malloc_debug/FreeTrackData.cpp
index ed41981..8e6502e 100644
--- a/libc/malloc_debug/FreeTrackData.cpp
+++ b/libc/malloc_debug/FreeTrackData.cpp
@@ -36,22 +36,19 @@
#include "FreeTrackData.h"
#include "malloc_debug.h"
-FreeTrackData::FreeTrackData(const Config& config)
- : backtrace_num_frames_(config.free_track_backtrace_num_frames) {
+FreeTrackData::FreeTrackData(DebugData* debug, const Config& config)
+ : OptionData(debug), backtrace_num_frames_(config.free_track_backtrace_num_frames) {
cmp_mem_.resize(4096);
memset(cmp_mem_.data(), config.fill_free_value, cmp_mem_.size());
}
-void FreeTrackData::LogFreeError(DebugData& debug, const Header* header,
- const uint8_t* pointer) {
- ScopedDisableDebugCalls disable;
-
+void FreeTrackData::LogFreeError(const Header* header, const uint8_t* pointer) {
error_log(LOG_DIVIDER);
error_log("+++ ALLOCATION %p USED AFTER FREE", pointer);
- uint8_t fill_free_value = debug.config().fill_free_value;
+ uint8_t fill_free_value = debug_->config().fill_free_value;
for (size_t i = 0; i < header->usable_size; i++) {
if (pointer[i] != fill_free_value) {
- error_log(" pointer[%zu] = 0x%02x (expected 0x%02x)", i, pointer[i], fill_free_value);
+ error_log(" allocation[%zu] = 0x%02x (expected 0x%02x)", i, pointer[i], fill_free_value);
}
}
auto back_iter = backtraces_.find(header);
@@ -63,10 +60,8 @@
error_log(LOG_DIVIDER);
}
-void FreeTrackData::VerifyAndFree(DebugData& debug, const Header* header,
- const void* pointer) {
- ScopedDisableDebugCalls disable;
-
+void FreeTrackData::VerifyAndFree(const Header* header) {
+ const void* pointer = debug_->GetPointer(header);
if (header->tag != DEBUG_FREE_TAG) {
error_log(LOG_DIVIDER);
error_log("+++ ALLOCATION %p HAS CORRUPTED HEADER TAG 0x%x AFTER FREE", pointer, header->tag);
@@ -74,11 +69,12 @@
} else {
const uint8_t* memory = reinterpret_cast<const uint8_t*>(pointer);
size_t bytes = header->usable_size;
- bytes = (bytes < debug.config().fill_on_free_bytes) ? bytes : debug.config().fill_on_free_bytes;
+ bytes = (bytes < debug_->config().fill_on_free_bytes) ? bytes
+ : debug_->config().fill_on_free_bytes;
while (bytes > 0) {
size_t bytes_to_cmp = (bytes < cmp_mem_.size()) ? bytes : cmp_mem_.size();
if (memcmp(memory, cmp_mem_.data(), bytes_to_cmp) != 0) {
- LogFreeError(debug, header, reinterpret_cast<const uint8_t*>(pointer));
+ LogFreeError(header, reinterpret_cast<const uint8_t*>(pointer));
break;
}
bytes -= bytes_to_cmp;
@@ -94,14 +90,11 @@
g_dispatch->free(header->orig_pointer);
}
-void FreeTrackData::Add(DebugData& debug, const Header* header) {
- // Make sure the stl calls below don't call the debug_XXX functions.
- ScopedDisableDebugCalls disable;
-
+void FreeTrackData::Add(const Header* header) {
pthread_mutex_lock(&mutex_);
- if (list_.size() == debug.config().free_track_allocations) {
+ if (list_.size() == debug_->config().free_track_allocations) {
const Header* old_header = list_.back();
- VerifyAndFree(debug, old_header, debug.GetPointer(old_header));
+ VerifyAndFree(old_header);
list_.pop_back();
}
@@ -118,19 +111,14 @@
pthread_mutex_unlock(&mutex_);
}
-void FreeTrackData::VerifyAll(DebugData& debug) {
- // Make sure the stl calls below don't call the debug_XXX functions.
- ScopedDisableDebugCalls disable;
-
+void FreeTrackData::VerifyAll() {
for (const auto& header : list_) {
- VerifyAndFree(debug, header, debug.GetPointer(header));
+ VerifyAndFree(header);
}
list_.clear();
}
void FreeTrackData::LogBacktrace(const Header* header) {
- ScopedDisableDebugCalls disable;
-
auto back_iter = backtraces_.find(header);
if (back_iter == backtraces_.end()) {
return;
diff --git a/libc/malloc_debug/FreeTrackData.h b/libc/malloc_debug/FreeTrackData.h
index 804b5a6..21f845f 100644
--- a/libc/malloc_debug/FreeTrackData.h
+++ b/libc/malloc_debug/FreeTrackData.h
@@ -38,26 +38,28 @@
#include <private/bionic_macros.h>
-// Forward declarations.
-struct Header;
-class DebugData;
-struct Config;
-struct BacktraceHeader;
+#include "OptionData.h"
-class FreeTrackData {
+// Forward declarations.
+struct BacktraceHeader;
+struct Config;
+class DebugData;
+struct Header;
+
+class FreeTrackData : public OptionData {
public:
- FreeTrackData(const Config& config);
+ FreeTrackData(DebugData* debug_data, const Config& config);
virtual ~FreeTrackData() = default;
- void Add(DebugData& debug, const Header* header);
+ void Add(const Header* header);
- void VerifyAll(DebugData& debug);
+ void VerifyAll();
void LogBacktrace(const Header* header);
private:
- void LogFreeError(DebugData& debug, const Header* header, const uint8_t* pointer);
- void VerifyAndFree(DebugData& debug, const Header* header, const void* pointer);
+ void LogFreeError(const Header* header, const uint8_t* pointer);
+ void VerifyAndFree(const Header* header);
pthread_mutex_t mutex_ = PTHREAD_MUTEX_INITIALIZER;
std::deque<const Header*> list_;
diff --git a/libc/malloc_debug/GuardData.cpp b/libc/malloc_debug/GuardData.cpp
index c70e8f1..e207b86 100644
--- a/libc/malloc_debug/GuardData.cpp
+++ b/libc/malloc_debug/GuardData.cpp
@@ -39,15 +39,14 @@
#include "malloc_debug.h"
#include "GuardData.h"
-GuardData::GuardData(int init_value, size_t num_bytes) {
+GuardData::GuardData(DebugData* debug_data, int init_value, size_t num_bytes)
+ : OptionData(debug_data) {
// Create a buffer for fast comparisons of the front guard.
cmp_mem_.resize(num_bytes);
memset(cmp_mem_.data(), init_value, cmp_mem_.size());
}
void GuardData::LogFailure(const Header* header, const void* pointer, const void* data) {
- ScopedDisableDebugCalls disable;
-
error_log(LOG_DIVIDER);
error_log("+++ ALLOCATION %p SIZE %zu HAS A CORRUPTED %s GUARD", pointer,
header->real_size(), GetTypeName());
@@ -58,7 +57,7 @@
const uint8_t* real = reinterpret_cast<const uint8_t*>(data);
for (size_t i = 0; i < cmp_mem_.size(); i++, pointer_idx++) {
if (real[i] != expected[i]) {
- error_log(" pointer[%d] = 0x%02x (expected 0x%02x)", pointer_idx, real[i], expected[i]);
+ error_log(" allocation[%d] = 0x%02x (expected 0x%02x)", pointer_idx, real[i], expected[i]);
}
}
@@ -70,8 +69,8 @@
error_log(LOG_DIVIDER);
}
-FrontGuardData::FrontGuardData(const Config& config, size_t* offset)
- : GuardData(config.front_guard_value, config.front_guard_bytes) {
+FrontGuardData::FrontGuardData(DebugData* debug_data, const Config& config, size_t* offset)
+ : GuardData(debug_data, config.front_guard_value, config.front_guard_bytes) {
// Create a buffer for fast comparisons of the front guard.
cmp_mem_.resize(config.front_guard_bytes);
memset(cmp_mem_.data(), config.front_guard_value, cmp_mem_.size());
@@ -80,22 +79,22 @@
*offset += config.front_guard_bytes;
}
-bool FrontGuardData::Valid(DebugData& debug, const Header* header) {
- return GuardData::Valid(debug.GetFrontGuard(header));
+bool FrontGuardData::Valid(const Header* header) {
+ return GuardData::Valid(debug_->GetFrontGuard(header));
}
-void FrontGuardData::LogFailure(DebugData& debug, const Header* header) {
- GuardData::LogFailure(header, debug.GetPointer(header), debug.GetFrontGuard(header));
+void FrontGuardData::LogFailure(const Header* header) {
+ GuardData::LogFailure(header, debug_->GetPointer(header), debug_->GetFrontGuard(header));
}
-RearGuardData::RearGuardData(const Config& config)
- : GuardData(config.rear_guard_value, config.rear_guard_bytes) {
+RearGuardData::RearGuardData(DebugData* debug_data, const Config& config)
+ : GuardData(debug_data, config.rear_guard_value, config.rear_guard_bytes) {
}
-bool RearGuardData::Valid(DebugData& debug, const Header* header) {
- return GuardData::Valid(debug.GetRearGuard(header));
+bool RearGuardData::Valid(const Header* header) {
+ return GuardData::Valid(debug_->GetRearGuard(header));
}
-void RearGuardData::LogFailure(DebugData& debug, const Header* header) {
- GuardData::LogFailure(header, debug.GetPointer(header), debug.GetRearGuard(header));
+void RearGuardData::LogFailure(const Header* header) {
+ GuardData::LogFailure(header, debug_->GetPointer(header), debug_->GetRearGuard(header));
}
diff --git a/libc/malloc_debug/GuardData.h b/libc/malloc_debug/GuardData.h
index 4de2702..bfb3949 100644
--- a/libc/malloc_debug/GuardData.h
+++ b/libc/malloc_debug/GuardData.h
@@ -36,14 +36,16 @@
#include <private/bionic_macros.h>
+#include "OptionData.h"
+
// Forward declarations.
class DebugData;
struct Header;
struct Config;
-class GuardData {
+class GuardData : public OptionData {
public:
- GuardData(int init_value, size_t num_bytes);
+ GuardData(DebugData* debug_data, int init_value, size_t num_bytes);
virtual ~GuardData() = default;
bool Valid(void* data) { return memcmp(data, cmp_mem_.data(), cmp_mem_.size()) == 0; }
@@ -60,12 +62,12 @@
class FrontGuardData : public GuardData {
public:
- FrontGuardData(const Config& config, size_t* offset);
+ FrontGuardData(DebugData* debug_data, const Config& config, size_t* offset);
virtual ~FrontGuardData() = default;
- bool Valid(DebugData& debug, const Header* header);
+ bool Valid(const Header* header);
- void LogFailure(DebugData& debug, const Header* header);
+ void LogFailure(const Header* header);
size_t offset() { return offset_; }
@@ -79,12 +81,12 @@
class RearGuardData : public GuardData {
public:
- RearGuardData(const Config& config);
+ RearGuardData(DebugData* debug_data, const Config& config);
virtual ~RearGuardData() = default;
- bool Valid(DebugData& debug, const Header* header);
+ bool Valid(const Header* header);
- void LogFailure(DebugData& debug, const Header* header);
+ void LogFailure(const Header* header);
private:
const char* GetTypeName() override { return "REAR"; }
diff --git a/libc/malloc_debug/OptionData.h b/libc/malloc_debug/OptionData.h
new file mode 100644
index 0000000..80190f5
--- /dev/null
+++ b/libc/malloc_debug/OptionData.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef DEBUG_MALLOC_OPTIONDATA_H
+#define DEBUG_MALLOC_OPTIONDATA_H
+
+// Forward Declarations
+class DebugData;
+
+class OptionData {
+ public:
+ OptionData(DebugData* debug) : debug_(debug) {}
+ ~OptionData() = default;
+
+ protected:
+ DebugData* debug_;
+
+ DISALLOW_COPY_AND_ASSIGN(OptionData);
+};
+
+#endif // MALLOC_DEBUG_OPTIONDATA_H
diff --git a/libc/malloc_debug/TrackData.cpp b/libc/malloc_debug/TrackData.cpp
index c9828d0..18f428b 100644
--- a/libc/malloc_debug/TrackData.cpp
+++ b/libc/malloc_debug/TrackData.cpp
@@ -44,9 +44,10 @@
#include "malloc_debug.h"
#include "TrackData.h"
-void TrackData::GetList(std::vector<const Header*>* list) {
- ScopedDisableDebugCalls disable;
+TrackData::TrackData(DebugData* debug_data) : OptionData(debug_data) {
+}
+void TrackData::GetList(std::vector<const Header*>* list) {
for (const auto& header : headers_) {
list->push_back(header);
}
@@ -59,8 +60,6 @@
}
void TrackData::Add(const Header* header, bool backtrace_found) {
- ScopedDisableDebugCalls disable;
-
pthread_mutex_lock(&mutex_);
if (backtrace_found) {
total_backtrace_allocs_++;
@@ -70,8 +69,6 @@
}
void TrackData::Remove(const Header* header, bool backtrace_found) {
- ScopedDisableDebugCalls disable;
-
pthread_mutex_lock(&mutex_);
headers_.erase(header);
if (backtrace_found) {
@@ -81,26 +78,22 @@
}
bool TrackData::Contains(const Header* header) {
- ScopedDisableDebugCalls disable;
-
pthread_mutex_lock(&mutex_);
bool found = headers_.count(header);
pthread_mutex_unlock(&mutex_);
return found;
}
-void TrackData::DisplayLeaks(DebugData& debug) {
- ScopedDisableDebugCalls disable;
-
+void TrackData::DisplayLeaks() {
std::vector<const Header*> list;
GetList(&list);
size_t track_count = 0;
for (const auto& header : list) {
error_log("+++ %s leaked block of size %zu at %p (leak %zu of %zu)", getprogname(),
- header->real_size(), debug.GetPointer(header), ++track_count, list.size());
- if (debug.config().options & BACKTRACE) {
- BacktraceHeader* back_header = debug.GetAllocBacktrace(header);
+ header->real_size(), debug_->GetPointer(header), ++track_count, list.size());
+ if (debug_->config().options & BACKTRACE) {
+ BacktraceHeader* back_header = debug_->GetAllocBacktrace(header);
if (back_header->num_frames > 0) {
error_log("Backtrace at time of allocation:");
backtrace_log(&back_header->frames[0], back_header->num_frames);
@@ -110,15 +103,15 @@
}
}
-void TrackData::GetInfo(DebugData& debug, uint8_t** info, size_t* overall_size,
- size_t* info_size, size_t* total_memory, size_t* backtrace_size) {
+void TrackData::GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size,
+ size_t* total_memory, size_t* backtrace_size) {
ScopedPthreadMutexLocker scoped(&mutex_);
if (headers_.size() == 0 || total_backtrace_allocs_ == 0) {
return;
}
- *backtrace_size = debug.config().backtrace_frames;
+ *backtrace_size = debug_->config().backtrace_frames;
*info_size = sizeof(size_t) * 2 + sizeof(uintptr_t) * *backtrace_size;
*info = reinterpret_cast<uint8_t*>(g_dispatch->calloc(*info_size, total_backtrace_allocs_));
if (*info == nullptr) {
@@ -131,7 +124,7 @@
uint8_t* data = *info;
for (const auto& header : list) {
- BacktraceHeader* back_header = debug.GetAllocBacktrace(header);
+ BacktraceHeader* back_header = debug_->GetAllocBacktrace(header);
if (back_header->num_frames > 0) {
memcpy(data, &header->size, sizeof(size_t));
memcpy(&data[sizeof(size_t)], &back_header->num_frames, sizeof(size_t));
diff --git a/libc/malloc_debug/TrackData.h b/libc/malloc_debug/TrackData.h
index 1234316..fcd8f2a 100644
--- a/libc/malloc_debug/TrackData.h
+++ b/libc/malloc_debug/TrackData.h
@@ -37,14 +37,16 @@
#include <private/bionic_macros.h>
+#include "OptionData.h"
+
// Forward declarations.
struct Header;
struct Config;
class DebugData;
-class TrackData {
+class TrackData : public OptionData {
public:
- TrackData() = default;
+ TrackData(DebugData* debug_data);
virtual ~TrackData() = default;
void GetList(std::vector<const Header*>* list);
@@ -55,10 +57,10 @@
bool Contains(const Header *header);
- void GetInfo(DebugData& debug, uint8_t** info, size_t* overall_size,
- size_t* info_size, size_t* total_memory, size_t* backtrace_size);
+ void GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size,
+ size_t* total_memory, size_t* backtrace_size);
- void DisplayLeaks(DebugData& debug);
+ void DisplayLeaks();
void PrepareFork() { pthread_mutex_lock(&mutex_); }
void PostForkParent() { pthread_mutex_unlock(&mutex_); }
diff --git a/libc/malloc_debug/debug_disable.cpp b/libc/malloc_debug/debug_disable.cpp
index af0264b..b80ba8c 100644
--- a/libc/malloc_debug/debug_disable.cpp
+++ b/libc/malloc_debug/debug_disable.cpp
@@ -32,7 +32,6 @@
#include "debug_disable.h"
#include "debug_log.h"
-extern DebugData* g_debug;
pthread_key_t g_disable_key;
bool DebugCallsDisabled() {
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 1ee7689..5da5b88 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -114,8 +114,6 @@
}
static void LogTagError(const Header* header, const void* pointer, const char* name) {
- ScopedDisableDebugCalls disable;
-
error_log(LOG_DIVIDER);
if (header->tag == DEBUG_FREE_TAG) {
error_log("+++ ALLOCATION %p USED AFTER FREE (%s)", pointer, name);
@@ -165,7 +163,6 @@
if (g_debug->config().options & BACKTRACE) {
BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
if (g_debug->backtrace->enabled()) {
- ScopedDisableDebugCalls disable;
back_header->num_frames = backtrace_get(
&back_header->frames[0], g_debug->config().backtrace_frames);
backtrace_found = back_header->num_frames > 0;
@@ -217,11 +214,11 @@
}
if (g_debug->config().options & FREE_TRACK) {
- g_debug->free_track->VerifyAll(*g_debug);
+ g_debug->free_track->VerifyAll();
}
if (g_debug->config().options & LEAK_TRACK) {
- g_debug->track->DisplayLeaks(*g_debug);
+ g_debug->track->DisplayLeaks();
}
DebugDisableSet(true);
@@ -257,32 +254,37 @@
return;
}
- g_debug->track->GetInfo(*g_debug, info, overall_size, info_size, total_memory, backtrace_size);
+ g_debug->track->GetInfo(info, overall_size, info_size, total_memory, backtrace_size);
}
void debug_free_malloc_leak_info(uint8_t* info) {
g_dispatch->free(info);
}
-size_t debug_malloc_usable_size(void* pointer) {
- if (DebugCallsDisabled() || !g_debug->need_header() || pointer == nullptr) {
+static size_t internal_malloc_usable_size(void* pointer) {
+ if (g_debug->need_header()) {
+ Header* header = g_debug->GetHeader(pointer);
+ if (header->tag != DEBUG_TAG) {
+ LogTagError(header, pointer, "malloc_usable_size");
+ return 0;
+ }
+
+ return header->usable_size;
+ } else {
return g_dispatch->malloc_usable_size(pointer);
}
-
- Header* header = g_debug->GetHeader(pointer);
- if (header->tag != DEBUG_TAG) {
- LogTagError(header, pointer, "malloc_usable_size");
- return 0;
- }
-
- return header->usable_size;
}
-void* debug_malloc(size_t size) {
- if (DebugCallsDisabled()) {
- return g_dispatch->malloc(size);
+size_t debug_malloc_usable_size(void* pointer) {
+ if (DebugCallsDisabled() || pointer == nullptr) {
+ return g_dispatch->malloc_usable_size(pointer);
}
+ ScopedDisableDebugCalls disable;
+ return internal_malloc_usable_size(pointer);
+}
+
+static void *internal_malloc(size_t size) {
if (size == 0) {
size = 1;
}
@@ -312,7 +314,7 @@
}
if (pointer != nullptr && g_debug->config().options & FILL_ON_ALLOC) {
- size_t bytes = debug_malloc_usable_size(pointer);
+ size_t bytes = internal_malloc_usable_size(pointer);
size_t fill_bytes = g_debug->config().fill_on_alloc_bytes;
bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
memset(pointer, g_debug->config().fill_alloc_value, bytes);
@@ -320,11 +322,16 @@
return pointer;
}
-void debug_free(void* pointer) {
- if (DebugCallsDisabled() || pointer == nullptr) {
- return g_dispatch->free(pointer);
+void* debug_malloc(size_t size) {
+ if (DebugCallsDisabled()) {
+ return g_dispatch->malloc(size);
}
+ ScopedDisableDebugCalls disable;
+ return internal_malloc(size);
+}
+
+static void internal_free(void* pointer) {
void* free_pointer = pointer;
size_t bytes;
Header* header;
@@ -337,13 +344,13 @@
free_pointer = header->orig_pointer;
if (g_debug->config().options & FRONT_GUARD) {
- if (!g_debug->front_guard->Valid(*g_debug, header)) {
- g_debug->front_guard->LogFailure(*g_debug, header);
+ if (!g_debug->front_guard->Valid(header)) {
+ g_debug->front_guard->LogFailure(header);
}
}
if (g_debug->config().options & REAR_GUARD) {
- if (!g_debug->rear_guard->Valid(*g_debug, header)) {
- g_debug->rear_guard->LogFailure(*g_debug, header);
+ if (!g_debug->rear_guard->Valid(header)) {
+ g_debug->rear_guard->LogFailure(header);
}
}
@@ -374,16 +381,26 @@
// frees at the same time and we wind up trying to really free this
// pointer from another thread, while still trying to free it in
// this function.
- g_debug->free_track->Add(*g_debug, header);
+ g_debug->free_track->Add(header);
} else {
g_dispatch->free(free_pointer);
}
}
+void debug_free(void* pointer) {
+ if (DebugCallsDisabled() || pointer == nullptr) {
+ return g_dispatch->free(pointer);
+ }
+ ScopedDisableDebugCalls disable;
+
+ internal_free(pointer);
+}
+
void* debug_memalign(size_t alignment, size_t bytes) {
if (DebugCallsDisabled()) {
return g_dispatch->memalign(alignment, bytes);
}
+ ScopedDisableDebugCalls disable;
if (bytes == 0) {
bytes = 1;
@@ -438,11 +455,12 @@
}
if (pointer != nullptr && g_debug->config().options & FILL_ON_ALLOC) {
- size_t bytes = debug_malloc_usable_size(pointer);
+ size_t bytes = internal_malloc_usable_size(pointer);
size_t fill_bytes = g_debug->config().fill_on_alloc_bytes;
bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
memset(pointer, g_debug->config().fill_alloc_value, bytes);
}
+
return pointer;
}
@@ -450,13 +468,14 @@
if (DebugCallsDisabled()) {
return g_dispatch->realloc(pointer, bytes);
}
+ ScopedDisableDebugCalls disable;
if (pointer == nullptr) {
- return debug_malloc(bytes);
+ return internal_malloc(bytes);
}
if (bytes == 0) {
- debug_free(pointer);
+ internal_free(pointer);
return nullptr;
}
@@ -486,6 +505,7 @@
// Same size, do nothing.
if (real_size == header->real_size()) {
+ // Do not bother recording, this is essentially a nop.
return pointer;
}
@@ -502,11 +522,12 @@
memset(g_debug->GetRearGuard(header), g_debug->config().rear_guard_value,
g_debug->config().rear_guard_bytes);
}
+ // Do not bother recording, this is essentially a nop.
return pointer;
}
// Allocate the new size.
- new_pointer = debug_malloc(bytes);
+ new_pointer = internal_malloc(bytes);
if (new_pointer == nullptr) {
errno = ENOMEM;
return nullptr;
@@ -514,7 +535,7 @@
prev_size = header->usable_size;
memcpy(new_pointer, pointer, prev_size);
- debug_free(pointer);
+ internal_free(pointer);
} else {
prev_size = g_dispatch->malloc_usable_size(pointer);
new_pointer = g_dispatch->realloc(pointer, real_size);
@@ -524,7 +545,7 @@
}
if (g_debug->config().options & FILL_ON_ALLOC) {
- size_t bytes = debug_malloc_usable_size(new_pointer);
+ size_t bytes = internal_malloc_usable_size(new_pointer);
if (bytes > g_debug->config().fill_on_alloc_bytes) {
bytes = g_debug->config().fill_on_alloc_bytes;
}
@@ -541,6 +562,7 @@
if (DebugCallsDisabled()) {
return g_dispatch->calloc(nmemb, bytes);
}
+ ScopedDisableDebugCalls disable;
size_t size;
if (__builtin_mul_overflow(nmemb, bytes, &size)) {
@@ -645,6 +667,7 @@
if (DebugCallsDisabled() || pointer == nullptr) {
return 0;
}
+ ScopedDisableDebugCalls disable;
if (g_debug->need_header()) {
Header* header;
diff --git a/libc/include/sys/_errdefs.h b/libc/private/bionic_errdefs.h
similarity index 100%
rename from libc/include/sys/_errdefs.h
rename to libc/private/bionic_errdefs.h
diff --git a/libc/include/sys/_sigdefs.h b/libc/private/bionic_sigdefs.h
similarity index 100%
rename from libc/include/sys/_sigdefs.h
rename to libc/private/bionic_sigdefs.h
diff --git a/libc/upstream-netbsd/lib/libc/gen/ftw.c b/libc/upstream-netbsd/lib/libc/gen/ftw.c
deleted file mode 100644
index a7f6bbd..0000000
--- a/libc/upstream-netbsd/lib/libc/gen/ftw.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/* $NetBSD: ftw.c,v 1.1 2005/12/30 23:07:32 agc Exp $ */
-
-/* From OpenBSD: ftw.c,v 1.2 2003/07/21 21:15:32 millert Exp */
-
-/*
- * Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Sponsored in part by the Defense Advanced Research Projects
- * Agency (DARPA) and Air Force Research Laboratory, Air Force
- * Materiel Command, USAF, under agreement number F39502-99-1-0512.
- */
-#include <sys/cdefs.h>
-
-#ifndef lint
-__RCSID("$NetBSD: ftw.c,v 1.1 2005/12/30 23:07:32 agc Exp $");
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <fts.h>
-#include <ftw.h>
-#include <limits.h>
-
-int
-ftw(const char *path, int (*fn)(const char *, const struct stat *, int),
- int nfds)
-{
- /* LINTED */
- char * const paths[2] = { __UNCONST(path), NULL };
- FTSENT *cur;
- FTS *ftsp;
- int fnflag, error, sverrno;
-
- /* XXX - nfds is currently unused */
- if (nfds < 1 || nfds > OPEN_MAX) {
- errno = EINVAL;
- return (-1);
- }
-
- ftsp = fts_open(paths, FTS_COMFOLLOW | FTS_NOCHDIR, NULL);
- if (ftsp == NULL)
- return (-1);
- error = 0;
- while ((cur = fts_read(ftsp)) != NULL) {
- switch (cur->fts_info) {
- case FTS_D:
- fnflag = FTW_D;
- break;
- case FTS_DNR:
- fnflag = FTW_DNR;
- break;
- case FTS_DP:
- /* we only visit in preorder */
- continue;
- case FTS_F:
- case FTS_DEFAULT:
- fnflag = FTW_F;
- break;
- case FTS_NS:
- case FTS_NSOK:
- case FTS_SLNONE:
- fnflag = FTW_NS;
- break;
- case FTS_SL:
- fnflag = FTW_SL;
- break;
- case FTS_DC:
- errno = ELOOP;
- /* FALLTHROUGH */
- default:
- error = -1;
- goto done;
- }
- error = fn(cur->fts_path, cur->fts_statp, fnflag);
- if (error != 0)
- break;
- }
-done:
- sverrno = errno;
- if (fts_close(ftsp) != 0 && error == 0)
- error = -1;
- else
- errno = sverrno;
- return (error);
-}
diff --git a/libc/upstream-netbsd/lib/libc/gen/nftw.c b/libc/upstream-netbsd/lib/libc/gen/nftw.c
deleted file mode 100644
index 0e51342..0000000
--- a/libc/upstream-netbsd/lib/libc/gen/nftw.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* $NetBSD */
-
-/* From OpenBSD: nftw.c,v 1.2 2003/07/21 21:15:32 millert Exp */
-
-/*
- * Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Sponsored in part by the Defense Advanced Research Projects
- * Agency (DARPA) and Air Force Research Laboratory, Air Force
- * Materiel Command, USAF, under agreement number F39502-99-1-0512.
- */
-
-#include <sys/cdefs.h>
-
-#ifndef lint
-__RCSID("$NetBSD: nftw.c,v 1.1 2005/12/30 23:07:32 agc Exp $");
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <fts.h>
-#include <ftw.h>
-#include <limits.h>
-
-int
-nftw(const char *path, int (*fn)(const char *, const struct stat *, int,
- struct FTW *), int nfds, int ftwflags)
-{
- /* LINTED */
- char * const paths[2] = { __UNCONST(path), NULL };
- struct FTW f;
- FTSENT *cur;
- FTS *ftsp;
- int ftsflags, fnflag, error, postorder, sverrno;
-
- /* XXX - nfds is currently unused */
- if (nfds < 1 || nfds > OPEN_MAX) {
- errno = EINVAL;
- return (-1);
- }
-
- ftsflags = FTS_COMFOLLOW;
- if (!(ftwflags & FTW_CHDIR))
- ftsflags |= FTS_NOCHDIR;
- if (ftwflags & FTW_MOUNT)
- ftsflags |= FTS_XDEV;
- if (ftwflags & FTW_PHYS)
- ftsflags |= FTS_PHYSICAL;
- postorder = (ftwflags & FTW_DEPTH) != 0;
- ftsp = fts_open(paths, ftsflags, NULL);
- if (ftsp == NULL)
- return (-1);
- error = 0;
- while ((cur = fts_read(ftsp)) != NULL) {
- switch (cur->fts_info) {
- case FTS_D:
- if (postorder)
- continue;
- fnflag = FTW_D;
- break;
- case FTS_DNR:
- fnflag = FTW_DNR;
- break;
- case FTS_DP:
- if (!postorder)
- continue;
- fnflag = FTW_DP;
- break;
- case FTS_F:
- case FTS_DEFAULT:
- fnflag = FTW_F;
- break;
- case FTS_NS:
- case FTS_NSOK:
- fnflag = FTW_NS;
- break;
- case FTS_SL:
- fnflag = FTW_SL;
- break;
- case FTS_SLNONE:
- fnflag = FTW_SLN;
- break;
- case FTS_DC:
- errno = ELOOP;
- /* FALLTHROUGH */
- default:
- error = -1;
- goto done;
- }
- f.base = cur->fts_pathlen - cur->fts_namelen;
- f.level = cur->fts_level;
- error = fn(cur->fts_path, cur->fts_statp, fnflag, &f);
- if (error != 0)
- break;
- }
-done:
- sverrno = errno;
- (void) fts_close(ftsp);
- errno = sverrno;
- return (error);
-}
diff --git a/libdl/libdl.arm.map b/libdl/libdl.arm.map
index 67c8d08..20efa9a 100644
--- a/libdl/libdl.arm.map
+++ b/libdl/libdl.arm.map
@@ -16,8 +16,6 @@
LIBC_N {
global:
- android_init_namespaces;
- android_create_namespace;
dlvsym;
} LIBC;
@@ -27,4 +25,6 @@
android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH;
+ android_init_namespaces;
+ android_create_namespace;
} LIBC_N;
diff --git a/libdl/libdl.arm64.map b/libdl/libdl.arm64.map
index 4d035f5..daf5a86 100644
--- a/libdl/libdl.arm64.map
+++ b/libdl/libdl.arm64.map
@@ -15,8 +15,6 @@
LIBC_N {
global:
- android_init_namespaces;
- android_create_namespace;
dlvsym;
} LIBC;
@@ -26,4 +24,6 @@
android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH;
+ android_init_namespaces;
+ android_create_namespace;
} LIBC_N;
diff --git a/libdl/libdl.map.txt b/libdl/libdl.map.txt
index 67ff64e..79bced3 100644
--- a/libdl/libdl.map.txt
+++ b/libdl/libdl.map.txt
@@ -30,8 +30,6 @@
LIBC_N {
global:
- android_init_namespaces;
- android_create_namespace;
dlvsym;
} LIBC;
@@ -41,4 +39,6 @@
android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH;
+ android_init_namespaces;
+ android_create_namespace;
} LIBC_N;
diff --git a/libdl/libdl.mips.map b/libdl/libdl.mips.map
index 4d035f5..daf5a86 100644
--- a/libdl/libdl.mips.map
+++ b/libdl/libdl.mips.map
@@ -15,8 +15,6 @@
LIBC_N {
global:
- android_init_namespaces;
- android_create_namespace;
dlvsym;
} LIBC;
@@ -26,4 +24,6 @@
android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH;
+ android_init_namespaces;
+ android_create_namespace;
} LIBC_N;
diff --git a/libdl/libdl.mips64.map b/libdl/libdl.mips64.map
index 4d035f5..daf5a86 100644
--- a/libdl/libdl.mips64.map
+++ b/libdl/libdl.mips64.map
@@ -15,8 +15,6 @@
LIBC_N {
global:
- android_init_namespaces;
- android_create_namespace;
dlvsym;
} LIBC;
@@ -26,4 +24,6 @@
android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH;
+ android_init_namespaces;
+ android_create_namespace;
} LIBC_N;
diff --git a/libdl/libdl.x86.map b/libdl/libdl.x86.map
index 4d035f5..daf5a86 100644
--- a/libdl/libdl.x86.map
+++ b/libdl/libdl.x86.map
@@ -15,8 +15,6 @@
LIBC_N {
global:
- android_init_namespaces;
- android_create_namespace;
dlvsym;
} LIBC;
@@ -26,4 +24,6 @@
android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH;
+ android_init_namespaces;
+ android_create_namespace;
} LIBC_N;
diff --git a/libdl/libdl.x86_64.map b/libdl/libdl.x86_64.map
index 4d035f5..daf5a86 100644
--- a/libdl/libdl.x86_64.map
+++ b/libdl/libdl.x86_64.map
@@ -15,8 +15,6 @@
LIBC_N {
global:
- android_init_namespaces;
- android_create_namespace;
dlvsym;
} LIBC;
@@ -26,4 +24,6 @@
android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH;
+ android_init_namespaces;
+ android_create_namespace;
} LIBC_N;
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 855b32b..77f5359 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -110,6 +110,7 @@
void add_soinfos(const soinfo::soinfo_list_t& soinfos) {
for (auto si : soinfos) {
add_soinfo(si);
+ si->add_secondary_namespace(this);
}
}
@@ -146,6 +147,7 @@
static LinkerTypeAllocator<LinkedListEntry<soinfo>> g_soinfo_links_allocator;
static LinkerTypeAllocator<android_namespace_t> g_namespace_allocator;
+static LinkerTypeAllocator<LinkedListEntry<android_namespace_t>> g_namespace_list_allocator;
static soinfo* solist;
static soinfo* sonext;
@@ -286,6 +288,14 @@
g_soinfo_links_allocator.free(entry);
}
+LinkedListEntry<android_namespace_t>* NamespaceListAllocator::alloc() {
+ return g_namespace_list_allocator.alloc();
+}
+
+void NamespaceListAllocator::free(LinkedListEntry<android_namespace_t>* entry) {
+ g_namespace_list_allocator.free(entry);
+}
+
static soinfo* soinfo_alloc(android_namespace_t* ns, const char* name,
struct stat* file_stat, off64_t file_offset,
uint32_t rtld_flags) {
@@ -349,9 +359,6 @@
sonext = prev;
}
- // remove from the namespace
- si->get_namespace()->remove_soinfo(si);
-
si->~soinfo();
g_soinfo_allocator.free(si);
}
@@ -843,7 +850,7 @@
}
this->rtld_flags_ = rtld_flags;
- this->namespace_ = ns;
+ this->primary_namespace_ = ns;
}
soinfo::~soinfo() {
@@ -1003,6 +1010,7 @@
g_soinfo_allocator.protect_all(protection);
g_soinfo_links_allocator.protect_all(protection);
g_namespace_allocator.protect_all(protection);
+ g_namespace_list_allocator.protect_all(protection);
}
static size_t ref_count_;
@@ -2122,7 +2130,7 @@
TRACE("deprecated (old format of soinfo): %s needs to unload %s",
si->get_realpath(), library_name);
- soinfo* needed = find_library(si->get_namespace(),
+ soinfo* needed = find_library(si->get_primary_namespace(),
library_name, RTLD_NOLOAD, nullptr, nullptr);
if (needed != nullptr) {
@@ -2172,6 +2180,10 @@
return std::string(sym_name) + ", version " + sym_ver;
}
+static android_namespace_t* get_caller_namespace(soinfo* caller) {
+ return caller != nullptr ? caller->get_primary_namespace() : g_anonymous_namespace;
+}
+
void do_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
// Use basic string manipulation calls to avoid snprintf.
// snprintf indirectly calls pthread_getspecific to get the size of a buffer.
@@ -2208,7 +2220,7 @@
return nullptr;
}
- android_namespace_t* ns = caller != nullptr ? caller->get_namespace() : g_anonymous_namespace;
+ android_namespace_t* ns = get_caller_namespace(caller);
if (extinfo != nullptr) {
if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) {
@@ -2302,7 +2314,7 @@
soinfo* found = nullptr;
const ElfW(Sym)* sym = nullptr;
soinfo* caller = find_containing_library(caller_addr);
- android_namespace_t* ns = caller != nullptr ? caller->get_namespace() : g_anonymous_namespace;
+ android_namespace_t* ns = get_caller_namespace(caller);
version_info vi_instance;
version_info* vi = nullptr;
@@ -2415,7 +2427,7 @@
soinfo* caller_soinfo = find_containing_library(caller_addr);
android_namespace_t* caller_ns = caller_soinfo != nullptr ?
- caller_soinfo->get_namespace() :
+ caller_soinfo->get_primary_namespace() :
g_anonymous_namespace;
ProtectedDataGuard guard;
@@ -3023,10 +3035,6 @@
// DT_FINI should be called after DT_FINI_ARRAY if both are present.
call_function("DT_FINI", fini_func_);
-
- // This is needed on second call to dlopen
- // after library has been unloaded with RTLD_NODELETE
- constructors_called = false;
}
void soinfo::add_child(soinfo* child) {
@@ -3054,9 +3062,20 @@
});
});
- // 2. Once everything untied - clear local lists.
+ // 2. Remove from the primary namespace
+ primary_namespace_->remove_soinfo(this);
+ primary_namespace_ = nullptr;
+
+ // 3. Remove from secondary namespaces
+ secondary_namespaces_.for_each([&](android_namespace_t* ns) {
+ ns->remove_soinfo(this);
+ });
+
+
+ // 4. Once everything untied - clear local lists.
parents_.clear();
children_.clear();
+ secondary_namespaces_.clear();
}
dev_t soinfo::get_st_dev() const {
@@ -3190,14 +3209,19 @@
return g_empty_runpath;
}
-android_namespace_t* soinfo::get_namespace() {
+android_namespace_t* soinfo::get_primary_namespace() {
if (has_min_version(3)) {
- return namespace_;
+ return primary_namespace_;
}
return &g_default_namespace;
}
+void soinfo::add_secondary_namespace(android_namespace_t* secondary_ns) {
+ CHECK(has_min_version(3));
+ secondary_namespaces_.push_back(secondary_ns);
+}
+
ElfW(Addr) soinfo::resolve_symbol_address(const ElfW(Sym)* s) const {
if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
return call_ifunc_resolver(s->st_value + load_bias);
@@ -3220,7 +3244,7 @@
}
bool soinfo::can_unload() const {
- return (get_rtld_flags() & (RTLD_NODELETE | RTLD_GLOBAL)) == 0;
+ return !is_linked() || ((get_rtld_flags() & (RTLD_NODELETE | RTLD_GLOBAL)) == 0);
}
bool soinfo::is_linked() const {
diff --git a/linker/linker.h b/linker/linker.h
index 81f93ac..4e2e0b9 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -114,6 +114,16 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(SoinfoListAllocator);
};
+class NamespaceListAllocator {
+ public:
+ static LinkedListEntry<android_namespace_t>* alloc();
+ static void free(LinkedListEntry<android_namespace_t>* entry);
+
+ private:
+ // unconstructable
+ DISALLOW_IMPLICIT_CONSTRUCTORS(NamespaceListAllocator);
+};
+
class SymbolName {
public:
explicit SymbolName(const char* name)
@@ -166,6 +176,7 @@
struct soinfo {
public:
typedef LinkedList<soinfo, SoinfoListAllocator> soinfo_list_t;
+ typedef LinkedList<android_namespace_t, NamespaceListAllocator> android_namespace_list_t;
#if defined(__work_around_b_24465209__)
private:
char old_name_[SOINFO_NAME_LEN];
@@ -342,7 +353,8 @@
void set_dt_runpath(const char *);
const std::vector<std::string>& get_dt_runpath() const;
- android_namespace_t* get_namespace();
+ android_namespace_t* get_primary_namespace();
+ void add_secondary_namespace(android_namespace_t* secondary_ns);
void set_mapped_by_caller(bool reserved_map);
bool is_mapped_by_caller() const;
@@ -414,7 +426,8 @@
// version >= 3
std::vector<std::string> dt_runpath_;
- android_namespace_t* namespace_;
+ android_namespace_t* primary_namespace_;
+ android_namespace_list_t secondary_namespaces_;
uintptr_t handle_;
friend soinfo* get_libdl_info();
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index bbdc024..87e5dbc 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -959,6 +959,70 @@
dlclose(handle2);
}
+TEST(dlext, ns_shared_dlclose) {
+ std::string path = "libc.so:libc++.so:libdl.so:libm.so";
+
+ const std::string lib_path = std::string(getenv("ANDROID_DATA")) + NATIVE_TESTS_PATH;
+
+ android_set_application_target_sdk_version(42U); // something > 23
+
+ ASSERT_TRUE(android_init_namespaces(path.c_str(), nullptr)) << dlerror();
+
+ // preload this library to the default namespace to check if it
+ // is shared later on.
+ void* handle_dlopened =
+ dlopen((lib_path + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
+ ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
+
+ android_namespace_t* ns_isolated_shared =
+ android_create_namespace("private_isolated_shared", nullptr,
+ (lib_path + "/private_namespace_libs").c_str(),
+ ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
+ nullptr);
+ ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
+
+ // Check if "libnstest_dlopened.so" is loaded (and the same)
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
+ extinfo.library_namespace = ns_isolated_shared;
+
+ void* handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+ ASSERT_TRUE(handle == handle_dlopened);
+ dlclose(handle);
+ dlclose(handle_dlopened);
+
+ // And now check that the library cannot be found by soname (and is no longer loaded)
+ handle = android_dlopen_ext("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD, &extinfo);
+ ASSERT_TRUE(handle == nullptr)
+ << "Error: libnstest_dlopened.so is still accessible in shared namespace";
+
+ handle = android_dlopen_ext((lib_path + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
+ RTLD_NOW | RTLD_NOLOAD, &extinfo);
+ ASSERT_TRUE(handle == nullptr)
+ << "Error: libnstest_dlopened.so is still accessible in shared namespace";
+
+ handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_NOLOAD);
+ ASSERT_TRUE(handle == nullptr)
+ << "Error: libnstest_dlopened.so is still accessible in default namespace";
+
+ handle = dlopen((lib_path + "/private_namespace_libs/libnstest_dlopened.so").c_str(),
+ RTLD_NOW | RTLD_NOLOAD);
+ ASSERT_TRUE(handle == nullptr)
+ << "Error: libnstest_dlopened.so is still accessible in default namespace";
+
+ // Now lets see if the soinfo area gets reused in the wrong way:
+ // load a library to default namespace.
+ const std::string lib_public_path = lib_path + "/public_namespace_libs/" + g_public_lib;
+ void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
+ ASSERT_TRUE(handle_public != nullptr) << dlerror();
+
+ // try to find it in shared namespace
+ handle = android_dlopen_ext(g_public_lib, RTLD_NOW | RTLD_NOLOAD, &extinfo);
+ ASSERT_TRUE(handle == nullptr)
+ << "Error: " << g_public_lib << " is accessible in shared namespace";
+}
+
TEST(dlext, ns_anonymous) {
static const char* root_lib = "libnstest_root.so";
std::string path = std::string("libc.so:libc++.so:libdl.so:libm.so:") + g_public_lib;
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 19f9978..748d0ca 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -256,6 +256,21 @@
ASSERT_STREQ("true", is_ctor_called());
dlclose(handle);
}
+
+TEST(dlfcn, ifunc_ctor_call_rtld_lazy) {
+ typedef const char* (*fn_ptr)();
+
+ void* handle = dlopen("libtest_ifunc.so", RTLD_LAZY);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+ fn_ptr is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_irelative"));
+ ASSERT_TRUE(is_ctor_called != nullptr) << dlerror();
+ ASSERT_STREQ("false", is_ctor_called());
+
+ is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_jump_slot"));
+ ASSERT_TRUE(is_ctor_called != nullptr) << dlerror();
+ ASSERT_STREQ("true", is_ctor_called());
+ dlclose(handle);
+}
#endif
TEST(dlfcn, dlopen_check_relocation_dt_needed_order) {
diff --git a/tests/ftw_test.cpp b/tests/ftw_test.cpp
index b7e5bd5..ea494ba 100644
--- a/tests/ftw_test.cpp
+++ b/tests/ftw_test.cpp
@@ -16,6 +16,7 @@
#include <ftw.h>
+#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
@@ -24,6 +25,7 @@
#include "TemporaryFile.h"
+#include <android-base/stringprintf.h>
#include <gtest/gtest.h>
static void MakeTree(const char* root) {
@@ -39,7 +41,7 @@
snprintf(path, sizeof(path), "%s/dangler", root);
ASSERT_EQ(0, symlink("/does-not-exist", path));
snprintf(path, sizeof(path), "%s/symlink", root);
- ASSERT_EQ(0, symlink("sub2", path));
+ ASSERT_EQ(0, symlink("dir/sub", path));
int fd;
snprintf(path, sizeof(path), "%s/regular", root);
@@ -51,8 +53,21 @@
ASSERT_TRUE(fpath != NULL);
ASSERT_TRUE(sb != NULL);
+ // Was it a case where the struct stat we're given is meaningless?
+ if (tflag == FTW_NS || tflag == FTW_SLN) {
+ // If so, double-check that we really can't stat.
+ struct stat sb;
+ EXPECT_EQ(-1, stat(fpath, &sb));
+ return;
+ }
+
+ // Otherwise check that the struct stat matches the type flag.
if (S_ISDIR(sb->st_mode)) {
- EXPECT_TRUE(tflag == FTW_D || tflag == FTW_DNR || tflag == FTW_DP) << fpath;
+ if (access(fpath, R_OK) == 0) {
+ EXPECT_TRUE(tflag == FTW_D || tflag == FTW_DP) << fpath << ' ' << tflag;
+ } else {
+ EXPECT_EQ(FTW_DNR, tflag) << fpath;
+ }
} else if (S_ISLNK(sb->st_mode)) {
EXPECT_EQ(FTW_SL, tflag) << fpath;
} else {
@@ -60,7 +75,7 @@
}
}
-void sanity_check_nftw(const char* fpath, const struct stat* sb, int tflag, struct FTW* ftwbuf) {
+void sanity_check_nftw(const char* fpath, const struct stat* sb, int tflag, FTW* ftwbuf) {
sanity_check_ftw(fpath, sb, tflag);
ASSERT_EQ('/', fpath[ftwbuf->base - 1]) << fpath;
}
@@ -75,12 +90,12 @@
return 0;
}
-int check_nftw(const char* fpath, const struct stat* sb, int tflag, struct FTW* ftwbuf) {
+int check_nftw(const char* fpath, const struct stat* sb, int tflag, FTW* ftwbuf) {
sanity_check_nftw(fpath, sb, tflag, ftwbuf);
return 0;
}
-int check_nftw64(const char* fpath, const struct stat64* sb, int tflag, struct FTW* ftwbuf) {
+int check_nftw64(const char* fpath, const struct stat64* sb, int tflag, FTW* ftwbuf) {
sanity_check_nftw(fpath, reinterpret_cast<const struct stat*>(sb), tflag, ftwbuf);
return 0;
}
@@ -108,3 +123,33 @@
MakeTree(root.dirname);
ASSERT_EQ(0, nftw64(root.dirname, check_nftw64, 128, 0));
}
+
+template <typename StatT>
+static int bug_28197840_ftw(const char* path, const StatT*, int flag) {
+ EXPECT_EQ(strstr(path, "unreadable") != nullptr ? FTW_DNR : FTW_D, flag) << path;
+ return 0;
+}
+
+template <typename StatT>
+static int bug_28197840_nftw(const char* path, const StatT* sb, int flag, FTW*) {
+ return bug_28197840_ftw(path, sb, flag);
+}
+
+TEST(ftw, bug_28197840) {
+ // Drop root for this test, because root can still read directories even if
+ // permissions would imply otherwise.
+ if (getuid() == 0) {
+ passwd* pwd = getpwnam("shell");
+ ASSERT_EQ(0, setuid(pwd->pw_uid));
+ }
+
+ TemporaryDir root;
+
+ std::string path = android::base::StringPrintf("%s/unreadable-directory", root.dirname);
+ ASSERT_EQ(0, mkdir(path.c_str(), 0000)) << path;
+
+ ASSERT_EQ(0, ftw(root.dirname, bug_28197840_ftw<struct stat>, 128));
+ ASSERT_EQ(0, ftw64(root.dirname, bug_28197840_ftw<struct stat64>, 128));
+ ASSERT_EQ(0, nftw(root.dirname, bug_28197840_nftw<struct stat>, 128, FTW_PHYS));
+ ASSERT_EQ(0, nftw64(root.dirname, bug_28197840_nftw<struct stat64>, 128, FTW_PHYS));
+}
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 019016d..589cab4 100755
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -24,6 +24,7 @@
#include <signal.h>
#include <stdio.h>
#include <sys/mman.h>
+#include <sys/prctl.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>
@@ -422,7 +423,21 @@
SpinFunctionHelper spin_helper;
pthread_t t;
- ASSERT_EQ(0, pthread_create(&t, NULL, spin_helper.GetFunction(), NULL));
+ ASSERT_EQ(0, pthread_create(&t, nullptr, spin_helper.GetFunction(), nullptr));
+ test_pthread_setname_np__pthread_getname_np(t);
+ spin_helper.UnSpin();
+ ASSERT_EQ(0, pthread_join(t, nullptr));
+}
+
+// http://b/28051133: a kernel misfeature means that you can't change the
+// name of another thread if you've set PR_SET_DUMPABLE to 0.
+TEST(pthread, pthread_setname_np__pthread_getname_np__other_PR_SET_DUMPABLE) {
+ ASSERT_EQ(0, prctl(PR_SET_DUMPABLE, 0)) << strerror(errno);
+
+ SpinFunctionHelper spin_helper;
+
+ pthread_t t;
+ ASSERT_EQ(0, pthread_create(&t, nullptr, spin_helper.GetFunction(), nullptr));
test_pthread_setname_np__pthread_getname_np(t);
spin_helper.UnSpin();
ASSERT_EQ(0, pthread_join(t, nullptr));