Merge "Add marking of DNS sockets for mark based routing"
diff --git a/libc/Android.mk b/libc/Android.mk
index 11ae09b..73aa2e6 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -9,7 +9,6 @@
unistd/alarm.c \
unistd/exec.c \
unistd/fnmatch.c \
- unistd/getopt_long.c \
unistd/syslog.c \
unistd/system.c \
unistd/time.c \
@@ -150,6 +149,7 @@
bionic/strntoumax.c \
bionic/strtotimeval.c \
bionic/system_properties.c \
+ bionic/system_properties_compat.c \
bionic/tcgetpgrp.c \
bionic/tcsetpgrp.c \
bionic/thread_atexit.c \
@@ -225,6 +225,7 @@
bionic/setlocale.cpp \
bionic/signalfd.cpp \
bionic/sigwait.cpp \
+ bionic/statvfs.cpp \
bionic/__strcat_chk.cpp \
bionic/__strchr_chk.cpp \
bionic/__strcpy_chk.cpp \
@@ -279,6 +280,7 @@
upstream-freebsd/lib/libc/stdio/tempnam.c \
upstream-freebsd/lib/libc/stdio/tmpnam.c \
upstream-freebsd/lib/libc/stdio/wsetup.c \
+ upstream-freebsd/lib/libc/stdlib/getopt_long.c \
upstream-freebsd/lib/libc/stdlib/qsort.c \
upstream-freebsd/lib/libc/stdlib/realpath.c \
upstream-freebsd/lib/libc/string/wcpcpy.c \
diff --git a/libc/NOTICE b/libc/NOTICE
index 2937518..8ed455c 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -3060,13 +3060,6 @@
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-3. All advertising materials mentioning features or use of this software
- must display the following acknowledgement:
- This product includes software developed by the NetBSD
- Foundation, Inc. and its contributors.
-4. Neither the name of The NetBSD Foundation nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -4116,6 +4109,38 @@
-------------------------------------------------------------------
+Copyright (c) 2013, Linaro Limited
+ 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.
+
+ 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.
+
+ 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.
+
+-------------------------------------------------------------------
+
Copyright (c)1999 Citrus Project,
All rights reserved.
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index ac04e51..88c980f 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -201,6 +201,8 @@
int lremovexattr(const char *, const char *) 1
int __statfs64:statfs64(const char *, size_t, struct statfs *) 1
long unshare(unsigned long) 1
+int swapon(const char *, int) 1
+int swapoff(const char *) 1
# time
int pause () 1
diff --git a/libc/arch-arm/bionic/memcpy.a9.S b/libc/arch-arm/bionic/memcpy.a9.S
new file mode 100644
index 0000000..2ba1ff5
--- /dev/null
+++ b/libc/arch-arm/bionic/memcpy.a9.S
@@ -0,0 +1,614 @@
+/* Copyright (c) 2013, Linaro Limited
+ 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.
+
+ * 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.
+
+ 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.
+
+ */
+
+/*
+ This memcpy routine is optimised for Cortex-A15 cores and takes advantage
+ of VFP or NEON when built with the appropriate flags.
+
+ Assumptions:
+
+ ARMv6 (ARMv7-a if using Neon)
+ ARM state
+ Unaligned accesses
+ LDRD/STRD support unaligned word accesses
+
+ */
+
+#include <machine/cpu-features.h>
+#include <machine/asm.h>
+
+ .syntax unified
+ /* This implementation requires ARM state. */
+ .arm
+
+#ifdef __ARM_NEON__
+
+ .fpu neon
+ .arch armv7-a
+# define FRAME_SIZE 4
+# define USE_VFP
+# define USE_NEON
+
+#elif !defined (__SOFTFP__)
+
+ .arch armv6
+ .fpu vfpv2
+# define FRAME_SIZE 32
+# define USE_VFP
+
+#else
+ .arch armv6
+# define FRAME_SIZE 32
+
+#endif
+
+/* Old versions of GAS incorrectly implement the NEON align semantics. */
+#ifdef BROKEN_ASM_NEON_ALIGN
+#define ALIGN(addr, align) addr,:align
+#else
+#define ALIGN(addr, align) addr:align
+#endif
+
+#define PC_OFFSET 8 /* PC pipeline compensation. */
+#define INSN_SIZE 4
+
+/* Call parameters. */
+#define dstin r0
+#define src r1
+#define count r2
+
+/* Locals. */
+#define tmp1 r3
+#define dst ip
+#define tmp2 r10
+
+#ifndef USE_NEON
+/* For bulk copies using GP registers. */
+#define A_l r2 /* Call-clobbered. */
+#define A_h r3 /* Call-clobbered. */
+#define B_l r4
+#define B_h r5
+#define C_l r6
+#define C_h r7
+#define D_l r8
+#define D_h r9
+#endif
+
+/* Number of lines ahead to pre-fetch data. If you change this the code
+ below will need adjustment to compensate. */
+
+#define prefetch_lines 5
+
+#ifdef USE_VFP
+ .macro cpy_line_vfp vreg, base
+ vstr \vreg, [dst, #\base]
+ vldr \vreg, [src, #\base]
+ vstr d0, [dst, #\base + 8]
+ vldr d0, [src, #\base + 8]
+ vstr d1, [dst, #\base + 16]
+ vldr d1, [src, #\base + 16]
+ vstr d2, [dst, #\base + 24]
+ vldr d2, [src, #\base + 24]
+ vstr \vreg, [dst, #\base + 32]
+ vldr \vreg, [src, #\base + prefetch_lines * 64 - 32]
+ vstr d0, [dst, #\base + 40]
+ vldr d0, [src, #\base + 40]
+ vstr d1, [dst, #\base + 48]
+ vldr d1, [src, #\base + 48]
+ vstr d2, [dst, #\base + 56]
+ vldr d2, [src, #\base + 56]
+ .endm
+
+ .macro cpy_tail_vfp vreg, base
+ vstr \vreg, [dst, #\base]
+ vldr \vreg, [src, #\base]
+ vstr d0, [dst, #\base + 8]
+ vldr d0, [src, #\base + 8]
+ vstr d1, [dst, #\base + 16]
+ vldr d1, [src, #\base + 16]
+ vstr d2, [dst, #\base + 24]
+ vldr d2, [src, #\base + 24]
+ vstr \vreg, [dst, #\base + 32]
+ vstr d0, [dst, #\base + 40]
+ vldr d0, [src, #\base + 40]
+ vstr d1, [dst, #\base + 48]
+ vldr d1, [src, #\base + 48]
+ vstr d2, [dst, #\base + 56]
+ vldr d2, [src, #\base + 56]
+ .endm
+#endif
+
+ .p2align 6
+ENTRY(memcpy)
+
+ mov dst, dstin /* Preserve dstin, we need to return it. */
+ cmp count, #64
+ bge .Lcpy_not_short
+ /* Deal with small copies quickly by dropping straight into the
+ exit block. */
+
+.Ltail63unaligned:
+#ifdef USE_NEON
+ and tmp1, count, #0x38
+ rsb tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
+ add pc, pc, tmp1
+ vld1.8 {d0}, [src]! /* 14 words to go. */
+ vst1.8 {d0}, [dst]!
+ vld1.8 {d0}, [src]! /* 12 words to go. */
+ vst1.8 {d0}, [dst]!
+ vld1.8 {d0}, [src]! /* 10 words to go. */
+ vst1.8 {d0}, [dst]!
+ vld1.8 {d0}, [src]! /* 8 words to go. */
+ vst1.8 {d0}, [dst]!
+ vld1.8 {d0}, [src]! /* 6 words to go. */
+ vst1.8 {d0}, [dst]!
+ vld1.8 {d0}, [src]! /* 4 words to go. */
+ vst1.8 {d0}, [dst]!
+ vld1.8 {d0}, [src]! /* 2 words to go. */
+ vst1.8 {d0}, [dst]!
+
+ tst count, #4
+ ldrne tmp1, [src], #4
+ strne tmp1, [dst], #4
+#else
+ /* Copy up to 15 full words of data. May not be aligned. */
+ /* Cannot use VFP for unaligned data. */
+ and tmp1, count, #0x3c
+ add dst, dst, tmp1
+ add src, src, tmp1
+ rsb tmp1, tmp1, #(60 - PC_OFFSET/2 + INSN_SIZE/2)
+ /* Jump directly into the sequence below at the correct offset. */
+ add pc, pc, tmp1, lsl #1
+
+ ldr tmp1, [src, #-60] /* 15 words to go. */
+ str tmp1, [dst, #-60]
+
+ ldr tmp1, [src, #-56] /* 14 words to go. */
+ str tmp1, [dst, #-56]
+ ldr tmp1, [src, #-52]
+ str tmp1, [dst, #-52]
+
+ ldr tmp1, [src, #-48] /* 12 words to go. */
+ str tmp1, [dst, #-48]
+ ldr tmp1, [src, #-44]
+ str tmp1, [dst, #-44]
+
+ ldr tmp1, [src, #-40] /* 10 words to go. */
+ str tmp1, [dst, #-40]
+ ldr tmp1, [src, #-36]
+ str tmp1, [dst, #-36]
+
+ ldr tmp1, [src, #-32] /* 8 words to go. */
+ str tmp1, [dst, #-32]
+ ldr tmp1, [src, #-28]
+ str tmp1, [dst, #-28]
+
+ ldr tmp1, [src, #-24] /* 6 words to go. */
+ str tmp1, [dst, #-24]
+ ldr tmp1, [src, #-20]
+ str tmp1, [dst, #-20]
+
+ ldr tmp1, [src, #-16] /* 4 words to go. */
+ str tmp1, [dst, #-16]
+ ldr tmp1, [src, #-12]
+ str tmp1, [dst, #-12]
+
+ ldr tmp1, [src, #-8] /* 2 words to go. */
+ str tmp1, [dst, #-8]
+ ldr tmp1, [src, #-4]
+ str tmp1, [dst, #-4]
+#endif
+
+ lsls count, count, #31
+ ldrhcs tmp1, [src], #2
+ ldrbne src, [src] /* Src is dead, use as a scratch. */
+ strhcs tmp1, [dst], #2
+ strbne src, [dst]
+ bx lr
+
+.Lcpy_not_short:
+ /* At least 64 bytes to copy, but don't know the alignment yet. */
+ str tmp2, [sp, #-FRAME_SIZE]!
+ and tmp2, src, #7
+ and tmp1, dst, #7
+ cmp tmp1, tmp2
+ bne .Lcpy_notaligned
+
+#ifdef USE_VFP
+ /* Magic dust alert! Force VFP on Cortex-A9. Experiments show
+ that the FP pipeline is much better at streaming loads and
+ stores. This is outside the critical loop. */
+ vmov.f32 s0, s0
+#endif
+
+ /* SRC and DST have the same mutual 32-bit alignment, but we may
+ still need to pre-copy some bytes to get to natural alignment.
+ We bring DST into full 64-bit alignment. */
+ lsls tmp2, dst, #29
+ beq 1f
+ rsbs tmp2, tmp2, #0
+ sub count, count, tmp2, lsr #29
+ ldrmi tmp1, [src], #4
+ strmi tmp1, [dst], #4
+ lsls tmp2, tmp2, #2
+ ldrhcs tmp1, [src], #2
+ ldrbne tmp2, [src], #1
+ strhcs tmp1, [dst], #2
+ strbne tmp2, [dst], #1
+
+1:
+ subs tmp2, count, #64 /* Use tmp2 for count. */
+ blt .Ltail63aligned
+
+ cmp tmp2, #512
+ bge .Lcpy_body_long
+
+.Lcpy_body_medium: /* Count in tmp2. */
+#ifdef USE_VFP
+1:
+ vldr d0, [src, #0]
+ subs tmp2, tmp2, #64
+ vldr d1, [src, #8]
+ vstr d0, [dst, #0]
+ vldr d0, [src, #16]
+ vstr d1, [dst, #8]
+ vldr d1, [src, #24]
+ vstr d0, [dst, #16]
+ vldr d0, [src, #32]
+ vstr d1, [dst, #24]
+ vldr d1, [src, #40]
+ vstr d0, [dst, #32]
+ vldr d0, [src, #48]
+ vstr d1, [dst, #40]
+ vldr d1, [src, #56]
+ vstr d0, [dst, #48]
+ add src, src, #64
+ vstr d1, [dst, #56]
+ add dst, dst, #64
+ bge 1b
+ tst tmp2, #0x3f
+ beq .Ldone
+
+.Ltail63aligned: /* Count in tmp2. */
+ and tmp1, tmp2, #0x38
+ add dst, dst, tmp1
+ add src, src, tmp1
+ rsb tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
+ add pc, pc, tmp1
+
+ vldr d0, [src, #-56] /* 14 words to go. */
+ vstr d0, [dst, #-56]
+ vldr d0, [src, #-48] /* 12 words to go. */
+ vstr d0, [dst, #-48]
+ vldr d0, [src, #-40] /* 10 words to go. */
+ vstr d0, [dst, #-40]
+ vldr d0, [src, #-32] /* 8 words to go. */
+ vstr d0, [dst, #-32]
+ vldr d0, [src, #-24] /* 6 words to go. */
+ vstr d0, [dst, #-24]
+ vldr d0, [src, #-16] /* 4 words to go. */
+ vstr d0, [dst, #-16]
+ vldr d0, [src, #-8] /* 2 words to go. */
+ vstr d0, [dst, #-8]
+#else
+ sub src, src, #8
+ sub dst, dst, #8
+1:
+ ldrd A_l, A_h, [src, #8]
+ strd A_l, A_h, [dst, #8]
+ ldrd A_l, A_h, [src, #16]
+ strd A_l, A_h, [dst, #16]
+ ldrd A_l, A_h, [src, #24]
+ strd A_l, A_h, [dst, #24]
+ ldrd A_l, A_h, [src, #32]
+ strd A_l, A_h, [dst, #32]
+ ldrd A_l, A_h, [src, #40]
+ strd A_l, A_h, [dst, #40]
+ ldrd A_l, A_h, [src, #48]
+ strd A_l, A_h, [dst, #48]
+ ldrd A_l, A_h, [src, #56]
+ strd A_l, A_h, [dst, #56]
+ ldrd A_l, A_h, [src, #64]!
+ strd A_l, A_h, [dst, #64]!
+ subs tmp2, tmp2, #64
+ bge 1b
+ tst tmp2, #0x3f
+ bne 1f
+ ldr tmp2,[sp], #FRAME_SIZE
+ bx lr
+1:
+ add src, src, #8
+ add dst, dst, #8
+
+.Ltail63aligned: /* Count in tmp2. */
+ /* Copy up to 7 d-words of data. Similar to Ltail63unaligned, but
+ we know that the src and dest are 32-bit aligned so we can use
+ LDRD/STRD to improve efficiency. */
+ /* TMP2 is now negative, but we don't care about that. The bottom
+ six bits still tell us how many bytes are left to copy. */
+
+ and tmp1, tmp2, #0x38
+ add dst, dst, tmp1
+ add src, src, tmp1
+ rsb tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
+ add pc, pc, tmp1
+ ldrd A_l, A_h, [src, #-56] /* 14 words to go. */
+ strd A_l, A_h, [dst, #-56]
+ ldrd A_l, A_h, [src, #-48] /* 12 words to go. */
+ strd A_l, A_h, [dst, #-48]
+ ldrd A_l, A_h, [src, #-40] /* 10 words to go. */
+ strd A_l, A_h, [dst, #-40]
+ ldrd A_l, A_h, [src, #-32] /* 8 words to go. */
+ strd A_l, A_h, [dst, #-32]
+ ldrd A_l, A_h, [src, #-24] /* 6 words to go. */
+ strd A_l, A_h, [dst, #-24]
+ ldrd A_l, A_h, [src, #-16] /* 4 words to go. */
+ strd A_l, A_h, [dst, #-16]
+ ldrd A_l, A_h, [src, #-8] /* 2 words to go. */
+ strd A_l, A_h, [dst, #-8]
+
+#endif
+ tst tmp2, #4
+ ldrne tmp1, [src], #4
+ strne tmp1, [dst], #4
+ lsls tmp2, tmp2, #31 /* Count (tmp2) now dead. */
+ ldrhcs tmp1, [src], #2
+ ldrbne tmp2, [src]
+ strhcs tmp1, [dst], #2
+ strbne tmp2, [dst]
+
+.Ldone:
+ ldr tmp2, [sp], #FRAME_SIZE
+ bx lr
+
+.Lcpy_body_long: /* Count in tmp2. */
+
+ /* Long copy. We know that there's at least (prefetch_lines * 64)
+ bytes to go. */
+#ifdef USE_VFP
+ /* Don't use PLD. Instead, read some data in advance of the current
+ copy position into a register. This should act like a PLD
+ operation but we won't have to repeat the transfer. */
+
+ vldr d3, [src, #0]
+ vldr d4, [src, #64]
+ vldr d5, [src, #128]
+ vldr d6, [src, #192]
+ vldr d7, [src, #256]
+
+ vldr d0, [src, #8]
+ vldr d1, [src, #16]
+ vldr d2, [src, #24]
+ add src, src, #32
+
+ subs tmp2, tmp2, #prefetch_lines * 64 * 2
+ blt 2f
+1:
+ cpy_line_vfp d3, 0
+ cpy_line_vfp d4, 64
+ cpy_line_vfp d5, 128
+ add dst, dst, #3 * 64
+ add src, src, #3 * 64
+ cpy_line_vfp d6, 0
+ cpy_line_vfp d7, 64
+ add dst, dst, #2 * 64
+ add src, src, #2 * 64
+ subs tmp2, tmp2, #prefetch_lines * 64
+ bge 1b
+
+2:
+ cpy_tail_vfp d3, 0
+ cpy_tail_vfp d4, 64
+ cpy_tail_vfp d5, 128
+ add src, src, #3 * 64
+ add dst, dst, #3 * 64
+ cpy_tail_vfp d6, 0
+ vstr d7, [dst, #64]
+ vldr d7, [src, #64]
+ vstr d0, [dst, #64 + 8]
+ vldr d0, [src, #64 + 8]
+ vstr d1, [dst, #64 + 16]
+ vldr d1, [src, #64 + 16]
+ vstr d2, [dst, #64 + 24]
+ vldr d2, [src, #64 + 24]
+ vstr d7, [dst, #64 + 32]
+ add src, src, #96
+ vstr d0, [dst, #64 + 40]
+ vstr d1, [dst, #64 + 48]
+ vstr d2, [dst, #64 + 56]
+ add dst, dst, #128
+ add tmp2, tmp2, #prefetch_lines * 64
+ b .Lcpy_body_medium
+#else
+ /* Long copy. Use an SMS style loop to maximize the I/O
+ bandwidth of the core. We don't have enough spare registers
+ to synthesise prefetching, so use PLD operations. */
+ /* Pre-bias src and dst. */
+ sub src, src, #8
+ sub dst, dst, #8
+ pld [src, #8]
+ pld [src, #72]
+ subs tmp2, tmp2, #64
+ pld [src, #136]
+ ldrd A_l, A_h, [src, #8]
+ strd B_l, B_h, [sp, #8]
+ ldrd B_l, B_h, [src, #16]
+ strd C_l, C_h, [sp, #16]
+ ldrd C_l, C_h, [src, #24]
+ strd D_l, D_h, [sp, #24]
+ pld [src, #200]
+ ldrd D_l, D_h, [src, #32]!
+ b 1f
+ .p2align 6
+2:
+ pld [src, #232]
+ strd A_l, A_h, [dst, #40]
+ ldrd A_l, A_h, [src, #40]
+ strd B_l, B_h, [dst, #48]
+ ldrd B_l, B_h, [src, #48]
+ strd C_l, C_h, [dst, #56]
+ ldrd C_l, C_h, [src, #56]
+ strd D_l, D_h, [dst, #64]!
+ ldrd D_l, D_h, [src, #64]!
+ subs tmp2, tmp2, #64
+1:
+ strd A_l, A_h, [dst, #8]
+ ldrd A_l, A_h, [src, #8]
+ strd B_l, B_h, [dst, #16]
+ ldrd B_l, B_h, [src, #16]
+ strd C_l, C_h, [dst, #24]
+ ldrd C_l, C_h, [src, #24]
+ strd D_l, D_h, [dst, #32]
+ ldrd D_l, D_h, [src, #32]
+ bcs 2b
+ /* Save the remaining bytes and restore the callee-saved regs. */
+ strd A_l, A_h, [dst, #40]
+ add src, src, #40
+ strd B_l, B_h, [dst, #48]
+ ldrd B_l, B_h, [sp, #8]
+ strd C_l, C_h, [dst, #56]
+ ldrd C_l, C_h, [sp, #16]
+ strd D_l, D_h, [dst, #64]
+ ldrd D_l, D_h, [sp, #24]
+ add dst, dst, #72
+ tst tmp2, #0x3f
+ bne .Ltail63aligned
+ ldr tmp2, [sp], #FRAME_SIZE
+ bx lr
+#endif
+
+.Lcpy_notaligned:
+ pld [src]
+ pld [src, #64]
+ /* There's at least 64 bytes to copy, but there is no mutual
+ alignment. */
+ /* Bring DST to 64-bit alignment. */
+ lsls tmp2, dst, #29
+ pld [src, #(2 * 64)]
+ beq 1f
+ rsbs tmp2, tmp2, #0
+ sub count, count, tmp2, lsr #29
+ ldrmi tmp1, [src], #4
+ strmi tmp1, [dst], #4
+ lsls tmp2, tmp2, #2
+ ldrbne tmp1, [src], #1
+ ldrhcs tmp2, [src], #2
+ strbne tmp1, [dst], #1
+ strhcs tmp2, [dst], #2
+1:
+ pld [src, #(3 * 64)]
+ subs count, count, #64
+ ldrmi tmp2, [sp], #FRAME_SIZE
+ bmi .Ltail63unaligned
+ pld [src, #(4 * 64)]
+
+#ifdef USE_NEON
+ vld1.8 {d0-d3}, [src]!
+ vld1.8 {d4-d7}, [src]!
+ subs count, count, #64
+ bmi 2f
+1:
+ pld [src, #(4 * 64)]
+ vst1.8 {d0-d3}, [ALIGN (dst, 64)]!
+ vld1.8 {d0-d3}, [src]!
+ vst1.8 {d4-d7}, [ALIGN (dst, 64)]!
+ vld1.8 {d4-d7}, [src]!
+ subs count, count, #64
+ bpl 1b
+2:
+ vst1.8 {d0-d3}, [ALIGN (dst, 64)]!
+ vst1.8 {d4-d7}, [ALIGN (dst, 64)]!
+ ands count, count, #0x3f
+#else
+ /* Use an SMS style loop to maximize the I/O bandwidth. */
+ sub src, src, #4
+ sub dst, dst, #8
+ subs tmp2, count, #64 /* Use tmp2 for count. */
+ ldr A_l, [src, #4]
+ ldr A_h, [src, #8]
+ strd B_l, B_h, [sp, #8]
+ ldr B_l, [src, #12]
+ ldr B_h, [src, #16]
+ strd C_l, C_h, [sp, #16]
+ ldr C_l, [src, #20]
+ ldr C_h, [src, #24]
+ strd D_l, D_h, [sp, #24]
+ ldr D_l, [src, #28]
+ ldr D_h, [src, #32]!
+ b 1f
+ .p2align 6
+2:
+ pld [src, #(5 * 64) - (32 - 4)]
+ strd A_l, A_h, [dst, #40]
+ ldr A_l, [src, #36]
+ ldr A_h, [src, #40]
+ strd B_l, B_h, [dst, #48]
+ ldr B_l, [src, #44]
+ ldr B_h, [src, #48]
+ strd C_l, C_h, [dst, #56]
+ ldr C_l, [src, #52]
+ ldr C_h, [src, #56]
+ strd D_l, D_h, [dst, #64]!
+ ldr D_l, [src, #60]
+ ldr D_h, [src, #64]!
+ subs tmp2, tmp2, #64
+1:
+ strd A_l, A_h, [dst, #8]
+ ldr A_l, [src, #4]
+ ldr A_h, [src, #8]
+ strd B_l, B_h, [dst, #16]
+ ldr B_l, [src, #12]
+ ldr B_h, [src, #16]
+ strd C_l, C_h, [dst, #24]
+ ldr C_l, [src, #20]
+ ldr C_h, [src, #24]
+ strd D_l, D_h, [dst, #32]
+ ldr D_l, [src, #28]
+ ldr D_h, [src, #32]
+ bcs 2b
+
+ /* Save the remaining bytes and restore the callee-saved regs. */
+ strd A_l, A_h, [dst, #40]
+ add src, src, #36
+ strd B_l, B_h, [dst, #48]
+ ldrd B_l, B_h, [sp, #8]
+ strd C_l, C_h, [dst, #56]
+ ldrd C_l, C_h, [sp, #16]
+ strd D_l, D_h, [dst, #64]
+ ldrd D_l, D_h, [sp, #24]
+ add dst, dst, #72
+ ands count, tmp2, #0x3f
+#endif
+ ldr tmp2, [sp], #FRAME_SIZE
+ bne .Ltail63unaligned
+ bx lr
+END(memcpy)
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index 3c8f204..252a428 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -126,6 +126,8 @@
syscall_src += arch-arm/syscalls/lremovexattr.S
syscall_src += arch-arm/syscalls/__statfs64.S
syscall_src += arch-arm/syscalls/unshare.S
+syscall_src += arch-arm/syscalls/swapon.S
+syscall_src += arch-arm/syscalls/swapoff.S
syscall_src += arch-arm/syscalls/pause.S
syscall_src += arch-arm/syscalls/gettimeofday.S
syscall_src += arch-arm/syscalls/settimeofday.S
diff --git a/libc/arch-arm/syscalls/swapoff.S b/libc/arch-arm/syscalls/swapoff.S
new file mode 100644
index 0000000..070d160
--- /dev/null
+++ b/libc/arch-arm/syscalls/swapoff.S
@@ -0,0 +1,15 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+#include <linux/err.h>
+#include <machine/asm.h>
+
+ENTRY(swapoff)
+ mov ip, r7
+ ldr r7, =__NR_swapoff
+ swi #0
+ mov r7, ip
+ cmn r0, #(MAX_ERRNO + 1)
+ bxls lr
+ neg r0, r0
+ b __set_errno
+END(swapoff)
diff --git a/libc/arch-arm/syscalls/swapon.S b/libc/arch-arm/syscalls/swapon.S
new file mode 100644
index 0000000..a77e0cd
--- /dev/null
+++ b/libc/arch-arm/syscalls/swapon.S
@@ -0,0 +1,15 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+#include <linux/err.h>
+#include <machine/asm.h>
+
+ENTRY(swapon)
+ mov ip, r7
+ ldr r7, =__NR_swapon
+ swi #0
+ mov r7, ip
+ cmn r0, #(MAX_ERRNO + 1)
+ bxls lr
+ neg r0, r0
+ b __set_errno
+END(swapon)
diff --git a/libc/arch-mips/syscalls.mk b/libc/arch-mips/syscalls.mk
index d3096bc..23393a2 100644
--- a/libc/arch-mips/syscalls.mk
+++ b/libc/arch-mips/syscalls.mk
@@ -129,6 +129,8 @@
syscall_src += arch-mips/syscalls/lremovexattr.S
syscall_src += arch-mips/syscalls/__statfs64.S
syscall_src += arch-mips/syscalls/unshare.S
+syscall_src += arch-mips/syscalls/swapon.S
+syscall_src += arch-mips/syscalls/swapoff.S
syscall_src += arch-mips/syscalls/pause.S
syscall_src += arch-mips/syscalls/gettimeofday.S
syscall_src += arch-mips/syscalls/settimeofday.S
diff --git a/libc/arch-mips/syscalls/swapoff.S b/libc/arch-mips/syscalls/swapoff.S
new file mode 100644
index 0000000..4f204c9
--- /dev/null
+++ b/libc/arch-mips/syscalls/swapoff.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+ .text
+ .globl swapoff
+ .align 4
+ .ent swapoff
+
+swapoff:
+ .set noreorder
+ .cpload $t9
+ li $v0, __NR_swapoff
+ syscall
+ bnez $a3, 1f
+ move $a0, $v0
+ j $ra
+ nop
+1:
+ la $t9,__set_errno
+ j $t9
+ nop
+ .set reorder
+ .end swapoff
diff --git a/libc/arch-mips/syscalls/swapon.S b/libc/arch-mips/syscalls/swapon.S
new file mode 100644
index 0000000..af3dda6
--- /dev/null
+++ b/libc/arch-mips/syscalls/swapon.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+ .text
+ .globl swapon
+ .align 4
+ .ent swapon
+
+swapon:
+ .set noreorder
+ .cpload $t9
+ li $v0, __NR_swapon
+ syscall
+ bnez $a3, 1f
+ move $a0, $v0
+ j $ra
+ nop
+1:
+ la $t9,__set_errno
+ j $t9
+ nop
+ .set reorder
+ .end swapon
diff --git a/libc/arch-x86/include/machine/endian.h b/libc/arch-x86/include/machine/endian.h
index e7ad257..e1506b1 100644
--- a/libc/arch-x86/include/machine/endian.h
+++ b/libc/arch-x86/include/machine/endian.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: endian.h,v 1.14 2005/12/13 00:35:23 millert Exp $ */
+/* $OpenBSD: endian.h,v 1.17 2011/03/12 04:03:04 guenther Exp $ */
/*-
* Copyright (c) 1997 Niklas Hallqvist. All rights reserved.
@@ -24,38 +24,28 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _I386_ENDIAN_H_
-#define _I386_ENDIAN_H_
+#ifndef _MACHINE_ENDIAN_H_
+#define _MACHINE_ENDIAN_H_
#ifdef __GNUC__
-#if defined(_KERNEL) && !defined(I386_CPU)
-#define __swap32md(x) ({ \
+#define __swap32md(x) __statement({ \
uint32_t __swap32md_x = (x); \
\
- __asm ("bswap %1" : "+r" (__swap32md_x)); \
+ __asm ("bswap %0" : "+r" (__swap32md_x)); \
__swap32md_x; \
})
-#else
-#define __swap32md(x) ({ \
- uint32_t __swap32md_x = (x); \
- \
- __asm ("rorw $8, %w1; rorl $16, %1; rorw $8, %w1" : \
- "+r" (__swap32md_x)); \
- __swap32md_x; \
-})
-#endif /* _KERNEL && !I386_CPU */
-#define __swap64md(x) ({ \
+#define __swap64md(x) __statement({ \
uint64_t __swap64md_x = (x); \
\
(uint64_t)__swap32md(__swap64md_x >> 32) | \
(uint64_t)__swap32md(__swap64md_x & 0xffffffff) << 32; \
})
-#define __swap16md(x) ({ \
+#define __swap16md(x) __statement({ \
uint16_t __swap16md_x = (x); \
\
- __asm ("rorw $8, %w1" : "+r" (__swap16md_x)); \
+ __asm ("rorw $8, %w0" : "+r" (__swap16md_x)); \
__swap16md_x; \
})
@@ -68,4 +58,4 @@
#include <sys/types.h>
#include <sys/endian.h>
-#endif /* _I386_ENDIAN_H_ */
+#endif /* _MACHINE_ENDIAN_H_ */
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index 31eb930..11573de 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -130,6 +130,8 @@
syscall_src += arch-x86/syscalls/lremovexattr.S
syscall_src += arch-x86/syscalls/__statfs64.S
syscall_src += arch-x86/syscalls/unshare.S
+syscall_src += arch-x86/syscalls/swapon.S
+syscall_src += arch-x86/syscalls/swapoff.S
syscall_src += arch-x86/syscalls/pause.S
syscall_src += arch-x86/syscalls/gettimeofday.S
syscall_src += arch-x86/syscalls/settimeofday.S
diff --git a/libc/arch-x86/syscalls/swapoff.S b/libc/arch-x86/syscalls/swapoff.S
new file mode 100644
index 0000000..f2d6ddb
--- /dev/null
+++ b/libc/arch-x86/syscalls/swapoff.S
@@ -0,0 +1,21 @@
+/* autogenerated by gensyscalls.py */
+#include <linux/err.h>
+#include <machine/asm.h>
+#include <asm/unistd.h>
+
+ENTRY(swapoff)
+ pushl %ebx
+ mov 8(%esp), %ebx
+ movl $__NR_swapoff, %eax
+ int $0x80
+ cmpl $-MAX_ERRNO, %eax
+ jb 1f
+ negl %eax
+ pushl %eax
+ call __set_errno
+ addl $4, %esp
+ orl $-1, %eax
+1:
+ popl %ebx
+ ret
+END(swapoff)
diff --git a/libc/arch-x86/syscalls/swapon.S b/libc/arch-x86/syscalls/swapon.S
new file mode 100644
index 0000000..08602fb
--- /dev/null
+++ b/libc/arch-x86/syscalls/swapon.S
@@ -0,0 +1,24 @@
+/* autogenerated by gensyscalls.py */
+#include <linux/err.h>
+#include <machine/asm.h>
+#include <asm/unistd.h>
+
+ENTRY(swapon)
+ pushl %ebx
+ pushl %ecx
+ mov 12(%esp), %ebx
+ mov 16(%esp), %ecx
+ movl $__NR_swapon, %eax
+ int $0x80
+ cmpl $-MAX_ERRNO, %eax
+ jb 1f
+ negl %eax
+ pushl %eax
+ call __set_errno
+ addl $4, %esp
+ orl $-1, %eax
+1:
+ popl %ecx
+ popl %ebx
+ ret
+END(swapon)
diff --git a/libc/bionic/dl_iterate_phdr_static.c b/libc/bionic/dl_iterate_phdr_static.c
index 90ed1b7..fc79ce5 100644
--- a/libc/bionic/dl_iterate_phdr_static.c
+++ b/libc/bionic/dl_iterate_phdr_static.c
@@ -27,39 +27,56 @@
*/
#include <elf.h>
+#include <sys/auxv.h>
#include <sys/types.h>
#include <link.h>
-/* Dynamic binaries get this from the dynamic linker (system/linker), which
- * we don't pull in for static bins. We also don't have a list of so's to
- * iterate over, since there's really only a single monolithic blob of
- * code/data.
- *
- * All we need to do is to find where the executable is in memory, and grab the
- * phdr and phnum from there.
- */
-
/* ld provides this to us in the default link script */
-extern void *__executable_start;
+extern void* __executable_start;
-int
-dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data),
- void *data)
-{
- struct dl_phdr_info dl_info;
- Elf32_Ehdr *ehdr = (Elf32_Ehdr *) &__executable_start;
- Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned long)ehdr + ehdr->e_phoff);
+int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data), void* data) {
+ Elf32_Ehdr* ehdr = (Elf32_Ehdr*) &__executable_start;
- /* TODO: again, copied from linker.c. Find a better home for this
- * later. */
+ // TODO: again, copied from linker.c. Find a better home for this later.
if (ehdr->e_ident[EI_MAG0] != ELFMAG0) return -1;
if (ehdr->e_ident[EI_MAG1] != ELFMAG1) return -1;
if (ehdr->e_ident[EI_MAG2] != ELFMAG2) return -1;
if (ehdr->e_ident[EI_MAG3] != ELFMAG3) return -1;
- dl_info.dlpi_addr = 0;
- dl_info.dlpi_name = NULL;
- dl_info.dlpi_phdr = phdr;
- dl_info.dlpi_phnum = ehdr->e_phnum;
- return cb(&dl_info, sizeof (struct dl_phdr_info), data);
+ // Dynamic binaries get their dl_iterate_phdr from the dynamic linker, but
+ // static binaries get this. We don't have a list of shared objects to
+ // iterate over, since there's really only a single monolithic blob of
+ // code/data, plus optionally a VDSO.
+
+ struct dl_phdr_info exe_info;
+ exe_info.dlpi_addr = 0;
+ exe_info.dlpi_name = NULL;
+ exe_info.dlpi_phdr = (Elf32_Phdr*) ((unsigned long) ehdr + ehdr->e_phoff);
+ exe_info.dlpi_phnum = ehdr->e_phnum;
+
+#ifdef AT_SYSINFO_EHDR
+ // Try the executable first.
+ int rc = cb(&exe_info, sizeof(exe_info), data);
+ if (rc != 0) {
+ return rc;
+ }
+
+ // Try the VDSO if that didn't work.
+ Elf32_Ehdr* ehdr_vdso = (Elf32_Ehdr*) getauxval(AT_SYSINFO_EHDR);
+ struct dl_phdr_info vdso_info;
+ vdso_info.dlpi_addr = 0;
+ vdso_info.dlpi_name = NULL;
+ vdso_info.dlpi_phdr = (Elf32_Phdr*) ((char*) ehdr_vdso + ehdr_vdso->e_phoff);
+ vdso_info.dlpi_phnum = ehdr_vdso->e_phnum;
+ for (size_t i = 0; i < vdso_info.dlpi_phnum; ++i) {
+ if (vdso_info.dlpi_phdr[i].p_type == PT_LOAD) {
+ vdso_info.dlpi_addr = (Elf32_Addr) ehdr_vdso - vdso_info.dlpi_phdr[i].p_vaddr;
+ break;
+ }
+ }
+ return cb(&vdso_info, sizeof(vdso_info), data);
+#else
+ // There's only the executable to try.
+ return cb(&exe_info, sizeof(exe_info), data);
+#endif
}
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index ffc5335..6bf7415 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -42,7 +42,6 @@
#include <unistd.h>
static pthread_mutex_t gAbortMsgLock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t gLogInitializationLock = PTHREAD_MUTEX_INITIALIZER;
__LIBC_HIDDEN__ abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common.
@@ -421,13 +420,9 @@
}
static int __libc_write_log(int priority, const char* tag, const char* msg) {
- static int main_log_fd = -1;
+ int main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY));
if (main_log_fd == -1) {
- ScopedPthreadMutexLocker locker(&gLogInitializationLock);
- main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY));
- if (main_log_fd == -1) {
- return -1;
- }
+ return -1;
}
iovec vec[3];
@@ -438,7 +433,9 @@
vec[2].iov_base = const_cast<char*>(msg);
vec[2].iov_len = strlen(msg) + 1;
- return TEMP_FAILURE_RETRY(writev(main_log_fd, vec, 3));
+ int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, 3));
+ close(main_log_fd);
+ return result;
}
int __libc_format_log_va_list(int priority, const char* tag, const char* format, va_list args) {
@@ -465,12 +462,13 @@
vec[2].iov_base = const_cast<void*>(payload);
vec[2].iov_len = len;
- static int event_log_fd = -1;
+ int event_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/events", O_CLOEXEC | O_WRONLY));
if (event_log_fd == -1) {
- ScopedPthreadMutexLocker locker(&gLogInitializationLock);
- event_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/events", O_CLOEXEC | O_WRONLY));
+ return -1;
}
- return TEMP_FAILURE_RETRY(writev(event_log_fd, vec, 3));
+ int result = TEMP_FAILURE_RETRY(writev(event_log_fd, vec, 3));
+ close(event_log_fd);
+ return result;
}
void __libc_android_log_event_int(int32_t tag, int value) {
diff --git a/libc/bionic/mmap.c b/libc/bionic/mmap.c
index e097086..36aee85 100644
--- a/libc/bionic/mmap.c
+++ b/libc/bionic/mmap.c
@@ -43,8 +43,9 @@
ret = __mmap2(addr, size, prot, flags, fd, (size_t)offset >> MMAP2_SHIFT);
- if (ret && (flags & (MAP_PRIVATE | MAP_ANONYMOUS)))
- madvise(ret, size, MADV_MERGEABLE);
+ if ((ret != MAP_FAILED) && (flags & (MAP_PRIVATE | MAP_ANONYMOUS))) {
+ madvise(ret, size, MADV_MERGEABLE);
+ }
return ret;
}
diff --git a/libc/bionic/statvfs.cpp b/libc/bionic/statvfs.cpp
new file mode 100644
index 0000000..5d42aaa
--- /dev/null
+++ b/libc/bionic/statvfs.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 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 <sys/statvfs.h>
+
+#include <sys/statfs.h>
+
+extern "C" int __statfs64(const char*, size_t, struct statfs*);
+extern "C" int __fstatfs64(int, size_t, struct statfs*);
+
+#define ST_VALID 0x0020
+
+#if defined(__mips__)
+#define __val val
+#endif
+
+static void __statfs_to_statvfs(const struct statfs& in, struct statvfs* out) {
+ out->f_bsize = in.f_bsize;
+ out->f_frsize = in.f_frsize;
+ out->f_blocks = in.f_blocks;
+ out->f_bfree = in.f_bfree;
+ out->f_bavail = in.f_bavail;
+ out->f_files = in.f_files;
+ out->f_ffree = in.f_ffree;
+ out->f_favail = in.f_ffree;
+ out->f_fsid = in.f_fsid.__val[0] | (static_cast<uint64_t>(in.f_fsid.__val[1]) << 32);
+ out->f_flag = in.f_flags & ~ST_VALID;
+ out->f_namemax = in.f_namelen;
+}
+
+int statvfs(const char* path, struct statvfs* result) {
+ struct statfs tmp;
+ int rc = __statfs64(path, sizeof(tmp), &tmp);
+ if (rc != 0) {
+ return rc;
+ }
+ __statfs_to_statvfs(tmp, result);
+ return 0;
+}
+
+int fstatvfs(int fd, struct statvfs* result) {
+ struct statfs tmp;
+ int rc = __fstatfs64(fd, sizeof(tmp), &tmp);
+ if (rc != 0) {
+ return rc;
+ }
+ __statfs_to_statvfs(tmp, result);
+ return 0;
+}
diff --git a/libc/bionic/system_properties.c b/libc/bionic/system_properties.c
index 800c8b8..4c2e5a2 100644
--- a/libc/bionic/system_properties.c
+++ b/libc/bionic/system_properties.c
@@ -34,6 +34,7 @@
#include <poll.h>
#include <fcntl.h>
#include <stdbool.h>
+#include <string.h>
#include <sys/mman.h>
@@ -49,29 +50,71 @@
#include <sys/_system_properties.h>
#include <sys/atomics.h>
+#include <bionic_atomic_inline.h>
+
+#define ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
struct prop_area {
- unsigned volatile count;
+ unsigned bytes_used;
unsigned volatile serial;
unsigned magic;
unsigned version;
- unsigned toc[1];
+ unsigned reserved[28];
+ char data[0];
};
typedef struct prop_area prop_area;
struct prop_info {
- char name[PROP_NAME_MAX];
unsigned volatile serial;
char value[PROP_VALUE_MAX];
+ char name[0];
};
typedef struct prop_info prop_info;
+/*
+ * Properties are stored in a hybrid trie/binary tree structure.
+ * Each property's name is delimited at '.' characters, and the tokens are put
+ * into a trie structure. Siblings at each level of the trie are stored in a
+ * binary tree. For instance, "ro.secure"="1" could be stored as follows:
+ *
+ * +-----+ children +----+ children +--------+
+ * | |-------------->| ro |-------------->| secure |
+ * +-----+ +----+ +--------+
+ * / \ / |
+ * left / \ right left / | prop +===========+
+ * v v v +-------->| ro.secure |
+ * +-----+ +-----+ +-----+ +-----------+
+ * | net | | sys | | com | | 1 |
+ * +-----+ +-----+ +-----+ +===========+
+ */
+
+typedef volatile uint32_t prop_off_t;
+struct prop_bt {
+ uint8_t namelen;
+ uint8_t reserved[3];
+
+ prop_off_t prop;
+
+ prop_off_t left;
+ prop_off_t right;
+
+ prop_off_t children;
+
+ char name[0];
+};
+
+typedef struct prop_bt prop_bt;
+
static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
static char property_filename[PATH_MAX] = PROP_FILENAME;
+static bool compat_mode = false;
-prop_area *__system_property_regions__[PA_REGION_COUNT] = { NULL, };
+prop_area *__system_property_area__ = NULL;
+
+size_t pa_data_size;
+size_t pa_size;
static int get_fd_from_env(void)
{
@@ -84,20 +127,17 @@
return atoi(env);
}
-static int map_prop_region_rw(size_t region)
+static int map_prop_area_rw()
{
prop_area *pa;
int fd;
- size_t offset = region * PA_SIZE;
-
- if (__system_property_regions__[region]) {
- return 0;
- }
+ int ret;
/* dev is a tmpfs that we can use to carve a shared workspace
* out of, so let's do that...
*/
- fd = open(property_filename, O_RDWR | O_CREAT | O_NOFOLLOW, 0644);
+ fd = open(property_filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC |
+ O_EXCL, 0444);
if (fd < 0) {
if (errno == EACCES) {
/* for consistency with the case where the process has already
@@ -108,19 +148,29 @@
return -1;
}
- if (ftruncate(fd, offset + PA_SIZE) < 0)
+ ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (ret < 0)
goto out;
- pa = mmap(NULL, PA_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
+ if (ftruncate(fd, PA_SIZE) < 0)
+ goto out;
+
+ pa_size = PA_SIZE;
+ pa_data_size = pa_size - sizeof(prop_area);
+ compat_mode = false;
+
+ pa = mmap(NULL, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(pa == MAP_FAILED)
goto out;
- memset(pa, 0, PA_SIZE);
+ memset(pa, 0, pa_size);
pa->magic = PROP_AREA_MAGIC;
pa->version = PROP_AREA_VERSION;
+ /* reserve root node */
+ pa->bytes_used = sizeof(prop_bt);
/* plug into the lib property services */
- __system_property_regions__[region] = pa;
+ __system_property_area__ = pa;
close(fd);
return 0;
@@ -142,22 +192,24 @@
int __system_property_area_init()
{
- return map_prop_region_rw(0);
+ return map_prop_area_rw();
}
-static int map_prop_region(size_t region)
+static int map_prop_area()
{
bool fromFile = true;
- bool swapped;
- size_t offset = region * PA_SIZE;
int result = -1;
+ int fd;
+ int ret;
- if(__system_property_regions__[region]) {
- return 0;
+ fd = open(property_filename, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+ if (fd >= 0) {
+ /* For old kernels that don't support O_CLOEXEC */
+ ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (ret < 0)
+ goto cleanup;
}
- int fd = open(property_filename, O_RDONLY | O_NOFOLLOW);
-
if ((fd < 0) && (errno == ENOENT)) {
/*
* For backwards compatibility, if the file doesn't
@@ -184,33 +236,32 @@
if ((fd_stat.st_uid != 0)
|| (fd_stat.st_gid != 0)
|| ((fd_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0)
- || (fd_stat.st_size < offset + PA_SIZE) ) {
+ || (fd_stat.st_size < sizeof(prop_area)) ) {
goto cleanup;
}
- prop_area *pa = mmap(NULL, PA_SIZE, PROT_READ, MAP_SHARED, fd, offset);
+ pa_size = fd_stat.st_size;
+ pa_data_size = pa_size - sizeof(prop_area);
+ prop_area *pa = mmap(NULL, pa_size, PROT_READ, MAP_SHARED, fd, 0);
if (pa == MAP_FAILED) {
goto cleanup;
}
- if((pa->magic != PROP_AREA_MAGIC) || (pa->version != PROP_AREA_VERSION)) {
- munmap(pa, PA_SIZE);
+ if((pa->magic != PROP_AREA_MAGIC) || (pa->version != PROP_AREA_VERSION &&
+ pa->version != PROP_AREA_VERSION_COMPAT)) {
+ munmap(pa, pa_size);
goto cleanup;
}
- result = 0;
- swapped = __sync_bool_compare_and_swap(&__system_property_regions__[region],
- NULL, pa);
- if (!swapped) {
- /**
- * In the event of a race either mapping is equally good, so
- * the thread that lost can just throw its mapping away and proceed as
- * normal.
- */
- munmap(pa, PA_SIZE);
+ if (pa->version == PROP_AREA_VERSION_COMPAT) {
+ compat_mode = true;
}
+ result = 0;
+
+ __system_property_area__ = pa;
+
cleanup:
if (fromFile) {
close(fd);
@@ -221,92 +272,180 @@
int __system_properties_init()
{
- return map_prop_region(0);
+ return map_prop_area();
}
-int __system_property_foreach(
- void (*propfn)(const prop_info *pi, void *cookie),
- void *cookie)
+static void *new_prop_obj(size_t size, prop_off_t *off)
{
- size_t region;
+ prop_area *pa = __system_property_area__;
+ size = ALIGN(size, sizeof(uint32_t));
- for (region = 0; region < PA_REGION_COUNT; region++) {
- prop_area *pa;
- unsigned i;
+ if (pa->bytes_used + size > pa_data_size)
+ return NULL;
- int err = map_prop_region(region);
- if (err < 0)
- break;
- pa = __system_property_regions__[region];
+ *off = pa->bytes_used;
+ __system_property_area__->bytes_used += size;
+ return __system_property_area__->data + *off;
+}
- for (i = 0; i < pa->count; i++) {
- unsigned entry = pa->toc[i];
- prop_info *pi = TOC_TO_INFO(pa, entry);
- propfn(pi, cookie);
- }
+static prop_bt *new_prop_bt(const char *name, uint8_t namelen, prop_off_t *off)
+{
+ prop_off_t off_tmp;
+ prop_bt *bt = new_prop_obj(sizeof(prop_bt) + namelen + 1, &off_tmp);
+ if (bt) {
+ memcpy(bt->name, name, namelen);
+ bt->name[namelen] = '\0';
+ bt->namelen = namelen;
+ ANDROID_MEMBAR_FULL();
+ *off = off_tmp;
}
- return 0;
+ return bt;
}
-const prop_info *__system_property_find_nth(unsigned n)
+static prop_info *new_prop_info(const char *name, uint8_t namelen,
+ const char *value, uint8_t valuelen, prop_off_t *off)
{
- size_t region = n / PA_COUNT_MAX;
- prop_area *pa;
+ prop_off_t off_tmp;
+ prop_info *info = new_prop_obj(sizeof(prop_info) + namelen + 1, &off_tmp);
+ if (info) {
+ memcpy(info->name, name, namelen);
+ info->name[namelen] = '\0';
+ info->serial = (valuelen << 24);
+ memcpy(info->value, value, valuelen);
+ info->value[valuelen] = '\0';
+ ANDROID_MEMBAR_FULL();
+ *off = off_tmp;
+ }
- int err = map_prop_region(region);
- if (err < 0)
+ return info;
+}
+
+static void *to_prop_obj(prop_off_t off)
+{
+ if (off > pa_data_size)
return NULL;
- pa = __system_property_regions__[region];
- if((n % PA_COUNT_MAX) >= pa->count) {
- return 0;
+ return __system_property_area__->data + off;
+}
+
+static prop_bt *root_node()
+{
+ return to_prop_obj(0);
+}
+
+static int cmp_prop_name(const char *one, uint8_t one_len, const char *two,
+ uint8_t two_len)
+{
+ if (one_len < two_len)
+ return -1;
+ else if (one_len > two_len)
+ return 1;
+ else
+ return strncmp(one, two, one_len);
+}
+
+static prop_bt *find_prop_bt(prop_bt *bt, const char *name, uint8_t namelen,
+ bool alloc_if_needed)
+{
+ while (true) {
+ int ret;
+ if (!bt)
+ return bt;
+ ret = cmp_prop_name(name, namelen, bt->name, bt->namelen);
+
+ if (ret == 0) {
+ return bt;
+ } else if (ret < 0) {
+ if (bt->left) {
+ bt = to_prop_obj(bt->left);
+ } else {
+ if (!alloc_if_needed)
+ return NULL;
+
+ bt = new_prop_bt(name, namelen, &bt->left);
+ }
+ } else {
+ if (bt->right) {
+ bt = to_prop_obj(bt->right);
+ } else {
+ if (!alloc_if_needed)
+ return NULL;
+
+ bt = new_prop_bt(name, namelen, &bt->right);
+ }
+ }
+ }
+}
+
+static const prop_info *find_property(prop_bt *trie, const char *name,
+ uint8_t namelen, const char *value, uint8_t valuelen,
+ bool alloc_if_needed)
+{
+ const char *remaining_name = name;
+
+ while (true) {
+ char *sep = strchr(remaining_name, '.');
+ bool want_subtree = (sep != NULL);
+ uint8_t substr_size;
+
+ prop_bt *root;
+
+ if (want_subtree) {
+ substr_size = sep - remaining_name;
+ } else {
+ substr_size = strlen(remaining_name);
+ }
+
+ if (!substr_size)
+ return NULL;
+
+ if (trie->children) {
+ root = to_prop_obj(trie->children);
+ } else if (alloc_if_needed) {
+ root = new_prop_bt(remaining_name, substr_size, &trie->children);
+ } else {
+ root = NULL;
+ }
+
+ if (!root)
+ return NULL;
+
+ trie = find_prop_bt(root, remaining_name, substr_size, alloc_if_needed);
+ if (!trie)
+ return NULL;
+
+ if (!want_subtree)
+ break;
+
+ remaining_name = sep + 1;
+ }
+
+ if (trie->prop) {
+ return to_prop_obj(trie->prop);
+ } else if (alloc_if_needed) {
+ return new_prop_info(name, namelen, value, valuelen, &trie->prop);
} else {
- return TOC_TO_INFO(pa, pa->toc[n]);
+ return NULL;
}
}
const prop_info *__system_property_find(const char *name)
{
- unsigned len = strlen(name);
- size_t region;
-
- if (len >= PROP_NAME_MAX)
- return 0;
- if (len < 1)
- return 0;
-
- for (region = 0; region < PA_REGION_COUNT; region++) {
- prop_area *pa;
- unsigned count;
- unsigned *toc;
- prop_info *pi;
-
- int err = map_prop_region(region);
- if (err < 0)
- return 0;
- pa = __system_property_regions__[region];
- count = pa->count;
- toc = pa->toc;
-
- while(count--) {
- unsigned entry = *toc++;
- if(TOC_NAME_LEN(entry) != len) continue;
-
- pi = TOC_TO_INFO(pa, entry);
- if(memcmp(name, pi->name, len)) continue;
-
- return pi;
- }
+ if (__predict_false(compat_mode)) {
+ return __system_property_find_compat(name);
}
-
- return 0;
+ return find_property(root_node(), name, strlen(name), NULL, 0, false);
}
int __system_property_read(const prop_info *pi, char *name, char *value)
{
unsigned serial, len;
+ if (__predict_false(compat_mode)) {
+ return __system_property_read_compat(pi, name, value);
+ }
+
for(;;) {
serial = pi->serial;
while(SERIAL_DIRTY(serial)) {
@@ -315,6 +454,7 @@
}
len = SERIAL_VALUE_LEN(serial);
memcpy(value, pi->value, len + 1);
+ ANDROID_MEMBAR_FULL();
if(serial == pi->serial) {
if(name != 0) {
strcpy(name, pi->name);
@@ -424,7 +564,7 @@
{
unsigned n;
if(pi == 0) {
- prop_area *pa = __system_property_regions__[0];
+ prop_area *pa = __system_property_area__;
n = pa->serial;
do {
__futex_wait(&pa->serial, n, 0);
@@ -440,13 +580,15 @@
int __system_property_update(prop_info *pi, const char *value, unsigned int len)
{
- prop_area *pa = __system_property_regions__[0];
+ prop_area *pa = __system_property_area__;
if (len >= PROP_VALUE_MAX)
return -1;
pi->serial = pi->serial | 1;
+ ANDROID_MEMBAR_FULL();
memcpy(pi->value, value, len + 1);
+ ANDROID_MEMBAR_FULL();
pi->serial = (len << 24) | ((pi->serial + 1) & 0xffffff);
__futex_wake(&pi->serial, INT32_MAX);
@@ -459,10 +601,8 @@
int __system_property_add(const char *name, unsigned int namelen,
const char *value, unsigned int valuelen)
{
- prop_area *pa;
- prop_info *pa_info_array;
- prop_info *pi;
- size_t region;
+ prop_area *pa = __system_property_area__;
+ const prop_info *pi;
if (namelen >= PROP_NAME_MAX)
return -1;
@@ -471,33 +611,12 @@
if (namelen < 1)
return -1;
- for (region = 0; region < PA_REGION_COUNT; region++)
- {
- int err = map_prop_region_rw(region);
- if (err < 0)
- return -1;
-
- pa = __system_property_regions__[region];
-
- if (pa->count < PA_COUNT_MAX)
- break;
- }
-
- if (region == PA_REGION_COUNT)
+ pi = find_property(root_node(), name, namelen, value, valuelen, true);
+ if (!pi)
return -1;
- pa_info_array = (void*) (((char*) pa) + PA_INFO_START);
- pi = pa_info_array + pa->count;
- pi->serial = (valuelen << 24);
- memcpy(pi->name, name, namelen + 1);
- memcpy(pi->value, value, valuelen + 1);
-
- pa->toc[pa->count] = (namelen << 24) | (((unsigned) pi) - ((unsigned) pa));
-
- pa->count++;
pa->serial++;
__futex_wake(&pa->serial, INT32_MAX);
-
return 0;
}
@@ -508,7 +627,7 @@
unsigned int __system_property_wait_any(unsigned int serial)
{
- prop_area *pa = __system_property_regions__[0];
+ prop_area *pa = __system_property_area__;
do {
__futex_wait(&pa->serial, serial, 0);
@@ -516,3 +635,75 @@
return pa->serial;
}
+
+struct find_nth_cookie {
+ unsigned count;
+ unsigned n;
+ const prop_info *pi;
+};
+
+static void find_nth_fn(const prop_info *pi, void *ptr)
+{
+ struct find_nth_cookie *cookie = ptr;
+
+ if (cookie->n == cookie->count)
+ cookie->pi = pi;
+
+ cookie->count++;
+}
+
+const prop_info *__system_property_find_nth(unsigned n)
+{
+ struct find_nth_cookie cookie;
+ int err;
+
+ memset(&cookie, 0, sizeof(cookie));
+ cookie.n = n;
+
+ err = __system_property_foreach(find_nth_fn, &cookie);
+ if (err < 0)
+ return NULL;
+
+ return cookie.pi;
+}
+
+static int foreach_property(prop_off_t off,
+ void (*propfn)(const prop_info *pi, void *cookie), void *cookie)
+{
+ prop_bt *trie = to_prop_obj(off);
+ if (!trie)
+ return -1;
+
+ if (trie->left) {
+ int err = foreach_property(trie->left, propfn, cookie);
+ if (err < 0)
+ return -1;
+ }
+ if (trie->prop) {
+ prop_info *info = to_prop_obj(trie->prop);
+ if (!info)
+ return -1;
+ propfn(info, cookie);
+ }
+ if (trie->children) {
+ int err = foreach_property(trie->children, propfn, cookie);
+ if (err < 0)
+ return -1;
+ }
+ if (trie->right) {
+ int err = foreach_property(trie->right, propfn, cookie);
+ if (err < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+int __system_property_foreach(void (*propfn)(const prop_info *pi, void *cookie),
+ void *cookie)
+{
+ if (__predict_false(compat_mode)) {
+ return __system_property_foreach_compat(propfn, cookie);
+ }
+ return foreach_property(0, propfn, cookie);
+}
diff --git a/libc/bionic/system_properties_compat.c b/libc/bionic/system_properties_compat.c
new file mode 100644
index 0000000..6dbc4cc
--- /dev/null
+++ b/libc/bionic/system_properties_compat.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This file is only used to provide backwards compatibility to property areas
+ * created by old versions of init, which occurs when an ota runs. The updater
+ * binary is compiled statically against the newest bionic, but the recovery
+ * ramdisk may be using an old version of init. This can all be removed once
+ * OTAs from pre-K versions are no longer supported.
+ */
+
+#include <string.h>
+#include <sys/atomics.h>
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+#define TOC_NAME_LEN(toc) ((toc) >> 24)
+#define TOC_TO_INFO(area, toc) ((prop_info_compat*) (((char*) area) + ((toc) & 0xFFFFFF)))
+
+struct prop_area_compat {
+ unsigned volatile count;
+ unsigned volatile serial;
+ unsigned magic;
+ unsigned version;
+ unsigned toc[1];
+};
+
+typedef struct prop_area_compat prop_area_compat;
+
+struct prop_area;
+typedef struct prop_area prop_area;
+
+struct prop_info_compat {
+ char name[PROP_NAME_MAX];
+ unsigned volatile serial;
+ char value[PROP_VALUE_MAX];
+};
+
+typedef struct prop_info_compat prop_info_compat;
+
+extern prop_area *__system_property_area__;
+
+const prop_info *__system_property_find_compat(const char *name)
+{
+ prop_area_compat *pa = (prop_area_compat *)__system_property_area__;
+ unsigned count = pa->count;
+ unsigned *toc = pa->toc;
+ unsigned len = strlen(name);
+ prop_info_compat *pi;
+
+ if (len >= PROP_NAME_MAX)
+ return 0;
+ if (len < 1)
+ return 0;
+
+ while(count--) {
+ unsigned entry = *toc++;
+ if(TOC_NAME_LEN(entry) != len) continue;
+
+ pi = TOC_TO_INFO(pa, entry);
+ if(memcmp(name, pi->name, len)) continue;
+
+ return (const prop_info *)pi;
+ }
+
+ return 0;
+}
+
+int __system_property_read_compat(const prop_info *_pi, char *name, char *value)
+{
+ unsigned serial, len;
+ const prop_info_compat *pi = (const prop_info_compat *)_pi;
+
+ for(;;) {
+ serial = pi->serial;
+ while(SERIAL_DIRTY(serial)) {
+ __futex_wait((volatile void *)&pi->serial, serial, 0);
+ serial = pi->serial;
+ }
+ len = SERIAL_VALUE_LEN(serial);
+ memcpy(value, pi->value, len + 1);
+ if(serial == pi->serial) {
+ if(name != 0) {
+ strcpy(name, pi->name);
+ }
+ return len;
+ }
+ }
+}
+
+int __system_property_foreach_compat(
+ void (*propfn)(const prop_info *pi, void *cookie),
+ void *cookie)
+{
+ prop_area_compat *pa = (prop_area_compat *)__system_property_area__;
+ unsigned i;
+
+ for (i = 0; i < pa->count; i++) {
+ unsigned entry = pa->toc[i];
+ prop_info_compat *pi = TOC_TO_INFO(pa, entry);
+ propfn((const prop_info *)pi, cookie);
+ }
+
+ return 0;
+}
diff --git a/libc/include/getopt.h b/libc/include/getopt.h
index 56f1983..4451941 100644
--- a/libc/include/getopt.h
+++ b/libc/include/getopt.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: getopt.h,v 1.1 2002/12/03 20:24:29 millert Exp $ */
/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */
+/* $FreeBSD$ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -16,13 +16,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -43,7 +36,8 @@
#include <sys/cdefs.h>
/*
- * GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions
+ * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension.
+ * getopt() is declared here too for GNU programs.
*/
#define no_argument 0
#define required_argument 1
@@ -64,26 +58,20 @@
};
__BEGIN_DECLS
-int getopt_long(int, char * const *, const char *,
- const struct option *, int *);
-int getopt_long_only(int, char * const *, const char *,
- const struct option *, int *);
-#ifndef _GETOPT_DEFINED_
-#define _GETOPT_DEFINED_
-int getopt(int, char * const *, const char *);
+int getopt_long(int, char * const *, const char *,
+ const struct option *, int *);
+int getopt_long_only(int, char * const *, const char *,
+ const struct option *, int *);
+#ifndef _GETOPT_DECLARED
+#define _GETOPT_DECLARED
+int getopt(int, char * const [], const char *);
-
-extern char *optarg; /* getopt(3) external variables */
-extern int opterr;
-extern int optind;
-extern int optopt;
-extern int optreset;
-
-#if 0 /* MISSING FROM BIONIC */
-int getsubopt(char **, char * const *, char **);
-extern char *suboptarg; /* getsubopt(3) external variable */
-#endif /* MISSING */
-
+extern char *optarg; /* getopt(3) external variables */
+extern int optind, opterr, optopt;
+#endif
+#ifndef _OPTRESET_DECLARED
+#define _OPTRESET_DECLARED
+extern int optreset; /* getopt(3) external variable */
#endif
__END_DECLS
diff --git a/libc/include/inttypes.h b/libc/include/inttypes.h
index 81d2315..73b22db 100644
--- a/libc/include/inttypes.h
+++ b/libc/include/inttypes.h
@@ -56,7 +56,7 @@
#define PRIdFAST64 "lld" /* int_fast64_t */
#define PRIdMAX "jd" /* intmax_t */
-#define PRIdPTR "ld" /* intptr_t */
+#define PRIdPTR "d" /* intptr_t */
#define PRIi8 "i" /* int8_t */
#define PRIi16 "i" /* int16_t */
@@ -74,7 +74,7 @@
#define PRIiFAST64 "lli" /* int_fast64_t */
#define PRIiMAX "ji" /* intmax_t */
-#define PRIiPTR "li" /* intptr_t */
+#define PRIiPTR "i" /* intptr_t */
/* fprintf macros for unsigned integers */
#define PRIo8 "o" /* int8_t */
@@ -93,7 +93,7 @@
#define PRIoFAST64 "llo" /* int_fast64_t */
#define PRIoMAX "jo" /* intmax_t */
-#define PRIoPTR "lo" /* intptr_t */
+#define PRIoPTR "o" /* intptr_t */
#define PRIu8 "u" /* uint8_t */
#define PRIu16 "u" /* uint16_t */
@@ -111,7 +111,7 @@
#define PRIuFAST64 "llu" /* uint_fast64_t */
#define PRIuMAX "ju" /* uintmax_t */
-#define PRIuPTR "lu" /* uintptr_t */
+#define PRIuPTR "u" /* uintptr_t */
#define PRIx8 "x" /* uint8_t */
#define PRIx16 "x" /* uint16_t */
@@ -129,7 +129,7 @@
#define PRIxFAST64 "llx" /* uint_fast64_t */
#define PRIxMAX "jx" /* uintmax_t */
-#define PRIxPTR "lx" /* uintptr_t */
+#define PRIxPTR "x" /* uintptr_t */
#define PRIX8 "X" /* uint8_t */
#define PRIX16 "X" /* uint16_t */
@@ -147,7 +147,7 @@
#define PRIXFAST64 "llX" /* uint_fast64_t */
#define PRIXMAX "jX" /* uintmax_t */
-#define PRIXPTR "lX" /* uintptr_t */
+#define PRIXPTR "X" /* uintptr_t */
/* fscanf macros for signed integers */
#define SCNd8 "hhd" /* int8_t */
@@ -166,7 +166,7 @@
#define SCNdFAST64 "lld" /* int_fast64_t */
#define SCNdMAX "jd" /* intmax_t */
-#define SCNdPTR "ld" /* intptr_t */
+#define SCNdPTR "d" /* intptr_t */
#define SCNi8 "hhi" /* int8_t */
#define SCNi16 "hi" /* int16_t */
@@ -184,7 +184,7 @@
#define SCNiFAST64 "lli" /* int_fast64_t */
#define SCNiMAX "ji" /* intmax_t */
-#define SCNiPTR "li" /* intptr_t */
+#define SCNiPTR "i" /* intptr_t */
/* fscanf macros for unsigned integers */
#define SCNo8 "hho" /* uint8_t */
@@ -203,7 +203,7 @@
#define SCNoFAST64 "llo" /* uint_fast64_t */
#define SCNoMAX "jo" /* uintmax_t */
-#define SCNoPTR "lo" /* uintptr_t */
+#define SCNoPTR "o" /* uintptr_t */
#define SCNu8 "hhu" /* uint8_t */
#define SCNu16 "hu" /* uint16_t */
@@ -221,7 +221,7 @@
#define SCNuFAST64 "llu" /* uint_fast64_t */
#define SCNuMAX "ju" /* uintmax_t */
-#define SCNuPTR "lu" /* uintptr_t */
+#define SCNuPTR "u" /* uintptr_t */
#define SCNx8 "hhx" /* uint8_t */
#define SCNx16 "hx" /* uint16_t */
@@ -239,7 +239,7 @@
#define SCNxFAST64 "llx" /* uint_fast64_t */
#define SCNxMAX "jx" /* uintmax_t */
-#define SCNxPTR "lx" /* uintptr_t */
+#define SCNxPTR "x" /* uintptr_t */
#endif /* __cplusplus || __STDC_FORMAT_MACROS */
diff --git a/libc/include/netinet/icmp6.h b/libc/include/netinet/icmp6.h
index fbc8234..6625712 100644
--- a/libc/include/netinet/icmp6.h
+++ b/libc/include/netinet/icmp6.h
@@ -1,4 +1,4 @@
-/* $NetBSD: icmp6.h,v 1.40 2009/10/31 22:32:17 christos Exp $ */
+/* $NetBSD: icmp6.h,v 1.47 2013/07/01 12:43:15 christos Exp $ */
/* $KAME: icmp6.h,v 1.84 2003/04/23 10:26:51 itojun Exp $ */
@@ -65,6 +65,8 @@
#ifndef _NETINET_ICMP6_H_
#define _NETINET_ICMP6_H_
+#include <netinet/in.h> /* android-added: glibc source compatibility. */
+
#define ICMPV6_PLD_MAXLEN 1232 /* IPV6_MMTU - sizeof(struct ip6_hdr)
- sizeof(struct icmp6_hdr) */
@@ -98,6 +100,7 @@
#define MLD_LISTENER_QUERY 130 /* multicast listener query */
#define MLD_LISTENER_REPORT 131 /* multicast listener report */
#define MLD_LISTENER_DONE 132 /* multicast listener done */
+#define MLD_LISTENER_REDUCTION MLD_LISTENER_DONE /* RFC3542 definition */
/* RFC2292 decls */
#define ICMP6_MEMBERSHIP_QUERY 130 /* group membership query */
@@ -125,6 +128,7 @@
#define ICMP6_FQDN_REPLY 140 /* FQDN reply */
#define ICMP6_NI_QUERY 139 /* node information request */
#define ICMP6_NI_REPLY 140 /* node information reply */
+#define MLDV2_LISTENER_REPORT 143 /* RFC3810 listener report */
/* The definitions below are experimental. TBA */
#define MLD_MTRACE_RESP 200 /* mtrace response(to sender) */
@@ -144,6 +148,9 @@
#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */
#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
#define ICMP6_DST_UNREACH_NOPORT 4 /* port unreachable */
+#define ICMP6_DST_UNREACH_POLICY 5 /* source address failed ingress/egress policy */
+#define ICMP6_DST_UNREACH_REJROUTE 6 /* reject route to destination */
+#define ICMP6_DST_UNREACH_SOURCERT 7 /* error in source routing header */
#define ICMP6_TIME_EXCEED_TRANSIT 0 /* ttl==0 in transit */
#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* ttl==0 in reass */
@@ -229,7 +236,7 @@
#define ND_RA_FLAG_HOME_AGENT 0x20
/*
- * Router preference values based on RFC4199.
+ * Router preference values based on RFC4191.
*/
#define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */
@@ -300,11 +307,10 @@
#define ND_OPT_HOMEAGENT_INFO 8
#define ND_OPT_SOURCE_ADDRLIST 9
#define ND_OPT_TARGET_ADDRLIST 10
-#define ND_OPT_RDNSS 25
-/* draft-ietf-ipngwg-router-preference, not officially assigned yet */
-#define ND_OPT_ROUTE_INFO 200
-/* draft-ietf-mobileip-hmipv6, not officially assigned yet */
-#define ND_OPT_MAP 201
+#define ND_OPT_MAP 23 /* RFC 5380 */
+#define ND_OPT_ROUTE_INFO 24 /* RFC 4191 */
+#define ND_OPT_RDNSS 25 /* RFC 6016 */
+#define ND_OPT_DNSSL 31 /* RFC 6016 */
struct nd_opt_route_info { /* route info */
u_int8_t nd_opt_rti_type;
@@ -344,7 +350,7 @@
u_int32_t nd_opt_mtu_mtu;
} __packed;
-struct nd_opt_rdnss { /* RDNSS option RFC 5006 */
+struct nd_opt_rdnss { /* RDNSS option RFC 6106 */
u_int8_t nd_opt_rdnss_type;
u_int8_t nd_opt_rdnss_len;
u_int16_t nd_opt_rdnss_reserved;
@@ -352,6 +358,14 @@
/* followed by list of IP prefixes */
} __packed;
+struct nd_opt_dnssl { /* DNSSL option RFC 6106 */
+ u_int8_t nd_opt_dnssl_type;
+ u_int8_t nd_opt_dnssl_len;
+ u_int16_t nd_opt_dnssl_reserved;
+ u_int32_t nd_opt_dnssl_lifetime;
+ /* followed by list of IP prefixes */
+} __packed;
+
/*
* icmp6 namelookup
*/
@@ -376,11 +390,15 @@
/* could be followed by reply data */
} __packed;
+/*
+ * BEGIN android-removed: glibc doesn't have these, and external/ping declares them itself.
#define ni_type icmp6_ni_hdr.icmp6_type
#define ni_code icmp6_ni_hdr.icmp6_code
#define ni_cksum icmp6_ni_hdr.icmp6_cksum
#define ni_qtype icmp6_ni_hdr.icmp6_data16[0]
#define ni_flags icmp6_ni_hdr.icmp6_data16[1]
+ * END android-removed
+ */
#define NI_QTYPE_NOOP 0 /* NOOP */
#define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes */
@@ -521,18 +539,28 @@
u_int32_t icmp6_filt[8];
};
+/*
+ * BEGIN android-changed
+ * Linux and *BSD kernels use opposite values to indicate pass/block in ICMPv6
+ * filters, and assign a different value to the ICMP6_FILTER sockopt.
+ */
+#define ICMP6_FILTER 1
+
#define ICMP6_FILTER_SETPASSALL(filterp) \
- (void)memset(filterp, 0xff, sizeof(struct icmp6_filter))
-#define ICMP6_FILTER_SETBLOCKALL(filterp) \
(void)memset(filterp, 0x00, sizeof(struct icmp6_filter))
+#define ICMP6_FILTER_SETBLOCKALL(filterp) \
+ (void)memset(filterp, 0xff, sizeof(struct icmp6_filter))
#define ICMP6_FILTER_SETPASS(type, filterp) \
- (((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31)))
-#define ICMP6_FILTER_SETBLOCK(type, filterp) \
(((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31)))
+#define ICMP6_FILTER_SETBLOCK(type, filterp) \
+ (((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31)))
#define ICMP6_FILTER_WILLPASS(type, filterp) \
- ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
-#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
+#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
+ ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
+/*
+ * END android-changed
+ */
/*
* Variables related to this implementation
@@ -569,8 +597,9 @@
#define ICMP6_STAT_BADRS 538 /* bad router solicitiation */
#define ICMP6_STAT_BADRA 539 /* bad router advertisement */
#define ICMP6_STAT_BADREDIRECT 540 /* bad redirect message */
+#define ICMP6_STAT_DROPPED_RAROUTE 541 /* discarded routes from router advertisement */
-#define ICMP6_NSTATS 541
+#define ICMP6_NSTATS 542
#define ICMP6_ERRSTAT_DST_UNREACH_NOROUTE 0
#define ICMP6_ERRSTAT_DST_UNREACH_ADMIN 1
@@ -640,8 +669,6 @@
{ "nd6_maxqueuelen", CTLTYPE_INT }, \
}
-#define RTF_PROBEMTU RTF_PROTO1
-
#ifdef _KERNEL
struct rtentry;
struct rttimer;
@@ -727,4 +754,41 @@
extern int icmp6_redirtimeout; /* cache time for redirect routes */
#endif /* _KERNEL */
+#ifdef ICMP6_STRINGS
+/* Info: http://www.iana.org/assignments/icmpv6-parameters */
+
+static const char * const icmp6_type_err[] = {
+ "reserved0", "unreach", "packet_too_big", "timxceed", "paramprob",
+ NULL
+};
+
+static const char * const icmp6_type_info[] = {
+ "echo", "echoreply",
+ "mcastlistenq", "mcastlistenrep", "mcastlistendone",
+ "rtsol", "rtadv", "neighsol", "neighadv", "redirect",
+ "routerrenum", "nodeinfoq", "nodeinfor", "invneighsol", "invneighrep",
+ "mcastlistenrep2", "haad_req", "haad_rep",
+ "mobile_psol", "mobile_padv", "cga_sol", "cga_adv",
+ "experimental150", "mcast_rtadv", "mcast_rtsol", "mcast_rtterm",
+ "fmipv6_msg", "rpl_control", NULL
+};
+
+static const char * const icmp6_code_none[] = { "none", NULL };
+
+static const char * const icmp6_code_unreach[] = {
+ "noroute", "admin", "beyondscope", "addr", "port",
+ "srcaddr_policy", "reject_route", "source_route_err", NULL
+};
+
+static const char * const icmp6_code_timxceed[] = {
+ "intrans", "reass", NULL
+};
+
+static const char * const icmp6_code_paramprob[] = {
+ "hdr_field", "nxthdr_type", "option", NULL
+};
+
+/* not all informational icmps that have codes have a names array */
+#endif
+
#endif /* !_NETINET_ICMP6_H_ */
diff --git a/libc/include/resolv.h b/libc/include/resolv.h
index 7c34012..36b93ee 100644
--- a/libc/include/resolv.h
+++ b/libc/include/resolv.h
@@ -43,12 +43,14 @@
extern struct __res_state *__res_state(void);
#define _res (*__res_state())
-/* Base-64 functions - because some code expects it there */
+#define b64_ntop __b64_ntop
+#define b64_pton __b64_pton
+extern int b64_ntop(u_char const*, size_t, char*, size_t);
+extern int b64_pton(char const*, u_char*, size_t);
-#define b64_ntop __b64_ntop
-#define b64_pton __b64_pton
-extern int b64_ntop(u_char const *, size_t, char *, size_t);
-extern int b64_pton(char const *, u_char *, size_t);
+#define dn_comp __dn_comp
+extern int dn_comp(const char*, u_char*, int, u_char**, u_char**);
+extern int dn_expand(const u_char*, const u_char*, const u_char*, char*, int);
__END_DECLS
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 511bcd2..23fc944 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -450,7 +450,7 @@
__END_DECLS
#endif /* _GNU_SOURCE */
-#if defined(__BIONIC_FORTIFY) && !defined(__clang__)
+#if defined(__BIONIC_FORTIFY)
__BEGIN_DECLS
@@ -468,14 +468,21 @@
return __builtin___vsprintf_chk(dest, 0, __bos(dest), format, ap);
}
+#if defined(__clang__)
+#define snprintf(dest, size, ...) __builtin___snprintf_chk(dest, size, 0, __bos(dest), __VA_ARGS__)
+#else
__BIONIC_FORTIFY_INLINE
__printflike(3, 4)
-int snprintf(char *str, size_t size, const char *format, ...)
+int snprintf(char *dest, size_t size, const char *format, ...)
{
- return __builtin___snprintf_chk(str, size, 0,
- __bos(str), format, __builtin_va_arg_pack());
+ return __builtin___snprintf_chk(dest, size, 0,
+ __bos(dest), format, __builtin_va_arg_pack());
}
+#endif
+#if defined(__clang__)
+#define sprintf(dest, ...) __builtin___sprintf_chk(dest, 0, __bos(dest), __VA_ARGS__)
+#else
__BIONIC_FORTIFY_INLINE
__printflike(2, 3)
int sprintf(char *dest, const char *format, ...)
@@ -483,7 +490,9 @@
return __builtin___sprintf_chk(dest, 0,
__bos(dest), format, __builtin_va_arg_pack());
}
+#endif
+#if !defined(__clang__)
extern char *__fgets_real(char *, int, FILE *)
__asm__(__USER_LABEL_PREFIX__ "fgets");
__errordecl(__fgets_too_big_error, "fgets called with size bigger than buffer");
@@ -521,8 +530,10 @@
return __fgets_chk(dest, size, stream, bos);
}
+#endif /* !defined(__clang__) */
+
__END_DECLS
-#endif /* defined(__BIONIC_FORTIFY) && !defined(__clang__) */
+#endif /* defined(__BIONIC_FORTIFY) */
#endif /* _STDIO_H_ */
diff --git a/libc/include/string.h b/libc/include/string.h
index 2b7d47c..7801ee9 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -175,7 +175,6 @@
return __strlcpy_chk(dest, src, size, bos);
}
-#if !defined(__clang__)
extern size_t __strlcat_real(char* __restrict, const char* __restrict, size_t)
__asm__(__USER_LABEL_PREFIX__ "strlcat");
__errordecl(__strlcat_error, "strlcat called with size bigger than buffer");
@@ -186,6 +185,7 @@
size_t strlcat(char* __restrict dest, const char* __restrict src, size_t size) {
size_t bos = __bos(dest);
+#if !defined(__clang__)
// Compiler doesn't know destination size. Don't call __strlcat_chk
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
return __strlcat_real(dest, src, size);
@@ -202,10 +202,10 @@
if (__builtin_constant_p(size) && (size > bos)) {
__strlcat_error();
}
+#endif /* !defined(__clang__) */
return __strlcat_chk(dest, src, size, bos);
}
-#endif /* !defined(__clang__) */
__BIONIC_FORTIFY_INLINE
size_t strlen(const char *s) {
diff --git a/libc/include/strings.h b/libc/include/strings.h
index faa12a4..e72798b 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -50,12 +50,12 @@
int strcasecmp(const char *, const char *);
int strncasecmp(const char *, const char *, size_t);
-#if defined(__BIONIC_FORTIFY) && !defined(__clang__)
+#if defined(__BIONIC_FORTIFY)
__BIONIC_FORTIFY_INLINE
void bzero (void *s, size_t n) {
__builtin___memset_chk(s, '\0', n, __builtin_object_size (s, 0));
}
-#endif /* defined(__BIONIC_FORTIFY) && !defined(__clang__) */
+#endif /* defined(__BIONIC_FORTIFY) */
__END_DECLS
diff --git a/libc/include/sys/_system_properties.h b/libc/include/sys/_system_properties.h
index 4971a4c..5eee7f0 100644
--- a/libc/include/sys/_system_properties.h
+++ b/libc/include/sys/_system_properties.h
@@ -37,21 +37,13 @@
typedef struct prop_msg prop_msg;
#define PROP_AREA_MAGIC 0x504f5250
-#define PROP_AREA_VERSION 0x45434f76
+#define PROP_AREA_VERSION 0xfc6ed0ab
+#define PROP_AREA_VERSION_COMPAT 0x45434f76
#define PROP_SERVICE_NAME "property_service"
#define PROP_FILENAME "/dev/__properties__"
-/* (4 header words + 28 toc words) = 128 bytes */
-/* 128 bytes header and toc + 28 prop_infos @ 128 bytes = 3712 bytes */
-
-#define PA_COUNT_MAX 28
-#define PA_REGION_COUNT 128
-#define PA_INFO_START 128
-#define PA_SIZE 4096
-
-#define TOC_NAME_LEN(toc) ((toc) >> 24)
-#define TOC_TO_INFO(area, toc) ((prop_info*) (((char*) area) + ((toc) & 0xFFFFFF)))
+#define PA_SIZE (128 * 1024)
#define SERIAL_VALUE_LEN(serial) ((serial) >> 24)
#define SERIAL_DIRTY(serial) ((serial) & 1)
@@ -84,11 +76,6 @@
** 1. pi->serial = pi->serial | 1
** 2. memcpy(pi->value, local_value, value_len)
** 3. pi->serial = (value_len << 24) | ((pi->serial + 1) & 0xffffff)
-**
-** Improvements:
-** - maintain the toc sorted by pi->name to allow lookup
-** by binary search
-**
*/
#define PROP_PATH_RAMDISK_DEFAULT "/default.prop"
@@ -143,6 +130,15 @@
** successive call. */
unsigned int __system_property_wait_any(unsigned int serial);
+/* Compatibility functions to support using an old init with a new libc,
+ ** mostly for the OTA updater binary. These can be deleted once OTAs from
+ ** a pre-K release no longer needed to be supported. */
+const prop_info *__system_property_find_compat(const char *name);
+int __system_property_read_compat(const prop_info *pi, char *name, char *value);
+int __system_property_foreach_compat(
+ void (*propfn)(const prop_info *pi, void *cookie),
+ void *cookie);
+
__END_DECLS
#endif
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index c7fb9de..a4c1aff 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -211,8 +211,10 @@
#define __statement(x) (x)
#endif
-#define __printflike(x, y) __attribute__((__format__(printf, x, y))) __attribute__((__nonnull__(x)))
-#define __scanflike(x, y) __attribute__((__format__(scanf, x, y))) __attribute__((__nonnull__(x)))
+#define __nonnull(args) __attribute__((__nonnull__ args))
+
+#define __printflike(x, y) __attribute__((__format__(printf, x, y))) __nonnull((x))
+#define __scanflike(x, y) __attribute__((__format__(scanf, x, y))) __nonnull((x))
/*
* C99 defines the restrict type qualifier keyword, which was made available
diff --git a/libc/include/sys/ioctl.h b/libc/include/sys/ioctl.h
index 9f68510..49d452c 100644
--- a/libc/include/sys/ioctl.h
+++ b/libc/include/sys/ioctl.h
@@ -30,6 +30,11 @@
#include <sys/cdefs.h>
#include <linux/ioctl.h>
+/*
+ * NetBSD and glibc's <sys/ioctl.h> provide some of the
+ * terminal-related ioctl data structures such as struct winsize.
+ */
+#include <linux/termios.h>
#include <asm/ioctls.h>
#include <asm/termbits.h>
#include <sys/ioctl_compat.h>
diff --git a/libc/include/sys/mount.h b/libc/include/sys/mount.h
index 207527e..3c35d31 100644
--- a/libc/include/sys/mount.h
+++ b/libc/include/sys/mount.h
@@ -30,75 +30,18 @@
#include <sys/cdefs.h>
#include <sys/ioctl.h>
+#include <linux/fs.h>
__BEGIN_DECLS
-/*
- * These are the fs-independent mount-flags: up to 32 flags are supported
- */
-#define MS_RDONLY 1 /* Mount read-only */
-#define MS_NOSUID 2 /* Ignore suid and sgid bits */
-#define MS_NODEV 4 /* Disallow access to device special files */
-#define MS_NOEXEC 8 /* Disallow program execution */
-#define MS_SYNCHRONOUS 16 /* Writes are synced at once */
-#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
-#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
-#define MS_DIRSYNC 128 /* Directory modifications are synchronous */
-#define MS_NOATIME 1024 /* Do not update access times. */
-#define MS_NODIRATIME 2048 /* Do not update directory access times */
-#define MS_BIND 4096
-#define MS_MOVE 8192
-#define MS_REC 16384
-#define MS_VERBOSE 32768
-#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */
-#define MS_UNBINDABLE (1<<17) /* change to unbindable */
-#define MS_PRIVATE (1<<18) /* change to private */
-#define MS_SLAVE (1<<19) /* change to slave */
-#define MS_SHARED (1<<20) /* change to shared */
-#define MS_ACTIVE (1<<30)
-#define MS_NOUSER (1<<31)
-
-/*
- * Superblock flags that can be altered by MS_REMOUNT
- */
-#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|MS_NODIRATIME)
-
-/*
- * Old magic mount flag and mask
- */
-#define MS_MGC_VAL 0xC0ED0000
-#define MS_MGC_MSK 0xffff0000
-
-/*
- * umount2() flags
- */
+/* umount2 flags. */
#define MNT_FORCE 1 /* Forcibly unmount */
#define MNT_DETACH 2 /* Detach from tree only */
#define MNT_EXPIRE 4 /* Mark for expiry */
-/*
- * Block device ioctls
- */
-#define BLKROSET _IO(0x12, 93) /* Set device read-only (0 = read-write). */
-#define BLKROGET _IO(0x12, 94) /* Get read-only status (0 = read_write). */
-#define BLKRRPART _IO(0x12, 95) /* Re-read partition table. */
-#define BLKGETSIZE _IO(0x12, 96) /* Return device size. */
-#define BLKFLSBUF _IO(0x12, 97) /* Flush buffer cache. */
-#define BLKRASET _IO(0x12, 98) /* Set read ahead for block device. */
-#define BLKRAGET _IO(0x12, 99) /* Get current read ahead setting. */
-
-/*
- * Prototypes
- */
-extern int mount(const char *, const char *,
- const char *, unsigned long,
- const void *);
-extern int umount(const char *);
-extern int umount2(const char *, int);
-
-#if 0 /* MISSING FROM BIONIC */
-extern int pivot_root(const char *, const char *);
-#endif /* MISSING */
+extern int mount(const char*, const char*, const char*, unsigned long, const void*);
+extern int umount(const char*);
+extern int umount2(const char*, int);
__END_DECLS
diff --git a/libc/include/sys/signalfd.h b/libc/include/sys/signalfd.h
index a249d65..2537ab9 100644
--- a/libc/include/sys/signalfd.h
+++ b/libc/include/sys/signalfd.h
@@ -35,7 +35,7 @@
__BEGIN_DECLS
-extern int signalfd(int fd, const sigset_t* mask, int flags) __attribute__((__nonnull__(2)));
+extern int signalfd(int fd, const sigset_t* mask, int flags) __nonnull((2));
__END_DECLS
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index c9ad23d..c7715a3 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -129,7 +129,7 @@
extern int mknod(const char *, mode_t, dev_t);
extern mode_t umask(mode_t);
-#if defined(__BIONIC_FORTIFY) && !defined(__clang__)
+#if defined(__BIONIC_FORTIFY)
extern mode_t __umask_chk(mode_t);
extern mode_t __umask_real(mode_t)
@@ -138,15 +138,17 @@
__BIONIC_FORTIFY_INLINE
mode_t umask(mode_t mode) {
+#if !defined(__clang__)
if (__builtin_constant_p(mode)) {
if ((mode & 0777) != mode) {
__umask_invalid_mode();
}
return __umask_real(mode);
}
+#endif
return __umask_chk(mode);
}
-#endif /* defined(__BIONIC_FORTIFY) && !defined(__clang__) */
+#endif /* defined(__BIONIC_FORTIFY) */
#define stat64 stat
diff --git a/libc/include/sys/statvfs.h b/libc/include/sys/statvfs.h
new file mode 100644
index 0000000..e910c03
--- /dev/null
+++ b/libc/include/sys/statvfs.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 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 _SYS_STATVFS_H_
+#define _SYS_STATVFS_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+struct statvfs {
+ unsigned long f_bsize;
+ unsigned long f_frsize;
+ fsblkcnt_t f_blocks;
+ fsblkcnt_t f_bfree;
+ fsblkcnt_t f_bavail;
+ fsfilcnt_t f_files;
+ fsfilcnt_t f_ffree;
+ fsfilcnt_t f_favail;
+ unsigned long f_fsid;
+ unsigned long f_flag;
+ unsigned long f_namemax;
+};
+
+#define ST_RDONLY 0x0001
+#define ST_NOSUID 0x0002
+#define ST_NODEV 0x0004
+#define ST_NOEXEC 0x0008
+#define ST_SYNCHRONOUS 0x0010
+#define ST_MANDLOCK 0x0040
+#define ST_NOATIME 0x0400
+#define ST_NODIRATIME 0x0800
+#define ST_RELATIME 0x1000
+
+extern int statvfs(const char* __restrict, struct statvfs* __restrict) __nonnull((1, 2));
+extern int fstatvfs(int, struct statvfs*) __nonnull((2));
+
+__END_DECLS
+
+#endif /* _SYS_STATVFS_H_ */
diff --git a/libc/include/sys/swap.h b/libc/include/sys/swap.h
new file mode 100644
index 0000000..97a6f36
--- /dev/null
+++ b/libc/include/sys/swap.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 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 _SYS_SWAP_H_
+#define _SYS_SWAP_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+extern int swapon(const char*, int) __nonnull((1));
+extern int swapoff(const char*) __nonnull((1));
+
+__END_DECLS
+
+#endif /* _SYS_SWAP_H_ */
diff --git a/libc/include/sys/vfs.h b/libc/include/sys/vfs.h
index d14944d..6a55c99 100644
--- a/libc/include/sys/vfs.h
+++ b/libc/include/sys/vfs.h
@@ -34,7 +34,7 @@
__BEGIN_DECLS
-/* note: this corresponds to the kernel's statfs64 type */
+/* These correspond to the kernel's statfs64 type. */
#ifdef __mips__
struct statfs {
uint32_t f_type;
@@ -48,7 +48,8 @@
uint64_t f_bavail;
__kernel_fsid_t f_fsid;
uint32_t f_namelen;
- uint32_t f_spare[6];
+ uint32_t f_flags;
+ uint32_t f_spare[5];
};
#else
struct statfs {
@@ -62,7 +63,8 @@
__kernel_fsid_t f_fsid;
uint32_t f_namelen;
uint32_t f_frsize;
- uint32_t f_spare[5];
+ uint32_t f_flags;
+ uint32_t f_spare[4];
};
#endif
diff --git a/libc/kernel/common/linux/fs.h b/libc/kernel/common/linux/fs.h
index 6b7e6b8..538d0e4 100644
--- a/libc/kernel/common/linux/fs.h
+++ b/libc/kernel/common/linux/fs.h
@@ -33,190 +33,195 @@
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define SEEK_CUR 1
#define SEEK_END 2
-#define SEEK_MAX SEEK_END
-struct fstrim_range {
+#define SEEK_DATA 3
+#define SEEK_HOLE 4
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SEEK_MAX SEEK_HOLE
+struct fstrim_range {
__u64 start;
__u64 len;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__u64 minlen;
};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct files_stat_struct {
unsigned long nr_files;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
unsigned long nr_free_files;
unsigned long max_files;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
struct inodes_stat_t {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
int nr_inodes;
int nr_unused;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
int dummy[5];
};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define NR_FILE 8192
-#define MAY_EXEC 1
+#define MAY_EXEC 0x00000001
+#define MAY_WRITE 0x00000002
+#define MAY_READ 0x00000004
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define MAY_WRITE 2
-#define MAY_READ 4
-#define MAY_APPEND 8
-#define MAY_ACCESS 16
+#define MAY_APPEND 0x00000008
+#define MAY_ACCESS 0x00000010
+#define MAY_OPEN 0x00000020
+#define MAY_CHDIR 0x00000040
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define MAY_OPEN 32
-#define MAY_CHDIR 64
+#define MAY_NOT_BLOCK 0x00000080
#define FMODE_READ ((__force fmode_t)0x1)
#define FMODE_WRITE ((__force fmode_t)0x2)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define FMODE_LSEEK ((__force fmode_t)0x4)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define FMODE_PREAD ((__force fmode_t)0x8)
#define FMODE_PWRITE ((__force fmode_t)0x10)
#define FMODE_EXEC ((__force fmode_t)0x20)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define FMODE_NDELAY ((__force fmode_t)0x40)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define FMODE_EXCL ((__force fmode_t)0x80)
#define FMODE_WRITE_IOCTL ((__force fmode_t)0x100)
-#define FMODE_NOCMTIME ((__force fmode_t)0x800)
+#define FMODE_32BITHASH ((__force fmode_t)0x200)
+#define FMODE_64BITHASH ((__force fmode_t)0x400)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define FMODE_NOCMTIME ((__force fmode_t)0x800)
#define FMODE_RANDOM ((__force fmode_t)0x1000)
#define FMODE_UNSIGNED_OFFSET ((__force fmode_t)0x2000)
#define FMODE_PATH ((__force fmode_t)0x4000)
-#define FMODE_NONOTIFY ((__force fmode_t)0x1000000)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define FMODE_NONOTIFY ((__force fmode_t)0x1000000)
#define RW_MASK REQ_WRITE
#define RWA_MASK REQ_RAHEAD
#define READ 0
-#define WRITE RW_MASK
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define WRITE RW_MASK
#define READA RWA_MASK
#define READ_SYNC (READ | REQ_SYNC)
-#define READ_META (READ | REQ_META)
#define WRITE_SYNC (WRITE | REQ_SYNC | REQ_NOIDLE)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define WRITE_ODIRECT (WRITE | REQ_SYNC)
-#define WRITE_META (WRITE | REQ_META)
#define WRITE_FLUSH (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH)
#define WRITE_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FUA)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define WRITE_FLUSH_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH | REQ_FUA)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define SEL_IN 1
#define SEL_OUT 2
#define SEL_EX 4
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define FS_REQUIRES_DEV 1
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define FS_BINARY_MOUNTDATA 2
#define FS_HAS_SUBTYPE 4
#define FS_REVAL_DOT 16384
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define FS_RENAME_DOES_D_MOVE 32768
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_RDONLY 1
#define MS_NOSUID 2
#define MS_NODEV 4
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_NOEXEC 8
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_SYNCHRONOUS 16
#define MS_REMOUNT 32
#define MS_MANDLOCK 64
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_DIRSYNC 128
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_NOATIME 1024
#define MS_NODIRATIME 2048
#define MS_BIND 4096
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_MOVE 8192
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_REC 16384
#define MS_VERBOSE 32768
#define MS_SILENT 32768
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_POSIXACL (1<<16)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_UNBINDABLE (1<<17)
#define MS_PRIVATE (1<<18)
#define MS_SLAVE (1<<19)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_SHARED (1<<20)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_RELATIME (1<<21)
#define MS_KERNMOUNT (1<<22)
#define MS_I_VERSION (1<<23)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_STRICTATIME (1<<24)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_NOSEC (1<<28)
#define MS_BORN (1<<29)
#define MS_ACTIVE (1<<30)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_NOUSER (1<<31)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION)
#define MS_MGC_VAL 0xC0ED0000
#define MS_MGC_MSK 0xffff0000
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define S_SYNC 1
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define S_NOATIME 2
#define S_APPEND 4
#define S_IMMUTABLE 8
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define S_DEAD 16
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define S_NOQUOTA 32
#define S_DIRSYNC 64
#define S_NOCMTIME 128
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define S_SWAPFILE 256
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define S_PRIVATE 512
#define S_IMA 1024
#define S_AUTOMOUNT 2048
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define S_NOSEC 4096
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define __IS_FLG(inode,flg) ((inode)->i_sb->s_flags & (flg))
#define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY)
#define IS_SYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS) || ((inode)->i_flags & S_SYNC))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define IS_DIRSYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) || ((inode)->i_flags & (S_SYNC|S_DIRSYNC)))
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK)
#define IS_NOATIME(inode) __IS_FLG(inode, MS_RDONLY|MS_NOATIME)
#define IS_I_VERSION(inode) __IS_FLG(inode, MS_I_VERSION)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND)
#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
#define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
#define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE)
#define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define IS_IMA(inode) ((inode)->i_flags & S_IMA)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define IS_AUTOMOUNT(inode) ((inode)->i_flags & S_AUTOMOUNT)
#define IS_NOSEC(inode) ((inode)->i_flags & S_NOSEC)
#define BLKROSET _IO(0x12,93)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKROGET _IO(0x12,94)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKRRPART _IO(0x12,95)
#define BLKGETSIZE _IO(0x12,96)
#define BLKFLSBUF _IO(0x12,97)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKRASET _IO(0x12,98)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKRAGET _IO(0x12,99)
#define BLKFRASET _IO(0x12,100)
#define BLKFRAGET _IO(0x12,101)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKSECTSET _IO(0x12,102)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKSECTGET _IO(0x12,103)
#define BLKSSZGET _IO(0x12,104)
#define BLKBSZGET _IOR(0x12,112,size_t)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKBSZSET _IOW(0x12,113,size_t)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKGETSIZE64 _IOR(0x12,114,size_t)
#define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup)
#define BLKTRACESTART _IO(0x12,116)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKTRACESTOP _IO(0x12,117)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKTRACETEARDOWN _IO(0x12,118)
#define BLKDISCARD _IO(0x12,119)
#define BLKIOMIN _IO(0x12,120)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKIOOPT _IO(0x12,121)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKALIGNOFF _IO(0x12,122)
#define BLKPBSZGET _IO(0x12,123)
#define BLKDISCARDZEROES _IO(0x12,124)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define BLKSECDISCARD _IO(0x12,125)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define BLKROTATIONAL _IO(0x12,126)
#define BMAP_IOCTL 1
#define FIBMAP _IO(0x00,1)
#define FIGETBSZ _IO(0x00,2)
diff --git a/libc/kernel/common/linux/types.h b/libc/kernel/common/linux/types.h
index 90b0f6b..b40959c 100644
--- a/libc/kernel/common/linux/types.h
+++ b/libc/kernel/common/linux/types.h
@@ -33,12 +33,14 @@
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
typedef __u64 __bitwise __be64;
#endif
+typedef __u16 __bitwise __sum16;
+typedef __u32 __bitwise __wsum;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct ustat {
__kernel_daddr_t f_tfree;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__kernel_ino_t f_tinode;
char f_fname[6];
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
char f_fpack[6];
};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
diff --git a/libc/private/bionic_atomic_arm.h b/libc/private/bionic_atomic_arm.h
index 275c1c9..3bb639e 100644
--- a/libc/private/bionic_atomic_arm.h
+++ b/libc/private/bionic_atomic_arm.h
@@ -70,10 +70,6 @@
* code is going to run on a single or multi-core device, so we
* need to be cautious.
*
- * Fortunately, we can use the kernel helper function that is
- * mapped at address 0xffff0fa0 in all user process, and that
- * provides a device-specific barrier operation.
- *
* I.e. on single-core devices, the helper immediately returns,
* on multi-core devices, it uses "dmb" or any other means to
* perform a full-memory barrier.
@@ -82,7 +78,7 @@
*
* - multi-core ARMv7-A => use the 'dmb' hardware instruction
* - multi-core ARMv6 => use the coprocessor
- * - single core ARMv5TE/6/7 => do not use any hardware barrier
+ * - single core ARMv6+ => do not use any hardware barrier
*/
#if defined(ANDROID_SMP) && ANDROID_SMP == 1
@@ -124,18 +120,14 @@
}
#endif /* !ANDROID_SMP */
+#ifndef __ARM_HAVE_LDREX_STREX
+#error Only ARM devices which have LDREX / STREX are supported
+#endif
+
/* Compare-and-swap, without any explicit barriers. Note that this functions
* returns 0 on success, and 1 on failure. The opposite convention is typically
* used on other platforms.
- *
- * There are two cases to consider:
- *
- * - ARMv6+ => use LDREX/STREX instructions
- * - < ARMv6 => use kernel helper function mapped at 0xffff0fc0
- *
- * LDREX/STREX are only available starting from ARMv6
*/
-#ifdef __ARM_HAVE_LDREX_STREX
__ATOMIC_INLINE__ int
__bionic_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr)
{
@@ -157,32 +149,8 @@
} while (__builtin_expect(status != 0, 0));
return prev != old_value;
}
-# else /* !__ARM_HAVE_LDREX_STREX */
-/* Use the handy kernel helper function mapped at 0xffff0fc0 */
-typedef int (kernel_cmpxchg)(int32_t, int32_t, volatile int32_t *);
-
-__ATOMIC_INLINE__ int
-__kernel_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr)
-{
- /* Note: the kernel function returns 0 on success too */
- return (*(kernel_cmpxchg *)0xffff0fc0)(old_value, new_value, ptr);
-}
-
-__ATOMIC_INLINE__ int
-__bionic_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr)
-{
- return __kernel_cmpxchg(old_value, new_value, ptr);
-}
-#endif /* !__ARM_HAVE_LDREX_STREX */
-
-/* Swap operation, without any explicit barriers.
- * There are again two similar cases to consider:
- *
- * ARMv6+ => use LDREX/STREX
- * < ARMv6 => use SWP instead.
- */
-#ifdef __ARM_HAVE_LDREX_STREX
+/* Swap operation, without any explicit barriers. */
__ATOMIC_INLINE__ int32_t
__bionic_swap(int32_t new_value, volatile int32_t* ptr)
{
@@ -199,24 +167,10 @@
} while (__builtin_expect(status != 0, 0));
return prev;
}
-#else /* !__ARM_HAVE_LDREX_STREX */
-__ATOMIC_INLINE__ int32_t
-__bionic_swap(int32_t new_value, volatile int32_t* ptr)
-{
- int32_t prev;
- /* NOTE: SWP is available in Thumb-1 too */
- __asm__ __volatile__ ("swp %0, %2, [%3]"
- : "=&r" (prev), "+m" (*ptr)
- : "r" (new_value), "r" (ptr)
- : "cc");
- return prev;
-}
-#endif /* !__ARM_HAVE_LDREX_STREX */
/* Atomic increment - without any barriers
* This returns the old value
*/
-#ifdef __ARM_HAVE_LDREX_STREX
__ATOMIC_INLINE__ int32_t
__bionic_atomic_inc(volatile int32_t* ptr)
{
@@ -234,23 +188,10 @@
} while (__builtin_expect(status != 0, 0));
return prev;
}
-#else
-__ATOMIC_INLINE__ int32_t
-__bionic_atomic_inc(volatile int32_t* ptr)
-{
- int32_t prev, status;
- do {
- prev = *ptr;
- status = __kernel_cmpxchg(prev, prev+1, ptr);
- } while (__builtin_expect(status != 0, 0));
- return prev;
-}
-#endif
/* Atomic decrement - without any barriers
* This returns the old value.
*/
-#ifdef __ARM_HAVE_LDREX_STREX
__ATOMIC_INLINE__ int32_t
__bionic_atomic_dec(volatile int32_t* ptr)
{
@@ -268,17 +209,5 @@
} while (__builtin_expect(status != 0, 0));
return prev;
}
-#else
-__ATOMIC_INLINE__ int32_t
-__bionic_atomic_dec(volatile int32_t* ptr)
-{
- int32_t prev, status;
- do {
- prev = *ptr;
- status = __kernel_cmpxchg(prev, prev-1, ptr);
- } while (__builtin_expect(status != 0, 0));
- return prev;
-}
-#endif
#endif /* SYS_ATOMICS_ARM_H */
diff --git a/libc/private/resolv_private.h b/libc/private/resolv_private.h
index 61db8c8..c7bcb89 100644
--- a/libc/private/resolv_private.h
+++ b/libc/private/resolv_private.h
@@ -346,12 +346,9 @@
extern const struct res_sym __p_rcode_syms[];
#endif /* SHARED_LIBBIND */
-#ifndef ADNROID_CHANGES
-#define b64_ntop __b64_ntop
-#define b64_pton __b64_pton
-#endif
-
+#ifndef ANDROID_CHANGES
#define dn_comp __dn_comp
+#endif
#define dn_count_labels __dn_count_labels
#define dn_skipname __dn_skipname
#define fp_resstat __fp_resstat
@@ -446,9 +443,6 @@
const char * p_option(u_long);
char * p_secstodate(u_long);
int dn_count_labels(const char *);
-int dn_comp(const char *, u_char *, int, u_char **, u_char **);
-int dn_expand(const u_char *, const u_char *, const u_char *,
- char *, int);
u_int res_randomid(void);
int res_nameinquery(const char *, int, int, const u_char *,
const u_char *);
diff --git a/libc/upstream-freebsd/freebsd-compat.h b/libc/upstream-freebsd/freebsd-compat.h
index 5298663..8030eea 100644
--- a/libc/upstream-freebsd/freebsd-compat.h
+++ b/libc/upstream-freebsd/freebsd-compat.h
@@ -18,6 +18,7 @@
#define _BIONIC_FREEBSD_COMPAT_H_included
#define __USE_BSD
+#define REPLACE_GETOPT
#define _close close
#define _fcntl fcntl
diff --git a/libc/unistd/getopt_long.c b/libc/upstream-freebsd/lib/libc/stdlib/getopt_long.c
similarity index 79%
rename from libc/unistd/getopt_long.c
rename to libc/upstream-freebsd/lib/libc/stdlib/getopt_long.c
index dbdf01a..9f7f6d5 100644
--- a/libc/unistd/getopt_long.c
+++ b/libc/upstream-freebsd/lib/libc/stdlib/getopt_long.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getopt_long.c,v 1.20 2005/10/25 15:49:37 jmc Exp $ */
+/* $OpenBSD: getopt_long.c,v 1.22 2006/10/04 21:29:04 jmc Exp $ */
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
/*
@@ -35,13 +35,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -56,22 +49,33 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <err.h>
#include <errno.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
-#include <stdio.h>
+#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */
+
+#if 0 /* we prefer to keep our getopt(3) */
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
+#endif
#ifdef REPLACE_GETOPT
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
+int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#endif
-int optreset; /* reset getopt */
#define PRINT_ERROR ((opterr) && (*options != ':'))
@@ -86,10 +90,17 @@
#define EMSG ""
+#ifdef GNU_COMPATIBLE
+#define NO_PREFIX (-1)
+#define D_PREFIX 0
+#define DD_PREFIX 1
+#define W_PREFIX 2
+#endif
+
static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int);
static int parse_long_options(char * const *, const char *,
- const struct option *, int *, int);
+ const struct option *, int *, int, int);
static int gcd(int, int);
static void permute_args(int, int, int, char * const *);
@@ -101,11 +112,21 @@
/* Error messages */
static const char recargchar[] = "option requires an argument -- %c";
+static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
+#ifdef GNU_COMPATIBLE
+static int dash_prefix = NO_PREFIX;
+static const char gnuoptchar[] = "invalid option -- %c";
+
+static const char recargstring[] = "option `%s%s' requires an argument";
+static const char ambig[] = "option `%s%.*s' is ambiguous";
+static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
+static const char illoptstring[] = "unrecognized option `%s%s'";
+#else
static const char recargstring[] = "option requires an argument -- %s";
static const char ambig[] = "ambiguous option -- %.*s";
static const char noarg[] = "option doesn't take an argument -- %.*s";
-static const char illoptchar[] = "unknown option -- %c";
static const char illoptstring[] = "unknown option -- %s";
+#endif
/*
* Compute the greatest common divisor of a and b.
@@ -169,14 +190,35 @@
*/
static int
parse_long_options(char * const *nargv, const char *options,
- const struct option *long_options, int *idx, int short_too)
+ const struct option *long_options, int *idx, int short_too, int flags)
{
char *current_argv, *has_equal;
+#ifdef GNU_COMPATIBLE
+ char *current_dash;
+#endif
size_t current_argv_len;
- int i, match;
+ int i, match, exact_match, second_partial_match;
current_argv = place;
+#ifdef GNU_COMPATIBLE
+ switch (dash_prefix) {
+ case D_PREFIX:
+ current_dash = "-";
+ break;
+ case DD_PREFIX:
+ current_dash = "--";
+ break;
+ case W_PREFIX:
+ current_dash = "-W ";
+ break;
+ default:
+ current_dash = "";
+ break;
+ }
+#endif
match = -1;
+ exact_match = 0;
+ second_partial_match = 0;
optind++;
@@ -196,6 +238,7 @@
if (strlen(long_options[i].name) == current_argv_len) {
/* exact match */
match = i;
+ exact_match = 1;
break;
}
/*
@@ -205,25 +248,37 @@
if (short_too && current_argv_len == 1)
continue;
- if (match == -1) /* partial match */
+ if (match == -1) /* first partial match */
match = i;
- else {
- /* ambiguous abbreviation */
- if (PRINT_ERROR)
- fprintf(stderr,
- ambig, (int)current_argv_len,
- current_argv);
- optopt = 0;
- return (BADCH);
- }
+ else if ((flags & FLAG_LONGONLY) ||
+ long_options[i].has_arg !=
+ long_options[match].has_arg ||
+ long_options[i].flag != long_options[match].flag ||
+ long_options[i].val != long_options[match].val)
+ second_partial_match = 1;
+ }
+ if (!exact_match && second_partial_match) {
+ /* ambiguous abbreviation */
+ if (PRINT_ERROR)
+ warnx(ambig,
+#ifdef GNU_COMPATIBLE
+ current_dash,
+#endif
+ (int)current_argv_len,
+ current_argv);
+ optopt = 0;
+ return (BADCH);
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
- fprintf(stderr,
- noarg, (int)current_argv_len,
- current_argv);
+ warnx(noarg,
+#ifdef GNU_COMPATIBLE
+ current_dash,
+#endif
+ (int)current_argv_len,
+ current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
@@ -231,7 +286,11 @@
optopt = long_options[match].val;
else
optopt = 0;
+#ifdef GNU_COMPATIBLE
+ return (BADCH);
+#else
return (BADARG);
+#endif
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
@@ -252,9 +311,11 @@
* should be generated.
*/
if (PRINT_ERROR)
- fprintf(stderr,
- recargstring,
- current_argv);
+ warnx(recargstring,
+#ifdef GNU_COMPATIBLE
+ current_dash,
+#endif
+ current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
@@ -271,7 +332,11 @@
return (-1);
}
if (PRINT_ERROR)
- fprintf(stderr, illoptstring, current_argv);
+ warnx(illoptstring,
+#ifdef GNU_COMPATIBLE
+ current_dash,
+#endif
+ current_argv);
optopt = 0;
return (BADCH);
}
@@ -294,7 +359,7 @@
{
char *oli; /* option letter list index */
int optchar, short_too;
- static int posixly_correct = -1;
+ int posixly_correct; /* no static, can be changed on the fly */
if (options == NULL)
return (-1);
@@ -303,12 +368,18 @@
* Disable GNU extensions if POSIXLY_CORRECT is set or options
* string begins with a '+'.
*/
- if (posixly_correct == -1)
- posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+ posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+#ifdef GNU_COMPATIBLE
+ if (*options == '-')
+ flags |= FLAG_ALLARGS;
+ else if (posixly_correct || *options == '+')
+ flags &= ~FLAG_PERMUTE;
+#else
if (posixly_correct || *options == '+')
flags &= ~FLAG_PERMUTE;
else if (*options == '-')
flags |= FLAG_ALLARGS;
+#endif
if (*options == '+' || *options == '-')
options++;
@@ -344,7 +415,11 @@
return (-1);
}
if (*(place = nargv[optind]) != '-' ||
+#ifdef GNU_COMPATIBLE
+ place[1] == '\0') {
+#else
(place[1] == '\0' && strchr(options, '-') == NULL)) {
+#endif
place = EMSG; /* found non-option */
if (flags & FLAG_ALLARGS) {
/*
@@ -407,20 +482,26 @@
if (long_options != NULL && place != nargv[optind] &&
(*place == '-' || (flags & FLAG_LONGONLY))) {
short_too = 0;
- if (*place == '-')
+#ifdef GNU_COMPATIBLE
+ dash_prefix = D_PREFIX;
+#endif
+ if (*place == '-') {
place++; /* --foo long option */
- else if (*place != ':' && strchr(options, *place) != NULL)
+#ifdef GNU_COMPATIBLE
+ dash_prefix = DD_PREFIX;
+#endif
+ } else if (*place != ':' && strchr(options, *place) != NULL)
short_too = 1; /* could be short option too */
optchar = parse_long_options(nargv, options, long_options,
- idx, short_too);
+ idx, short_too, flags);
if (optchar != -1) {
place = EMSG;
return (optchar);
}
}
- if (((optchar = (int)*place++) == (int)':') ||
+ if ((optchar = (int)*place++) == (int)':' ||
(optchar == (int)'-' && *place != '\0') ||
(oli = strchr(options, optchar)) == NULL) {
/*
@@ -432,8 +513,14 @@
return (-1);
if (!*place)
++optind;
+#ifdef GNU_COMPATIBLE
if (PRINT_ERROR)
- fprintf(stderr, illoptchar, optchar);
+ warnx(posixly_correct ? illoptchar : gnuoptchar,
+ optchar);
+#else
+ if (PRINT_ERROR)
+ warnx(illoptchar, optchar);
+#endif
optopt = optchar;
return (BADCH);
}
@@ -444,13 +531,16 @@
else if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
- fprintf(stderr, recargchar, optchar);
+ warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else /* white space */
place = nargv[optind];
+#ifdef GNU_COMPATIBLE
+ dash_prefix = W_PREFIX;
+#endif
optchar = parse_long_options(nargv, options, long_options,
- idx, 0);
+ idx, 0, flags);
place = EMSG;
return (optchar);
}
@@ -461,24 +551,15 @@
optarg = NULL;
if (*place) /* no white space */
optarg = place;
- /* XXX: disable test for :: if PC? (GNU doesn't) */
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
- fprintf(stderr, recargchar, optchar);
+ warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else
optarg = nargv[optind];
- } else if (!(flags & FLAG_PERMUTE)) {
- /*
- * If permutation is disabled, we can accept an
- * optional arg separated by whitespace so long
- * as it does not start with a dash (-).
- */
- if (optind + 1 < nargc && *nargv[optind + 1] != '-')
- optarg = nargv[++optind];
}
place = EMSG;
++optind;
@@ -516,7 +597,7 @@
*/
int
getopt_long(int nargc, char * const *nargv, const char *options,
- const struct option *long_options, int *idx)
+ const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
@@ -529,7 +610,7 @@
*/
int
getopt_long_only(int nargc, char * const *nargv, const char *options,
- const struct option *long_options, int *idx)
+ const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
diff --git a/libc/zoneinfo/tzdata b/libc/zoneinfo/tzdata
index 9594284..bce6e50 100644
--- a/libc/zoneinfo/tzdata
+++ b/libc/zoneinfo/tzdata
Binary files differ
diff --git a/linker/linker.cpp b/linker/linker.cpp
index c53d52f..386f6dc 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1533,6 +1533,8 @@
* phdr_table_protect_segments() after all of them are applied
* and all constructors are run.
*/
+ DL_WARN("%s has text relocations. This is wasting memory and is "
+ "a security risk. Please fix.", si->name);
if (phdr_table_unprotect_segments(si->phdr, si->phnum, si->load_bias) < 0) {
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
si->name, strerror(errno));
@@ -1584,6 +1586,28 @@
}
/*
+ * This function add vdso to internal dso list.
+ * It helps to stack unwinding through signal handlers.
+ * Also, it makes bionic more like glibc.
+ */
+static void add_vdso(KernelArgumentBlock& args UNUSED) {
+#ifdef AT_SYSINFO_EHDR
+ Elf32_Ehdr* ehdr_vdso = reinterpret_cast<Elf32_Ehdr*>(args.getauxval(AT_SYSINFO_EHDR));
+
+ soinfo* si = soinfo_alloc("[vdso]");
+ si->phdr = reinterpret_cast<Elf32_Phdr*>(reinterpret_cast<char*>(ehdr_vdso) + ehdr_vdso->e_phoff);
+ si->phnum = ehdr_vdso->e_phnum;
+ si->link_map.l_name = si->name;
+ for (size_t i = 0; i < si->phnum; ++i) {
+ if (si->phdr[i].p_type == PT_LOAD) {
+ si->link_map.l_addr = reinterpret_cast<Elf32_Addr>(ehdr_vdso) - si->phdr[i].p_vaddr;
+ break;
+ }
+ }
+#endif
+}
+
+/*
* This code is called after the linker has linked itself and
* fixed it's own GOT. It is safe to make references to externs
* and other non-local data at this point.
@@ -1708,6 +1732,8 @@
exit(EXIT_FAILURE);
}
+ add_vdso(args);
+
si->CallPreInitConstructors();
for (size_t i = 0; gLdPreloads[i] != NULL; ++i) {
diff --git a/tests/Android.mk b/tests/Android.mk
index fe794c4..efee17b 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -61,10 +61,9 @@
dirent_test.cpp \
eventfd_test.cpp \
fenv_test.cpp \
- fortify1_test.cpp \
- fortify2_test.cpp \
getauxval_test.cpp \
getcwd_test.cpp \
+ inttypes_test.cpp \
libc_logging_test.cpp \
libgen_test.cpp \
malloc_test.cpp \
@@ -74,6 +73,8 @@
regex_test.cpp \
signal_test.cpp \
stack_protector_test.cpp \
+ stack_unwinding_test.cpp \
+ statvfs_test.cpp \
stdio_test.cpp \
stdlib_test.cpp \
string_test.cpp \
@@ -87,6 +88,21 @@
test_dynamic_src_files = \
dlfcn_test.cpp \
+test_fortify_static_libraries = \
+ fortify1-tests-gcc fortify2-tests-gcc fortify1-tests-clang fortify2-tests-clang
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := bionic-unit-tests-unwind-test-impl
+LOCAL_CFLAGS += $(test_c_flags) -fexceptions -fnon-call-exceptions
+LOCAL_SRC_FILES := stack_unwinding_test_impl.c
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := bionic-unit-tests-unwind-test-impl-host
+LOCAL_CFLAGS += $(test_c_flags) -fexceptions -fnon-call-exceptions
+LOCAL_SRC_FILES := stack_unwinding_test_impl.c
+include $(BUILD_HOST_STATIC_LIBRARY)
+
# Build tests for the device (with bionic's .so). Run with:
# adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests
include $(CLEAR_VARS)
@@ -96,7 +112,8 @@
LOCAL_LDFLAGS += $(test_dynamic_ldflags)
LOCAL_SHARED_LIBRARIES += libdl
LOCAL_SRC_FILES := $(test_src_files) $(test_dynamic_src_files)
-LOCAL_WHOLE_STATIC_LIBRARIES := bionic-unit-tests-clang
+LOCAL_WHOLE_STATIC_LIBRARIES := $(test_fortify_static_libraries)
+LOCAL_STATIC_LIBRARIES += bionic-unit-tests-unwind-test-impl
include $(BUILD_NATIVE_TEST)
# Build tests for the device (with bionic's .a). Run with:
@@ -107,8 +124,8 @@
LOCAL_CFLAGS += $(test_c_flags)
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_SRC_FILES := $(test_src_files)
-LOCAL_STATIC_LIBRARIES += libstlport_static libstdc++ libm libc
-LOCAL_WHOLE_STATIC_LIBRARIES := bionic-unit-tests-clang
+LOCAL_STATIC_LIBRARIES += libstlport_static libstdc++ libm libc bionic-unit-tests-unwind-test-impl
+LOCAL_WHOLE_STATIC_LIBRARIES := $(test_fortify_static_libraries)
include $(BUILD_NATIVE_TEST)
# -----------------------------------------------------------------------------
@@ -142,29 +159,59 @@
LOCAL_LDFLAGS += -lpthread -ldl
LOCAL_LDFLAGS += $(test_dynamic_ldflags)
LOCAL_SRC_FILES := $(test_src_files) $(test_dynamic_src_files)
+LOCAL_STATIC_LIBRARIES += bionic-unit-tests-unwind-test-impl-host
include $(BUILD_HOST_NATIVE_TEST)
endif
# -----------------------------------------------------------------------------
-# Unit tests which depend on clang as the compiler
+# FORTIFY_SOURCE tests
# -----------------------------------------------------------------------------
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := fortify1_test_clang.cpp fortify2_test_clang.cpp
-LOCAL_MODULE := bionic-unit-tests-clang
-LOCAL_CLANG := true
+
+fortify_c_includes = \
+ bionic \
+ bionic/libstdc++/include \
+ external/stlport/stlport \
+ external/gtest/include
+fortify_test_files = fortify_test.cpp
# -Wno-error=unused-parameter needed as
# external/stlport/stlport/stl/_threads.c (included from
# external/gtest/include/gtest/gtest.h) does not compile cleanly under
# clang. TODO: fix this.
-LOCAL_CFLAGS += $(test_c_flags) -Wno-error=unused-parameter
+fortify_c_flags = $(test_c_flags) -Wno-error=unused-parameter
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(fortify_test_files)
+LOCAL_MODULE := fortify1-tests-gcc
+LOCAL_CFLAGS += $(fortify_c_flags) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -DTEST_NAME=Fortify1_Gcc
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_C_INCLUDES += bionic \
- bionic/libstdc++/include \
- external/stlport/stlport \
- external/gtest/include
+LOCAL_C_INCLUDES += $(fortify_c_includes)
+include $(BUILD_STATIC_LIBRARY)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(fortify_test_files)
+LOCAL_MODULE := fortify2-tests-gcc
+LOCAL_CFLAGS += $(fortify_c_flags) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -DTEST_NAME=Fortify2_Gcc
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_C_INCLUDES += $(fortify_c_includes)
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(fortify_test_files)
+LOCAL_MODULE := fortify1-tests-clang
+LOCAL_CLANG := true
+LOCAL_CFLAGS += $(fortify_c_flags) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -DTEST_NAME=Fortify1_Clang
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_C_INCLUDES += $(fortify_c_includes)
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(fortify_test_files)
+LOCAL_MODULE := fortify2-tests-clang
+LOCAL_CLANG := true
+LOCAL_CFLAGS += $(fortify_c_flags) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -DTEST_NAME=Fortify2_Clang
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_C_INCLUDES += $(fortify_c_includes)
include $(BUILD_STATIC_LIBRARY)
endif # !BUILD_TINY_ANDROID
diff --git a/tests/fortify1_test.cpp b/tests/fortify1_test.cpp
deleted file mode 100644
index b8751bb..0000000
--- a/tests/fortify1_test.cpp
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#undef _FORTIFY_SOURCE
-#define _FORTIFY_SOURCE 1
-
-#include <gtest/gtest.h>
-#include <string.h>
-
-#if __BIONIC__
-// We have to say "DeathTest" here so gtest knows to run this test (which exits)
-// in its own process.
-
-// multibyte target where we over fill (should fail)
-TEST(Fortify1_DeathTest, strcpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- char *orig = strdup("0123456789");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-// zero sized target with "\0" source (should fail)
-TEST(Fortify1_DeathTest, strcpy2_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[0];
- char *orig = strdup("");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-// zero sized target with longer source (should fail)
-TEST(Fortify1_DeathTest, strcpy3_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[0];
- char *orig = strdup("1");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-// one byte target with longer source (should fail)
-TEST(Fortify1_DeathTest, strcpy4_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[1];
- char *orig = strdup("12");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-TEST(Fortify1_DeathTest, strlen_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strchr_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strrchr_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strlcpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char bufa[15];
- char bufb[10];
- strcpy(bufa, "01234567890123");
- size_t n = strlen(bufa);
- ASSERT_EXIT(strlcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-#endif
-
-TEST(Fortify1_DeathTest, sprintf_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- char source_buf[15];
- memcpy(source_buf, "12345678901234", 15);
- ASSERT_EXIT(sprintf(buf, "%s", source_buf), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strncat_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- size_t n = atoi("10"); // avoid compiler optimizations
- strncpy(buf, "012345678", n);
- ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strncat2_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- buf[0] = '\0';
- size_t n = atoi("10"); // avoid compiler optimizations
- ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strcat_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char src[11];
- strcpy(src, "0123456789");
- char buf[10];
- buf[0] = '\0';
- ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, memmove_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[20];
- strcpy(buf, "0123456789");
- size_t n = atoi("10");
- ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, memcpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char bufa[10];
- char bufb[10];
- strcpy(bufa, "012345678");
- size_t n = atoi("11");
- ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_DeathTest, strncpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char bufa[15];
- char bufb[10];
- strcpy(bufa, "01234567890123");
- size_t n = strlen(bufa);
- ASSERT_EXIT(strncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-extern "C" char* __strncat_chk(char*, const char*, size_t, size_t);
-extern "C" char* __strcat_chk(char*, const char*, size_t);
-
-TEST(Fortify1, strncat) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = 'a';
- buf[1] = '\0';
- char* res = __strncat_chk(buf, "01234", sizeof(buf) - strlen(buf) - 1, sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('a', buf[0]);
- ASSERT_EQ('0', buf[1]);
- ASSERT_EQ('1', buf[2]);
- ASSERT_EQ('2', buf[3]);
- ASSERT_EQ('3', buf[4]);
- ASSERT_EQ('4', buf[5]);
- ASSERT_EQ('\0', buf[6]);
- ASSERT_EQ('A', buf[7]);
- ASSERT_EQ('A', buf[8]);
- ASSERT_EQ('A', buf[9]);
-}
-
-TEST(Fortify1, strncat2) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = 'a';
- buf[1] = '\0';
- char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('a', buf[0]);
- ASSERT_EQ('0', buf[1]);
- ASSERT_EQ('1', buf[2]);
- ASSERT_EQ('2', buf[3]);
- ASSERT_EQ('3', buf[4]);
- ASSERT_EQ('4', buf[5]);
- ASSERT_EQ('\0', buf[6]);
- ASSERT_EQ('A', buf[7]);
- ASSERT_EQ('A', buf[8]);
- ASSERT_EQ('A', buf[9]);
-}
-
-TEST(Fortify1, strncat3) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = '\0';
- char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('0', buf[0]);
- ASSERT_EQ('1', buf[1]);
- ASSERT_EQ('2', buf[2]);
- ASSERT_EQ('3', buf[3]);
- ASSERT_EQ('4', buf[4]);
- ASSERT_EQ('\0', buf[5]);
- ASSERT_EQ('A', buf[6]);
- ASSERT_EQ('A', buf[7]);
- ASSERT_EQ('A', buf[8]);
- ASSERT_EQ('A', buf[9]);
-}
-
-TEST(Fortify1, strncat4) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[9] = '\0';
- char* res = __strncat_chk(buf, "", 5, sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('A', buf[0]);
- ASSERT_EQ('A', buf[1]);
- ASSERT_EQ('A', buf[2]);
- ASSERT_EQ('A', buf[3]);
- ASSERT_EQ('A', buf[4]);
- ASSERT_EQ('A', buf[5]);
- ASSERT_EQ('A', buf[6]);
- ASSERT_EQ('A', buf[7]);
- ASSERT_EQ('A', buf[8]);
- ASSERT_EQ('\0', buf[9]);
-}
-
-TEST(Fortify1, strncat5) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = 'a';
- buf[1] = '\0';
- char* res = __strncat_chk(buf, "01234567", 8, sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('a', buf[0]);
- ASSERT_EQ('0', buf[1]);
- ASSERT_EQ('1', buf[2]);
- ASSERT_EQ('2', buf[3]);
- ASSERT_EQ('3', buf[4]);
- ASSERT_EQ('4', buf[5]);
- ASSERT_EQ('5', buf[6]);
- ASSERT_EQ('6', buf[7]);
- ASSERT_EQ('7', buf[8]);
- ASSERT_EQ('\0', buf[9]);
-}
-
-TEST(Fortify1, strncat6) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = 'a';
- buf[1] = '\0';
- char* res = __strncat_chk(buf, "01234567", 9, sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('a', buf[0]);
- ASSERT_EQ('0', buf[1]);
- ASSERT_EQ('1', buf[2]);
- ASSERT_EQ('2', buf[3]);
- ASSERT_EQ('3', buf[4]);
- ASSERT_EQ('4', buf[5]);
- ASSERT_EQ('5', buf[6]);
- ASSERT_EQ('6', buf[7]);
- ASSERT_EQ('7', buf[8]);
- ASSERT_EQ('\0', buf[9]);
-}
-
-
-TEST(Fortify1, strcat) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = 'a';
- buf[1] = '\0';
- char* res = __strcat_chk(buf, "01234", sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('a', buf[0]);
- ASSERT_EQ('0', buf[1]);
- ASSERT_EQ('1', buf[2]);
- ASSERT_EQ('2', buf[3]);
- ASSERT_EQ('3', buf[4]);
- ASSERT_EQ('4', buf[5]);
- ASSERT_EQ('\0', buf[6]);
- ASSERT_EQ('A', buf[7]);
- ASSERT_EQ('A', buf[8]);
- ASSERT_EQ('A', buf[9]);
-}
-
-TEST(Fortify1, strcat2) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = 'a';
- buf[1] = '\0';
- char* res = __strcat_chk(buf, "01234567", sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('a', buf[0]);
- ASSERT_EQ('0', buf[1]);
- ASSERT_EQ('1', buf[2]);
- ASSERT_EQ('2', buf[3]);
- ASSERT_EQ('3', buf[4]);
- ASSERT_EQ('4', buf[5]);
- ASSERT_EQ('5', buf[6]);
- ASSERT_EQ('6', buf[7]);
- ASSERT_EQ('7', buf[8]);
- ASSERT_EQ('\0', buf[9]);
-}
diff --git a/tests/fortify1_test_clang.cpp b/tests/fortify1_test_clang.cpp
deleted file mode 100644
index fed9f13..0000000
--- a/tests/fortify1_test_clang.cpp
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#undef _FORTIFY_SOURCE
-#define _FORTIFY_SOURCE 1
-
-#include <gtest/gtest.h>
-#include <string.h>
-
-#if __BIONIC__
-// We have to say "DeathTest" here so gtest knows to run this test (which exits)
-// in its own process.
-
-// multibyte target where we over fill (should fail)
-TEST(Fortify1_Clang_DeathTest, strcpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- char *orig = strdup("0123456789");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-// zero sized target with "\0" source (should fail)
-TEST(Fortify1_Clang_DeathTest, strcpy2_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[0];
- char *orig = strdup("");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-// zero sized target with longer source (should fail)
-TEST(Fortify1_Clang_DeathTest, strcpy3_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[0];
- char *orig = strdup("1");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-// one byte target with longer source (should fail)
-TEST(Fortify1_Clang_DeathTest, strcpy4_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[1];
- char *orig = strdup("12");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-TEST(Fortify1_Clang_DeathTest, strlen_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, strchr_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, strrchr_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, strlcpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char bufa[15];
- char bufb[10];
- strcpy(bufa, "01234567890123");
- size_t n = strlen(bufa);
- ASSERT_EXIT(strlcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-#endif
-
-TEST(Fortify1_Clang_DeathTest, strncat_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- size_t n = atoi("10"); // avoid compiler optimizations
- strncpy(buf, "012345678", n);
- ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, strncat2_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- buf[0] = '\0';
- size_t n = atoi("10"); // avoid compiler optimizations
- ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, strcat_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char src[11];
- strcpy(src, "0123456789");
- char buf[10];
- buf[0] = '\0';
- ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, memmove_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[20];
- strcpy(buf, "0123456789");
- size_t n = atoi("10");
- ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, memcpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char bufa[10];
- char bufb[10];
- strcpy(bufa, "012345678");
- size_t n = atoi("11");
- ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify1_Clang_DeathTest, strncpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char bufa[15];
- char bufb[10];
- strcpy(bufa, "01234567890123");
- size_t n = strlen(bufa);
- ASSERT_EXIT(strncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-extern "C" char* __strncat_chk(char*, const char*, size_t, size_t);
-extern "C" char* __strcat_chk(char*, const char*, size_t);
-
-TEST(Fortify1_Clang, strncat) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = 'a';
- buf[1] = '\0';
- char* res = __strncat_chk(buf, "01234", sizeof(buf) - strlen(buf) - 1, sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('a', buf[0]);
- ASSERT_EQ('0', buf[1]);
- ASSERT_EQ('1', buf[2]);
- ASSERT_EQ('2', buf[3]);
- ASSERT_EQ('3', buf[4]);
- ASSERT_EQ('4', buf[5]);
- ASSERT_EQ('\0', buf[6]);
- ASSERT_EQ('A', buf[7]);
- ASSERT_EQ('A', buf[8]);
- ASSERT_EQ('A', buf[9]);
-}
-
-TEST(Fortify1_Clang, strncat2) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = 'a';
- buf[1] = '\0';
- char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('a', buf[0]);
- ASSERT_EQ('0', buf[1]);
- ASSERT_EQ('1', buf[2]);
- ASSERT_EQ('2', buf[3]);
- ASSERT_EQ('3', buf[4]);
- ASSERT_EQ('4', buf[5]);
- ASSERT_EQ('\0', buf[6]);
- ASSERT_EQ('A', buf[7]);
- ASSERT_EQ('A', buf[8]);
- ASSERT_EQ('A', buf[9]);
-}
-
-TEST(Fortify1_Clang, strncat3) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = '\0';
- char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('0', buf[0]);
- ASSERT_EQ('1', buf[1]);
- ASSERT_EQ('2', buf[2]);
- ASSERT_EQ('3', buf[3]);
- ASSERT_EQ('4', buf[4]);
- ASSERT_EQ('\0', buf[5]);
- ASSERT_EQ('A', buf[6]);
- ASSERT_EQ('A', buf[7]);
- ASSERT_EQ('A', buf[8]);
- ASSERT_EQ('A', buf[9]);
-}
-
-TEST(Fortify1_Clang, strncat4) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[9] = '\0';
- char* res = __strncat_chk(buf, "", 5, sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('A', buf[0]);
- ASSERT_EQ('A', buf[1]);
- ASSERT_EQ('A', buf[2]);
- ASSERT_EQ('A', buf[3]);
- ASSERT_EQ('A', buf[4]);
- ASSERT_EQ('A', buf[5]);
- ASSERT_EQ('A', buf[6]);
- ASSERT_EQ('A', buf[7]);
- ASSERT_EQ('A', buf[8]);
- ASSERT_EQ('\0', buf[9]);
-}
-
-TEST(Fortify1_Clang, strncat5) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = 'a';
- buf[1] = '\0';
- char* res = __strncat_chk(buf, "01234567", 8, sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('a', buf[0]);
- ASSERT_EQ('0', buf[1]);
- ASSERT_EQ('1', buf[2]);
- ASSERT_EQ('2', buf[3]);
- ASSERT_EQ('3', buf[4]);
- ASSERT_EQ('4', buf[5]);
- ASSERT_EQ('5', buf[6]);
- ASSERT_EQ('6', buf[7]);
- ASSERT_EQ('7', buf[8]);
- ASSERT_EQ('\0', buf[9]);
-}
-
-TEST(Fortify1_Clang, strncat6) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = 'a';
- buf[1] = '\0';
- char* res = __strncat_chk(buf, "01234567", 9, sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('a', buf[0]);
- ASSERT_EQ('0', buf[1]);
- ASSERT_EQ('1', buf[2]);
- ASSERT_EQ('2', buf[3]);
- ASSERT_EQ('3', buf[4]);
- ASSERT_EQ('4', buf[5]);
- ASSERT_EQ('5', buf[6]);
- ASSERT_EQ('6', buf[7]);
- ASSERT_EQ('7', buf[8]);
- ASSERT_EQ('\0', buf[9]);
-}
-
-
-TEST(Fortify1_Clang, strcat) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = 'a';
- buf[1] = '\0';
- char* res = __strcat_chk(buf, "01234", sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('a', buf[0]);
- ASSERT_EQ('0', buf[1]);
- ASSERT_EQ('1', buf[2]);
- ASSERT_EQ('2', buf[3]);
- ASSERT_EQ('3', buf[4]);
- ASSERT_EQ('4', buf[5]);
- ASSERT_EQ('\0', buf[6]);
- ASSERT_EQ('A', buf[7]);
- ASSERT_EQ('A', buf[8]);
- ASSERT_EQ('A', buf[9]);
-}
-
-TEST(Fortify1_Clang, strcat2) {
- char buf[10];
- memset(buf, 'A', sizeof(buf));
- buf[0] = 'a';
- buf[1] = '\0';
- char* res = __strcat_chk(buf, "01234567", sizeof(buf));
- ASSERT_EQ(buf, res);
- ASSERT_EQ('a', buf[0]);
- ASSERT_EQ('0', buf[1]);
- ASSERT_EQ('1', buf[2]);
- ASSERT_EQ('2', buf[3]);
- ASSERT_EQ('3', buf[4]);
- ASSERT_EQ('4', buf[5]);
- ASSERT_EQ('5', buf[6]);
- ASSERT_EQ('6', buf[7]);
- ASSERT_EQ('7', buf[8]);
- ASSERT_EQ('\0', buf[9]);
-}
-
-__BIONIC_FORTIFY_INLINE
-size_t test_fortify_inline(char* buf) {
- return __bos(buf);
-}
-
-TEST(Fortify1_Clang, fortify_inline) {
- char buf[1024];
- // no-op. Prints nothing. Needed to prevent the compiler
- // from optimizing out buf.
- buf[0] = '\0';
- printf("%s", buf);
- ASSERT_EQ(sizeof(buf), test_fortify_inline(buf));
-}
diff --git a/tests/fortify2_test.cpp b/tests/fortify2_test.cpp
deleted file mode 100644
index b6f6661..0000000
--- a/tests/fortify2_test.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#undef _FORTIFY_SOURCE
-#define _FORTIFY_SOURCE 2
-
-#include <gtest/gtest.h>
-#include <string.h>
-
-struct foo {
- char empty[0];
- char one[1];
- char a[10];
- char b[10];
-};
-
-// We have to say "DeathTest" here so gtest knows to run this test (which exits)
-// in its own process.
-TEST(Fortify2_DeathTest, strncpy_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- int copy_amt = atoi("11");
- ASSERT_EXIT(strncpy(myfoo.a, "01234567890", copy_amt),
- testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, sprintf_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- char source_buf[15];
- memcpy(source_buf, "12345678901234", 15);
- ASSERT_EXIT(sprintf(myfoo.a, "%s", source_buf),
- testing::KilledBySignal(SIGABRT), "");
-}
-
-#if __BIONIC__
-// zero sized target with "\0" source (should fail)
-TEST(Fortify2_DeathTest, strcpy_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- char* src = strdup("");
- ASSERT_EXIT(strcpy(myfoo.empty, src),
- testing::KilledBySignal(SIGABRT), "");
- free(src);
-}
-
-// zero sized target with longer source (should fail)
-TEST(Fortify2_DeathTest, strcpy2_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- char* src = strdup("1");
- ASSERT_EXIT(strcpy(myfoo.empty, src),
- testing::KilledBySignal(SIGABRT), "");
- free(src);
-}
-
-// one byte target with longer source (should fail)
-TEST(Fortify2_DeathTest, strcpy3_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- char* src = strdup("12");
- ASSERT_EXIT(strcpy(myfoo.one, src),
- testing::KilledBySignal(SIGABRT), "");
- free(src);
-}
-
-TEST(Fortify2_DeathTest, strchr_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
- myfoo.b[0] = '\0';
- ASSERT_EXIT(printf("%s", strchr(myfoo.a, 'a')),
- testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strrchr_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- memcpy(myfoo.a, "0123456789", 10);
- memcpy(myfoo.b, "01234", 6);
- ASSERT_EXIT(printf("%s", strrchr(myfoo.a, 'a')),
- testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strlcpy_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- strcpy(myfoo.a, "01");
- size_t n = strlen(myfoo.a);
- ASSERT_EXIT(strlcpy(myfoo.one, myfoo.a, n),
- testing::KilledBySignal(SIGABRT), "");
-}
-
-#endif
-
-TEST(Fortify2_DeathTest, strncat_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- size_t n = atoi("10"); // avoid compiler optimizations
- strncpy(myfoo.a, "012345678", n);
- ASSERT_EXIT(strncat(myfoo.a, "9", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strncat2_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- myfoo.a[0] = '\0';
- size_t n = atoi("10"); // avoid compiler optimizations
- ASSERT_EXIT(strncat(myfoo.a, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strncat3_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
- myfoo.b[0] = '\0';
- size_t n = atoi("10"); // avoid compiler optimizations
- ASSERT_EXIT(strncat(myfoo.b, myfoo.a, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strcat_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char src[11];
- strcpy(src, "0123456789");
- foo myfoo;
- myfoo.a[0] = '\0';
- ASSERT_EXIT(strcat(myfoo.a, src), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strcat2_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
- myfoo.b[0] = '\0';
- ASSERT_EXIT(strcat(myfoo.b, myfoo.a), testing::KilledBySignal(SIGABRT), "");
-}
-
-/***********************************************************/
-/* TESTS BELOW HERE DUPLICATE TESTS FROM fortify1_test.cpp */
-/***********************************************************/
-
-#if __BIONIC__
-// multibyte target where we over fill (should fail)
-TEST(Fortify2_DeathTest, strcpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- char *orig = strdup("0123456789");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-// zero sized target with "\0" source (should fail)
-TEST(Fortify2_DeathTest, strcpy2_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[0];
- char *orig = strdup("");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-// zero sized target with longer source (should fail)
-TEST(Fortify2_DeathTest, strcpy3_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[0];
- char *orig = strdup("1");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-// one byte target with longer source (should fail)
-TEST(Fortify2_DeathTest, strcpy4_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[1];
- char *orig = strdup("12");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-TEST(Fortify2_DeathTest, strlen_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strchr_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strrchr_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strlcpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char bufa[15];
- char bufb[10];
- strcpy(bufa, "01234567890123");
- size_t n = strlen(bufa);
- ASSERT_EXIT(strlcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-#endif
-
-TEST(Fortify2_DeathTest, sprintf_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- char source_buf[15];
- memcpy(source_buf, "12345678901234", 15);
- ASSERT_EXIT(sprintf(buf, "%s", source_buf), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strncat_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- size_t n = atoi("10"); // avoid compiler optimizations
- strncpy(buf, "012345678", n);
- ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strncat2_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- buf[0] = '\0';
- size_t n = atoi("10"); // avoid compiler optimizations
- ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strcat_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char src[11];
- strcpy(src, "0123456789");
- char buf[10];
- buf[0] = '\0';
- ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, memmove_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[20];
- strcpy(buf, "0123456789");
- size_t n = atoi("10");
- ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, memcpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char bufa[10];
- char bufb[10];
- strcpy(bufa, "012345678");
- size_t n = atoi("11");
- ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_DeathTest, strncpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char bufa[15];
- char bufb[10];
- strcpy(bufa, "01234567890123");
- size_t n = strlen(bufa);
- ASSERT_EXIT(strncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
diff --git a/tests/fortify2_test_clang.cpp b/tests/fortify2_test_clang.cpp
deleted file mode 100644
index d8a0ba6..0000000
--- a/tests/fortify2_test_clang.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#undef _FORTIFY_SOURCE
-#define _FORTIFY_SOURCE 2
-
-#include <gtest/gtest.h>
-#include <string.h>
-
-struct foo {
- char empty[0];
- char one[1];
- char a[10];
- char b[10];
-};
-
-// We have to say "DeathTest" here so gtest knows to run this test (which exits)
-// in its own process.
-TEST(Fortify2_Clang_DeathTest, strncat3_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
- myfoo.b[0] = '\0';
- size_t n = atoi("10"); // avoid compiler optimizations
- ASSERT_EXIT(strncat(myfoo.b, myfoo.a, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, strcat2_fortified2) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- foo myfoo;
- memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
- myfoo.b[0] = '\0';
- ASSERT_EXIT(strcat(myfoo.b, myfoo.a), testing::KilledBySignal(SIGABRT), "");
-}
-
-/*****************************************************************/
-/* TESTS BELOW HERE DUPLICATE TESTS FROM fortify1_test_clang.cpp */
-/*****************************************************************/
-
-#if __BIONIC__
-// multibyte target where we over fill (should fail)
-TEST(Fortify2_Clang_DeathTest, strcpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- char *orig = strdup("0123456789");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-// zero sized target with "\0" source (should fail)
-TEST(Fortify2_Clang_DeathTest, strcpy2_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[0];
- char *orig = strdup("");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-// zero sized target with longer source (should fail)
-TEST(Fortify2_Clang_DeathTest, strcpy3_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[0];
- char *orig = strdup("1");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-// one byte target with longer source (should fail)
-TEST(Fortify2_Clang_DeathTest, strcpy4_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[1];
- char *orig = strdup("12");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
- free(orig);
-}
-
-TEST(Fortify2_Clang_DeathTest, strlen_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, strchr_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, strrchr_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
-}
-#endif
-
-TEST(Fortify2_Clang_DeathTest, strncat_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- size_t n = atoi("10"); // avoid compiler optimizations
- strncpy(buf, "012345678", n);
- ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, strncat2_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- buf[0] = '\0';
- size_t n = atoi("10"); // avoid compiler optimizations
- ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, strcat_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char src[11];
- strcpy(src, "0123456789");
- char buf[10];
- buf[0] = '\0';
- ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, memmove_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[20];
- strcpy(buf, "0123456789");
- size_t n = atoi("10");
- ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, memcpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char bufa[10];
- char bufb[10];
- strcpy(bufa, "012345678");
- size_t n = atoi("11");
- ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-TEST(Fortify2_Clang_DeathTest, strncpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char bufa[15];
- char bufb[10];
- strcpy(bufa, "01234567890123");
- size_t n = strlen(bufa);
- ASSERT_EXIT(strncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
-}
-
-__BIONIC_FORTIFY_INLINE
-size_t test_fortify2_inline(char* buf) {
- return __bos(buf);
-}
-
-TEST(Fortify2_Clang, fortify_inline) {
- char buf[1024];
- // no-op. Prints nothing. Needed to prevent the compiler
- // from optimizing out buf.
- buf[0] = '\0';
- printf("%s", buf);
- ASSERT_EQ(sizeof(buf), test_fortify2_inline(buf));
-}
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
new file mode 100644
index 0000000..d8f0e76
--- /dev/null
+++ b/tests/fortify_test.cpp
@@ -0,0 +1,659 @@
+/*
+ * Copyright (C) 2013 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 <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.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
+// easy way to concatenate strings, so we need to use the complicated method
+// below. *sigh*
+#define DEATHTEST_PASTER(name) name##_DeathTest
+#define DEATHTEST_EVALUATOR(name) DEATHTEST_PASTER(name)
+#define DEATHTEST DEATHTEST_EVALUATOR(TEST_NAME)
+
+#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE == 2
+struct foo {
+ char empty[0];
+ char one[1];
+ char a[10];
+ char b[10];
+};
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strncpy_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ int copy_amt = atoi("11");
+ ASSERT_EXIT(strncpy(myfoo.a, "01234567890", copy_amt),
+ testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, sprintf_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ char source_buf[15];
+ memcpy(source_buf, "12345678901234", 15);
+ ASSERT_EXIT(sprintf(myfoo.a, "%s", source_buf),
+ testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, sprintf2_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ ASSERT_EXIT(sprintf(myfoo.a, "0123456789"),
+ testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// These tests are disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+static int vsprintf_helper2(const char *fmt, ...) {
+ foo myfoo;
+ va_list va;
+ int result;
+
+ va_start(va, fmt);
+ result = vsprintf(myfoo.a, fmt, va); // should crash here
+ va_end(va);
+ return result;
+}
+
+TEST(DEATHTEST, vsprintf_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ ASSERT_EXIT(vsprintf_helper2("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, vsprintf2_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ ASSERT_EXIT(vsprintf_helper2("0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// These tests are disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+static int vsnprintf_helper2(const char *fmt, ...) {
+ foo myfoo;
+ va_list va;
+ int result;
+ size_t size = atoi("11");
+
+ va_start(va, fmt);
+ result = vsnprintf(myfoo.a, size, fmt, va); // should crash here
+ va_end(va);
+ return result;
+}
+
+TEST(DEATHTEST, vsnprintf_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ ASSERT_EXIT(vsnprintf_helper2("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, vsnprintf2_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ ASSERT_EXIT(vsnprintf_helper2("0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#if __BIONIC__
+
+#ifndef __clang__
+// 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) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ char* src = strdup("");
+ ASSERT_EXIT(strcpy(myfoo.empty, src),
+ testing::KilledBySignal(SIGABRT), "");
+ free(src);
+}
+#endif
+
+#ifndef __clang__
+// 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) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ char* src = strdup("1");
+ ASSERT_EXIT(strcpy(myfoo.empty, src),
+ testing::KilledBySignal(SIGABRT), "");
+ free(src);
+}
+#endif
+
+#ifndef __clang__
+// 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) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ char* src = strdup("12");
+ ASSERT_EXIT(strcpy(myfoo.one, src),
+ testing::KilledBySignal(SIGABRT), "");
+ free(src);
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strchr_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
+ myfoo.b[0] = '\0';
+ ASSERT_EXIT(printf("%s", strchr(myfoo.a, 'a')),
+ testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strrchr_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ memcpy(myfoo.a, "0123456789", 10);
+ memcpy(myfoo.b, "01234", 6);
+ ASSERT_EXIT(printf("%s", strrchr(myfoo.a, 'a')),
+ testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strlcpy_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ strcpy(myfoo.a, "01");
+ size_t n = strlen(myfoo.a);
+ ASSERT_EXIT(strlcpy(myfoo.one, myfoo.a, n),
+ testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strlcat_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ strcpy(myfoo.a, "01");
+ myfoo.one[0] = '\0';
+ size_t n = strlen(myfoo.a);
+ ASSERT_EXIT(strlcat(myfoo.one, myfoo.a, n),
+ testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#endif /* __BIONIC__ */
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strncat_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ size_t n = atoi("10"); // avoid compiler optimizations
+ strncpy(myfoo.a, "012345678", n);
+ ASSERT_EXIT(strncat(myfoo.a, "9", n), testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strncat2_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ myfoo.a[0] = '\0';
+ size_t n = atoi("10"); // avoid compiler optimizations
+ ASSERT_EXIT(strncat(myfoo.a, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+TEST(DEATHTEST, strncat3_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
+ myfoo.b[0] = '\0';
+ size_t n = atoi("10"); // avoid compiler optimizations
+ ASSERT_EXIT(strncat(myfoo.b, myfoo.a, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+#ifndef __clang__
+// This test is disabled in clang because clang doesn't properly detect
+// this buffer overflow. TODO: Fix clang.
+TEST(DEATHTEST, strcat_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char src[11];
+ strcpy(src, "0123456789");
+ foo myfoo;
+ myfoo.a[0] = '\0';
+ ASSERT_EXIT(strcat(myfoo.a, src), testing::KilledBySignal(SIGABRT), "");
+}
+#endif
+
+TEST(DEATHTEST, strcat2_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
+ myfoo.b[0] = '\0';
+ ASSERT_EXIT(strcat(myfoo.b, myfoo.a), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, snprintf_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ strcpy(myfoo.a, "012345678");
+ size_t n = strlen(myfoo.a) + 2;
+ ASSERT_EXIT(snprintf(myfoo.b, n, "a%s", myfoo.a), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, bzero_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ memcpy(myfoo.b, "0123456789", sizeof(myfoo.b));
+ size_t n = atoi("11");
+ ASSERT_EXIT(bzero(myfoo.b, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+#endif /* defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE=2 */
+
+#if __BIONIC__
+// multibyte target where we over fill (should fail)
+TEST(DEATHTEST, strcpy_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ char *orig = strdup("0123456789");
+ ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
+ free(orig);
+}
+
+// zero sized target with "\0" source (should fail)
+TEST(DEATHTEST, strcpy2_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[0];
+ char *orig = strdup("");
+ ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
+ free(orig);
+}
+
+// zero sized target with longer source (should fail)
+TEST(DEATHTEST, strcpy3_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[0];
+ char *orig = strdup("1");
+ ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
+ free(orig);
+}
+
+// one byte target with longer source (should fail)
+TEST(DEATHTEST, strcpy4_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[1];
+ char *orig = strdup("12");
+ ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGABRT), "");
+ free(orig);
+}
+
+TEST(DEATHTEST, strlen_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ memcpy(buf, "0123456789", sizeof(buf));
+ ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strchr_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ memcpy(buf, "0123456789", sizeof(buf));
+ ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strrchr_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ memcpy(buf, "0123456789", sizeof(buf));
+ ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strlcpy_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char bufa[15];
+ char bufb[10];
+ strcpy(bufa, "01234567890123");
+ size_t n = strlen(bufa);
+ ASSERT_EXIT(strlcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strlcat_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char bufa[15];
+ char bufb[10];
+ bufb[0] = '\0';
+ strcpy(bufa, "01234567890123");
+ size_t n = strlen(bufa);
+ ASSERT_EXIT(strlcat(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+#endif
+
+TEST(DEATHTEST, sprintf_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ char source_buf[15];
+ memcpy(source_buf, "12345678901234", 15);
+ ASSERT_EXIT(sprintf(buf, "%s", source_buf), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, sprintf2_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[5];
+ ASSERT_EXIT(sprintf(buf, "aaaaa"), testing::KilledBySignal(SIGABRT), "");
+}
+
+static int vsprintf_helper(const char *fmt, ...) {
+ char buf[10];
+ va_list va;
+ int result;
+
+ va_start(va, fmt);
+ result = vsprintf(buf, fmt, va); // should crash here
+ va_end(va);
+ return result;
+}
+
+TEST(DEATHTEST, vsprintf_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ ASSERT_EXIT(vsprintf_helper("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, vsprintf2_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ ASSERT_EXIT(vsprintf_helper("0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+
+static int vsnprintf_helper(const char *fmt, ...) {
+ char buf[10];
+ va_list va;
+ int result;
+ size_t size = atoi("11");
+
+ va_start(va, fmt);
+ result = vsnprintf(buf, size, fmt, va); // should crash here
+ va_end(va);
+ return result;
+}
+
+TEST(DEATHTEST, vsnprintf_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ ASSERT_EXIT(vsnprintf_helper("%s", "0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, vsnprintf2_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ ASSERT_EXIT(vsnprintf_helper("0123456789"), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strncat_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ size_t n = atoi("10"); // avoid compiler optimizations
+ strncpy(buf, "012345678", n);
+ ASSERT_EXIT(strncat(buf, "9", n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strncat2_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ buf[0] = '\0';
+ size_t n = atoi("10"); // avoid compiler optimizations
+ ASSERT_EXIT(strncat(buf, "0123456789", n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strcat_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char src[11];
+ strcpy(src, "0123456789");
+ char buf[10];
+ buf[0] = '\0';
+ ASSERT_EXIT(strcat(buf, src), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, memmove_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[20];
+ strcpy(buf, "0123456789");
+ size_t n = atoi("10");
+ ASSERT_EXIT(memmove(buf + 11, buf, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, memcpy_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char bufa[10];
+ char bufb[10];
+ strcpy(bufa, "012345678");
+ size_t n = atoi("11");
+ ASSERT_EXIT(memcpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, strncpy_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char bufa[15];
+ char bufb[10];
+ strcpy(bufa, "01234567890123");
+ size_t n = strlen(bufa);
+ ASSERT_EXIT(strncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, snprintf_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char bufa[15];
+ char bufb[10];
+ strcpy(bufa, "0123456789");
+ size_t n = strlen(bufa) + 1;
+ ASSERT_EXIT(snprintf(bufb, n, "%s", bufa), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(DEATHTEST, bzero_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ memcpy(buf, "0123456789", sizeof(buf));
+ size_t n = atoi("11");
+ ASSERT_EXIT(bzero(buf, n), testing::KilledBySignal(SIGABRT), "");
+}
+
+TEST(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), "");
+}
+
+extern "C" char* __strncat_chk(char*, const char*, size_t, size_t);
+extern "C" char* __strcat_chk(char*, const char*, size_t);
+
+TEST(TEST_NAME, strncat) {
+ char buf[10];
+ memset(buf, 'A', sizeof(buf));
+ buf[0] = 'a';
+ buf[1] = '\0';
+ char* res = __strncat_chk(buf, "01234", sizeof(buf) - strlen(buf) - 1, sizeof(buf));
+ ASSERT_EQ(buf, res);
+ ASSERT_EQ('a', buf[0]);
+ ASSERT_EQ('0', buf[1]);
+ ASSERT_EQ('1', buf[2]);
+ ASSERT_EQ('2', buf[3]);
+ ASSERT_EQ('3', buf[4]);
+ ASSERT_EQ('4', buf[5]);
+ ASSERT_EQ('\0', buf[6]);
+ ASSERT_EQ('A', buf[7]);
+ ASSERT_EQ('A', buf[8]);
+ ASSERT_EQ('A', buf[9]);
+}
+
+TEST(TEST_NAME, strncat2) {
+ char buf[10];
+ memset(buf, 'A', sizeof(buf));
+ buf[0] = 'a';
+ buf[1] = '\0';
+ char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
+ ASSERT_EQ(buf, res);
+ ASSERT_EQ('a', buf[0]);
+ ASSERT_EQ('0', buf[1]);
+ ASSERT_EQ('1', buf[2]);
+ ASSERT_EQ('2', buf[3]);
+ ASSERT_EQ('3', buf[4]);
+ ASSERT_EQ('4', buf[5]);
+ ASSERT_EQ('\0', buf[6]);
+ ASSERT_EQ('A', buf[7]);
+ ASSERT_EQ('A', buf[8]);
+ ASSERT_EQ('A', buf[9]);
+}
+
+TEST(TEST_NAME, strncat3) {
+ char buf[10];
+ memset(buf, 'A', sizeof(buf));
+ buf[0] = '\0';
+ char* res = __strncat_chk(buf, "0123456789", 5, sizeof(buf));
+ ASSERT_EQ(buf, res);
+ ASSERT_EQ('0', buf[0]);
+ ASSERT_EQ('1', buf[1]);
+ ASSERT_EQ('2', buf[2]);
+ ASSERT_EQ('3', buf[3]);
+ ASSERT_EQ('4', buf[4]);
+ ASSERT_EQ('\0', buf[5]);
+ ASSERT_EQ('A', buf[6]);
+ ASSERT_EQ('A', buf[7]);
+ ASSERT_EQ('A', buf[8]);
+ ASSERT_EQ('A', buf[9]);
+}
+
+TEST(TEST_NAME, strncat4) {
+ char buf[10];
+ memset(buf, 'A', sizeof(buf));
+ buf[9] = '\0';
+ char* res = __strncat_chk(buf, "", 5, sizeof(buf));
+ ASSERT_EQ(buf, res);
+ ASSERT_EQ('A', buf[0]);
+ ASSERT_EQ('A', buf[1]);
+ ASSERT_EQ('A', buf[2]);
+ ASSERT_EQ('A', buf[3]);
+ ASSERT_EQ('A', buf[4]);
+ ASSERT_EQ('A', buf[5]);
+ ASSERT_EQ('A', buf[6]);
+ ASSERT_EQ('A', buf[7]);
+ ASSERT_EQ('A', buf[8]);
+ ASSERT_EQ('\0', buf[9]);
+}
+
+TEST(TEST_NAME, strncat5) {
+ char buf[10];
+ memset(buf, 'A', sizeof(buf));
+ buf[0] = 'a';
+ buf[1] = '\0';
+ char* res = __strncat_chk(buf, "01234567", 8, sizeof(buf));
+ ASSERT_EQ(buf, res);
+ ASSERT_EQ('a', buf[0]);
+ ASSERT_EQ('0', buf[1]);
+ ASSERT_EQ('1', buf[2]);
+ ASSERT_EQ('2', buf[3]);
+ ASSERT_EQ('3', buf[4]);
+ ASSERT_EQ('4', buf[5]);
+ ASSERT_EQ('5', buf[6]);
+ ASSERT_EQ('6', buf[7]);
+ ASSERT_EQ('7', buf[8]);
+ ASSERT_EQ('\0', buf[9]);
+}
+
+TEST(TEST_NAME, strncat6) {
+ char buf[10];
+ memset(buf, 'A', sizeof(buf));
+ buf[0] = 'a';
+ buf[1] = '\0';
+ char* res = __strncat_chk(buf, "01234567", 9, sizeof(buf));
+ ASSERT_EQ(buf, res);
+ ASSERT_EQ('a', buf[0]);
+ ASSERT_EQ('0', buf[1]);
+ ASSERT_EQ('1', buf[2]);
+ ASSERT_EQ('2', buf[3]);
+ ASSERT_EQ('3', buf[4]);
+ ASSERT_EQ('4', buf[5]);
+ ASSERT_EQ('5', buf[6]);
+ ASSERT_EQ('6', buf[7]);
+ ASSERT_EQ('7', buf[8]);
+ ASSERT_EQ('\0', buf[9]);
+}
+
+
+TEST(TEST_NAME, strcat) {
+ char buf[10];
+ memset(buf, 'A', sizeof(buf));
+ buf[0] = 'a';
+ buf[1] = '\0';
+ char* res = __strcat_chk(buf, "01234", sizeof(buf));
+ ASSERT_EQ(buf, res);
+ ASSERT_EQ('a', buf[0]);
+ ASSERT_EQ('0', buf[1]);
+ ASSERT_EQ('1', buf[2]);
+ ASSERT_EQ('2', buf[3]);
+ ASSERT_EQ('3', buf[4]);
+ ASSERT_EQ('4', buf[5]);
+ ASSERT_EQ('\0', buf[6]);
+ ASSERT_EQ('A', buf[7]);
+ ASSERT_EQ('A', buf[8]);
+ ASSERT_EQ('A', buf[9]);
+}
+
+TEST(TEST_NAME, strcat2) {
+ char buf[10];
+ memset(buf, 'A', sizeof(buf));
+ buf[0] = 'a';
+ buf[1] = '\0';
+ char* res = __strcat_chk(buf, "01234567", sizeof(buf));
+ ASSERT_EQ(buf, res);
+ ASSERT_EQ('a', buf[0]);
+ ASSERT_EQ('0', buf[1]);
+ ASSERT_EQ('1', buf[2]);
+ ASSERT_EQ('2', buf[3]);
+ ASSERT_EQ('3', buf[4]);
+ ASSERT_EQ('4', buf[5]);
+ ASSERT_EQ('5', buf[6]);
+ ASSERT_EQ('6', buf[7]);
+ ASSERT_EQ('7', buf[8]);
+ ASSERT_EQ('\0', buf[9]);
+}
diff --git a/tests/inttypes_test.cpp b/tests/inttypes_test.cpp
new file mode 100644
index 0000000..ec4a104
--- /dev/null
+++ b/tests/inttypes_test.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 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>
+
+#define __STDC_FORMAT_MACROS // Otherwise not available in C++.
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#if defined(__BIONIC__) // Doesn't work on glibc because we use -m32.
+TEST(inttypes, misc) {
+ char buf[512];
+
+ intptr_t i = 0;
+ uintptr_t u = 0;
+
+ snprintf(buf, sizeof(buf), "%08" PRIdPTR, i);
+ snprintf(buf, sizeof(buf), "%08" PRIiPTR, i);
+ snprintf(buf, sizeof(buf), "%08" PRIoPTR, i);
+ snprintf(buf, sizeof(buf), "%08" PRIuPTR, u);
+ snprintf(buf, sizeof(buf), "%08" PRIxPTR, u);
+ snprintf(buf, sizeof(buf), "%08" PRIXPTR, u);
+
+ sscanf(buf, "%08" SCNdPTR, &i);
+ sscanf(buf, "%08" SCNiPTR, &i);
+ sscanf(buf, "%08" SCNoPTR, &u);
+ sscanf(buf, "%08" SCNuPTR, &u);
+ sscanf(buf, "%08" SCNxPTR, &u);
+}
+#endif
diff --git a/tests/property_benchmark.cpp b/tests/property_benchmark.cpp
index 7266bd0..d10be91 100644
--- a/tests/property_benchmark.cpp
+++ b/tests/property_benchmark.cpp
@@ -23,7 +23,7 @@
#include <vector>
#include <string>
-extern void *__system_property_regions__[PA_REGION_COUNT];
+extern void *__system_property_area__;
#define TEST_NUM_PROPS \
Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)->Arg(1024)
@@ -39,10 +39,8 @@
return;
}
- for (size_t i = 0; i < PA_REGION_COUNT; i++) {
- old_pa[i] = __system_property_regions__[i];
- __system_property_regions__[i] = NULL;
- }
+ old_pa = __system_property_area__;
+ __system_property_area__ = NULL;
pa_dirname = dirname;
pa_filename = pa_dirname + "/__properties__";
@@ -79,9 +77,7 @@
if (!valid)
return;
- for (size_t i = 0; i < PA_REGION_COUNT; i++) {
- __system_property_regions__[i] = old_pa[i];
- }
+ __system_property_area__ = old_pa;
__system_property_set_filename(PROP_FILENAME);
unlink(pa_filename.c_str());
@@ -107,7 +103,7 @@
private:
std::string pa_dirname;
std::string pa_filename;
- void *old_pa[PA_REGION_COUNT];
+ void *old_pa;
};
static void BM_property_get(int iters, int nprops)
diff --git a/tests/stack_unwinding_test.cpp b/tests/stack_unwinding_test.cpp
new file mode 100644
index 0000000..3b18daa
--- /dev/null
+++ b/tests/stack_unwinding_test.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * Contributed by: Intel Corporation
+ */
+
+#include <gtest/gtest.h>
+
+#if defined(i386) // Only our x86 unwinding is good enough. Switch to libunwind?
+
+extern "C" {
+ void do_test();
+}
+
+// We have to say "DeathTest" here so gtest knows to run this test (which exits)
+// in its own process.
+TEST(stack_unwinding_DeathTest, unwinding_through_signal_frame) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ ASSERT_EXIT(do_test(), ::testing::ExitedWithCode(42), "");
+}
+
+#endif
diff --git a/tests/stack_unwinding_test_impl.c b/tests/stack_unwinding_test_impl.c
new file mode 100644
index 0000000..b0099f0
--- /dev/null
+++ b/tests/stack_unwinding_test_impl.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * Contributed by: Intel Corporation
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unwind.h>
+
+#define noinline __attribute__((__noinline__))
+#define unused __attribute__((__unused__))
+
+static noinline _Unwind_Reason_Code stop_fn(int a unused,
+ _Unwind_Action action,
+ _Unwind_Exception_Class b unused, struct _Unwind_Exception* c unused,
+ struct _Unwind_Context* d unused, void* e unused) {
+ if ((action & _UA_END_OF_STACK) != 0) {
+ // We reached the end of the stack without executing foo_cleanup. Test failed.
+ abort();
+ }
+ return _URC_NO_REASON;
+}
+
+static void noinline foo_cleanup(char* param unused) {
+ exit(42);
+}
+
+static void noinline do_crash() {
+ char* ptr = NULL;
+ *ptr = 0; // Deliberately cause a SIGSEGV.
+}
+
+static void noinline foo() {
+ char c1 __attribute__((cleanup(foo_cleanup)));
+ do_crash();
+}
+
+// It's SEGSEGV handler. We start forced stack unwinding here.
+// If libgcc don't find dso for signal frame stack unwinding will be finished.
+// libgcc pass to stop_fn _UA_END_OF_STACK flag.
+// Test pass condition: stack unwinding through signal frame and foo1_handler execution.
+static void noinline sigsegv_handler(int param unused) {
+ struct _Unwind_Exception* exception = (struct _Unwind_Exception*) malloc(sizeof(*exception));
+ memset(&exception->exception_class, 0, sizeof(exception->exception_class));
+ exception->exception_cleanup = 0;
+ _Unwind_ForcedUnwind(exception, stop_fn, 0);
+}
+
+void do_test() {
+ signal(SIGSEGV, &sigsegv_handler);
+ foo();
+}
diff --git a/tests/statvfs_test.cpp b/tests/statvfs_test.cpp
new file mode 100644
index 0000000..8afc6fd
--- /dev/null
+++ b/tests/statvfs_test.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 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 <sys/statvfs.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+TEST(statvfs, statvfs) {
+ struct statvfs sb;
+ memset(&sb, 0, sizeof(sb));
+
+ ASSERT_EQ(0, statvfs("/", &sb));
+#if __BIONIC__
+ ASSERT_EQ(0U, sb.f_bfree);
+ ASSERT_EQ(0U, sb.f_ffree);
+ ASSERT_EQ(0U, sb.f_fsid);
+ ASSERT_TRUE((sb.f_flag & ST_RDONLY) != 0);
+#endif
+
+#if __BIONIC__
+ ASSERT_EQ(0, statvfs("/data/data", &sb));
+ ASSERT_NE(0U, sb.f_bfree);
+ ASSERT_NE(0U, sb.f_ffree);
+ ASSERT_NE(0U, sb.f_fsid);
+ ASSERT_FALSE((sb.f_flag & ST_RDONLY) != 0);
+ ASSERT_TRUE((sb.f_flag & ST_NOSUID) != 0);
+#endif
+}
+
+TEST(statvfs, fstatvfs) {
+ struct statvfs sb;
+ memset(&sb, 0, sizeof(sb));
+
+ int fd = open("/", O_RDONLY);
+ ASSERT_EQ(0, fstatvfs(fd, &sb));
+ close(fd);
+#if __BIONIC__
+ ASSERT_EQ(0U, sb.f_bfree);
+ ASSERT_EQ(0U, sb.f_ffree);
+ ASSERT_EQ(0U, sb.f_fsid);
+ ASSERT_TRUE((sb.f_flag & ST_RDONLY) != 0);
+#endif
+
+#if __BIONIC__
+ fd = open("/data/data", O_RDONLY);
+ ASSERT_EQ(0, fstatvfs(fd, &sb));
+ close(fd);
+ ASSERT_NE(0U, sb.f_bfree);
+ ASSERT_NE(0U, sb.f_ffree);
+ ASSERT_NE(0U, sb.f_fsid);
+ ASSERT_FALSE((sb.f_flag & ST_RDONLY) != 0);
+ ASSERT_TRUE((sb.f_flag & ST_NOSUID) != 0);
+#endif
+}
diff --git a/tests/system_properties_test.cpp b/tests/system_properties_test.cpp
index 50bdfdf..b9256c6 100644
--- a/tests/system_properties_test.cpp
+++ b/tests/system_properties_test.cpp
@@ -24,7 +24,7 @@
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
-extern void *__system_property_regions__[PA_REGION_COUNT];
+extern void *__system_property_area__;
struct LocalPropertyTestState {
LocalPropertyTestState() : valid(false) {
@@ -35,10 +35,8 @@
return;
}
- for (size_t i = 0; i < PA_REGION_COUNT; i++) {
- old_pa[i] = __system_property_regions__[i];
- __system_property_regions__[i] = NULL;
- }
+ old_pa = __system_property_area__;
+ __system_property_area__ = NULL;
pa_dirname = dirname;
pa_filename = pa_dirname + "/__properties__";
@@ -52,9 +50,7 @@
if (!valid)
return;
- for (size_t i = 0; i < PA_REGION_COUNT; i++) {
- __system_property_regions__[i] = old_pa[i];
- }
+ __system_property_area__ = old_pa;
__system_property_set_filename(PROP_FILENAME);
unlink(pa_filename.c_str());
@@ -65,7 +61,7 @@
private:
std::string pa_dirname;
std::string pa_filename;
- void *old_pa[PA_REGION_COUNT];
+ void *old_pa;
};
TEST(properties, add) {
@@ -202,6 +198,84 @@
ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(247));
}
+static void hierarchical_test_callback(const prop_info *pi, void *cookie) {
+ bool (*ok)[8][8] = static_cast<bool (*)[8][8]>(cookie);
+
+ char name[PROP_NAME_MAX];
+ char value[PROP_VALUE_MAX];
+
+ __system_property_read(pi, name, value);
+
+ int name_i, name_j, name_k;
+ int value_i, value_j, value_k;
+ ASSERT_EQ(3, sscanf(name, "property_%d.%d.%d", &name_i, &name_j, &name_k));
+ ASSERT_EQ(3, sscanf(value, "value_%d.%d.%d", &value_i, &value_j, &value_k));
+ ASSERT_EQ(name_i, value_i);
+ ASSERT_GE(name_i, 0);
+ ASSERT_LT(name_i, 8);
+ ASSERT_EQ(name_j, value_j);
+ ASSERT_GE(name_j, 0);
+ ASSERT_LT(name_j, 8);
+ ASSERT_EQ(name_k, value_k);
+ ASSERT_GE(name_k, 0);
+ ASSERT_LT(name_k, 8);
+
+ ok[name_i][name_j][name_k] = true;
+}
+
+TEST(properties, fill_hierarchical) {
+ LocalPropertyTestState pa;
+ ASSERT_TRUE(pa.valid);
+ char prop_name[PROP_NAME_MAX];
+ char prop_value[PROP_VALUE_MAX];
+ char prop_value_ret[PROP_VALUE_MAX];
+ int ret;
+
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 8; j++) {
+ for (int k = 0; k < 8; k++) {
+ ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
+ memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
+ ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
+ memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
+ prop_name[PROP_NAME_MAX - 1] = 0;
+ prop_value[PROP_VALUE_MAX - 1] = 0;
+
+ ASSERT_EQ(0, __system_property_add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1));
+ }
+ }
+ }
+
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 8; j++) {
+ for (int k = 0; k < 8; k++) {
+ ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
+ memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
+ ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
+ memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
+ prop_name[PROP_NAME_MAX - 1] = 0;
+ prop_value[PROP_VALUE_MAX - 1] = 0;
+ memset(prop_value_ret, '\0', PROP_VALUE_MAX);
+
+ ASSERT_EQ(PROP_VALUE_MAX - 1, __system_property_get(prop_name, prop_value_ret));
+ ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX));
+ }
+ }
+ }
+
+ bool ok[8][8][8];
+ memset(ok, 0, sizeof(ok));
+ __system_property_foreach(hierarchical_test_callback, ok);
+
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 8; j++) {
+ for (int k = 0; k < 8; k++) {
+ ASSERT_TRUE(ok[i][j][k]);
+ }
+ }
+ }
+}
+
TEST(properties, errors) {
LocalPropertyTestState pa;
ASSERT_TRUE(pa.valid);