Merge "[MIPSR6] Use C-coded string ops on mips32r6/mips64r6"
diff --git a/benchmarks/time_benchmark.cpp b/benchmarks/time_benchmark.cpp
index 0a146ae..22f6e8e 100644
--- a/benchmarks/time_benchmark.cpp
+++ b/benchmarks/time_benchmark.cpp
@@ -19,26 +19,6 @@
#include <sys/syscall.h>
#include <time.h>
-#if defined(__BIONIC__)
-
-// Used by the horrible android.text.format.Time class, which is used by Calendar. http://b/8270865.
-extern "C" void localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz);
-
-static void BM_time_localtime_tz(int iters) {
- StartBenchmarkTiming();
-
- time_t now(time(NULL));
- tm broken_down_time;
- for (int i = 0; i < iters; ++i) {
- localtime_tz(&now, &broken_down_time, "Europe/Berlin");
- }
-
- StopBenchmarkTiming();
-}
-BENCHMARK(BM_time_localtime_tz);
-
-#endif
-
static void BM_time_clock_gettime(int iters) {
StartBenchmarkTiming();
diff --git a/libc/Android.mk b/libc/Android.mk
index 0bdf1a5..9554e18 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -45,7 +45,6 @@
bionic/fts.c \
bionic/gethostname.c \
bionic/getpriority.c \
- bionic/getpt.c \
bionic/if_indextoname.c \
bionic/if_nametoindex.c \
bionic/initgroups.c \
@@ -53,8 +52,6 @@
bionic/isatty.c \
bionic/memmem.c \
bionic/pathconf.c \
- bionic/ptsname.c \
- bionic/ptsname_r.c \
bionic/pututline.c \
bionic/sched_cpualloc.c \
bionic/sched_cpucount.c \
@@ -63,7 +60,6 @@
bionic/siginterrupt.c \
bionic/sigsetmask.c \
bionic/system_properties_compat.c \
- bionic/unlockpt.c \
stdio/snprintf.c\
stdio/sprintf.c \
@@ -94,6 +90,7 @@
bionic/access.cpp \
bionic/assert.cpp \
bionic/atof.cpp \
+ bionic/bionic_systrace.cpp \
bionic/bionic_time_conversions.cpp \
bionic/brk.cpp \
bionic/c16rtomb.cpp \
@@ -174,6 +171,7 @@
bionic/pthread_setschedparam.cpp \
bionic/pthread_sigmask.cpp \
bionic/ptrace.cpp \
+ bionic/pty.cpp \
bionic/raise.cpp \
bionic/rand.cpp \
bionic/readlink.cpp \
@@ -287,20 +285,18 @@
upstream-netbsd/lib/libc/stdlib/div.c \
upstream-netbsd/lib/libc/stdlib/drand48.c \
upstream-netbsd/lib/libc/stdlib/erand48.c \
+ upstream-netbsd/lib/libc/stdlib/insque.c \
upstream-netbsd/lib/libc/stdlib/jrand48.c \
upstream-netbsd/lib/libc/stdlib/ldiv.c \
upstream-netbsd/lib/libc/stdlib/lldiv.c \
upstream-netbsd/lib/libc/stdlib/lrand48.c \
- upstream-netbsd/lib/libc/stdlib/lsearch.c \
upstream-netbsd/lib/libc/stdlib/mrand48.c \
upstream-netbsd/lib/libc/stdlib/nrand48.c \
upstream-netbsd/lib/libc/stdlib/_rand48.c \
upstream-netbsd/lib/libc/stdlib/rand_r.c \
+ upstream-netbsd/lib/libc/stdlib/remque.c \
upstream-netbsd/lib/libc/stdlib/seed48.c \
upstream-netbsd/lib/libc/stdlib/srand48.c \
- upstream-netbsd/lib/libc/stdlib/tdelete.c \
- upstream-netbsd/lib/libc/stdlib/tfind.c \
- upstream-netbsd/lib/libc/stdlib/tsearch.c \
upstream-netbsd/lib/libc/string/memccpy.c \
upstream-netbsd/lib/libc/string/strcasestr.c \
upstream-netbsd/lib/libc/string/strcoll.c \
@@ -469,6 +465,7 @@
upstream-openbsd/lib/libc/stdlib/atoll.c \
upstream-openbsd/lib/libc/stdlib/exit.c \
upstream-openbsd/lib/libc/stdlib/getenv.c \
+ upstream-openbsd/lib/libc/stdlib/lsearch.c \
upstream-openbsd/lib/libc/stdlib/setenv.c \
upstream-openbsd/lib/libc/stdlib/strtoimax.c \
upstream-openbsd/lib/libc/stdlib/strtol.c \
@@ -477,6 +474,8 @@
upstream-openbsd/lib/libc/stdlib/strtoull.c \
upstream-openbsd/lib/libc/stdlib/strtoumax.c \
upstream-openbsd/lib/libc/stdlib/system.c \
+ upstream-openbsd/lib/libc/stdlib/tfind.c \
+ upstream-openbsd/lib/libc/stdlib/tsearch.c \
upstream-openbsd/lib/libc/string/strcasecmp.c \
upstream-openbsd/lib/libc/string/strcspn.c \
upstream-openbsd/lib/libc/string/strdup.c \
@@ -981,8 +980,6 @@
$(libc_arch_dynamic_src_files) \
$(libc_static_common_src_files) \
bionic/malloc_debug_common.cpp \
- bionic/debug_mapinfo.cpp \
- bionic/debug_stacktrace.cpp \
bionic/libc_init_dynamic.cpp \
bionic/NetdClient.cpp \
@@ -1048,7 +1045,10 @@
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
-LOCAL_C_INCLUDES := $(libc_common_c_includes)
+# Make sure that unwind.h comes from libunwind.
+LOCAL_C_INCLUDES := \
+ external/libunwind/include \
+ $(libc_common_c_includes) \
LOCAL_SRC_FILES := \
bionic/debug_mapinfo.cpp \
@@ -1063,6 +1063,7 @@
LOCAL_SHARED_LIBRARIES := libc libdl
LOCAL_SYSTEM_SHARED_LIBRARIES :=
+LOCAL_WHOLE_STATIC_LIBRARIES := libunwindbacktrace
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
# Don't install on release build
diff --git a/libc/NOTICE b/libc/NOTICE
index afbaecf..80d9a27 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -3,12 +3,12 @@
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
+ * 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
+ * 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.
- Neither the name of the Linaro nor the
+ * Neither the name of the Linaro nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
@@ -34,12 +34,12 @@
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
+ * 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
+ * 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.
- Neither the name of the company nor the names of its contributors
+ * Neither the name of the company nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
@@ -57,6 +57,34 @@
-------------------------------------------------------------------
+ Copyright (c) 1993 John Brezak
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. The name of the author may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
====================================================
Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
@@ -184,9 +212,9 @@
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
+ * 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
+ * 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.
@@ -228,9 +256,9 @@
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
+ * 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
+ * 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.
@@ -257,9 +285,9 @@
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
+ * 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
+ * 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.
@@ -285,9 +313,9 @@
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
+ * 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
+ * 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.
@@ -329,9 +357,9 @@
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
+ * 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
+ * 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.
@@ -373,9 +401,9 @@
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
+ * 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
+ * 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.
@@ -448,9 +476,9 @@
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
+ * 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
+ * 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.
@@ -492,9 +520,9 @@
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
+ * 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
+ * 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.
@@ -536,9 +564,9 @@
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
+ * 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
+ * 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.
@@ -565,9 +593,9 @@
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
+ * 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
+ * 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.
@@ -594,9 +622,9 @@
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
+ * 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
+ * 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.
@@ -638,9 +666,9 @@
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
+ * 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
+ * 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.
@@ -804,35 +832,6 @@
-------------------------------------------------------------------
-Copyright (c) 1983, 1988, 1993
- The Regents of the University of California. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-3. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
--------------------------------------------------------------------
-
Copyright (c) 1983, 1989
The Regents of the University of California. All rights reserved.
@@ -3164,35 +3163,6 @@
-------------------------------------------------------------------
-Copyright (c) 1999 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Michael Graff.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
--------------------------------------------------------------------
-
Copyright (c) 2000 Ben Harris.
Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
All rights reserved.
@@ -4132,6 +4102,22 @@
-------------------------------------------------------------------
+Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+
+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.
+
+-------------------------------------------------------------------
+
Copyright (c) 2009
MIPS Technologies, Inc., California.
@@ -4253,13 +4239,13 @@
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
+ * 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
+ * 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.
- Neither the name of MIPS Technologies Inc. nor the names of its
+ * Neither the name of MIPS Technologies Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
@@ -4299,16 +4285,16 @@
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 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.
+ * 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.
- Neither the name of Intel Corporation nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -4329,16 +4315,16 @@
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 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.
+ * 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.
- Neither the name of Intel Corporation nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -4412,16 +4398,16 @@
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 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.
+ * 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.
- Neither the name of Intel Corporation nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -4471,16 +4457,16 @@
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 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.
+ * 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.
- Neither the name of Intel Corporation nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -4501,16 +4487,16 @@
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 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.
+ * 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.
- Neither the name of Intel Corporation nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -4530,12 +4516,12 @@
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
+ * 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
+ * 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.
- Neither the name of the VMware, Inc. nor the names of its contributors
+ * Neither the name of the VMware, Inc. nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
@@ -4557,12 +4543,12 @@
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
+ * 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
+ * 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.
- Neither the name of the Linaro nor the
+ * Neither the name of the Linaro nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
@@ -4586,12 +4572,12 @@
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
+ * 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
+ * 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.
- Neither the name of the Linaro nor the
+ * Neither the name of the Linaro nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
@@ -4660,14 +4646,14 @@
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
+ * 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
+ * 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.
- Neither the name of Linaro Limited nor the names of its
+ * Neither the name of Linaro Limited nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
@@ -4685,22 +4671,42 @@
-------------------------------------------------------------------
+Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
+Copyright (c) 2014 Bob Beck <beck@obtuse.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.
+
+Emulation of getentropy(2) as documented at:
+http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
+
+-------------------------------------------------------------------
+
Copyright (c) 2014, Intel Corporation
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 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.
+ * 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.
- Neither the name of Intel Corporation nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
+ * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -4720,12 +4726,12 @@
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
+ * 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
+ * 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.
- Neither the name of the Linaro nor the
+ * Neither the name of the Linaro nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
@@ -5149,3 +5155,34 @@
-------------------------------------------------------------------
+memchr - find a character in a memory zone
+
+Copyright (c) 2014, ARM Limited
+All rights Reserved.
+Copyright (c) 2014, Linaro Ltd.
+
+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.
+ * Neither the name of the company nor the names of its contributors
+ may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE 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
+HOLDER 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.
+
+-------------------------------------------------------------------
+
diff --git a/libc/arch-mips/bionic/_setjmp.S b/libc/arch-mips/bionic/_setjmp.S
index 4465cd2..d237e6d 100644
--- a/libc/arch-mips/bionic/_setjmp.S
+++ b/libc/arch-mips/bionic/_setjmp.S
@@ -44,17 +44,6 @@
FRAMESZ= MKFSIZ(0,4)
GPOFF= FRAMESZ-2*REGSZ
-#define FPREG64_S(FPR, OFF, BASE) \
- swc1 FPR, OFF(BASE) ; \
- mfhc1 t0, FPR ; \
- sw t0, OFF+4(BASE) ;
-
-#define FPREG64_L(FPR, OFF, BASE) \
- lw t0, OFF+4(BASE) ; \
- lw t1, OFF(BASE) ; \
- mtc1 t1, FPR ; \
- mthc1 t0, FPR ; \
-
LEAF(_setjmp, FRAMESZ)
PTR_SUBU sp, FRAMESZ
SETUP_GP64(GPOFF, _setjmp)
@@ -85,32 +74,19 @@
li v0, 1 # be nice if we could tell
REG_S v0, SC_FPUSED(a0) # sc_fpused = 1
cfc1 v0, $31
+ s.d $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+ s.d $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+ s.d $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+ s.d $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+ s.d $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+ s.d $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
#if _MIPS_FPSET == 32
- FPREG64_S($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
- FPREG64_S($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
- FPREG64_S($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
- FPREG64_S($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
- FPREG64_S($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
- FPREG64_S($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
- FPREG64_S($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
- FPREG64_S($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
- FPREG64_S($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
- FPREG64_S($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
- FPREG64_S($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
- FPREG64_S($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
- swc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
- swc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
- swc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
- swc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
- swc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
- swc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
- swc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
- swc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
- swc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
- swc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
- swc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
- swc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+ s.d $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+ s.d $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+ s.d $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+ s.d $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+ s.d $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+ s.d $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
#endif
REG_S v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
#endif /* !SOFTFLOAT */
@@ -142,32 +118,19 @@
REG_L sp, SC_REGS+SP*REGSZ(a0)
#if !defined(SOFTFLOAT)
ctc1 v0, $31
+ l.d $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+ l.d $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+ l.d $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+ l.d $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+ l.d $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+ l.d $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
#if _MIPS_FPSET == 32
- FPREG64_L($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
- FPREG64_L($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
- FPREG64_L($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
- FPREG64_L($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
- FPREG64_L($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
- FPREG64_L($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
- FPREG64_L($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
- FPREG64_L($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
- FPREG64_L($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
- FPREG64_L($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
- FPREG64_L($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
- FPREG64_L($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
- lwc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
- lwc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
- lwc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
- lwc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
- lwc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
- lwc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
- lwc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
- lwc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
- lwc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
- lwc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
- lwc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
- lwc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+ l.d $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+ l.d $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+ l.d $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+ l.d $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+ l.d $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+ l.d $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
#endif
#endif /* !SOFTFLOAT */
bne a1, zero, 1f
diff --git a/libc/arch-mips/bionic/setjmp.S b/libc/arch-mips/bionic/setjmp.S
index 2af1fbd..31786be 100644
--- a/libc/arch-mips/bionic/setjmp.S
+++ b/libc/arch-mips/bionic/setjmp.S
@@ -45,17 +45,6 @@
GPOFF= FRAMESZ-2*REGSZ
RAOFF= FRAMESZ-1*REGSZ
-#define FPREG64_S(FPR, OFF, BASE) \
- swc1 FPR, OFF(BASE) ; \
- mfhc1 t0, FPR ; \
- sw t0, OFF+4(BASE) ;
-
-#define FPREG64_L(FPR, OFF, BASE) \
- lw t0, OFF+4(BASE) ; \
- lw t1, OFF(BASE) ; \
- mtc1 t1, FPR ; \
- mthc1 t0, FPR ; \
-
NON_LEAF(setjmp, FRAMESZ, ra)
.mask 0x80000000, RAOFF
PTR_SUBU sp, FRAMESZ # allocate stack frame
@@ -98,32 +87,19 @@
li v0, 1 # be nice if we could tell
REG_S v0, SC_FPUSED(a0) # sc_fpused = 1
cfc1 v0, $31
+ s.d $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+ s.d $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+ s.d $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+ s.d $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+ s.d $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+ s.d $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
#if _MIPS_FPSET == 32
- FPREG64_S($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
- FPREG64_S($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
- FPREG64_S($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
- FPREG64_S($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
- FPREG64_S($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
- FPREG64_S($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
- FPREG64_S($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
- FPREG64_S($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
- FPREG64_S($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
- FPREG64_S($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
- FPREG64_S($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
- FPREG64_S($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
- swc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
- swc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
- swc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
- swc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
- swc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
- swc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
- swc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
- swc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
- swc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
- swc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
- swc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
- swc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+ s.d $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+ s.d $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+ s.d $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+ s.d $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+ s.d $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+ s.d $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
#endif
REG_S v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
#endif /* !SOFTFLOAT */
@@ -173,32 +149,19 @@
#if !defined(SOFTFLOAT)
REG_L v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
ctc1 v0, $31
+ l.d $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+ l.d $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+ l.d $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+ l.d $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+ l.d $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+ l.d $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
#if _MIPS_FPSET == 32
- FPREG64_L($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
- FPREG64_L($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
- FPREG64_L($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
- FPREG64_L($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
- FPREG64_L($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
- FPREG64_L($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
- FPREG64_L($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
- FPREG64_L($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
- FPREG64_L($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
- FPREG64_L($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
- FPREG64_L($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
- FPREG64_L($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
- lwc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
- lwc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
- lwc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
- lwc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
- lwc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
- lwc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
- lwc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
- lwc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
- lwc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
- lwc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
- lwc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
- lwc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+ l.d $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+ l.d $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+ l.d $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+ l.d $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+ l.d $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+ l.d $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
#endif
#endif /* !SOFTFLOAT */
bne a1, zero, 1f
diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk
index e244f88..bf3b8ae 100644
--- a/libc/arch-mips/mips.mk
+++ b/libc/arch-mips/mips.mk
@@ -47,11 +47,6 @@
bionic/__strcat_chk.cpp \
-ifneq ($(ARCH_MIPS_HAS_FPU),true)
-libc_common_cflags_mips := \
- -DSOFTFLOAT
-endif
-
##########################################
### CPU specific source files
libc_bionic_src_files_mips += \
@@ -94,3 +89,6 @@
libc_crt_target_so_cflags_mips := \
-fPIC
+
+libc_crt_target_ldflags_mips := \
+ -melf32ltsmip
diff --git a/libc/arch-mips64/bionic/_setjmp.S b/libc/arch-mips64/bionic/_setjmp.S
index 4465cd2..d237e6d 100644
--- a/libc/arch-mips64/bionic/_setjmp.S
+++ b/libc/arch-mips64/bionic/_setjmp.S
@@ -44,17 +44,6 @@
FRAMESZ= MKFSIZ(0,4)
GPOFF= FRAMESZ-2*REGSZ
-#define FPREG64_S(FPR, OFF, BASE) \
- swc1 FPR, OFF(BASE) ; \
- mfhc1 t0, FPR ; \
- sw t0, OFF+4(BASE) ;
-
-#define FPREG64_L(FPR, OFF, BASE) \
- lw t0, OFF+4(BASE) ; \
- lw t1, OFF(BASE) ; \
- mtc1 t1, FPR ; \
- mthc1 t0, FPR ; \
-
LEAF(_setjmp, FRAMESZ)
PTR_SUBU sp, FRAMESZ
SETUP_GP64(GPOFF, _setjmp)
@@ -85,32 +74,19 @@
li v0, 1 # be nice if we could tell
REG_S v0, SC_FPUSED(a0) # sc_fpused = 1
cfc1 v0, $31
+ s.d $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+ s.d $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+ s.d $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+ s.d $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+ s.d $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+ s.d $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
#if _MIPS_FPSET == 32
- FPREG64_S($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
- FPREG64_S($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
- FPREG64_S($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
- FPREG64_S($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
- FPREG64_S($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
- FPREG64_S($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
- FPREG64_S($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
- FPREG64_S($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
- FPREG64_S($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
- FPREG64_S($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
- FPREG64_S($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
- FPREG64_S($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
- swc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
- swc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
- swc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
- swc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
- swc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
- swc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
- swc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
- swc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
- swc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
- swc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
- swc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
- swc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+ s.d $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+ s.d $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+ s.d $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+ s.d $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+ s.d $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+ s.d $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
#endif
REG_S v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
#endif /* !SOFTFLOAT */
@@ -142,32 +118,19 @@
REG_L sp, SC_REGS+SP*REGSZ(a0)
#if !defined(SOFTFLOAT)
ctc1 v0, $31
+ l.d $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+ l.d $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+ l.d $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+ l.d $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+ l.d $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+ l.d $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
#if _MIPS_FPSET == 32
- FPREG64_L($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
- FPREG64_L($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
- FPREG64_L($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
- FPREG64_L($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
- FPREG64_L($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
- FPREG64_L($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
- FPREG64_L($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
- FPREG64_L($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
- FPREG64_L($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
- FPREG64_L($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
- FPREG64_L($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
- FPREG64_L($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
- lwc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
- lwc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
- lwc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
- lwc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
- lwc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
- lwc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
- lwc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
- lwc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
- lwc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
- lwc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
- lwc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
- lwc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+ l.d $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+ l.d $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+ l.d $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+ l.d $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+ l.d $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+ l.d $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
#endif
#endif /* !SOFTFLOAT */
bne a1, zero, 1f
diff --git a/libc/arch-mips64/bionic/setjmp.S b/libc/arch-mips64/bionic/setjmp.S
index 2af1fbd..31786be 100644
--- a/libc/arch-mips64/bionic/setjmp.S
+++ b/libc/arch-mips64/bionic/setjmp.S
@@ -45,17 +45,6 @@
GPOFF= FRAMESZ-2*REGSZ
RAOFF= FRAMESZ-1*REGSZ
-#define FPREG64_S(FPR, OFF, BASE) \
- swc1 FPR, OFF(BASE) ; \
- mfhc1 t0, FPR ; \
- sw t0, OFF+4(BASE) ;
-
-#define FPREG64_L(FPR, OFF, BASE) \
- lw t0, OFF+4(BASE) ; \
- lw t1, OFF(BASE) ; \
- mtc1 t1, FPR ; \
- mthc1 t0, FPR ; \
-
NON_LEAF(setjmp, FRAMESZ, ra)
.mask 0x80000000, RAOFF
PTR_SUBU sp, FRAMESZ # allocate stack frame
@@ -98,32 +87,19 @@
li v0, 1 # be nice if we could tell
REG_S v0, SC_FPUSED(a0) # sc_fpused = 1
cfc1 v0, $31
+ s.d $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+ s.d $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+ s.d $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+ s.d $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+ s.d $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+ s.d $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
#if _MIPS_FPSET == 32
- FPREG64_S($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
- FPREG64_S($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
- FPREG64_S($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
- FPREG64_S($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
- FPREG64_S($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
- FPREG64_S($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
- FPREG64_S($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
- FPREG64_S($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
- FPREG64_S($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
- FPREG64_S($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
- FPREG64_S($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
- FPREG64_S($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
- swc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
- swc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
- swc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
- swc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
- swc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
- swc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
- swc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
- swc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
- swc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
- swc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
- swc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
- swc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+ s.d $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+ s.d $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+ s.d $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+ s.d $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+ s.d $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+ s.d $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
#endif
REG_S v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
#endif /* !SOFTFLOAT */
@@ -173,32 +149,19 @@
#if !defined(SOFTFLOAT)
REG_L v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0)
ctc1 v0, $31
+ l.d $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
+ l.d $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
+ l.d $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
+ l.d $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
+ l.d $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
+ l.d $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
#if _MIPS_FPSET == 32
- FPREG64_L($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0)
- FPREG64_L($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0)
- FPREG64_L($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0)
- FPREG64_L($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0)
- FPREG64_L($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0)
- FPREG64_L($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0)
- FPREG64_L($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0)
- FPREG64_L($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0)
- FPREG64_L($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0)
- FPREG64_L($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0)
- FPREG64_L($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0)
- FPREG64_L($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0)
-#else
- lwc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0)
- lwc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
- lwc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0)
- lwc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
- lwc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0)
- lwc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
- lwc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0)
- lwc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
- lwc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0)
- lwc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
- lwc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0)
- lwc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
+ l.d $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0)
+ l.d $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0)
+ l.d $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0)
+ l.d $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0)
+ l.d $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0)
+ l.d $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0)
#endif
#endif /* !SOFTFLOAT */
bne a1, zero, 1f
diff --git a/libc/arch-x86/generic/string/swab.S b/libc/arch-x86/generic/string/swab.S
deleted file mode 100644
index b44d134..0000000
--- a/libc/arch-x86/generic/string/swab.S
+++ /dev/null
@@ -1,68 +0,0 @@
-/* $OpenBSD: swab.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
-/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
- * Public domain.
- */
-
-#include <private/bionic_asm.h>
-
-/*
- * On the i486, this code is negligibly faster than the code generated
- * by gcc at about half the size. If my i386 databook is correct, it
- * should be considerably faster than the gcc code on a i386.
- */
-
-ENTRY(swab)
- pushl %esi
- pushl %edi
- movl 12(%esp),%esi
- movl 16(%esp),%edi
- movl 20(%esp),%ecx
-
- cld # set direction forward
-
- shrl $1,%ecx
- testl $7,%ecx # copy first group of 1 to 7 words
- jz L2 # while swaping alternate bytes.
- .align 2,0x90
-L1: lodsw
- rorw $8,%ax
- stosw
- decl %ecx
- testl $7,%ecx
- jnz L1
-
-L2: shrl $3,%ecx # copy remainder 8 words at a time
- jz L4 # while swapping alternate bytes.
- .align 2,0x90
-L3: lodsw
- rorw $8,%ax
- stosw
- lodsw
- rorw $8,%ax
- stosw
- lodsw
- rorw $8,%ax
- stosw
- lodsw
- rorw $8,%ax
- stosw
- lodsw
- rorw $8,%ax
- stosw
- lodsw
- rorw $8,%ax
- stosw
- lodsw
- rorw $8,%ax
- stosw
- lodsw
- rorw $8,%ax
- stosw
- decl %ecx
- jnz L3
-
-L4: popl %edi
- popl %esi
- ret
-END(swab)
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
new file mode 100644
index 0000000..b8e892e
--- /dev/null
+++ b/libc/bionic/bionic_systrace.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cutils/trace.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "private/bionic_systrace.h"
+#include "private/libc_logging.h"
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+#define WRITE_OFFSET 32
+
+static const prop_info* g_pinfo = NULL;
+static uint32_t g_serial = -1;
+static uint64_t g_tags = 0;
+static int g_trace_marker_fd = -1;
+
+static bool should_trace() {
+ // If g_pinfo is null, this means that systrace hasn't been run and it's safe to
+ // assume that no trace writing will need to take place. However, to avoid running
+ // this costly find check each time, we set it to a non-tracing value so that next
+ // time, it will just check the serial to see if the value has been changed.
+ // this function also deals with the bootup case, during which the call to property
+ // set will fail if the property server hasn't yet started.
+ if (g_pinfo == NULL) {
+ g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
+ if (g_pinfo == NULL) {
+ __system_property_set("debug.atrace.tags.enableflags", "0");
+ g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
+ if (g_pinfo == NULL) {
+ return false;
+ }
+ }
+ }
+
+ // Find out which tags have been enabled on the command line and set
+ // the value of tags accordingly. If the value of the property changes,
+ // the serial will also change, so the costly system_property_read function
+ // can be avoided by calling the much cheaper system_property_serial
+ // first. The values within pinfo may change, but its location is guaranteed
+ // not to move.
+ const uint32_t cur_serial = __system_property_serial(g_pinfo);
+ if (cur_serial != g_serial) {
+ g_serial = cur_serial;
+ char value[PROP_VALUE_MAX];
+ __system_property_read(g_pinfo, 0, value);
+ g_tags = strtoull(value, NULL, 0);
+ }
+
+ // Finally, verify that this tag value enables bionic tracing.
+ return ((g_tags & ATRACE_TAG_BIONIC) != 0);
+}
+
+ScopedTrace::ScopedTrace(const char* message) {
+ if (!should_trace()) {
+ return;
+ }
+
+ if (g_trace_marker_fd == -1) {
+ g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY | O_CLOEXEC);
+ if (g_trace_marker_fd == -1) {
+ __libc_fatal("Could not open kernel trace file: %s\n", strerror(errno));
+ }
+ }
+
+ // If bionic tracing has been enabled, then write the message to the
+ // kernel trace_marker.
+ int length = strlen(message);
+ char buf[length + WRITE_OFFSET];
+ size_t len = snprintf(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
+ ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, buf, len));
+
+ // Error while writing
+ if (static_cast<size_t>(wbytes) != len) {
+ __libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
+ }
+}
+
+ScopedTrace::~ScopedTrace() {
+ if (!should_trace()) {
+ return;
+ }
+
+ ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, "E", 1));
+
+ // Error while writing
+ if (static_cast<size_t>(wbytes) != 1) {
+ __libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
+ }
+}
diff --git a/libc/bionic/debug_mapinfo.cpp b/libc/bionic/debug_mapinfo.cpp
index 17276ce..d83799a 100644
--- a/libc/bionic/debug_mapinfo.cpp
+++ b/libc/bionic/debug_mapinfo.cpp
@@ -26,39 +26,48 @@
* SUCH DAMAGE.
*/
+#include <ctype.h>
+#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <sys/mman.h>
#include "debug_mapinfo.h"
+#include "malloc_debug_disable.h"
-// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so
-// 012345678901234567890123456789012345678901234567890123456789
-// 0 1 2 3 4 5
-
+// Format of /proc/<PID>/maps:
+// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so
static mapinfo_t* parse_maps_line(char* line) {
- int len = strlen(line);
+ uintptr_t start;
+ uintptr_t end;
+ int name_pos;
+ if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d%n", &start,
+ &end, &name_pos) < 2) {
+ return NULL;
+ }
- if (len < 1) return 0;
- line[--len] = 0;
+ while (isspace(line[name_pos])) {
+ name_pos += 1;
+ }
+ const char* name = line + name_pos;
+ size_t name_len = strlen(name);
+ if (name_len && name[name_len - 1] == '\n') {
+ name_len -= 1;
+ }
- if (len < 50) return 0;
- if (line[20] != 'x') return 0;
-
- mapinfo_t* mi = static_cast<mapinfo_t*>(
- mmap(NULL, sizeof(mapinfo_t) + (len - 47), PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0));
- if (mi == MAP_FAILED) return 0;
-
- mi->start = strtoul(line, 0, 16);
- mi->end = strtoul(line + 9, 0, 16);
- mi->next = 0;
- strcpy(mi->name, line + 49);
-
+ mapinfo_t* mi = reinterpret_cast<mapinfo_t*>(calloc(1, sizeof(mapinfo_t) + name_len + 1));
+ if (mi) {
+ mi->start = start;
+ mi->end = end;
+ memcpy(mi->name, name, name_len);
+ mi->name[name_len] = '\0';
+ }
return mi;
}
__LIBC_HIDDEN__ mapinfo_t* mapinfo_create(pid_t pid) {
+ ScopedDisableDebugCalls disable;
+
struct mapinfo_t* milist = NULL;
char data[1024]; // Used to read lines as well as to construct the filename.
snprintf(data, sizeof(data), "/proc/%d/maps", pid);
@@ -77,10 +86,12 @@
}
__LIBC_HIDDEN__ void mapinfo_destroy(mapinfo_t* mi) {
+ ScopedDisableDebugCalls disable;
+
while (mi != NULL) {
mapinfo_t* del = mi;
mi = mi->next;
- munmap(del, sizeof(mapinfo_t) + strlen(del->name) + 2);
+ free(del);
}
}
diff --git a/libc/bionic/debug_mapinfo.h b/libc/bionic/debug_mapinfo.h
index cccd2e3..926b377 100644
--- a/libc/bionic/debug_mapinfo.h
+++ b/libc/bionic/debug_mapinfo.h
@@ -33,8 +33,8 @@
struct mapinfo_t {
struct mapinfo_t* next;
- unsigned start;
- unsigned end;
+ uintptr_t start;
+ uintptr_t end;
char name[];
};
diff --git a/libc/bionic/debug_stacktrace.cpp b/libc/bionic/debug_stacktrace.cpp
index 713e761..b86e2af 100644
--- a/libc/bionic/debug_stacktrace.cpp
+++ b/libc/bionic/debug_stacktrace.cpp
@@ -35,6 +35,7 @@
#include <sys/types.h>
#include "debug_mapinfo.h"
+#include "malloc_debug_disable.h"
#include "private/libc_logging.h"
#if defined(__LP64__)
@@ -56,6 +57,8 @@
static DemanglerFn g_demangler_fn = NULL;
__LIBC_HIDDEN__ void backtrace_startup() {
+ ScopedDisableDebugCalls disable;
+
g_map_info = mapinfo_create(getpid());
g_demangler = dlopen("libgccdemangle.so", RTLD_NOW);
if (g_demangler != NULL) {
@@ -65,6 +68,8 @@
}
__LIBC_HIDDEN__ void backtrace_shutdown() {
+ ScopedDisableDebugCalls disable;
+
mapinfo_destroy(g_map_info);
dlclose(g_demangler);
}
@@ -98,7 +103,7 @@
return _URC_NO_REASON;
}
-#ifdef __arm__
+#if defined(__arm__)
/*
* The instruction pointer is pointing at the instruction after the bl(x), and
* the _Unwind_Backtrace routine already masks the Thumb mode indicator (LSB
@@ -121,12 +126,16 @@
}
__LIBC_HIDDEN__ int get_backtrace(uintptr_t* frames, size_t max_depth) {
+ ScopedDisableDebugCalls disable;
+
stack_crawl_state_t state(frames, max_depth);
_Unwind_Backtrace(trace_function, &state);
return state.frame_count;
}
__LIBC_HIDDEN__ void log_backtrace(uintptr_t* frames, size_t frame_count) {
+ ScopedDisableDebugCalls disable;
+
uintptr_t self_bt[16];
if (frames == NULL) {
frame_count = get_backtrace(self_bt, 16);
@@ -146,7 +155,7 @@
symbol = info.dli_sname;
}
- uintptr_t rel_pc;
+ uintptr_t rel_pc = offset;
const mapinfo_t* mi = (g_map_info != NULL) ? mapinfo_find(g_map_info, frames[i], &rel_pc) : NULL;
const char* soname = (mi != NULL) ? mi->name : info.dli_fname;
if (soname == NULL) {
diff --git a/libc/bionic/getpt.c b/libc/bionic/getpt.c
deleted file mode 100644
index 8bb5c11..0000000
--- a/libc/bionic/getpt.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <unistd.h>
-#include <fcntl.h>
-
-int getpt(void)
-{
- return open("/dev/ptmx", O_RDWR|O_NOCTTY);
-}
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index d6fa1db..d0172ed 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -378,9 +378,6 @@
} else if (c == '%') {
buffer[0] = '%';
buffer[1] = '\0';
- } else if (c == 'm') {
- // syslog-like %m for strerror(errno).
- str = strerror(errno);
} else {
__assert(__FILE__, __LINE__, "conversion specifier unsupported");
}
diff --git a/libc/bionic/locale.cpp b/libc/bionic/locale.cpp
index 5a1da43..363140e 100644
--- a/libc/bionic/locale.cpp
+++ b/libc/bionic/locale.cpp
@@ -79,7 +79,9 @@
static bool __is_supported_locale(const char* locale) {
return (strcmp(locale, "") == 0 ||
- strcmp(locale, "C") == 0 || strcmp(locale, "C.UTF-8") == 0 ||
+ strcmp(locale, "C") == 0 ||
+ strcmp(locale, "C.UTF-8") == 0 ||
+ strcmp(locale, "en_US.UTF-8") == 0 ||
strcmp(locale, "POSIX") == 0);
}
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index 1c63d4d..94ba6f5 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -49,6 +49,7 @@
#include "debug_mapinfo.h"
#include "debug_stacktrace.h"
#include "malloc_debug_common.h"
+#include "malloc_debug_disable.h"
#include "private/bionic_macros.h"
#include "private/libc_logging.h"
#include "private/ScopedPthreadMutexLocker.h"
@@ -331,6 +332,9 @@
extern "C" void* chk_malloc(size_t bytes) {
// log_message("%s: %s\n", __FILE__, __FUNCTION__);
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->malloc(bytes);
+ }
size_t size = sizeof(hdr_t) + bytes + sizeof(ftr_t);
if (size < bytes) { // Overflow
@@ -348,6 +352,10 @@
}
extern "C" void* chk_memalign(size_t alignment, size_t bytes) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->memalign(alignment, bytes);
+ }
+
if (alignment <= MALLOC_ALIGNMENT) {
return chk_malloc(bytes);
}
@@ -386,6 +394,9 @@
extern "C" void chk_free(void* ptr) {
// log_message("%s: %s\n", __FILE__, __FUNCTION__);
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->free(ptr);
+ }
if (!ptr) /* ignore free(NULL) */
return;
@@ -421,6 +432,9 @@
extern "C" void* chk_realloc(void* ptr, size_t bytes) {
// log_message("%s: %s\n", __FILE__, __FUNCTION__);
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->realloc(ptr, bytes);
+ }
if (!ptr) {
return chk_malloc(bytes);
@@ -496,6 +510,10 @@
extern "C" void* chk_calloc(size_t nmemb, size_t bytes) {
// log_message("%s: %s\n", __FILE__, __FUNCTION__);
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->calloc(nmemb, bytes);
+ }
+
size_t total_bytes = nmemb * bytes;
size_t size = sizeof(hdr_t) + total_bytes + sizeof(ftr_t);
if (size < total_bytes || (nmemb && SIZE_MAX / nmemb < bytes)) { // Overflow
@@ -513,6 +531,10 @@
}
extern "C" size_t chk_malloc_usable_size(const void* ptr) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->malloc_usable_size(ptr);
+ }
+
// malloc_usable_size returns 0 for NULL and unknown blocks.
if (ptr == NULL)
return 0;
@@ -529,6 +551,10 @@
}
extern "C" int chk_posix_memalign(void** memptr, size_t alignment, size_t size) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->posix_memalign(memptr, alignment, size);
+ }
+
if (!powerof2(alignment)) {
return EINVAL;
}
@@ -538,7 +564,12 @@
return (*memptr != NULL) ? 0 : ENOMEM;
}
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
extern "C" void* chk_pvalloc(size_t bytes) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->pvalloc(bytes);
+ }
+
size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
@@ -548,10 +579,16 @@
}
extern "C" void* chk_valloc(size_t size) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->valloc(size);
+ }
return chk_memalign(getpagesize(), size);
}
+#endif
static void ReportMemoryLeaks() {
+ ScopedDisableDebugCalls disable;
+
// Use /proc/self/exe link to obtain the program name for logging
// purposes. If it's not available, we set it to "<unknown>".
char exe[PATH_MAX];
@@ -585,10 +622,14 @@
}
}
+pthread_key_t g_debug_calls_disabled;
+
extern "C" bool malloc_debug_initialize(HashTable* hash_table, const MallocDebug* malloc_dispatch) {
g_hash_table = hash_table;
g_malloc_dispatch = malloc_dispatch;
+ pthread_key_create(&g_debug_calls_disabled, NULL);
+
char debug_backlog[PROP_VALUE_MAX];
if (__system_property_get("libc.debug.malloc.backlog", debug_backlog)) {
g_malloc_debug_backlog = atoi(debug_backlog);
@@ -605,4 +646,6 @@
ReportMemoryLeaks();
}
backtrace_shutdown();
+
+ pthread_setspecific(g_debug_calls_disabled, NULL);
}
diff --git a/libc/bionic/malloc_debug_disable.h b/libc/bionic/malloc_debug_disable.h
new file mode 100644
index 0000000..9503128
--- /dev/null
+++ b/libc/bionic/malloc_debug_disable.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014 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 MALLOC_DEBUG_DISABLE_H
+#define MALLOC_DEBUG_DISABLE_H
+
+#include <pthread.h>
+
+#include "private/bionic_macros.h"
+
+// =============================================================================
+// Used to disable the debug allocation calls.
+// =============================================================================
+extern pthread_key_t g_debug_calls_disabled;
+
+static inline bool DebugCallsDisabled() {
+ return pthread_getspecific(g_debug_calls_disabled) != NULL;
+}
+
+class ScopedDisableDebugCalls {
+ public:
+ ScopedDisableDebugCalls() : disabled_(DebugCallsDisabled()) {
+ if (!disabled_) {
+ pthread_setspecific(g_debug_calls_disabled, reinterpret_cast<const void*>(1));
+ }
+ }
+ ~ScopedDisableDebugCalls() {
+ if (!disabled_) {
+ pthread_setspecific(g_debug_calls_disabled, NULL);
+ }
+ }
+
+ private:
+ bool disabled_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedDisableDebugCalls);
+};
+
+#endif // MALLOC_DEBUG_DISABLE_H
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index d9824f0..7926a1f 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -48,6 +48,7 @@
#include "debug_stacktrace.h"
#include "malloc_debug_common.h"
+#include "malloc_debug_disable.h"
#include "private/bionic_macros.h"
#include "private/libc_logging.h"
@@ -267,6 +268,7 @@
return (*memptr != NULL) ? 0 : ENOMEM;
}
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
extern "C" void* fill_pvalloc(size_t bytes) {
size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
@@ -279,6 +281,7 @@
extern "C" void* fill_valloc(size_t size) {
return fill_memalign(getpagesize(), size);
}
+#endif
// =============================================================================
// malloc leak functions
@@ -287,6 +290,10 @@
static uint32_t MEMALIGN_GUARD = 0xA1A41520;
extern "C" void* leak_malloc(size_t bytes) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->malloc(bytes);
+ }
+
// allocate enough space infront of the allocation to store the pointer for
// the alloc structure. This will making free'ing the structer really fast!
@@ -319,6 +326,10 @@
}
extern "C" void leak_free(void* mem) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->free(mem);
+ }
+
if (mem == NULL) {
return;
}
@@ -355,6 +366,10 @@
}
extern "C" void* leak_calloc(size_t n_elements, size_t elem_size) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->calloc(n_elements, elem_size);
+ }
+
// Fail on overflow - just to be safe even though this code runs only
// within the debugging C library, not the production one.
if (n_elements && SIZE_MAX / n_elements < elem_size) {
@@ -370,6 +385,10 @@
}
extern "C" void* leak_realloc(void* oldMem, size_t bytes) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->realloc(oldMem, bytes);
+ }
+
if (oldMem == NULL) {
return leak_malloc(bytes);
}
@@ -398,6 +417,10 @@
}
extern "C" void* leak_memalign(size_t alignment, size_t bytes) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->memalign(alignment, bytes);
+ }
+
// we can just use malloc
if (alignment <= MALLOC_ALIGNMENT) {
return leak_malloc(bytes);
@@ -439,6 +462,10 @@
}
extern "C" size_t leak_malloc_usable_size(const void* mem) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->malloc_usable_size(mem);
+ }
+
if (mem != NULL) {
// Check the guard to make sure it is valid.
const AllocationEntry* header = const_to_header((void*)mem);
@@ -467,6 +494,10 @@
}
extern "C" int leak_posix_memalign(void** memptr, size_t alignment, size_t size) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->posix_memalign(memptr, alignment, size);
+ }
+
if (!powerof2(alignment)) {
return EINVAL;
}
@@ -476,7 +507,12 @@
return (*memptr != NULL) ? 0 : ENOMEM;
}
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
extern "C" void* leak_pvalloc(size_t bytes) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->pvalloc(bytes);
+ }
+
size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
@@ -486,5 +522,10 @@
}
extern "C" void* leak_valloc(size_t size) {
+ if (DebugCallsDisabled()) {
+ return g_malloc_dispatch->valloc(size);
+ }
+
return leak_memalign(getpagesize(), size);
}
+#endif
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 174e308..fc8afa2 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -51,9 +51,9 @@
// This code is used both by each new pthread and the code that initializes the main thread.
void __init_tls(pthread_internal_t* thread) {
- // Zero-initialize all the slots after TLS_SLOT_SELF and TLS_SLOT_THREAD_ID.
- for (size_t i = TLS_SLOT_ERRNO; i < BIONIC_TLS_SLOTS; ++i) {
- thread->tls[i] = NULL;
+ if (thread->user_allocated_stack()) {
+ // We don't know where the user got their stack, so assume the worst and zero the TLS area.
+ memset(&thread->tls[0], 0, BIONIC_TLS_SLOTS * sizeof(void*));
}
// Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
@@ -66,7 +66,7 @@
void __init_alternate_signal_stack(pthread_internal_t* thread) {
// Create and set an alternate signal stack.
stack_t ss;
- ss.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+ ss.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (ss.ss_sp != MAP_FAILED) {
ss.ss_size = SIGSTKSZ;
ss.ss_flags = 0;
@@ -227,7 +227,7 @@
// be unblocked, but we're about to unmap the memory the mutex is stored in, so this serves as a
// reminder that you can't rewrite this function to use a ScopedPthreadMutexLocker.
pthread_mutex_unlock(&thread->startup_handshake_mutex);
- if ((thread->attr.flags & PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK) == 0) {
+ if (!thread->user_allocated_stack()) {
munmap(thread->attr.stack_base, thread->attr.stack_size);
}
free(thread);
diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp
index 2470c9c..a6bb363 100644
--- a/libc/bionic/pthread_exit.cpp
+++ b/libc/bionic/pthread_exit.cpp
@@ -90,7 +90,7 @@
// Keep track of what we need to know about the stack before we lose the pthread_internal_t.
void* stack_base = thread->attr.stack_base;
size_t stack_size = thread->attr.stack_size;
- bool user_allocated_stack = ((thread->attr.flags & PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK) != 0);
+ bool user_allocated_stack = thread->user_allocated_stack();
pthread_mutex_lock(&g_thread_list_lock);
if ((thread->attr.flags & PTHREAD_ATTR_FLAG_DETACHED) != 0) {
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index e05d15c..7bcd758 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -30,6 +30,18 @@
#include <pthread.h>
+/* Has the thread been detached by a pthread_join or pthread_detach call? */
+#define PTHREAD_ATTR_FLAG_DETACHED 0x00000001
+
+/* Was the thread's stack allocated by the user rather than by us? */
+#define PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK 0x00000002
+
+/* Has the thread been joined by another thread? */
+#define PTHREAD_ATTR_FLAG_JOINED 0x00000004
+
+/* Is this the main thread? */
+#define PTHREAD_ATTR_FLAG_MAIN_THREAD 0x80000000
+
struct pthread_internal_t {
struct pthread_internal_t* next;
struct pthread_internal_t* prev;
@@ -56,6 +68,10 @@
return (*cached_pid != 0);
}
+ bool user_allocated_stack() {
+ return (attr.flags & PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK) != 0;
+ }
+
void** tls;
pthread_attr_t attr;
@@ -87,20 +103,8 @@
__LIBC_HIDDEN__ void pthread_key_clean_all(void);
__LIBC_HIDDEN__ void _pthread_internal_remove_locked(pthread_internal_t* thread);
-/* Has the thread been detached by a pthread_join or pthread_detach call? */
-#define PTHREAD_ATTR_FLAG_DETACHED 0x00000001
-
-/* Was the thread's stack allocated by the user rather than by us? */
-#define PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK 0x00000002
-
-/* Has the thread been joined by another thread? */
-#define PTHREAD_ATTR_FLAG_JOINED 0x00000004
-
-/* Is this the main thread? */
-#define PTHREAD_ATTR_FLAG_MAIN_THREAD 0x80000000
-
/*
- * Traditionally we give threads a 1MiB stack. When we started
+ * Traditionally we gave threads a 1MiB stack. When we started
* allocating per-thread alternate signal stacks to ease debugging of
* stack overflows, we subtracted the same amount we were using there
* from the default thread stack size. This should keep memory usage
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index 5461661..e00ffb4 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -39,6 +39,8 @@
#include "private/bionic_futex.h"
#include "private/bionic_tls.h"
+#include "private/bionic_systrace.h"
+
extern void pthread_debug_mutex_lock_check(pthread_mutex_t *mutex);
extern void pthread_debug_mutex_unlock_check(pthread_mutex_t *mutex);
@@ -333,6 +335,10 @@
* that the mutex is in state 2 when we go to sleep on it, which
* guarantees a wake-up call.
*/
+
+ ScopedTrace trace("Contending for pthread mutex");
+
+
while (__bionic_swap(locked_contended, &mutex->value) != unlocked) {
__futex_wait_ex(&mutex->value, shared, locked_contended, NULL);
}
@@ -473,6 +479,8 @@
mvalue = mutex->value;
}
+ ScopedTrace trace("Contending for pthread mutex");
+
for (;;) {
int newval;
@@ -626,6 +634,8 @@
return 0;
}
+ ScopedTrace trace("Contending for timed pthread mutex");
+
// Loop while needed.
while (__bionic_swap(locked_contended, &mutex->value) != unlocked) {
if (__timespec_from_absolute(&ts, abs_timeout, clock) < 0) {
@@ -658,6 +668,8 @@
mvalue = mutex->value;
}
+ ScopedTrace trace("Contending for timed pthread mutex");
+
while (true) {
// If the value is 'unlocked', try to acquire it directly.
// NOTE: put state to 2 since we know there is contention.
diff --git a/libc/bionic/ptsname.c b/libc/bionic/ptsname.c
deleted file mode 100644
index 24d5d30..0000000
--- a/libc/bionic/ptsname.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <stdio.h>
-#include <unistd.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-
-/* not thread-safe */
-char* ptsname( int fd )
-{
- unsigned int pty_num;
- static char buff[64];
-
- if ( ioctl( fd, TIOCGPTN, &pty_num ) != 0 )
- return NULL;
-
- snprintf( buff, sizeof(buff), "/dev/pts/%u", pty_num );
- return buff;
-}
diff --git a/libc/bionic/ptsname_r.c b/libc/bionic/ptsname_r.c
deleted file mode 100644
index 2fa4c3d..0000000
--- a/libc/bionic/ptsname_r.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <stdio.h>
-#include <unistd.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <string.h>
-
-int ptsname_r( int fd, char* buf, size_t buflen)
-{
- unsigned int pty_num;
- char buff[64];
- int len;
-
- if (buf == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if ( ioctl( fd, TIOCGPTN, &pty_num ) != 0 ) {
- errno = ENOTTY;
- return -1;
- }
-
- len = snprintf( buff, sizeof(buff), "/dev/pts/%u", pty_num );
- if (len+1 > (int)buflen) {
- errno = ERANGE;
- return -1;
- }
- memcpy( buf, buff, len+1 );
- return 0;
-}
diff --git a/libc/bionic/pty.cpp b/libc/bionic/pty.cpp
new file mode 100644
index 0000000..995e006
--- /dev/null
+++ b/libc/bionic/pty.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <unistd.h>
+
+int getpt(void) {
+ return posix_openpt(O_RDWR|O_NOCTTY);
+}
+
+int grantpt(int) {
+ return 0;
+}
+
+int posix_openpt(int flags) {
+ return open("/dev/ptmx", flags);
+}
+
+char* ptsname(int fd) {
+ static char buf[64];
+ return ptsname_r(fd, buf, sizeof(buf)) == 0 ? buf : NULL;
+}
+
+int ptsname_r(int fd, char* buf, size_t len) {
+ if (buf == NULL) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ unsigned int pty_num;
+ if (ioctl(fd, TIOCGPTN, &pty_num) != 0) {
+ errno = ENOTTY;
+ return errno;
+ }
+
+ if (snprintf(buf, len, "/dev/pts/%u", pty_num) >= static_cast<int>(len)) {
+ errno = ERANGE;
+ return errno;
+ }
+
+ return 0;
+}
+
+char* ttyname(int fd) {
+ static char buf[64];
+ return ttyname_r(fd, buf, sizeof(buf)) == 0 ? buf : NULL;
+}
+
+int ttyname_r(int fd, char* buf, size_t len) {
+ if (buf == NULL) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ if (!isatty(fd)) {
+ return errno;
+ }
+
+ char path[64];
+ snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
+
+ ssize_t count = readlink(path, buf, len);
+ if (count == -1) {
+ return errno;
+ }
+ if (static_cast<size_t>(count) == len) {
+ errno = ERANGE;
+ return errno;
+ }
+ buf[count] = '\0';
+ return 0;
+}
+
+int unlockpt(int fd) {
+ int unlock = 0;
+ return ioctl(fd, TIOCSPTLCK, &unlock);
+}
diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp
index 0937e9c..b1e38be 100644
--- a/libc/bionic/stubs.cpp
+++ b/libc/bionic/stubs.cpp
@@ -444,16 +444,6 @@
UNIMPLEMENTED;
}
-char* ttyname(int /*fd*/) { // NOLINT: implementing bad function.
- UNIMPLEMENTED;
- return NULL;
-}
-
-int ttyname_r(int /*fd*/, char* /*buf*/, size_t /*buflen*/) {
- UNIMPLEMENTED;
- return -ERANGE;
-}
-
char* getusershell() {
UNIMPLEMENTED;
return NULL;
diff --git a/libc/bionic/syslog.cpp b/libc/bionic/syslog.cpp
index 7e153eb..d8b8b19 100644
--- a/libc/bionic/syslog.cpp
+++ b/libc/bionic/syslog.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include <syslog.h>
-
+#include <errno.h>
#include <stdlib.h>
+#include <syslog.h>
#include "private/libc_logging.h"
@@ -24,6 +24,7 @@
static int syslog_priority_mask = 0xff;
void closelog() {
+ syslog_log_tag = NULL;
}
void openlog(const char* log_tag, int /*options*/, int /*facility*/) {
@@ -47,6 +48,8 @@
}
void vsyslog(int priority, const char* fmt, va_list args) {
+ int caller_errno = errno;
+
// Check whether we're supposed to be logging messages of this priority.
if ((syslog_priority_mask & LOG_MASK(LOG_PRI(priority))) == 0) {
return;
@@ -61,7 +64,7 @@
// What's our Android log priority?
priority &= LOG_PRIMASK;
int android_log_priority;
- if (priority < LOG_ERR) {
+ if (priority <= LOG_ERR) {
android_log_priority = ANDROID_LOG_ERROR;
} else if (priority == LOG_WARNING) {
android_log_priority = ANDROID_LOG_WARN;
@@ -71,5 +74,48 @@
android_log_priority = ANDROID_LOG_DEBUG;
}
- __libc_format_log_va_list(android_log_priority, log_tag, fmt, args);
+ // glibc's printf family support %m directly, but our BSD-based one doesn't.
+ // If the format string seems to contain "%m", rewrite it.
+ const char* log_fmt = fmt;
+ if (strstr(fmt, "%m") != NULL) {
+ size_t dst_len = 1024;
+ char* dst = reinterpret_cast<char*>(malloc(dst_len));
+ log_fmt = dst;
+
+ const char* src = fmt;
+ for (; dst_len > 0 && *src != '\0'; ++src) {
+ if (*src == '%' && *(src + 1) == 'm') {
+ // Expand %m.
+ size_t n = strlcpy(dst, strerror(caller_errno), dst_len);
+ if (n >= dst_len) {
+ n = dst_len;
+ }
+ dst += n;
+ dst_len -= n;
+ ++src;
+ } else if (*src == '%' && *(src + 1) == '%') {
+ // We need to copy pairs of '%'s so the %m test works.
+ if (dst_len <= 2) {
+ break;
+ }
+ *dst++ = '%'; --dst_len;
+ *dst++ = '%'; --dst_len;
+ ++src;
+ } else {
+ *dst++ = *src; --dst_len;
+ }
+ }
+ *dst = '\0';
+ }
+
+ // We can't let __libc_format_log do the formatting because it doesn't support
+ // all the printf functionality.
+ char log_line[1024];
+ vsnprintf(log_line, sizeof(log_line), log_fmt, args);
+
+ if (log_fmt != fmt) {
+ free(const_cast<char*>(log_fmt));
+ }
+
+ __libc_format_log(android_log_priority, log_tag, "%s", log_line);
}
diff --git a/libc/bionic/tdestroy.cpp b/libc/bionic/tdestroy.cpp
index decde4d..49614b8 100644
--- a/libc/bionic/tdestroy.cpp
+++ b/libc/bionic/tdestroy.cpp
@@ -19,7 +19,7 @@
#include <stdlib.h>
// Destroy a tree and free all allocated resources.
-// This is a GNU extension, not available from NetBSD.
+// This is a GNU extension, not available from BSD.
void tdestroy(void* root, void (*destroy_func)(void*)) {
node_t* root_node = (node_t*) root;
if (root_node == NULL) {
diff --git a/libc/bionic/unlockpt.c b/libc/bionic/unlockpt.c
deleted file mode 100644
index 998b7a3..0000000
--- a/libc/bionic/unlockpt.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <unistd.h>
-#include <sys/ioctl.h>
-
-int unlockpt( int fd )
-{
- int unlock = 0;
-
- return ioctl( fd, TIOCSPTLCK, &unlock );
-}
diff --git a/libc/include/grp.h b/libc/include/grp.h
index 86d99f3..fc4d520 100644
--- a/libc/include/grp.h
+++ b/libc/include/grp.h
@@ -43,10 +43,6 @@
#include <sys/cdefs.h>
#include <sys/types.h>
-#if __BSD_VISIBLE
-#define _PATH_GROUP "/etc/group"
-#endif
-
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
@@ -57,7 +53,7 @@
__BEGIN_DECLS
struct group *getgrgid(gid_t);
struct group *getgrnam(const char *);
-#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XPG_VISIBLE
+#if __POSIX_VISIBLE >= 200112 || __XPG_VISIBLE
struct group *getgrent(void);
void setgrent(void);
void endgrent(void);
@@ -66,11 +62,6 @@
int getgrnam_r(const char *, struct group *, char *,
size_t, struct group **);
#endif
-#if __BSD_VISIBLE
-void setgrfile(const char *);
-int setgroupent(int);
-char *group_from_gid(gid_t, int);
-#endif
int getgrouplist (const char *user, gid_t group,
gid_t *groups, int *ngroups);
diff --git a/libc/include/search.h b/libc/include/search.h
index b2c0e6b..9b01e12 100644
--- a/libc/include/search.h
+++ b/libc/include/search.h
@@ -29,6 +29,9 @@
__BEGIN_DECLS
+void insque(void*, void*);
+void remque(void*);
+
void* lfind(const void*, const void*, size_t*, size_t, int (*)(const void*, const void*));
void* lsearch(const void*, void*, size_t*, size_t, int (*)(const void*, const void*));
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index e532de4..9c6bd3f 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -223,12 +223,6 @@
FILE * __restrict);
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict);
-#if __BSD_VISIBLE && !defined(__SYS_ERRLIST)
-#define __SYS_ERRLIST
-extern int sys_nerr; /* perror(3) external variables */
-extern char *sys_errlist[];
-#endif
-
void perror(const char *);
int printf(const char * __restrict, ...)
__printflike(1, 2);
@@ -300,9 +294,6 @@
#define L_ctermid 1024 /* size for ctermid(); PATH_MAX */
__BEGIN_DECLS
-#if 0 /* MISSING FROM BIONIC */
-char *ctermid(char *);
-#endif /* MISSING */
FILE *fdopen(int, const char *);
int fileno(FILE *);
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 0dac650..eb39fc9 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -126,18 +126,12 @@
char* setstate(char*);
void srandom(unsigned int);
-/* Basic PTY functions. These only work if devpts is mounted! */
-
-extern int unlockpt(int);
-extern char* ptsname(int);
-extern int ptsname_r(int, char*, size_t);
-extern int getpt(void);
-
-static __inline__ int grantpt(int __fd __attribute((unused)))
-{
- (void)__fd;
- return 0; /* devpts does this all for us! */
-}
+int getpt(void);
+int grantpt(int);
+int posix_openpt(int);
+char* ptsname(int) __warnattr("ptsname is not thread-safe; use ptsname_r instead");
+int ptsname_r(int, char*, size_t);
+int unlockpt(int);
typedef struct {
int quot;
@@ -175,10 +169,6 @@
#define MB_CUR_MAX 4U
-#if 0 /* MISSING FROM BIONIC */
-extern int on_exit(void (*)(int, void *), void *);
-#endif /* MISSING */
-
__END_DECLS
#endif /* _STDLIB_H_ */
diff --git a/libc/include/sys/cdefs_elf.h b/libc/include/sys/cdefs_elf.h
index b5db13e..4dd7dc3 100644
--- a/libc/include/sys/cdefs_elf.h
+++ b/libc/include/sys/cdefs_elf.h
@@ -68,7 +68,7 @@
#ifdef __LP64__
#define __LIBC64_HIDDEN__ __LIBC_HIDDEN__
#else
-#define __LIBC64_HIDDEN__
+#define __LIBC64_HIDDEN__ __LIBC_ABI_PUBLIC__
#endif
/* Used to tag non-static symbols that are public and exposed by the shared library. */
diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h
index a44b2e5..34a29df 100644
--- a/libc/include/sys/syscall.h
+++ b/libc/include/sys/syscall.h
@@ -37,7 +37,7 @@
__BEGIN_DECLS
-int syscall(int number, ...);
+long syscall(long number, ...);
__END_DECLS
diff --git a/libc/include/syslog.h b/libc/include/syslog.h
index f396fec..cbceab2 100644
--- a/libc/include/syslog.h
+++ b/libc/include/syslog.h
@@ -35,45 +35,48 @@
__BEGIN_DECLS
-#define LOG_EMERG 0
-#define LOG_ALERT 1
-#define LOG_CRIT 2
-#define LOG_ERR 3
-#define LOG_WARNING 4
-#define LOG_NOTICE 5
-#define LOG_INFO 6
-#define LOG_DEBUG 7
+/* Priorities are translated to Android log priorities as shown. */
+#define LOG_EMERG 0 /* ERROR */
+#define LOG_ALERT 1 /* ERROR */
+#define LOG_CRIT 2 /* ERROR */
+#define LOG_ERR 3 /* ERROR */
+#define LOG_WARNING 4 /* WARN */
+#define LOG_NOTICE 5 /* INFO */
+#define LOG_INFO 6 /* INFO */
+#define LOG_DEBUG 7 /* DEBUG */
-#define LOG_PRIMASK 7
-#define LOG_PRI(x) ((x) & LOG_PRIMASK)
+#define LOG_PRIMASK 7
+#define LOG_PRI(x) ((x) & LOG_PRIMASK)
-#define LOG_KERN 0000
-#define LOG_USER 0010
-#define LOG_MAIL 0020
-#define LOG_DAEMON 0030
-#define LOG_AUTH 0040
-#define LOG_SYSLOG 0050
-#define LOG_LPR 0060
-#define LOG_NEWS 0070
-#define LOG_UUCP 0100
-#define LOG_CRON 0110
-#define LOG_AUTHPRIV 0120
-#define LOG_FTP 0130
-#define LOG_LOCAL0 0200
-#define LOG_LOCAL1 0210
-#define LOG_LOCAL2 0220
-#define LOG_LOCAL3 0230
-#define LOG_LOCAL4 0240
-#define LOG_LOCAL5 0250
-#define LOG_LOCAL6 0260
-#define LOG_LOCAL7 0270
+/* Facilities are currently ignored on Android. */
+#define LOG_KERN 0000
+#define LOG_USER 0010
+#define LOG_MAIL 0020
+#define LOG_DAEMON 0030
+#define LOG_AUTH 0040
+#define LOG_SYSLOG 0050
+#define LOG_LPR 0060
+#define LOG_NEWS 0070
+#define LOG_UUCP 0100
+#define LOG_CRON 0110
+#define LOG_AUTHPRIV 0120
+#define LOG_FTP 0130
+#define LOG_LOCAL0 0200
+#define LOG_LOCAL1 0210
+#define LOG_LOCAL2 0220
+#define LOG_LOCAL3 0230
+#define LOG_LOCAL4 0240
+#define LOG_LOCAL5 0250
+#define LOG_LOCAL6 0260
+#define LOG_LOCAL7 0270
-#define LOG_FACMASK 01770
-#define LOG_FAC(x) (((x) >> 3) & (LOG_FACMASK >> 3))
+#define LOG_FACMASK 01770
+#define LOG_FAC(x) (((x) >> 3) & (LOG_FACMASK >> 3))
#define LOG_MASK(pri) (1 << (pri))
#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1)
+/* openlog(3) flags are currently ignored on Android. */
#define LOG_PID 0x01
#define LOG_CONS 0x02
#define LOG_ODELAY 0x04
@@ -81,11 +84,11 @@
#define LOG_NOWAIT 0x10
#define LOG_PERROR 0x20
-extern void closelog(void);
-extern void openlog(const char*, int, int);
-extern int setlogmask(int);
-extern void syslog(int, const char*, ...) __printflike(2, 3);
-extern void vsyslog(int, const char*, va_list) __printflike(2, 0);
+void closelog(void);
+void openlog(const char*, int, int);
+int setlogmask(int);
+void syslog(int, const char*, ...) __printflike(2, 3);
+void vsyslog(int, const char*, va_list) __printflike(2, 0);
__END_DECLS
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 12e6257..7fbafdf 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -170,7 +170,7 @@
extern int optind, opterr, optopt;
extern int isatty(int);
-extern char* ttyname(int);
+extern char* ttyname(int) __warnattr("ttyname is not thread-safe; use ttyname_r instead");
extern int ttyname_r(int, char*, size_t);
extern int acct(const char* filepath);
@@ -189,16 +189,6 @@
extern pid_t tcgetpgrp(int fd);
extern int tcsetpgrp(int fd, pid_t _pid);
-#if 0 /* MISSING FROM BIONIC */
-extern int execlpe(const char *, const char *, ...);
-extern int getfsuid(uid_t);
-extern int setfsuid(uid_t);
-extern int getlogin_r(char* name, size_t namesize);
-extern int sethostname(const char *, size_t);
-extern int getdomainname(char *, size_t);
-extern int setdomainname(const char *, size_t);
-#endif /* MISSING */
-
/* Used to retry syscalls that can return EINTR. */
#define TEMP_FAILURE_RETRY(exp) ({ \
__typeof__(exp) _rc; \
diff --git a/libc/private/bionic_systrace.h b/libc/private/bionic_systrace.h
new file mode 100644
index 0000000..ad9ff7f
--- /dev/null
+++ b/libc/private/bionic_systrace.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BIONIC_SYSTRACE_H
+#define BIONIC_SYSTRACE_H
+
+#include "bionic_macros.h"
+
+// Tracing class for bionic. To begin a trace at a specified point:
+// ScopedTrace("Trace message");
+// The trace will end when the contructor goes out of scope.
+
+class ScopedTrace {
+ public:
+ explicit ScopedTrace(const char* message);
+ ~ScopedTrace();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedTrace);
+};
+
+#endif
diff --git a/libc/private/bionic_time.h b/libc/private/bionic_time.h
index ca5c146..030dcfd 100644
--- a/libc/private/bionic_time.h
+++ b/libc/private/bionic_time.h
@@ -33,32 +33,8 @@
__BEGIN_DECLS
-#ifndef _BIONIC_STRFTIME_TZ_DECLARED
-#define _BIONIC_STRFTIME_TZ_DECLARED
-
-struct strftime_locale {
- const char * mon[12];
- const char * month[12];
- const char * standalone_month[12];
- const char * wday[7];
- const char * weekday[7];
- const char * X_fmt;
- const char * x_fmt;
- const char * c_fmt;
- const char * am;
- const char * pm;
- const char * date_fmt;
-};
-
-/*
- * Note: you should consider these extensions deprecated and use managed code or icu4c instead.
- * We'd like to hide them but they're currently still used in frameworks code.
- */
-extern size_t strftime_tz(char*, size_t, const char*, const struct tm*, const struct strftime_locale*);
-extern time_t mktime_tz(struct tm* const, char const*);
-extern void localtime_tz(const time_t* const, struct tm*, const char*);
-
-#endif /* _BIONIC_STRFTIME_TZ_DECLARED */
+// We can't remove this (and this file) until we fix MtpUtils.cpp.
+time_t mktime_tz(struct tm* const, char const*);
__END_DECLS
diff --git a/libc/tools/generate-NOTICE.py b/libc/tools/generate-NOTICE.py
index 6d4c761..8cd75a3 100755
--- a/libc/tools/generate-NOTICE.py
+++ b/libc/tools/generate-NOTICE.py
@@ -77,7 +77,7 @@
for line in lines[start:end]:
line = line.replace("\t", " ")
line = line.replace("/* ", "")
- line = line.replace(" * ", "")
+ line = re.sub("^ \* ", "", line)
line = line.replace("** ", "")
line = line.replace("# ", "")
if line.startswith("++Copyright++"):
@@ -144,7 +144,7 @@
i = 0
while i < len(lines):
- if "Copyright" in lines[i]:
+ if "Copyright" in lines[i] and not "@(#) Copyright" in lines[i]:
i = ExtractCopyrightAt(lines, i)
i += 1
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 4dd7ab0..5e4e962 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -2293,7 +2293,8 @@
}
// Non-standard API: mktime(3) but with an explicit timezone parameter.
-time_t __attribute__((visibility("default"))) mktime_tz(struct tm* const tmp, const char* tz) {
+// This can't actually be hidden/removed until we fix MtpUtils.cpp
+__attribute__((visibility("default"))) time_t mktime_tz(struct tm* const tmp, const char* tz) {
struct state* st = malloc(sizeof(*st));
time_t return_value;
@@ -2309,18 +2310,4 @@
return return_value;
}
-// Non-standard API: localtime(3) but with an explicit timezone parameter.
-void __attribute__((visibility("default"))) localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz) {
- struct state* st = malloc(sizeof(*st));
-
- if (st == NULL)
- return;
- if (__bionic_tzload_cached(tz, st, TRUE) != 0) {
- // TODO: not sure what's best here, but for now, we fall back to gmt.
- gmtload(st);
- }
- localsub(timep, 0L, tmp, st);
- free(st);
-}
-
// END android-added
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index f996f48..4328b4c 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -29,17 +29,19 @@
#include "locale.h"
#if __ANDROID__
-/* Android: struct lc_time_T is defined as strftime_locale in "bionic_time.h" */
-#include "private/bionic_time.h" /* for strftime_tz */
-#define lc_time_T strftime_locale
+
+/* LP32 had a 32-bit time_t, so we need to work around that here. */
#if defined(__LP64__)
#define time64_t time_t
#define mktime64 mktime
#else
#include <time64.h>
#endif
+
#include <ctype.h>
-#else // not __ANDROID__
+
+#endif
+
struct lc_time_T {
const char * mon[MONSPERYEAR];
const char * month[MONSPERYEAR];
@@ -52,9 +54,8 @@
const char * pm;
const char * date_fmt;
};
-#endif
-#if LOCALE_HOME
+#ifdef LOCALE_HOME
#include "sys/stat.h"
static struct lc_time_T localebuf;
static struct lc_time_T * _loc(void);
@@ -72,9 +73,6 @@
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
}, {
- "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December"
- }, {
"Sun", "Mon", "Tue", "Wed",
"Thu", "Fri", "Sat"
}, {
@@ -116,7 +114,7 @@
static char * _add(const char *, char *, const char *, int);
static char * _conv(int, const char *, char *, const char *);
static char * _fmt(const char *, const struct tm *, char *, const char *,
- int *, const struct strftime_locale*);
+ int *);
static char * _yconv(int, int, int, int, char *, const char *, int);
static char * getformat(int, char *, char *, char *, char *);
@@ -134,29 +132,18 @@
#define FORCE_LOWER_CASE 0x100
size_t
-strftime(s, maxsize, format, t)
-char * const s;
-const size_t maxsize;
-const char * const format;
-const struct tm * const t;
-{
- return strftime_tz(s, maxsize, format, t, Locale);
-}
-
-size_t
-__attribute__((visibility("default"))) strftime_tz(s, maxsize, format, t, locale)
-char * const s;
-const size_t maxsize;
-const char * const format;
-const struct tm * const t;
-const struct strftime_locale *locale;
+strftime(char * const s, const size_t maxsize, const char *const format,
+ const struct tm *const t)
{
char * p;
int warn;
tzset();
+#ifdef LOCALE_HOME
+ localebuf.mon[0] = 0;
+#endif /* defined LOCALE_HOME */
warn = IN_NONE;
- p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, locale);
+ p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
(void) fprintf(stderr, "\n");
@@ -196,13 +183,8 @@
}
static char *
-_fmt(format, t, pt, ptlim, warnp, locale)
-const char * format;
-const struct tm * const t;
-char * pt;
-const char * const ptlim;
-int * warnp;
-const struct strftime_locale* locale;
+_fmt(const char *format, const struct tm *const t, char * pt,
+ const char *const ptlim, int *warnp)
{
for ( ; *format; ++format) {
if (*format == '%') {
@@ -215,33 +197,26 @@
case 'A':
pt = _add((t->tm_wday < 0 ||
t->tm_wday >= DAYSPERWEEK) ?
- "?" : locale->weekday[t->tm_wday],
+ "?" : Locale->weekday[t->tm_wday],
pt, ptlim, modifier);
continue;
case 'a':
pt = _add((t->tm_wday < 0 ||
t->tm_wday >= DAYSPERWEEK) ?
- "?" : locale->wday[t->tm_wday],
+ "?" : Locale->wday[t->tm_wday],
pt, ptlim, modifier);
continue;
case 'B':
- if (modifier == '-') {
- pt = _add((t->tm_mon < 0 ||
+ pt = _add((t->tm_mon < 0 ||
t->tm_mon >= MONSPERYEAR) ?
- "?" : locale->standalone_month[t->tm_mon],
+ "?" : Locale->month[t->tm_mon],
pt, ptlim, modifier);
- } else {
- pt = _add((t->tm_mon < 0 ||
- t->tm_mon >= MONSPERYEAR) ?
- "?" : locale->month[t->tm_mon],
- pt, ptlim, modifier);
- }
continue;
case 'b':
case 'h':
pt = _add((t->tm_mon < 0 ||
t->tm_mon >= MONSPERYEAR) ?
- "?" : locale->mon[t->tm_mon],
+ "?" : Locale->mon[t->tm_mon],
pt, ptlim, modifier);
continue;
case 'C':
@@ -259,7 +234,7 @@
{
int warn2 = IN_SOME;
- pt = _fmt(locale->c_fmt, t, pt, ptlim, warnp, locale);
+ pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
@@ -267,7 +242,7 @@
}
continue;
case 'D':
- pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, locale);
+ pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
continue;
case 'd':
pt = _conv(t->tm_mday,
@@ -301,7 +276,7 @@
pt, ptlim);
continue;
case 'F':
- pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, locale);
+ pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
continue;
case 'H':
pt = _conv(t->tm_hour,
@@ -342,7 +317,7 @@
/*
** After all this time, still unclaimed!
*/
- pt = _add("kitchen sink", pt, ptlim, modifier);
+ pt = _add("kitchen sink", pt, ptlim);
continue;
#endif /* defined KITCHEN_SINK */
case 'l':
@@ -378,21 +353,21 @@
continue;
case 'p':
pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
- locale->pm :
- locale->am,
+ Locale->pm :
+ Locale->am,
pt, ptlim, modifier);
continue;
case 'P':
pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
- locale->pm :
- locale->am,
+ Locale->pm :
+ Locale->am,
pt, ptlim, FORCE_LOWER_CASE);
continue;
case 'R':
- pt = _fmt("%H:%M", t, pt, ptlim, warnp, locale);
+ pt = _fmt("%H:%M", t, pt, ptlim, warnp);
continue;
case 'r':
- pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp, locale);
+ pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);
continue;
case 'S':
pt = _conv(t->tm_sec,
@@ -418,7 +393,7 @@
}
continue;
case 'T':
- pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, locale);
+ pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
continue;
case 't':
pt = _add("\t", pt, ptlim, modifier);
@@ -449,7 +424,7 @@
** (01-53)."
** (ado, 1993-05-24)
**
-** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
+** From <http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html> by Markus Kuhn:
** "Week 01 of a year is per definition the first week which has the
** Thursday in this year, which is equivalent to the week which contains
** the fourth day of January. In other words, the first week of a new year
@@ -519,11 +494,7 @@
#endif /* defined XPG4_1994_04_09 */
if (*format == 'V')
pt = _conv(w,
- getformat(modifier,
- "%02d",
- "%2d",
- "%d",
- "%02d"),
+ getformat(modifier, "%02d", "%2d", "%d", "%02d"),
pt, ptlim);
else if (*format == 'g') {
*warnp = IN_ALL;
@@ -539,7 +510,7 @@
** "date as dd-bbb-YYYY"
** (ado, 1993-05-24)
*/
- pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, locale);
+ pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
continue;
case 'W':
pt = _conv((t->tm_yday + DAYSPERWEEK -
@@ -554,13 +525,13 @@
pt = _conv(t->tm_wday, "%d", pt, ptlim);
continue;
case 'X':
- pt = _fmt(locale->X_fmt, t, pt, ptlim, warnp, locale);
+ pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp);
continue;
case 'x':
{
int warn2 = IN_SOME;
- pt = _fmt(locale->x_fmt, t, pt, ptlim, &warn2, locale);
+ pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
@@ -649,8 +620,8 @@
}
continue;
case '+':
- pt = _fmt(locale->date_fmt, t, pt, ptlim,
- warnp, locale);
+ pt = _fmt(Locale->date_fmt, t, pt, ptlim,
+ warnp);
continue;
case '%':
/*
@@ -670,11 +641,8 @@
}
static char *
-_conv(n, format, pt, ptlim)
-const int n;
-const char * const format;
-char * const pt;
-const char * const ptlim;
+_conv(const int n, const char *const format, char *const pt,
+ const char *const ptlim)
{
char buf[INT_STRLEN_MAXIMUM(int) + 1];
@@ -683,11 +651,7 @@
}
static char *
-_add(str, pt, ptlim, modifier)
-const char * str;
-char * pt;
-const char * const ptlim;
-int modifier;
+_add(const char *str, char *pt, const char *const ptlim, int modifier)
{
int c;
@@ -735,14 +699,8 @@
*/
static char *
-_yconv(a, b, convert_top, convert_yy, pt, ptlim, modifier)
-const int a;
-const int b;
-const int convert_top;
-const int convert_yy;
-char * pt;
-const char * const ptlim;
-int modifier;
+_yconv(const int a, const int b, const int convert_top, const int convert_yy,
+ char *pt, const char *const ptlim, int modifier)
{
register int lead;
register int trail;
@@ -761,13 +719,9 @@
if (convert_top) {
if (lead == 0 && trail < 0)
pt = _add("-0", pt, ptlim, modifier);
- else pt = _conv(lead, getformat(modifier, "%02d",
- "%2d", "%d", "%02d"),
- pt, ptlim);
+ else pt = _conv(lead, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
}
if (convert_yy)
- pt = _conv(((trail < 0) ? -trail : trail),
- getformat(modifier, "%02d", "%2d", "%d", "%02d"),
- pt, ptlim);
+ pt = _conv(((trail < 0) ? -trail : trail), getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
return pt;
}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/insque.c b/libc/upstream-netbsd/lib/libc/stdlib/insque.c
new file mode 100644
index 0000000..09020ae
--- /dev/null
+++ b/libc/upstream-netbsd/lib/libc/stdlib/insque.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1993 John Brezak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: insque.c,v 1.3 2012/06/25 22:32:45 abs Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include <assert.h>
+#include <search.h>
+
+struct qelem {
+ struct qelem *q_forw;
+ struct qelem *q_back;
+};
+
+void
+insque(void *entry, void *pred)
+{
+ struct qelem *e = (struct qelem *) entry;
+ struct qelem *p = (struct qelem *) pred;
+
+ _DIAGASSERT(e != 0);
+
+ e->q_back = p;
+ if (p) {
+ e->q_forw = p->q_forw;
+ if (p->q_forw)
+ p->q_forw->q_back = e;
+ p->q_forw = e;
+ } else
+ e->q_forw = 0;
+}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/remque.c b/libc/upstream-netbsd/lib/libc/stdlib/remque.c
new file mode 100644
index 0000000..6060ad8
--- /dev/null
+++ b/libc/upstream-netbsd/lib/libc/stdlib/remque.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1993 John Brezak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: remque.c,v 1.3 2012/06/25 22:32:45 abs Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include <assert.h>
+#include <search.h>
+
+struct qelem {
+ struct qelem *q_forw;
+ struct qelem *q_back;
+};
+
+void
+remque(void *element)
+{
+ struct qelem *e = (struct qelem *) element;
+
+ _DIAGASSERT(e != 0);
+
+ if (e->q_forw)
+ e->q_forw->q_back = e->q_back;
+ if (e->q_back)
+ e->q_back->q_forw = e->q_forw;
+}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/tdelete.c b/libc/upstream-netbsd/lib/libc/stdlib/tdelete.c
deleted file mode 100644
index 84017dc..0000000
--- a/libc/upstream-netbsd/lib/libc/stdlib/tdelete.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* $NetBSD: tdelete.c,v 1.6 2012/06/25 22:32:45 abs Exp $ */
-
-/*
- * Tree search generalized from Knuth (6.2.2) Algorithm T just like
- * the AT&T man page says.
- *
- * The node_t structure is for internal use only, lint doesn't grok it.
- *
- * Written by reading the System V Interface Definition, not the code.
- *
- * Totally public domain.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: tdelete.c,v 1.6 2012/06/25 22:32:45 abs Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
-#define _SEARCH_PRIVATE
-#include <search.h>
-#include <stdlib.h>
-
-
-/* find a node with key "vkey" in tree "vrootp" */
-void *
-tdelete(const void *vkey, void **vrootp,
- int (*compar)(const void *, const void *))
-{
- node_t **rootp = (node_t **)vrootp;
- node_t *p, *q, *r;
- int cmp;
-
- _DIAGASSERT(vkey != NULL);
- _DIAGASSERT(compar != NULL);
-
- if (rootp == NULL || (p = *rootp) == NULL)
- return NULL;
-
- while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) {
- p = *rootp;
- rootp = (cmp < 0) ?
- &(*rootp)->llink : /* follow llink branch */
- &(*rootp)->rlink; /* follow rlink branch */
- if (*rootp == NULL)
- return NULL; /* key not found */
- }
- r = (*rootp)->rlink; /* D1: */
- if ((q = (*rootp)->llink) == NULL) /* Left NULL? */
- q = r;
- else if (r != NULL) { /* Right link is NULL? */
- if (r->llink == NULL) { /* D2: Find successor */
- r->llink = q;
- q = r;
- } else { /* D3: Find NULL link */
- for (q = r->llink; q->llink != NULL; q = r->llink)
- r = q;
- r->llink = q->rlink;
- q->llink = (*rootp)->llink;
- q->rlink = (*rootp)->rlink;
- }
- }
- if (p != *rootp)
- free(*rootp); /* D4: Free node */
- *rootp = q; /* link parent to new node */
- return p;
-}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/tfind.c b/libc/upstream-netbsd/lib/libc/stdlib/tfind.c
deleted file mode 100644
index fd3f362..0000000
--- a/libc/upstream-netbsd/lib/libc/stdlib/tfind.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* $NetBSD: tfind.c,v 1.7 2012/06/25 22:32:45 abs Exp $ */
-
-/*
- * Tree search generalized from Knuth (6.2.2) Algorithm T just like
- * the AT&T man page says.
- *
- * The node_t structure is for internal use only, lint doesn't grok it.
- *
- * Written by reading the System V Interface Definition, not the code.
- *
- * Totally public domain.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: tfind.c,v 1.7 2012/06/25 22:32:45 abs Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
-#define _SEARCH_PRIVATE
-#include <stdlib.h>
-#include <search.h>
-
-/* find a node by key "vkey" in tree "vrootp", or return 0 */
-void *
-tfind(const void *vkey, void * const *vrootp,
- int (*compar)(const void *, const void *))
-{
- node_t * const *rootp = (node_t * const*)vrootp;
-
- _DIAGASSERT(vkey != NULL);
- _DIAGASSERT(compar != NULL);
-
- if (rootp == NULL)
- return NULL;
-
- while (*rootp != NULL) { /* T1: */
- int r;
-
- if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */
- return *rootp; /* key found */
- rootp = (r < 0) ?
- &(*rootp)->llink : /* T3: follow left branch */
- &(*rootp)->rlink; /* T4: follow right branch */
- }
- return NULL;
-}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/tsearch.c b/libc/upstream-netbsd/lib/libc/stdlib/tsearch.c
deleted file mode 100644
index af2fe9c..0000000
--- a/libc/upstream-netbsd/lib/libc/stdlib/tsearch.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/* $NetBSD: tsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $ */
-
-/*
- * Tree search generalized from Knuth (6.2.2) Algorithm T just like
- * the AT&T man page says.
- *
- * The node_t structure is for internal use only, lint doesn't grok it.
- *
- * Written by reading the System V Interface Definition, not the code.
- *
- * Totally public domain.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: tsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
-#define _SEARCH_PRIVATE
-#include <search.h>
-#include <stdlib.h>
-
-/* find or insert datum into search tree */
-void *
-tsearch(const void *vkey, void **vrootp,
- int (*compar)(const void *, const void *))
-{
- node_t *q;
- node_t **rootp = (node_t **)vrootp;
-
- _DIAGASSERT(vkey != NULL);
- _DIAGASSERT(compar != NULL);
-
- if (rootp == NULL)
- return NULL;
-
- while (*rootp != NULL) { /* Knuth's T1: */
- int r;
-
- if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */
- return *rootp; /* we found it! */
-
- rootp = (r < 0) ?
- &(*rootp)->llink : /* T3: follow left branch */
- &(*rootp)->rlink; /* T4: follow right branch */
- }
-
- q = malloc(sizeof(node_t)); /* T5: key not found */
- if (q != 0) { /* make new node */
- *rootp = q; /* link new node to old */
- q->key = __UNCONST(vkey); /* initialize new node */
- q->llink = q->rlink = NULL;
- }
- return q;
-}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/lsearch.c b/libc/upstream-openbsd/lib/libc/stdlib/lsearch.c
similarity index 70%
rename from libc/upstream-netbsd/lib/libc/stdlib/lsearch.c
rename to libc/upstream-openbsd/lib/libc/stdlib/lsearch.c
index e17130b..8cad05f 100644
--- a/libc/upstream-netbsd/lib/libc/stdlib/lsearch.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/lsearch.c
@@ -1,3 +1,5 @@
+/* $OpenBSD: lsearch.c,v 1.5 2014/07/18 04:16:09 matthew Exp $ */
+
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,64 +32,39 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)lsearch.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: lsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
#include <sys/types.h>
-
-#include <assert.h>
-#include <errno.h>
#include <string.h>
#include <search.h>
typedef int (*cmp_fn_t)(const void *, const void *);
-static void *linear_base(const void *, void *, size_t *, size_t,
- cmp_fn_t, int);
+static void *linear_base(const void *, const void *, size_t *, size_t,
+ cmp_fn_t, int);
void *
lsearch(const void *key, void *base, size_t *nelp, size_t width,
- cmp_fn_t compar)
+ cmp_fn_t compar)
{
- _DIAGASSERT(key != NULL);
- _DIAGASSERT(base != NULL);
- _DIAGASSERT(compar != NULL);
-
return(linear_base(key, base, nelp, width, compar, 1));
}
void *
lfind(const void *key, const void *base, size_t *nelp, size_t width,
- cmp_fn_t compar)
+ cmp_fn_t compar)
{
-
- _DIAGASSERT(key != NULL);
- _DIAGASSERT(base != NULL);
- _DIAGASSERT(compar != NULL);
-
- return(linear_base(key, __UNCONST(base), nelp, width, compar, 0));
+ return(linear_base(key, base, nelp, width, compar, 0));
}
static void *
-linear_base(const void *key, void *base, size_t *nelp, size_t width,
+linear_base(const void *key, const void *base, size_t *nelp, size_t width,
cmp_fn_t compar, int add_flag)
{
- char *element, *end;
+ const char *element, *end;
- _DIAGASSERT(key != NULL);
- _DIAGASSERT(base != NULL);
- _DIAGASSERT(compar != NULL);
-
- end = (char *)base + *nelp * width;
- for (element = (char *)base; element < end; element += width)
- if (!compar(element, key)) /* key found */
- return element;
+ end = (const char *)base + *nelp * width;
+ for (element = base; element < end; element += width)
+ if (!compar(key, element)) /* key found */
+ return((void *)element);
if (!add_flag) /* key not found */
return(NULL);
@@ -102,6 +79,6 @@
* manual.
*/
++*nelp;
- memcpy(end, key, width);
- return end;
+ memcpy((void *)end, key, width);
+ return((void *)end);
}
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/tfind.c b/libc/upstream-openbsd/lib/libc/stdlib/tfind.c
new file mode 100644
index 0000000..0d1d519
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdlib/tfind.c
@@ -0,0 +1,41 @@
+/* $OpenBSD: tfind.c,v 1.6 2014/03/16 18:38:30 guenther Exp $ */
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+/*LINTLIBRARY*/
+#include <search.h>
+
+typedef struct node_t
+{
+ char *key;
+ struct node_t *llink, *rlink;
+} node;
+
+/* find a node, or return 0 */
+void *
+tfind(const void *vkey, void * const *vrootp,
+ int (*compar)(const void *, const void *))
+{
+ char *key = (char *)vkey;
+ node **rootp = (node **)vrootp;
+
+ if (rootp == (struct node_t **)0)
+ return ((struct node_t *)0);
+ while (*rootp != (struct node_t *)0) { /* T1: */
+ int r;
+ if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
+ return (*rootp); /* key found */
+ rootp = (r < 0) ?
+ &(*rootp)->llink : /* T3: follow left branch */
+ &(*rootp)->rlink; /* T4: follow right branch */
+ }
+ return (node *)0;
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/tsearch.c b/libc/upstream-openbsd/lib/libc/stdlib/tsearch.c
new file mode 100644
index 0000000..a141085
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdlib/tsearch.c
@@ -0,0 +1,119 @@
+/* $OpenBSD: tsearch.c,v 1.8 2014/03/16 18:38:30 guenther Exp $ */
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+/*LINTLIBRARY*/
+
+#include <search.h>
+#include <stdlib.h>
+
+typedef struct node_t {
+ char *key;
+ struct node_t *left, *right;
+} node;
+
+/* find or insert datum into search tree */
+void *
+tsearch(const void *vkey, void **vrootp,
+ int (*compar)(const void *, const void *))
+{
+ node *q;
+ char *key = (char *)vkey;
+ node **rootp = (node **)vrootp;
+
+ if (rootp == (struct node_t **)0)
+ return ((void *)0);
+ while (*rootp != (struct node_t *)0) { /* Knuth's T1: */
+ int r;
+
+ if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
+ return ((void *)*rootp); /* we found it! */
+ rootp = (r < 0) ?
+ &(*rootp)->left : /* T3: follow left branch */
+ &(*rootp)->right; /* T4: follow right branch */
+ }
+ q = (node *) malloc(sizeof(node)); /* T5: key not found */
+ if (q != (struct node_t *)0) { /* make new node */
+ *rootp = q; /* link new node to old */
+ q->key = key; /* initialize new node */
+ q->left = q->right = (struct node_t *)0;
+ }
+ return ((void *)q);
+}
+
+/* delete node with given key */
+void *
+tdelete(const void *vkey, void **vrootp,
+ int (*compar)(const void *, const void *))
+{
+ node **rootp = (node **)vrootp;
+ char *key = (char *)vkey;
+ node *p = (node *)1;
+ node *q;
+ node *r;
+ int cmp;
+
+ if (rootp == (struct node_t **)0 || *rootp == (struct node_t *)0)
+ return ((struct node_t *)0);
+ while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
+ p = *rootp;
+ rootp = (cmp < 0) ?
+ &(*rootp)->left : /* follow left branch */
+ &(*rootp)->right; /* follow right branch */
+ if (*rootp == (struct node_t *)0)
+ return ((void *)0); /* key not found */
+ }
+ r = (*rootp)->right; /* D1: */
+ if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */
+ q = r;
+ else if (r != (struct node_t *)0) { /* Right link is null? */
+ if (r->left == (struct node_t *)0) { /* D2: Find successor */
+ r->left = q;
+ q = r;
+ } else { /* D3: Find (struct node_t *)0 link */
+ for (q = r->left; q->left != (struct node_t *)0; q = r->left)
+ r = q;
+ r->left = q->right;
+ q->left = (*rootp)->left;
+ q->right = (*rootp)->right;
+ }
+ }
+ free((struct node_t *) *rootp); /* D4: Free node */
+ *rootp = q; /* link parent to new node */
+ return(p);
+}
+
+/* Walk the nodes of a tree */
+static void
+trecurse(node *root, void (*action)(const void *, VISIT, int), int level)
+{
+ if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
+ (*action)(root, leaf, level);
+ else {
+ (*action)(root, preorder, level);
+ if (root->left != (struct node_t *)0)
+ trecurse(root->left, action, level + 1);
+ (*action)(root, postorder, level);
+ if (root->right != (struct node_t *)0)
+ trecurse(root->right, action, level + 1);
+ (*action)(root, endorder, level);
+ }
+}
+
+/* Walk the nodes of a tree */
+void
+twalk(const void *vroot, void (*action)(const void *, VISIT, int))
+{
+ node *root = (node *)vroot;
+
+ if (root != (node *)0 && action != (void (*)(const void *, VISIT, int))0)
+ trecurse(root, action, 0);
+}
diff --git a/libstdc++/NOTICE b/libstdc++/NOTICE
index 59d6106..492770d 100644
--- a/libstdc++/NOTICE
+++ b/libstdc++/NOTICE
@@ -4,9 +4,9 @@
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
+ * 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
+ * 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.
@@ -32,9 +32,9 @@
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
+ * 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
+ * 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.
diff --git a/libstdc++/include/cstdlib b/libstdc++/include/cstdlib
index bb6f5a5..bd1deae 100644
--- a/libstdc++/include/cstdlib
+++ b/libstdc++/include/cstdlib
@@ -42,9 +42,6 @@
using ::exit;
using ::abort;
using ::atexit;
-#if 0 /* MISSING FROM BIONIC */
-using ::on_exit;
-#endif
using ::getenv;
using ::putenv;
diff --git a/linker/NOTICE b/linker/NOTICE
index db4ec7b..cb3a1dd 100644
--- a/linker/NOTICE
+++ b/linker/NOTICE
@@ -20,9 +20,9 @@
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
+ * 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
+ * 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.
@@ -48,9 +48,9 @@
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
+ * 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
+ * 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.
@@ -76,9 +76,9 @@
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
+ * 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
+ * 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.
@@ -104,9 +104,9 @@
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
+ * 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
+ * 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.
@@ -132,9 +132,9 @@
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
+ * 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
+ * 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.
@@ -176,9 +176,9 @@
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
+ * 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
+ * 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.
diff --git a/linker/arch/mips/begin.S b/linker/arch/mips/begin.S
index 4a855e6..cbe1e37 100644
--- a/linker/arch/mips/begin.S
+++ b/linker/arch/mips/begin.S
@@ -32,7 +32,9 @@
.ent __start
.globl __start
+ .globl _start
__start:
+_start:
.set noreorder
bal 1f
nop
diff --git a/linker/arch/mips64/begin.S b/linker/arch/mips64/begin.S
index 6827a2c..8f6b94a 100644
--- a/linker/arch/mips64/begin.S
+++ b/linker/arch/mips64/begin.S
@@ -46,7 +46,9 @@
.ent __start
.globl __start
+ .globl _start
__start:
+_start:
.set noreorder
bal 1f
nop
diff --git a/linker/debugger.cpp b/linker/debugger.cpp
index 9ebb09b..079682c 100644
--- a/linker/debugger.cpp
+++ b/linker/debugger.cpp
@@ -206,6 +206,15 @@
}
static void send_debuggerd_packet(siginfo_t* info) {
+ if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
+ // process has disabled core dumps and PTRACE_ATTACH, and does not want to be dumped.
+ // Honor that intention by not connecting to debuggerd and asking it
+ // to dump our internal state.
+ __libc_format_log(ANDROID_LOG_INFO, "libc",
+ "Suppressing debuggerd output because prctl(PR_GET_DUMPABLE)==0");
+ return;
+ }
+
int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);
if (s == -1) {
__libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index efb829e..8ebf357 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -111,8 +111,7 @@
sym = dlsym_linear_lookup(symbol, &found, caller_si->next, caller_si);
}
} else {
- found = reinterpret_cast<soinfo*>(handle);
- sym = dlsym_handle_lookup(found, symbol, caller_si);
+ sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, symbol, caller_si);
}
if (sym != NULL && sym->st_shndx != 0) {
diff --git a/linker/linked_list.h b/linker/linked_list.h
index 52af0f1..7f8c901 100644
--- a/linker/linked_list.h
+++ b/linker/linked_list.h
@@ -31,13 +31,45 @@
template<typename T, typename Allocator>
class LinkedList {
public:
- LinkedList() : head_(nullptr) {}
+ LinkedList() : head_(nullptr), tail_(nullptr) {}
void push_front(T* const element) {
LinkedListEntry<T>* new_entry = Allocator::alloc();
new_entry->next = head_;
new_entry->element = element;
head_ = new_entry;
+ if (tail_ == nullptr) {
+ tail_ = new_entry;
+ }
+ }
+
+ void push_back(T* const element) {
+ LinkedListEntry<T>* new_entry = Allocator::alloc();
+ new_entry->next = nullptr;
+ new_entry->element = element;
+ if (tail_ == nullptr) {
+ tail_ = head_ = new_entry;
+ } else {
+ tail_->next = new_entry;
+ tail_ = new_entry;
+ }
+ }
+
+ T* pop_front() {
+ if (head_ == nullptr) {
+ return nullptr;
+ }
+
+ LinkedListEntry<T>* entry = head_;
+ T* element = entry->element;
+ head_ = entry->next;
+ Allocator::free(entry);
+
+ if (head_ == nullptr) {
+ tail_ = nullptr;
+ }
+
+ return element;
}
void clear() {
@@ -46,6 +78,8 @@
head_ = head_->next;
Allocator::free(p);
}
+
+ tail_ = nullptr;
}
template<typename F>
@@ -68,6 +102,7 @@
private:
LinkedListEntry<T>* head_;
+ LinkedListEntry<T>* tail_;
DISALLOW_COPY_AND_ASSIGN(LinkedList);
};
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 04ffe59..f8b35d7 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -469,6 +469,10 @@
}
}
+ TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd",
+ name, si->name, reinterpret_cast<void*>(si->base), hash, hash % si->nbucket);
+
+
return NULL;
}
@@ -585,18 +589,43 @@
return NULL;
}
-/* This is used by dlsym(3). It performs symbol lookup only within the
- specified soinfo object and not in any of its dependencies.
+// Another soinfo list allocator to use in dlsym. We don't reuse
+// SoinfoListAllocator because it is write-protected most of the time.
+static LinkerAllocator<LinkedListEntry<soinfo>> g_soinfo_list_allocator_rw;
+class SoinfoListAllocatorRW {
+ public:
+ static LinkedListEntry<soinfo>* alloc() {
+ return g_soinfo_list_allocator_rw.alloc();
+ }
- TODO: Only looking in the specified soinfo seems wrong. dlsym(3) says
- that it should do a breadth first search through the dependency
- tree. This agrees with the ELF spec (aka System V Application
- Binary Interface) where in Chapter 5 it discuss resolving "Shared
- Object Dependencies" in breadth first search order.
- */
-ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name, soinfo* caller) {
- return soinfo_elf_lookup(si, elfhash(name), name,
- caller == si ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
+ static void free(LinkedListEntry<soinfo>* ptr) {
+ g_soinfo_list_allocator_rw.free(ptr);
+ }
+};
+
+// This is used by dlsym(3). It performs symbol lookup only within the
+// specified soinfo object and its dependencies in breadth first order.
+ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soinfo* caller) {
+ LinkedList<soinfo, SoinfoListAllocatorRW> visit_list;
+ visit_list.push_back(si);
+ soinfo* current_soinfo;
+ while ((current_soinfo = visit_list.pop_front()) != nullptr) {
+ ElfW(Sym)* result = soinfo_elf_lookup(current_soinfo, elfhash(name), name,
+ caller == current_soinfo ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
+
+ if (result != nullptr) {
+ *found = current_soinfo;
+ visit_list.clear();
+ return result;
+ }
+
+ current_soinfo->get_children().for_each([&](soinfo* child) {
+ visit_list.push_back(child);
+ });
+ }
+
+ visit_list.clear();
+ return nullptr;
}
/* This is used by dlsym(3) to performs a global symbol lookup. If the
@@ -2077,12 +2106,6 @@
ldpreload_env = linker_env_get("LD_PRELOAD");
}
- // Linker does not call constructors for its own
- // global variables so we need to initialize
- // the allocators explicitly.
- g_soinfo_allocator.init();
- g_soinfo_links_allocator.init();
-
INFO("[ android linker & debugger ]");
soinfo* si = soinfo_alloc(args.argv[0], NULL);
@@ -2227,6 +2250,8 @@
return 0;
}
+extern "C" void _start();
+
/*
* This is the entry point for the linker, called from begin.S. This
* method is responsible for fixing the linker's own relocations, and
@@ -2244,12 +2269,23 @@
KernelArgumentBlock args(raw_args);
ElfW(Addr) linker_addr = args.getauxval(AT_BASE);
+ ElfW(Addr) entry_point = args.getauxval(AT_ENTRY);
ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr);
ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff);
soinfo linker_so;
memset(&linker_so, 0, sizeof(soinfo));
+ // If the linker is not acting as PT_INTERP entry_point is equal to
+ // _start. Which means that the linker is running as an executable and
+ // already linked by PT_INTERP.
+ //
+ // This happens when user tries to run 'adb shell /system/bin/linker'
+ // see also https://code.google.com/p/android/issues/detail?id=63174
+ if (reinterpret_cast<ElfW(Addr)>(&_start) == entry_point) {
+ __libc_fatal("This is %s, the helper program for shared library executables.\n", args.argv[0]);
+ }
+
strcpy(linker_so.name, "[dynamic linker]");
linker_so.base = linker_addr;
linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum);
@@ -2271,6 +2307,9 @@
_exit(EXIT_FAILURE);
}
+ // Initialize the linker's own global variables
+ linker_so.CallConstructors();
+
// We have successfully fixed our own relocations. It's safe to run
// the main part of the linker now.
args.abort_message_ptr = &g_abort_message;
diff --git a/linker/linker.h b/linker/linker.h
index e1112e6..03672b2 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -238,7 +238,7 @@
soinfo* find_containing_library(const void* addr);
ElfW(Sym)* dladdr_find_symbol(soinfo* si, const void* addr);
-ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name, soinfo* caller_si);
+ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soinfo* caller_si);
void debuggerd_init();
extern "C" abort_msg_t* g_abort_message;
diff --git a/linker/linker_allocator.cpp b/linker/linker_allocator.cpp
index c8b97b1..f5d3745 100644
--- a/linker/linker_allocator.cpp
+++ b/linker/linker_allocator.cpp
@@ -28,17 +28,12 @@
size_t num_free_blocks;
};
-LinkerBlockAllocator::LinkerBlockAllocator()
- : block_size_(0),
+LinkerBlockAllocator::LinkerBlockAllocator(size_t block_size)
+ : block_size_(block_size < sizeof(FreeBlockInfo) ? sizeof(FreeBlockInfo) : block_size),
page_list_(nullptr),
free_block_list_(nullptr)
{}
-void LinkerBlockAllocator::init(size_t block_size) {
- block_size_ = block_size < sizeof(FreeBlockInfo) ? sizeof(FreeBlockInfo) : block_size;
-}
-
-
void* LinkerBlockAllocator::alloc() {
if (free_block_list_ == nullptr) {
create_new_page();
diff --git a/linker/linker_allocator.h b/linker/linker_allocator.h
index fbf58fe..5d3563f 100644
--- a/linker/linker_allocator.h
+++ b/linker/linker_allocator.h
@@ -32,9 +32,8 @@
*/
class LinkerBlockAllocator {
public:
- LinkerBlockAllocator();
+ explicit LinkerBlockAllocator(size_t block_size);
- void init(size_t block_size);
void* alloc();
void free(void* block);
void protect_all(int prot);
@@ -60,8 +59,7 @@
template<typename T>
class LinkerAllocator {
public:
- LinkerAllocator() : block_allocator_() {}
- void init() { block_allocator_.init(sizeof(T)); }
+ LinkerAllocator() : block_allocator_(sizeof(T)) {}
T* alloc() { return reinterpret_cast<T*>(block_allocator_.alloc()); }
void free(T* t) { block_allocator_.free(t); }
void protect_all(int prot) { block_allocator_.protect_all(prot); }
diff --git a/linker/tests/linked_list_test.cpp b/linker/tests/linked_list_test.cpp
index 31ec7d5..b9816fa 100644
--- a/linker/tests/linked_list_test.cpp
+++ b/linker/tests/linked_list_test.cpp
@@ -95,3 +95,23 @@
ASSERT_TRUE(free_called);
ASSERT_EQ("", test_list_to_string(list));
}
+
+TEST(linked_list, push_pop) {
+ test_list_t list;
+ list.push_front("b");
+ list.push_front("a");
+ ASSERT_EQ("ab", test_list_to_string(list));
+ list.push_back("c");
+ ASSERT_EQ("abc", test_list_to_string(list));
+ ASSERT_EQ("a", list.pop_front());
+ ASSERT_EQ("bc", test_list_to_string(list));
+ ASSERT_EQ("b", list.pop_front());
+ ASSERT_EQ("c", test_list_to_string(list));
+ ASSERT_EQ("c", list.pop_front());
+ ASSERT_EQ("", test_list_to_string(list));
+ ASSERT_TRUE(list.pop_front() == nullptr);
+ list.push_back("r");
+ ASSERT_EQ("r", test_list_to_string(list));
+ ASSERT_EQ("r", list.pop_front());
+ ASSERT_TRUE(list.pop_front() == nullptr);
+}
diff --git a/linker/tests/linker_allocator_test.cpp b/linker/tests/linker_allocator_test.cpp
index 0ed8252..9292a05 100644
--- a/linker/tests/linker_allocator_test.cpp
+++ b/linker/tests/linker_allocator_test.cpp
@@ -50,7 +50,6 @@
TEST(linker_allocator, test_nominal) {
LinkerAllocator<test_struct_nominal> allocator;
- allocator.init();
test_struct_nominal* ptr1 = allocator.alloc();
ASSERT_TRUE(ptr1 != nullptr);
@@ -67,7 +66,6 @@
TEST(linker_allocator, test_small) {
LinkerAllocator<test_struct_small> allocator;
- allocator.init();
char* ptr1 = reinterpret_cast<char*>(allocator.alloc());
char* ptr2 = reinterpret_cast<char*>(allocator.alloc());
@@ -79,7 +77,6 @@
TEST(linker_allocator, test_larger) {
LinkerAllocator<test_struct_larger> allocator;
- allocator.init();
test_struct_larger* ptr1 = allocator.alloc();
test_struct_larger* ptr2 = allocator.alloc();
@@ -103,7 +100,6 @@
static void protect_all() {
LinkerAllocator<test_struct_larger> allocator;
- allocator.init();
// number of allocs to reach the end of first page
size_t n = kPageSize/sizeof(test_struct_larger) - 1;
diff --git a/tests/Android.mk b/tests/Android.mk
index 3e8fbe6..b370b92 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -85,6 +85,7 @@
pthread_test.cpp \
regex_test.cpp \
sched_test.cpp \
+ search_test.cpp \
signal_test.cpp \
stack_protector_test.cpp \
stack_unwinding_test.cpp \
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index f056fb6..9bc2557 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -62,10 +62,9 @@
ASSERT_EQ(0, dlclose(self));
}
-#if !defined(__LP64__)
-// Current compiler/static linker used for aarch64
-// platform optimizes LOCAL PROTECTED symbol
-// in libtest_local_symbol.so out of existence
+#if defined(__arm__)
+// This seems to be working only for arm.
+// Others platforms optimize LOCAL PROTECTED symbols.
TEST(dlfcn, dlsym_local_symbol) {
void* handle = dlopen("libtest_local_symbol.so", RTLD_NOW);
ASSERT_TRUE(handle != NULL);
@@ -78,9 +77,23 @@
f = reinterpret_cast<uint32_t (*)(void)>(dlsym(handle, "dlsym_local_symbol_get_taxicab_number_using_dlsym"));
ASSERT_TRUE(f != NULL);
ASSERT_EQ(1729U, f());
+ dlclose(handle);
}
#endif
+TEST(dlfcn, dlsym_with_dependencies) {
+ void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW);
+ ASSERT_TRUE(handle != NULL);
+ dlerror();
+ // This symbol is in DT_NEEDED library.
+ void* sym = dlsym(handle, "getRandomNumber");
+ ASSERT_TRUE(sym != NULL);
+ int (*fn)(void);
+ fn = reinterpret_cast<int (*)(void)>(sym);
+ EXPECT_EQ(4, fn());
+ dlclose(handle);
+}
+
TEST(dlfcn, dlopen_noload) {
void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
ASSERT_TRUE(handle == NULL);
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 873c71e..352cac6 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -23,6 +23,7 @@
#include <sys/socket.h>
#include <malloc.h>
#include <fcntl.h>
+#include <sys/prctl.h>
// We have to say "DeathTest" here so gtest knows to run this test (which exits)
// in its own process. Unfortunately, the C preprocessor doesn't give us an
@@ -32,6 +33,21 @@
#define DEATHTEST_EVALUATOR(name) DEATHTEST_PASTER(name)
#define DEATHTEST DEATHTEST_EVALUATOR(TEST_NAME)
+class DEATHTEST : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ old_dumpable_ = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
+ // Suppress debuggerd stack traces. Too slow.
+ prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
+ }
+
+ virtual void TearDown() {
+ prctl(PR_SET_DUMPABLE, old_dumpable_, 0, 0, 0, 0);
+ }
+ private:
+ int old_dumpable_;
+};
+
#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE == 2
struct foo {
char empty[0];
@@ -43,7 +59,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, stpncpy_fortified2) {
+TEST_F(DEATHTEST, stpncpy_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
int copy_amt = atoi("11");
@@ -55,7 +71,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, stpncpy2_fortified2) {
+TEST_F(DEATHTEST, stpncpy2_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
memset(&myfoo, 0, sizeof(myfoo));
@@ -68,7 +84,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strncpy_fortified2) {
+TEST_F(DEATHTEST, strncpy_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
int copy_amt = atoi("11");
@@ -80,7 +96,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strncpy2_fortified2) {
+TEST_F(DEATHTEST, strncpy2_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
memset(&myfoo, 0, sizeof(myfoo));
@@ -93,7 +109,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, sprintf_fortified2) {
+TEST_F(DEATHTEST, sprintf_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
char source_buf[15];
@@ -106,7 +122,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, sprintf2_fortified2) {
+TEST_F(DEATHTEST, sprintf2_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
ASSERT_EXIT(sprintf(myfoo.a, "0123456789"),
@@ -128,12 +144,12 @@
return result;
}
-TEST(DEATHTEST, vsprintf_fortified2) {
+TEST_F(DEATHTEST, vsprintf_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_EXIT(vsprintf_helper2("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, vsprintf2_fortified2) {
+TEST_F(DEATHTEST, vsprintf2_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_EXIT(vsprintf_helper2("0123456789"), testing::KilledBySignal(SIGABRT), "");
}
@@ -154,12 +170,12 @@
return result;
}
-TEST(DEATHTEST, vsnprintf_fortified2) {
+TEST_F(DEATHTEST, vsnprintf_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_EXIT(vsnprintf_helper2("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, vsnprintf2_fortified2) {
+TEST_F(DEATHTEST, vsnprintf2_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_EXIT(vsnprintf_helper2("0123456789"), testing::KilledBySignal(SIGABRT), "");
}
@@ -169,7 +185,7 @@
// zero sized target with "\0" source (should fail)
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, stpcpy_fortified2) {
+TEST_F(DEATHTEST, stpcpy_fortified2) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
@@ -187,7 +203,7 @@
// zero sized target with "\0" source (should fail)
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strcpy_fortified2) {
+TEST_F(DEATHTEST, strcpy_fortified2) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
@@ -205,7 +221,7 @@
// zero sized target with longer source (should fail)
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strcpy2_fortified2) {
+TEST_F(DEATHTEST, strcpy2_fortified2) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
@@ -223,7 +239,7 @@
// one byte target with longer source (should fail)
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strcpy3_fortified2) {
+TEST_F(DEATHTEST, strcpy3_fortified2) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
@@ -240,7 +256,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strchr_fortified2) {
+TEST_F(DEATHTEST, strchr_fortified2) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
@@ -257,7 +273,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strrchr_fortified2) {
+TEST_F(DEATHTEST, strrchr_fortified2) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
@@ -274,7 +290,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strlcpy_fortified2) {
+TEST_F(DEATHTEST, strlcpy_fortified2) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
@@ -291,7 +307,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strlcat_fortified2) {
+TEST_F(DEATHTEST, strlcat_fortified2) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
@@ -309,7 +325,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strncat_fortified2) {
+TEST_F(DEATHTEST, strncat_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
size_t n = atoi("10"); // avoid compiler optimizations
@@ -321,7 +337,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strncat2_fortified2) {
+TEST_F(DEATHTEST, strncat2_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
myfoo.a[0] = '\0';
@@ -330,7 +346,7 @@
}
#endif
-TEST(DEATHTEST, strncat3_fortified2) {
+TEST_F(DEATHTEST, strncat3_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
@@ -342,7 +358,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, strcat_fortified2) {
+TEST_F(DEATHTEST, strcat_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char src[11];
strcpy(src, "0123456789");
@@ -352,7 +368,7 @@
}
#endif
-TEST(DEATHTEST, strcat2_fortified2) {
+TEST_F(DEATHTEST, strcat2_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
@@ -360,7 +376,7 @@
ASSERT_EXIT(strcat(myfoo.b, myfoo.a), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, snprintf_fortified2) {
+TEST_F(DEATHTEST, snprintf_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
strcpy(myfoo.a, "012345678");
@@ -368,7 +384,7 @@
ASSERT_EXIT(snprintf(myfoo.b, n, "a%s", myfoo.a), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, bzero_fortified2) {
+TEST_F(DEATHTEST, bzero_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
memcpy(myfoo.b, "0123456789", sizeof(myfoo.b));
@@ -379,7 +395,7 @@
#endif /* defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE=2 */
// multibyte target where we over fill (should fail)
-TEST(DEATHTEST, strcpy_fortified) {
+TEST_F(DEATHTEST, strcpy_fortified) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[10];
@@ -392,7 +408,7 @@
}
// zero sized target with "\0" source (should fail)
-TEST(DEATHTEST, strcpy2_fortified) {
+TEST_F(DEATHTEST, strcpy2_fortified) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[0];
@@ -405,7 +421,7 @@
}
// zero sized target with longer source (should fail)
-TEST(DEATHTEST, strcpy3_fortified) {
+TEST_F(DEATHTEST, strcpy3_fortified) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[0];
@@ -418,7 +434,7 @@
}
// one byte target with longer source (should fail)
-TEST(DEATHTEST, strcpy4_fortified) {
+TEST_F(DEATHTEST, strcpy4_fortified) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[1];
@@ -430,7 +446,7 @@
#endif // __BIONIC__
}
-TEST(DEATHTEST, strlen_fortified) {
+TEST_F(DEATHTEST, strlen_fortified) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[10];
@@ -441,7 +457,7 @@
#endif // __BIONIC__
}
-TEST(DEATHTEST, strchr_fortified) {
+TEST_F(DEATHTEST, strchr_fortified) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[10];
@@ -452,7 +468,7 @@
#endif // __BIONIC__
}
-TEST(DEATHTEST, strrchr_fortified) {
+TEST_F(DEATHTEST, strrchr_fortified) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[10];
@@ -463,7 +479,7 @@
#endif // __BIONIC__
}
-TEST(DEATHTEST, strlcpy_fortified) {
+TEST_F(DEATHTEST, strlcpy_fortified) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char bufa[15];
@@ -476,7 +492,7 @@
#endif // __BIONIC__
}
-TEST(DEATHTEST, strlcat_fortified) {
+TEST_F(DEATHTEST, strlcat_fortified) {
#if defined(__BIONIC__)
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char bufa[15];
@@ -490,7 +506,7 @@
#endif // __BIONIC__
}
-TEST(DEATHTEST, sprintf_fortified) {
+TEST_F(DEATHTEST, sprintf_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[10];
char source_buf[15];
@@ -501,7 +517,7 @@
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
-TEST(DEATHTEST, sprintf_malloc_fortified) {
+TEST_F(DEATHTEST, sprintf_malloc_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char* buf = (char *) malloc(10);
char source_buf[11];
@@ -511,7 +527,7 @@
}
#endif
-TEST(DEATHTEST, sprintf2_fortified) {
+TEST_F(DEATHTEST, sprintf2_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[5];
ASSERT_EXIT(sprintf(buf, "aaaaa"), testing::KilledBySignal(SIGABRT), "");
@@ -528,12 +544,12 @@
return result;
}
-TEST(DEATHTEST, vsprintf_fortified) {
+TEST_F(DEATHTEST, vsprintf_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_EXIT(vsprintf_helper("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, vsprintf2_fortified) {
+TEST_F(DEATHTEST, vsprintf2_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_EXIT(vsprintf_helper("0123456789"), testing::KilledBySignal(SIGABRT), "");
}
@@ -550,17 +566,17 @@
return result;
}
-TEST(DEATHTEST, vsnprintf_fortified) {
+TEST_F(DEATHTEST, vsnprintf_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_EXIT(vsnprintf_helper("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, vsnprintf2_fortified) {
+TEST_F(DEATHTEST, vsnprintf2_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_EXIT(vsnprintf_helper("0123456789"), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, strncat_fortified) {
+TEST_F(DEATHTEST, strncat_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[10];
size_t n = atoi("10"); // avoid compiler optimizations
@@ -568,7 +584,7 @@
ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, strncat2_fortified) {
+TEST_F(DEATHTEST, strncat2_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[10];
buf[0] = '\0';
@@ -576,7 +592,7 @@
ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, strcat_fortified) {
+TEST_F(DEATHTEST, strcat_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char src[11];
strcpy(src, "0123456789");
@@ -585,7 +601,7 @@
ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, memmove_fortified) {
+TEST_F(DEATHTEST, memmove_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[20];
strcpy(buf, "0123456789");
@@ -593,7 +609,7 @@
ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, memcpy_fortified) {
+TEST_F(DEATHTEST, memcpy_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char bufa[10];
char bufb[10];
@@ -602,7 +618,7 @@
ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, stpncpy_fortified) {
+TEST_F(DEATHTEST, stpncpy_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char bufa[15];
char bufb[10];
@@ -611,7 +627,7 @@
ASSERT_EXIT(stpncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, stpncpy2_fortified) {
+TEST_F(DEATHTEST, stpncpy2_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char dest[11];
char src[10];
@@ -619,7 +635,7 @@
ASSERT_EXIT(stpncpy(dest, src, sizeof(dest)), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, strncpy_fortified) {
+TEST_F(DEATHTEST, strncpy_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char bufa[15];
char bufb[10];
@@ -629,7 +645,7 @@
}
-TEST(DEATHTEST, strncpy2_fortified) {
+TEST_F(DEATHTEST, strncpy2_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char dest[11];
char src[10];
@@ -637,7 +653,7 @@
ASSERT_EXIT(strncpy(dest, src, sizeof(dest)), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, snprintf_fortified) {
+TEST_F(DEATHTEST, snprintf_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char bufa[15];
char bufb[10];
@@ -646,7 +662,7 @@
ASSERT_EXIT(snprintf(bufb, n, "%s", bufa), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, bzero_fortified) {
+TEST_F(DEATHTEST, bzero_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[10];
memcpy(buf, "0123456789", sizeof(buf));
@@ -654,20 +670,20 @@
ASSERT_EXIT(bzero(buf, n), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, umask_fortified) {
+TEST_F(DEATHTEST, umask_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
mode_t mask = atoi("1023"); // 01777 in octal
ASSERT_EXIT(umask(mask), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, recv_fortified) {
+TEST_F(DEATHTEST, recv_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
size_t data_len = atoi("11"); // suppress compiler optimizations
char buf[10];
ASSERT_EXIT(recv(0, buf, data_len, 0), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, FD_ISSET_fortified) {
+TEST_F(DEATHTEST, FD_ISSET_fortified) {
#if defined(__BIONIC__) // glibc catches this at compile-time.
::testing::FLAGS_gtest_death_test_style = "threadsafe";
fd_set set;
@@ -676,7 +692,7 @@
#endif
}
-TEST(DEATHTEST, FD_ISSET_2_fortified) {
+TEST_F(DEATHTEST, FD_ISSET_2_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[1];
fd_set* set = (fd_set*) buf;
@@ -686,14 +702,14 @@
// gtest's ASSERT_EXIT needs a valid expression, but glibc has a do-while macro.
static void FD_ZERO_function(fd_set* s) { FD_ZERO(s); }
-TEST(DEATHTEST, FD_ZERO_fortified) {
+TEST_F(DEATHTEST, FD_ZERO_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[1];
fd_set* set = (fd_set*) buf;
ASSERT_EXIT(FD_ZERO_function(set), testing::KilledBySignal(SIGABRT), "");
}
-TEST(DEATHTEST, read_fortified) {
+TEST_F(DEATHTEST, read_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[1];
size_t ct = atoi("2"); // prevent optimizations
diff --git a/tests/libc_logging_test.cpp b/tests/libc_logging_test.cpp
index ef39d1c..950161e 100644
--- a/tests/libc_logging_test.cpp
+++ b/tests/libc_logging_test.cpp
@@ -176,14 +176,3 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif // __BIONIC__
}
-
-TEST(libc_logging, m) {
-#if defined(__BIONIC__)
- char buf[BUFSIZ];
- errno = EBADF;
- __libc_format_buffer(buf, sizeof(buf), "<%m>");
- EXPECT_STREQ("<Bad file number>", buf);
-#else // __BIONIC__
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
-}
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index a374e48..7ed3e7b 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -102,6 +102,19 @@
include $(TEST_PATH)/Android.build.mk
# -----------------------------------------------------------------------------
+# Library with dependency used by dlfcn tests
+# -----------------------------------------------------------------------------
+libtest_with_dependency_src_files := \
+ dlopen_testlib_simple.cpp
+
+libtest_with_dependency_shared_libraries := libdlext_test
+
+module := libtest_with_dependency
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+
+# -----------------------------------------------------------------------------
# Library used to test local symbol lookup
# -----------------------------------------------------------------------------
libtest_local_symbol_src_files := \
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 36da481..4da003f 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -82,6 +82,57 @@
ASSERT_EQ(EINVAL, pthread_setspecific(key, expected));
}
+TEST(pthread, pthread_key_fork) {
+ void* expected = reinterpret_cast<void*>(1234);
+ pthread_key_t key;
+ ASSERT_EQ(0, pthread_key_create(&key, NULL));
+ ASSERT_EQ(0, pthread_setspecific(key, expected));
+ ASSERT_EQ(expected, pthread_getspecific(key));
+
+ pid_t pid = fork();
+ ASSERT_NE(-1, pid) << strerror(errno);
+
+ if (pid == 0) {
+ // The surviving thread inherits all the forking thread's TLS values...
+ ASSERT_EQ(expected, pthread_getspecific(key));
+ _exit(99);
+ }
+
+ int status;
+ ASSERT_EQ(pid, waitpid(pid, &status, 0));
+ ASSERT_TRUE(WIFEXITED(status));
+ ASSERT_EQ(99, WEXITSTATUS(status));
+
+ ASSERT_EQ(expected, pthread_getspecific(key));
+}
+
+static void* DirtyKeyFn(void* key) {
+ return pthread_getspecific(*reinterpret_cast<pthread_key_t*>(key));
+}
+
+TEST(pthread, pthread_key_dirty) {
+ pthread_key_t key;
+ ASSERT_EQ(0, pthread_key_create(&key, NULL));
+
+ size_t stack_size = 128 * 1024;
+ void* stack = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ ASSERT_NE(MAP_FAILED, stack);
+ memset(stack, 0xff, stack_size);
+
+ pthread_attr_t attr;
+ ASSERT_EQ(0, pthread_attr_init(&attr));
+ ASSERT_EQ(0, pthread_attr_setstack(&attr, stack, stack_size));
+
+ pthread_t t;
+ ASSERT_EQ(0, pthread_create(&t, &attr, DirtyKeyFn, &key));
+
+ void* result;
+ ASSERT_EQ(0, pthread_join(t, &result));
+ ASSERT_EQ(nullptr, result); // Not ~0!
+
+ ASSERT_EQ(0, munmap(stack, stack_size));
+}
+
static void* IdFn(void* arg) {
return arg;
}
diff --git a/tests/search_test.cpp b/tests/search_test.cpp
new file mode 100644
index 0000000..3900c89
--- /dev/null
+++ b/tests/search_test.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <search.h>
+
+static int int_cmp(const void* lhs, const void* rhs) {
+ return *reinterpret_cast<const int*>(rhs) - *reinterpret_cast<const int*>(lhs);
+}
+
+TEST(search, lfind_lsearch) {
+ int xs[10];
+ memset(xs, 0, sizeof(xs));
+ size_t x_size = 0;
+
+ int needle;
+
+ // lfind(3) can't find '2' in the empty table.
+ needle = 2;
+ ASSERT_EQ(nullptr, lfind(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
+ ASSERT_EQ(0U, x_size);
+
+ // lsearch(3) will add it.
+ ASSERT_EQ(&xs[0], lsearch(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
+ ASSERT_EQ(2, xs[0]);
+ ASSERT_EQ(1U, x_size);
+
+ // And then lfind(3) can find it.
+ ASSERT_EQ(&xs[0], lfind(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
+ ASSERT_EQ(1U, x_size);
+
+ // Inserting a duplicate does nothing (but returns the existing element).
+ ASSERT_EQ(&xs[0], lsearch(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
+ ASSERT_EQ(1U, x_size);
+}
+
+struct node {
+ node(const char* s) : s(strdup(s)) {}
+
+ char* s;
+};
+
+static int node_cmp(const void* lhs, const void* rhs) {
+ return strcmp(reinterpret_cast<const node*>(lhs)->s, reinterpret_cast<const node*>(rhs)->s);
+}
+
+static std::vector<std::string> g_nodes;
+
+static void node_walk(const void* p, VISIT order, int) {
+ const node* n = *reinterpret_cast<const node* const*>(p);
+ if (order == postorder || order == leaf) {
+ g_nodes.push_back(n->s);
+ }
+}
+
+static size_t g_free_calls;
+
+static void node_free(void* p) {
+ node* n = reinterpret_cast<node*>(p);
+ free(n->s);
+ ++g_free_calls;
+}
+
+TEST(search, tfind_tsearch_twalk_tdestroy) {
+ void* root = nullptr;
+
+ node n1("z");
+ node n2("a");
+ node n3("m");
+
+ // tfind(3) can't find anything in the empty tree.
+ ASSERT_EQ(nullptr, tfind(&n1, &root, node_cmp));
+ ASSERT_EQ(nullptr, tfind(&n2, &root, node_cmp));
+ ASSERT_EQ(nullptr, tfind(&n3, &root, node_cmp));
+
+ // tsearch(3) inserts and returns a pointer to a new node.
+ void* i1 = tsearch(&n1, &root, node_cmp);
+ ASSERT_NE(nullptr, i1);
+
+ // ...which tfind(3) will then return.
+ ASSERT_EQ(i1, tfind(&n1, &root, node_cmp));
+ ASSERT_EQ(nullptr, tfind(&n2, &root, node_cmp));
+ ASSERT_EQ(nullptr, tfind(&n3, &root, node_cmp));
+
+ // Add the other nodes.
+ ASSERT_NE(nullptr, tsearch(&n2, &root, node_cmp));
+ ASSERT_NE(nullptr, tsearch(&n3, &root, node_cmp));
+
+ // Use twalk(3) to iterate over the nodes.
+ g_nodes.clear();
+ twalk(root, node_walk);
+ ASSERT_EQ(3U, g_nodes.size());
+ ASSERT_EQ("a", g_nodes[0]);
+ ASSERT_EQ("m", g_nodes[1]);
+ ASSERT_EQ("z", g_nodes[2]);
+
+ // tdestroy(3) removes nodes under a node, calling our callback to destroy each one.
+ g_free_calls = 0;
+ tdestroy(root, node_free);
+ ASSERT_EQ(3U, g_free_calls);
+}
+
+struct pod_node {
+ pod_node(int i) : i(i) {}
+ int i;
+};
+
+static int pod_node_cmp(const void* lhs, const void* rhs) {
+ return reinterpret_cast<const pod_node*>(rhs)->i - reinterpret_cast<const pod_node*>(lhs)->i;
+}
+
+TEST(search, tdelete) {
+ void* root = nullptr;
+
+ pod_node n1(123);
+ ASSERT_NE(nullptr, tsearch(&n1, &root, pod_node_cmp));
+
+ // tdelete(3) leaks n1.
+ pod_node not_there(456);
+ ASSERT_EQ(nullptr, tdelete(¬_there, &root, pod_node_cmp));
+ ASSERT_NE(nullptr, tdelete(&n1, &root, pod_node_cmp));
+}
+
+struct q_node {
+ q_node(int i) : i(i) {}
+
+ q_node* next;
+ q_node* prev;
+
+ int i;
+};
+
+TEST(search, insque_remque) {
+ q_node zero(0);
+ q_node one(1);
+ q_node two(2);
+
+ // Linear (not circular).
+
+ insque(&zero, NULL);
+ insque(&one, &zero);
+ insque(&two, &one);
+
+ int expected = 0;
+ for (q_node* q = &zero; q != NULL; q = q->next) {
+ ASSERT_EQ(expected, q->i);
+ ++expected;
+ }
+ ASSERT_EQ(3, expected);
+
+ for (q_node* q = &two; q != NULL; q = q->prev) {
+ --expected;
+ ASSERT_EQ(expected, q->i);
+ }
+ ASSERT_EQ(0, expected);
+
+ q_node* head = &zero;
+
+ remque(&one);
+ ASSERT_EQ(0, head->i);
+ ASSERT_EQ(2, head->next->i);
+ ASSERT_EQ(nullptr, head->next->next);
+
+ remque(&two);
+ ASSERT_EQ(0, head->i);
+ ASSERT_EQ(nullptr, head->next);
+
+ remque(&zero);
+
+ // Circular.
+
+ zero.next = &zero;
+ zero.prev = &zero;
+
+ insque(&one, &zero);
+ insque(&two, &one);
+
+ ASSERT_EQ(0, head->i);
+ ASSERT_EQ(1, head->next->i);
+ ASSERT_EQ(2, head->next->next->i);
+ ASSERT_EQ(0, head->next->next->next->i);
+ ASSERT_EQ(1, head->next->next->next->next->i);
+ ASSERT_EQ(2, head->next->next->next->next->next->i);
+
+ remque(&one);
+ ASSERT_EQ(0, head->i);
+ ASSERT_EQ(2, head->next->i);
+ ASSERT_EQ(0, head->next->next->i);
+ ASSERT_EQ(2, head->next->next->next->i);
+
+ remque(&two);
+ ASSERT_EQ(0, head->i);
+ ASSERT_EQ(0, head->next->i);
+
+ remque(&zero);
+}
diff --git a/tests/stdatomic_test.cpp b/tests/stdatomic_test.cpp
index d41bfa9..5e88c88 100644
--- a/tests/stdatomic_test.cpp
+++ b/tests/stdatomic_test.cpp
@@ -66,7 +66,12 @@
atomic_char small;
atomic_intmax_t big;
ASSERT_TRUE(atomic_is_lock_free(&small));
+ // atomic_intmax_t(size = 64) is not lock free on mips32.
+#if defined(__mips__) && !defined(__LP64__)
+ ASSERT_FALSE(atomic_is_lock_free(&big));
+#else
ASSERT_TRUE(atomic_is_lock_free(&big));
+#endif
}
TEST(stdatomic, atomic_flag) {
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 6d29421..553f018 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -262,3 +262,102 @@
ASSERT_TRUE(WIFEXITED(status));
ASSERT_EQ(99, WEXITSTATUS(status));
}
+
+TEST(stdlib, pty_smoke) {
+ // getpt returns a pty with O_RDWR|O_NOCTTY.
+ int fd = getpt();
+ ASSERT_NE(-1, fd);
+
+ // grantpt is a no-op.
+ ASSERT_EQ(0, grantpt(fd));
+
+ // ptsname_r should start "/dev/pts/".
+ char name_r[128];
+ ASSERT_EQ(0, ptsname_r(fd, name_r, sizeof(name_r)));
+ name_r[9] = 0;
+ ASSERT_STREQ("/dev/pts/", name_r);
+
+ close(fd);
+}
+
+TEST(stdlib, posix_openpt) {
+ int fd = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC);
+ ASSERT_NE(-1, fd);
+ close(fd);
+}
+
+TEST(stdlib, ptsname_r_ENOTTY) {
+ errno = 0;
+ char buf[128];
+ ASSERT_EQ(ENOTTY, ptsname_r(STDOUT_FILENO, buf, sizeof(buf)));
+ ASSERT_EQ(ENOTTY, errno);
+}
+
+TEST(stdlib, ptsname_r_EINVAL) {
+ int fd = getpt();
+ ASSERT_NE(-1, fd);
+ errno = 0;
+ char* buf = NULL;
+ ASSERT_EQ(EINVAL, ptsname_r(fd, buf, 128));
+ ASSERT_EQ(EINVAL, errno);
+ close(fd);
+}
+
+TEST(stdlib, ptsname_r_ERANGE) {
+ int fd = getpt();
+ ASSERT_NE(-1, fd);
+ errno = 0;
+ char buf[1];
+ ASSERT_EQ(ERANGE, ptsname_r(fd, buf, sizeof(buf)));
+ ASSERT_EQ(ERANGE, errno);
+ close(fd);
+}
+
+TEST(stdlib, ttyname_r) {
+ int fd = getpt();
+ ASSERT_NE(-1, fd);
+
+ // ttyname_r returns "/dev/ptmx" for a pty.
+ char name_r[128];
+ ASSERT_EQ(0, ttyname_r(fd, name_r, sizeof(name_r)));
+ ASSERT_STREQ("/dev/ptmx", name_r);
+
+ close(fd);
+}
+
+TEST(stdlib, ttyname_r_ENOTTY) {
+ int fd = open("/dev/null", O_WRONLY);
+ errno = 0;
+ char buf[128];
+ ASSERT_EQ(ENOTTY, ttyname_r(fd, buf, sizeof(buf)));
+ ASSERT_EQ(ENOTTY, errno);
+ close(fd);
+}
+
+TEST(stdlib, ttyname_r_EINVAL) {
+ int fd = getpt();
+ ASSERT_NE(-1, fd);
+ errno = 0;
+ char* buf = NULL;
+ ASSERT_EQ(EINVAL, ttyname_r(fd, buf, 128));
+ ASSERT_EQ(EINVAL, errno);
+ close(fd);
+}
+
+TEST(stdlib, ttyname_r_ERANGE) {
+ int fd = getpt();
+ ASSERT_NE(-1, fd);
+ errno = 0;
+ char buf[1];
+ ASSERT_EQ(ERANGE, ttyname_r(fd, buf, sizeof(buf)));
+ ASSERT_EQ(ERANGE, errno);
+ close(fd);
+}
+
+TEST(stdlib, unlockpt_ENOTTY) {
+ int fd = open("/dev/null", O_WRONLY);
+ errno = 0;
+ ASSERT_EQ(-1, unlockpt(fd));
+ ASSERT_EQ(ENOTTY, errno);
+ close(fd);
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 12b1ea7..241c4a0 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -27,34 +27,6 @@
#include "ScopedSignalHandler.h"
-#if defined(__BIONIC__) // mktime_tz is a bionic extension.
-#include <libc/private/bionic_time.h>
-#endif // __BIONIC__
-
-TEST(time, mktime_tz) {
-#if defined(__BIONIC__)
- struct tm epoch;
- memset(&epoch, 0, sizeof(tm));
- epoch.tm_year = 1970 - 1900;
- epoch.tm_mon = 1;
- epoch.tm_mday = 1;
-
- // Alphabetically first. Coincidentally equivalent to UTC.
- ASSERT_EQ(2678400, mktime_tz(&epoch, "Africa/Abidjan"));
-
- // Alphabetically last. Coincidentally equivalent to UTC.
- ASSERT_EQ(2678400, mktime_tz(&epoch, "Zulu"));
-
- // Somewhere in the middle, not UTC.
- ASSERT_EQ(2707200, mktime_tz(&epoch, "America/Los_Angeles"));
-
- // Missing. Falls back to UTC.
- ASSERT_EQ(2678400, mktime_tz(&epoch, "PST"));
-#else // __BIONIC__
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
-}
-
TEST(time, gmtime) {
time_t t = 0;
tm* broken_down = gmtime(&t);
@@ -108,9 +80,6 @@
#if !defined(__LP64__)
// 32-bit bionic stupidly had a signed 32-bit time_t.
ASSERT_EQ(-1, mktime(&t));
-#if defined(__BIONIC__)
- ASSERT_EQ(-1, mktime_tz(&t, "UTC"));
-#endif
#else
// Everyone else should be using a signed 64-bit time_t.
ASSERT_GE(sizeof(time_t) * 8, 64U);
@@ -118,16 +87,10 @@
setenv("TZ", "America/Los_Angeles", 1);
tzset();
ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&t));
-#if defined(__BIONIC__)
- ASSERT_EQ(static_cast<time_t>(4108320000U), mktime_tz(&t, "UTC"));
-#endif
setenv("TZ", "UTC", 1);
tzset();
ASSERT_EQ(static_cast<time_t>(4108320000U), mktime(&t));
-#if defined(__BIONIC__)
- ASSERT_EQ(static_cast<time_t>(4108348800U), mktime_tz(&t, "America/Los_Angeles"));
-#endif
#endif
}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 58c9ad9..2a65657 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -20,6 +20,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/syscall.h>
@@ -212,6 +213,14 @@
ASSERT_EQ(EBADF, errno);
}
+TEST(unistd, syscall_long) {
+ // Check that syscall(3) correctly returns long results.
+ // https://code.google.com/p/android/issues/detail?id=73952
+ // We assume that the break is > 4GiB, but this is potentially flaky.
+ uintptr_t p = reinterpret_cast<uintptr_t>(sbrk(0));
+ ASSERT_EQ(p, static_cast<uintptr_t>(syscall(__NR_brk, 0)));
+}
+
TEST(unistd, alarm) {
ASSERT_EQ(0U, alarm(0));
}