From 4c30130a2155c37e80af4c3b53bf4f6ce832e760 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 27 Oct 2014 13:38:21 -0700 Subject: [PATCH 1/9] Disable tzdata in $ANDROID_DATA. Bug: 18139284 Change-Id: I2670dc1791d635139a5d39a438dc08777439476b --- libc/tzcode/localtime.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c index 3bbed9086..28d13f417 100644 --- a/libc/tzcode/localtime.c +++ b/libc/tzcode/localtime.c @@ -2252,14 +2252,11 @@ static int __bionic_open_tzdata_path(const char* path_prefix_variable, const cha } static int __bionic_open_tzdata(const char* olson_id, int* data_size) { - int fd = __bionic_open_tzdata_path("ANDROID_DATA", "/misc/zoneinfo/tzdata", olson_id, data_size); - if (fd < 0) { - fd = __bionic_open_tzdata_path("ANDROID_ROOT", "/usr/share/zoneinfo/tzdata", olson_id, data_size); - if (fd == -2) { - // The first thing that 'recovery' does is try to format the current time. It doesn't have - // any tzdata available, so we must not abort here --- doing so breaks the recovery image! - fprintf(stderr, "%s: couldn't find any tzdata when looking for %s!\n", __FUNCTION__, olson_id); - } + int fd = __bionic_open_tzdata_path("ANDROID_ROOT", "/usr/share/zoneinfo/tzdata", olson_id, data_size); + if (fd == -2) { + // The first thing that 'recovery' does is try to format the current time. It doesn't have + // any tzdata available, so we must not abort here --- doing so breaks the recovery image! + fprintf(stderr, "%s: couldn't find any tzdata when looking for %s!\n", __FUNCTION__, olson_id); } return fd; } From 7dc2b7b30ddc158a5e7aa6945526eb65d354b96c Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 10 Sep 2014 15:20:40 -0700 Subject: [PATCH 2/9] Fix signal trampolines. * LP32 should use sa_restorer too. gdb expects this, and future (>= 3.15) x86 kernels will apparently stop supporting the case where SA_RESTORER isn't set. * gdb and libunwind care about the exact instruction sequences, so we need to modify the code slightly in a few cases to match what they're looking for. * gdb also cares about the exact function names (for some architectures), so we need to use __restore and __restore_rt rather than __sigreturn and __rt_sigreturn. * It's possible that we don't have a VDSO; dl_iterate_phdr shouldn't assume that getauxval(AT_SYSINFO_EHDR) will return a non-null pointer. This fixes unwinding through a signal handler in gdb for all architectures. It doesn't fix libunwind for arm and arm64. I'll keep investigating that... (cherry picked from commit 36f451a6d93b6807944d99fa23396e039c47e845) Bug: 17436734 Change-Id: Ic1ea1184db6655c5d96180dc07bcc09628e647cb --- libc/arch-arm/arm.mk | 2 + libc/arch-arm/bionic/__restore.S | 35 ++++++++++++++++++ libc/arch-arm/bionic/__restore_rt.S | 35 ++++++++++++++++++ libc/arch-arm64/arm64.mk | 2 +- .../{__rt_sigreturn.S => __restore_rt.S} | 9 +++-- libc/arch-x86/bionic/__restore.S | 37 +++++++++++++++++++ libc/arch-x86/bionic/__restore_rt.S | 36 ++++++++++++++++++ libc/arch-x86/x86.mk | 2 + .../{__rt_sigreturn.S => __restore_rt.S} | 8 ++-- libc/arch-x86_64/x86_64.mk | 2 +- libc/bionic/dl_iterate_phdr_static.cpp | 5 +++ libc/bionic/sigaction.cpp | 22 +++++++++-- 12 files changed, 183 insertions(+), 12 deletions(-) create mode 100644 libc/arch-arm/bionic/__restore.S create mode 100644 libc/arch-arm/bionic/__restore_rt.S rename libc/arch-arm64/bionic/{__rt_sigreturn.S => __restore_rt.S} (89%) create mode 100644 libc/arch-x86/bionic/__restore.S create mode 100644 libc/arch-x86/bionic/__restore_rt.S rename libc/arch-x86_64/bionic/{__rt_sigreturn.S => __restore_rt.S} (87%) diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk index 70cc8eba6..fbde87cef 100644 --- a/libc/arch-arm/arm.mk +++ b/libc/arch-arm/arm.mk @@ -55,6 +55,8 @@ libc_bionic_src_files_arm += \ arch-arm/bionic/_exit_with_stack_teardown.S \ arch-arm/bionic/libgcc_compat.c \ arch-arm/bionic/memcmp.S \ + arch-arm/bionic/__restore_rt.S \ + arch-arm/bionic/__restore.S \ arch-arm/bionic/_setjmp.S \ arch-arm/bionic/setjmp.S \ arch-arm/bionic/sigsetjmp.S \ diff --git a/libc/arch-arm/bionic/__restore.S b/libc/arch-arm/bionic/__restore.S new file mode 100644 index 000000000..e76628e16 --- /dev/null +++ b/libc/arch-arm/bionic/__restore.S @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +// This function must have exactly this instruction sequence for gdb and libunwind. +ENTRY_PRIVATE(__restore) + mov r7, #__NR_sigreturn + swi #0 +END(__restore) diff --git a/libc/arch-arm/bionic/__restore_rt.S b/libc/arch-arm/bionic/__restore_rt.S new file mode 100644 index 000000000..5a1fca182 --- /dev/null +++ b/libc/arch-arm/bionic/__restore_rt.S @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +// This function must have exactly this instruction sequence for gdb and libunwind. +ENTRY_PRIVATE(__restore_rt) + mov r7, #__NR_rt_sigreturn + swi #0 +END(__restore_rt) diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk index 6c4f6a6e8..91cd9fb1c 100644 --- a/libc/arch-arm64/arm64.mk +++ b/libc/arch-arm64/arm64.mk @@ -29,7 +29,7 @@ libc_common_src_files_arm64 += \ libc_bionic_src_files_arm64 := \ arch-arm64/bionic/__bionic_clone.S \ arch-arm64/bionic/_exit_with_stack_teardown.S \ - arch-arm64/bionic/__rt_sigreturn.S \ + arch-arm64/bionic/__restore_rt.S \ arch-arm64/bionic/_setjmp.S \ arch-arm64/bionic/setjmp.S \ arch-arm64/bionic/__set_tls.c \ diff --git a/libc/arch-arm64/bionic/__rt_sigreturn.S b/libc/arch-arm64/bionic/__restore_rt.S similarity index 89% rename from libc/arch-arm64/bionic/__rt_sigreturn.S rename to libc/arch-arm64/bionic/__restore_rt.S index 8fb6f0c28..95064903e 100644 --- a/libc/arch-arm64/bionic/__rt_sigreturn.S +++ b/libc/arch-arm64/bionic/__restore_rt.S @@ -28,7 +28,8 @@ #include -ENTRY_PRIVATE(__rt_sigreturn) - mov x8, __NR_rt_sigreturn - svc #0 -END(__rt_sigreturn) +// This function must have exactly this instruction sequence for gdb and libunwind. +ENTRY_PRIVATE(__restore_rt) + mov x8, __NR_rt_sigreturn + svc #0 +END(__restore_rt) diff --git a/libc/arch-x86/bionic/__restore.S b/libc/arch-x86/bionic/__restore.S new file mode 100644 index 000000000..755c3f8e5 --- /dev/null +++ b/libc/arch-x86/bionic/__restore.S @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +// This function must have exactly this instruction sequence for gdb and libunwind. +// This function must have exactly this name for gdb. +ENTRY(__restore) + popl %eax + movl $__NR_sigreturn, %eax + int $0x80 +END(__restore) diff --git a/libc/arch-x86/bionic/__restore_rt.S b/libc/arch-x86/bionic/__restore_rt.S new file mode 100644 index 000000000..0cd808125 --- /dev/null +++ b/libc/arch-x86/bionic/__restore_rt.S @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +// This function must have exactly this instruction sequence for gdb and libunwind. +// This function must have exactly this name for gdb. +ENTRY(__restore_rt) + movl $__NR_rt_sigreturn, %eax + int $0x80 +END(__restore_rt) diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk index 2a0609dde..905519745 100644 --- a/libc/arch-x86/x86.mk +++ b/libc/arch-x86/x86.mk @@ -26,6 +26,8 @@ libc_bionic_src_files_x86 += \ arch-x86/bionic/__bionic_clone.S \ arch-x86/bionic/_exit_with_stack_teardown.S \ arch-x86/bionic/libgcc_compat.c \ + arch-x86/bionic/__restore_rt.S \ + arch-x86/bionic/__restore.S \ arch-x86/bionic/_setjmp.S \ arch-x86/bionic/setjmp.S \ arch-x86/bionic/__set_tls.c \ diff --git a/libc/arch-x86_64/bionic/__rt_sigreturn.S b/libc/arch-x86_64/bionic/__restore_rt.S similarity index 87% rename from libc/arch-x86_64/bionic/__rt_sigreturn.S rename to libc/arch-x86_64/bionic/__restore_rt.S index eddceb15b..d84be219a 100644 --- a/libc/arch-x86_64/bionic/__rt_sigreturn.S +++ b/libc/arch-x86_64/bionic/__restore_rt.S @@ -28,7 +28,9 @@ #include -ENTRY_PRIVATE(__rt_sigreturn) - movl $__NR_rt_sigreturn, %eax +// This function must have exactly this instruction sequence for gdb and libunwind. +// This function must have exactly this name for gdb. +ENTRY(__restore_rt) + mov $__NR_rt_sigreturn, %rax syscall -END(__rt_sigreturn) +END(__restore_rt) diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk index b001b5e98..5f12a49d7 100644 --- a/libc/arch-x86_64/x86_64.mk +++ b/libc/arch-x86_64/x86_64.mk @@ -30,7 +30,7 @@ libc_common_src_files_x86_64 += \ libc_bionic_src_files_x86_64 := \ arch-x86_64/bionic/__bionic_clone.S \ arch-x86_64/bionic/_exit_with_stack_teardown.S \ - arch-x86_64/bionic/__rt_sigreturn.S \ + arch-x86_64/bionic/__restore_rt.S \ arch-x86_64/bionic/_setjmp.S \ arch-x86_64/bionic/setjmp.S \ arch-x86_64/bionic/__set_tls.c \ diff --git a/libc/bionic/dl_iterate_phdr_static.cpp b/libc/bionic/dl_iterate_phdr_static.cpp index 155a7a00a..2196ac8b2 100644 --- a/libc/bionic/dl_iterate_phdr_static.cpp +++ b/libc/bionic/dl_iterate_phdr_static.cpp @@ -62,6 +62,11 @@ int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data // Try the VDSO if that didn't work. ElfW(Ehdr)* ehdr_vdso = reinterpret_cast(getauxval(AT_SYSINFO_EHDR)); + if (ehdr_vdso == nullptr) { + // There is no VDSO, so there's nowhere left to look. + return rc; + } + struct dl_phdr_info vdso_info; vdso_info.dlpi_addr = 0; vdso_info.dlpi_name = NULL; diff --git a/libc/bionic/sigaction.cpp b/libc/bionic/sigaction.cpp index 225a8233e..8ba4e2a2d 100644 --- a/libc/bionic/sigaction.cpp +++ b/libc/bionic/sigaction.cpp @@ -28,8 +28,10 @@ #include +extern "C" void __restore_rt(void); +extern "C" void __restore(void); + #if __LP64__ -extern "C" void __rt_sigreturn(void); extern "C" int __rt_sigaction(int, const struct __kernel_sigaction*, struct __kernel_sigaction*, size_t); #else extern "C" int __sigaction(int, const struct sigaction*, struct sigaction*); @@ -47,7 +49,7 @@ int sigaction(int signal, const struct sigaction* bionic_new_action, struct siga if (!(kernel_new_action.sa_flags & SA_RESTORER)) { kernel_new_action.sa_flags |= SA_RESTORER; - kernel_new_action.sa_restorer = &__rt_sigreturn; + kernel_new_action.sa_restorer = &__restore_rt; } #endif } @@ -75,6 +77,20 @@ int sigaction(int signal, const struct sigaction* bionic_new_action, struct siga #else // The 32-bit ABI is broken. struct sigaction includes a too-small sigset_t. // TODO: if we also had correct struct sigaction definitions available, we could copy in and out. - return __sigaction(signal, bionic_new_action, bionic_old_action); + struct sigaction kernel_new_action; + if (bionic_new_action != NULL) { + kernel_new_action.sa_flags = bionic_new_action->sa_flags; + kernel_new_action.sa_handler = bionic_new_action->sa_handler; + kernel_new_action.sa_mask = bionic_new_action->sa_mask; +#ifdef SA_RESTORER + kernel_new_action.sa_restorer = bionic_new_action->sa_restorer; + + if (!(kernel_new_action.sa_flags & SA_RESTORER)) { + kernel_new_action.sa_flags |= SA_RESTORER; + kernel_new_action.sa_restorer = (kernel_new_action.sa_flags & SA_SIGINFO) ? &__restore_rt : &__restore; + } +#endif + } + return __sigaction(signal, (bionic_new_action != NULL) ? &kernel_new_action : NULL, bionic_old_action); #endif } From 5054e1a121fc5aca814815625fe230c4a8abd5a5 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 16 Sep 2014 13:57:39 -0700 Subject: [PATCH 3/9] Fix 32-bit arm unwinding through signal frames. gdb was already okay; libgcc and libunwind need a little extra help. Bug: 17436734 (cherry picked from commit 148dff3ec6114a03acc722ae43990f1b342abad9) Change-Id: I2cc997017acc57c930284af5264f353656b98c7b --- libc/arch-arm/arm.mk | 1 - libc/arch-arm/bionic/__restore.S | 28 ++++++++++++++++++++++- libc/arch-arm/bionic/__restore_rt.S | 35 ----------------------------- 3 files changed, 27 insertions(+), 37 deletions(-) delete mode 100644 libc/arch-arm/bionic/__restore_rt.S diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk index fbde87cef..b1edfccf3 100644 --- a/libc/arch-arm/arm.mk +++ b/libc/arch-arm/arm.mk @@ -55,7 +55,6 @@ libc_bionic_src_files_arm += \ arch-arm/bionic/_exit_with_stack_teardown.S \ arch-arm/bionic/libgcc_compat.c \ arch-arm/bionic/memcmp.S \ - arch-arm/bionic/__restore_rt.S \ arch-arm/bionic/__restore.S \ arch-arm/bionic/_setjmp.S \ arch-arm/bionic/setjmp.S \ diff --git a/libc/arch-arm/bionic/__restore.S b/libc/arch-arm/bionic/__restore.S index e76628e16..98981256b 100644 --- a/libc/arch-arm/bionic/__restore.S +++ b/libc/arch-arm/bionic/__restore.S @@ -28,8 +28,34 @@ #include -// This function must have exactly this instruction sequence for gdb and libunwind. +// gdb is smart enough to unwind through signal frames with just the regular +// CFI information but libgcc and libunwind both need extra help. We do this +// by using .fnstart/.fnend and inserting a nop before both __restore and +// __restore_rt (but covered by the .fnstart/.fnend) so that although they're +// not inside the functions from objdump's point of view, an unwinder that +// blindly looks at the previous instruction (but is then smart enough to check +// the DWARF information to find out where it landed) gets the right answer. + +// We need to place .fnstart ourselves (but we may as well keep the free .fnend). +#undef __bionic_asm_custom_entry +#define __bionic_asm_custom_entry(f) + + .fnstart + .save {r0-r15} + .pad #32 + nop ENTRY_PRIVATE(__restore) + // This function must have exactly this instruction sequence. mov r7, #__NR_sigreturn swi #0 END(__restore) + + .fnstart + .save {r0-r15} + .pad #160 + nop +ENTRY_PRIVATE(__restore_rt) + // This function must have exactly this instruction sequence. + mov r7, #__NR_rt_sigreturn + swi #0 +END(__restore_rt) diff --git a/libc/arch-arm/bionic/__restore_rt.S b/libc/arch-arm/bionic/__restore_rt.S deleted file mode 100644 index 5a1fca182..000000000 --- a/libc/arch-arm/bionic/__restore_rt.S +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -// This function must have exactly this instruction sequence for gdb and libunwind. -ENTRY_PRIVATE(__restore_rt) - mov r7, #__NR_rt_sigreturn - swi #0 -END(__restore_rt) From e5e61a0a920a8e6560735b2e565c3bd7a1e35ba5 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 16 Sep 2014 15:49:50 -0700 Subject: [PATCH 4/9] Use the kernel's sa_restorer for aarch64. gdb was happy with what we had, but libgcc and libunwind weren't. libgcc is happy with the kernel's restorer (because of the extra nop), though libunwind looks like it's going to need code changes regardless. We could make our restorer more like the kernel's one, but why bother when we can just let the kernel supply the canonical one? Bug: 17436734 (cherry picked from commit 1cff9a89645a8f362a9ce19c7f9544e98c1fd9e7) Change-Id: Ie13d73fd97395e1979a67c2294e036a97c50000d --- libc/arch-arm64/arm64.mk | 1 - libc/arch-arm64/bionic/__restore_rt.S | 35 --------------------------- libc/bionic/sigaction.cpp | 34 +++++++++++++++++--------- 3 files changed, 22 insertions(+), 48 deletions(-) delete mode 100644 libc/arch-arm64/bionic/__restore_rt.S diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk index 91cd9fb1c..eb65cfd1f 100644 --- a/libc/arch-arm64/arm64.mk +++ b/libc/arch-arm64/arm64.mk @@ -29,7 +29,6 @@ libc_common_src_files_arm64 += \ libc_bionic_src_files_arm64 := \ arch-arm64/bionic/__bionic_clone.S \ arch-arm64/bionic/_exit_with_stack_teardown.S \ - arch-arm64/bionic/__restore_rt.S \ arch-arm64/bionic/_setjmp.S \ arch-arm64/bionic/setjmp.S \ arch-arm64/bionic/__set_tls.c \ diff --git a/libc/arch-arm64/bionic/__restore_rt.S b/libc/arch-arm64/bionic/__restore_rt.S deleted file mode 100644 index 95064903e..000000000 --- a/libc/arch-arm64/bionic/__restore_rt.S +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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. - */ - -#include - -// This function must have exactly this instruction sequence for gdb and libunwind. -ENTRY_PRIVATE(__restore_rt) - mov x8, __NR_rt_sigreturn - svc #0 -END(__restore_rt) diff --git a/libc/bionic/sigaction.cpp b/libc/bionic/sigaction.cpp index 8ba4e2a2d..9038bd544 100644 --- a/libc/bionic/sigaction.cpp +++ b/libc/bionic/sigaction.cpp @@ -31,26 +31,29 @@ extern "C" void __restore_rt(void); extern "C" void __restore(void); -#if __LP64__ +#if defined(__LP64__) + extern "C" int __rt_sigaction(int, const struct __kernel_sigaction*, struct __kernel_sigaction*, size_t); -#else -extern "C" int __sigaction(int, const struct sigaction*, struct sigaction*); -#endif int sigaction(int signal, const struct sigaction* bionic_new_action, struct sigaction* bionic_old_action) { -#if __LP64__ __kernel_sigaction kernel_new_action; if (bionic_new_action != NULL) { kernel_new_action.sa_flags = bionic_new_action->sa_flags; kernel_new_action.sa_handler = bionic_new_action->sa_handler; kernel_new_action.sa_mask = bionic_new_action->sa_mask; -#ifdef SA_RESTORER +#if defined(SA_RESTORER) kernel_new_action.sa_restorer = bionic_new_action->sa_restorer; - +#if defined(__aarch64__) + // arm64 has sa_restorer, but unwinding works best if you just let the + // kernel supply the default restorer from [vdso]. gdb doesn't care, but + // libgcc needs the nop that the kernel includes before the actual code. + // (We could add that ourselves, but why bother?) +#else if (!(kernel_new_action.sa_flags & SA_RESTORER)) { kernel_new_action.sa_flags |= SA_RESTORER; kernel_new_action.sa_restorer = &__restore_rt; } +#endif #endif } @@ -64,7 +67,7 @@ int sigaction(int signal, const struct sigaction* bionic_new_action, struct siga bionic_old_action->sa_flags = kernel_old_action.sa_flags; bionic_old_action->sa_handler = kernel_old_action.sa_handler; bionic_old_action->sa_mask = kernel_old_action.sa_mask; -#ifdef SA_RESTORER +#if defined(SA_RESTORER) bionic_old_action->sa_restorer = kernel_old_action.sa_restorer; if (bionic_old_action->sa_restorer == &__rt_sigreturn) { @@ -74,15 +77,21 @@ int sigaction(int signal, const struct sigaction* bionic_new_action, struct siga } return result; +} + #else - // The 32-bit ABI is broken. struct sigaction includes a too-small sigset_t. - // TODO: if we also had correct struct sigaction definitions available, we could copy in and out. + +extern "C" int __sigaction(int, const struct sigaction*, struct sigaction*); + +int sigaction(int signal, const struct sigaction* bionic_new_action, struct sigaction* bionic_old_action) { + // The 32-bit ABI is broken. struct sigaction includes a too-small sigset_t, + // so we have to use sigaction(2) rather than rt_sigaction(2). struct sigaction kernel_new_action; if (bionic_new_action != NULL) { kernel_new_action.sa_flags = bionic_new_action->sa_flags; kernel_new_action.sa_handler = bionic_new_action->sa_handler; kernel_new_action.sa_mask = bionic_new_action->sa_mask; -#ifdef SA_RESTORER +#if defined(SA_RESTORER) kernel_new_action.sa_restorer = bionic_new_action->sa_restorer; if (!(kernel_new_action.sa_flags & SA_RESTORER)) { @@ -92,5 +101,6 @@ int sigaction(int signal, const struct sigaction* bionic_new_action, struct siga #endif } return __sigaction(signal, (bionic_new_action != NULL) ? &kernel_new_action : NULL, bionic_old_action); -#endif } + +#endif From 190dce9e56c750be6b8d113ffdd32a9c20c19e3d Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 17 Sep 2014 17:21:20 -0700 Subject: [PATCH 5/9] Stack unwinding unit tests. Bug: 17436734 (cherry picked from commit bee1993a14b47bc7acda544242f405ae45e42566) Change-Id: I7205a862ba2c3b474e287f5e9c8982cef4610af9 --- tests/Android.mk | 30 +++-------- tests/stack_unwinding_test.cpp | 83 +++++++++++++++++++++++++++---- tests/stack_unwinding_test_impl.c | 51 +++++++++---------- 3 files changed, 104 insertions(+), 60 deletions(-) diff --git a/tests/Android.mk b/tests/Android.mk index dd430490b..23a2cb3ed 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -88,7 +88,6 @@ libBionicStandardTests_src_files := \ search_test.cpp \ signal_test.cpp \ stack_protector_test.cpp \ - stack_unwinding_test.cpp \ stdatomic_test.cpp \ stdint_test.cpp \ stdio_test.cpp \ @@ -134,9 +133,6 @@ libBionicStandardTests_c_includes := \ libBionicStandardTests_ldlibs_host := \ -lrt \ -libBionicStandardTests_whole_static_libraries := \ - libBionicUnwindTest \ - module := libBionicStandardTests module_tag := optional build_type := target @@ -145,25 +141,6 @@ include $(LOCAL_PATH)/Android.build.mk build_type := host include $(LOCAL_PATH)/Android.build.mk -# ----------------------------------------------------------------------------- -# Special stack unwinding test library compiled with special flags. -# ----------------------------------------------------------------------------- -libBionicUnwindTest_cflags := \ - $(test_cflags) \ - -fexceptions \ - -fnon-call-exceptions \ - -libBionicUnwindTest_src_files := \ - stack_unwinding_test_impl.c \ - -module := libBionicUnwindTest -module_tag := optional -build_type := target -build_target := STATIC_TEST_LIBRARY -include $(LOCAL_PATH)/Android.build.mk -build_type := host -include $(LOCAL_PATH)/Android.build.mk - # ----------------------------------------------------------------------------- # Fortify tests. # ----------------------------------------------------------------------------- @@ -247,8 +224,15 @@ bionic-unit-tests_src_files := \ atexit_test.cpp \ dlext_test.cpp \ dlfcn_test.cpp \ + stack_unwinding_test.cpp \ + stack_unwinding_test_impl.c \ bionic-unit-tests_cflags := $(test_cflags) + +bionic-unit-tests_conlyflags := \ + -fexceptions \ + -fnon-call-exceptions \ + bionic-unit-tests_cppflags := $(test_cppflags) bionic-unit-tests_ldflags := \ diff --git a/tests/stack_unwinding_test.cpp b/tests/stack_unwinding_test.cpp index 1024f28f1..017a5f2e8 100644 --- a/tests/stack_unwinding_test.cpp +++ b/tests/stack_unwinding_test.cpp @@ -20,18 +20,83 @@ #include -extern "C" { - void do_test(); +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ScopedSignalHandler.h" + +#define noinline __attribute__((noinline)) + +static _Unwind_Reason_Code FrameCounter(_Unwind_Context* ctx __unused, void* arg) { + int* count_ptr = reinterpret_cast(arg); + +#if SHOW_FRAME_LOCATIONS + void* ip = reinterpret_cast(_Unwind_GetIP(ctx)); + + const char* symbol = ""; + int offset = 0; + + Dl_info info; + memset(&info, 0, sizeof(info)); + if (dladdr(ip, &info) != 0) { + symbol = info.dli_sname; + if (info.dli_saddr != nullptr) { + offset = static_cast(reinterpret_cast(ip) - reinterpret_cast(info.dli_saddr)); + } + } + + fprintf(stderr, " #%02d %p %s%+d (%s)\n", *count_ptr, ip, symbol, offset, info.dli_fname ? info.dli_fname : "??"); + fflush(stderr); +#endif + + ++*count_ptr; + return _URC_NO_REASON; } +static int noinline unwind_one_frame_deeper() { + int count = 0; + _Unwind_Backtrace(FrameCounter, &count); + return count; +} + +TEST(stack_unwinding, easy) { + int count = 0; + _Unwind_Backtrace(FrameCounter, &count); + int deeper_count = unwind_one_frame_deeper(); + ASSERT_EQ(count + 1, deeper_count); +} + +static int killer_count = 0; +static int handler_count = 0; +static int handler_one_deeper_count = 0; + +static void noinline UnwindSignalHandler(int) { + _Unwind_Backtrace(FrameCounter, &handler_count); + ASSERT_GT(handler_count, killer_count); + + handler_one_deeper_count = unwind_one_frame_deeper(); + ASSERT_EQ(handler_count + 1, handler_one_deeper_count); +} + +TEST(stack_unwinding, unwind_through_signal_frame) { + ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler); + + _Unwind_Backtrace(FrameCounter, &killer_count); + + ASSERT_EQ(0, kill(getpid(), SIGUSR1)); +} + +extern "C" void unwind_through_frame_with_cleanup_function(); + // 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) { -// Only our x86 unwinding is good enough. Switch to libunwind? -#if defined(__BIONIC__) && defined(__i386__) +TEST(stack_unwinding_DeathTest, unwind_through_frame_with_cleanup_function) { ::testing::FLAGS_gtest_death_test_style = "threadsafe"; - ASSERT_EXIT(do_test(), ::testing::ExitedWithCode(42), ""); -#else // __i386__ - GTEST_LOG_(INFO) << "This test does nothing.\n"; -#endif // __i386__ + ASSERT_EXIT(unwind_through_frame_with_cleanup_function(), ::testing::ExitedWithCode(42), ""); } diff --git a/tests/stack_unwinding_test_impl.c b/tests/stack_unwinding_test_impl.c index 7518a2cdd..2e0393847 100644 --- a/tests/stack_unwinding_test_impl.c +++ b/tests/stack_unwinding_test_impl.c @@ -18,52 +18,47 @@ * Contributed by: Intel Corporation */ -#include +#include #include +#include #include #include +#include #include #define noinline __attribute__((__noinline__)) -#define unused __attribute__((__unused__)) -static noinline _Unwind_Reason_Code stop_fn(int a unused, +#ifndef __unused +#define __unused __attribute__((__unused__)) +#endif + +static noinline _Unwind_Reason_Code cleanup_unwind_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) { + _Unwind_Exception_Class b __unused, + struct _Unwind_Exception* c __unused, + struct _Unwind_Context* ctx __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(); + abort(); // We reached the end of the stack without executing foo_cleanup (which would have exited). Test failed. } return _URC_NO_REASON; } -static void noinline foo_cleanup(char* param unused) { +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 function_with_cleanup_function() { + char c __attribute__((cleanup(foo_cleanup))) __unused; + *((int*) 1) = 0; } -static void noinline foo() { - char c1 __attribute__((cleanup(foo_cleanup))) unused; - do_crash(); +static void noinline cleanup_sigsegv_handler(int param __unused) { + struct _Unwind_Exception* exception = (struct _Unwind_Exception*) calloc(1, sizeof(*exception)); + _Unwind_ForcedUnwind(exception, cleanup_unwind_fn, 0); } -// 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(); +void unwind_through_frame_with_cleanup_function() { + signal(SIGSEGV, &cleanup_sigsegv_handler); + function_with_cleanup_function(); } From 8eb8c3929974060e0d8b5063886d6ed250198d41 Mon Sep 17 00:00:00 2001 From: Pavel Chupin Date: Fri, 26 Sep 2014 16:02:09 +0400 Subject: [PATCH 6/9] [x86,x86_64] Fix libgcc unwinding through signal This change provides __restore/__restore_rt on x86 and __restore_rt on x86_64 with unwinding information to be able to unwind through signal frame via libgcc provided unwinding interface. See comments inlined for more details. Also remove the test that had a dependency on __attribute__((cleanup(foo_cleanup))). It doesn't provide us with any better test coverage than we have from the newer tests, and it doesn't work well across a variety architectures (presumably because no one uses this attribute in the real world). Tested this on host via bionic-unit-tests-run-on-host on both x86 and x86-64. Bug: 17436734 Signed-off-by: Pavel Chupin (cherry picked from commit 50321e2e66f19998970e59d666bc9af387345b3a) Change-Id: Iba90e36958b00c7cc7db5eeebf888dc89ce4d619 --- libc/arch-x86/bionic/__restore.S | 104 ++++++++++++++++++++++- libc/arch-x86/bionic/__restore_rt.S | 36 -------- libc/arch-x86/x86.mk | 1 - libc/arch-x86_64/bionic/__restore_rt.S | 113 ++++++++++++++++++++++++- tests/Android.mk | 3 +- tests/ScopedSignalHandler.h | 5 +- tests/stack_unwinding_test.cpp | 17 ++-- tests/stack_unwinding_test_impl.c | 64 -------------- 8 files changed, 225 insertions(+), 118 deletions(-) delete mode 100644 libc/arch-x86/bionic/__restore_rt.S delete mode 100644 tests/stack_unwinding_test_impl.c diff --git a/libc/arch-x86/bionic/__restore.S b/libc/arch-x86/bionic/__restore.S index 755c3f8e5..cb18fd027 100644 --- a/libc/arch-x86/bionic/__restore.S +++ b/libc/arch-x86/bionic/__restore.S @@ -28,10 +28,108 @@ #include -// This function must have exactly this instruction sequence for gdb and libunwind. -// This function must have exactly this name for gdb. -ENTRY(__restore) +// DWARF constants. +#define DW_CFA_def_cfa_expression 0x0f +#define DW_CFA_expression 0x10 +#define DW_EH_PE_pcrel 0x10 +#define DW_EH_PE_sdata4 0x0b +#define DW_OP_breg4 0x74 +#define DW_OP_deref 0x06 + +// Offsets into struct sigcontext. +#define OFFSET_EDI 16 +#define OFFSET_ESI 20 +#define OFFSET_EBP 24 +#define OFFSET_ESP 28 +#define OFFSET_EBX 32 +#define OFFSET_EDX 36 +#define OFFSET_ECX 40 +#define OFFSET_EAX 44 +#define OFFSET_EIP 56 + +// Non-standard DWARF constants for the x86 registers. +#define DW_x86_REG_EAX 0 +#define DW_x86_REG_ECX 1 +#define DW_x86_REG_EDX 2 +#define DW_x86_REG_EBX 3 +#define DW_x86_REG_EBP 5 +#define DW_x86_REG_ESI 6 +#define DW_x86_REG_EDI 7 +#define DW_x86_REG_EIP 8 + +#define cfi_signal_frame_start(f) \ +.section .eh_frame,"a",@progbits; \ +.L ## f ## _START_EH_FRAME: \ + .long 2f - 1f; /* CIE length. */ \ +1:.long 0; /* CIE ID. */ \ + .byte 1; /* Version. */ \ + .string "zRS"; /* Augmentation string. */ \ + .uleb128 1; /* Code alignment factor. */ \ + .sleb128 -4; /* Data alignment factor. */ \ + .uleb128 DW_x86_REG_EIP; /* Return address register. */ \ + .uleb128 1; /* 1 byte of augmentation data. */ \ + .byte (DW_EH_PE_pcrel|DW_EH_PE_sdata4); /* FDE encoding. */ \ + .align 8; \ +2: \ + .long .L ## f ## _END_FDE - .L ## f ## _START_FDE; /* FDE length. */ \ +.L ## f ## _START_FDE: \ + .long .L ## f ## _START_FDE - .L ## f ## _START_EH_FRAME; /* CIE location. */ \ + .long (.L ## f ## _START - 1) - .; /* pcrel start address (see FDE encoding above). */ \ + .long .L ## f ## _END - (.L ## f ## _START - 1); /* Function this FDE applies to. */ \ + .uleb128 0; /* FDE augmentation length. */ \ + +#define cfi_signal_frame_end(f) \ +.L ## f ## _END_FDE: \ + +#define cfi_def_cfa(offset) \ + .byte DW_CFA_def_cfa_expression; \ + .uleb128 2f-1f; \ +1:.byte DW_OP_breg4; \ + .sleb128 offset; \ + .byte DW_OP_deref; \ +2: \ + +#define cfi_offset(reg_number,offset) \ + .byte DW_CFA_expression; \ + .uleb128 reg_number; \ + .uleb128 2f-1f; \ +1:.byte DW_OP_breg4; \ + .sleb128 offset; \ +2: \ + +ENTRY_PRIVATE(__restore) +.L__restore_START: popl %eax movl $__NR_sigreturn, %eax int $0x80 +.L__restore_END: END(__restore) +cfi_signal_frame_start(__restore) + cfi_def_cfa(OFFSET_ESP + 4) + cfi_offset(DW_x86_REG_EDI, OFFSET_EDI + 4) + cfi_offset(DW_x86_REG_ESI, OFFSET_ESI + 4) + cfi_offset(DW_x86_REG_EBP, OFFSET_EBP + 4) + cfi_offset(DW_x86_REG_EBX, OFFSET_EBX + 4) + cfi_offset(DW_x86_REG_EDX, OFFSET_EDX + 4) + cfi_offset(DW_x86_REG_ECX, OFFSET_ECX + 4) + cfi_offset(DW_x86_REG_EAX, OFFSET_EAX + 4) + cfi_offset(DW_x86_REG_EIP, OFFSET_EIP + 4) +cfi_signal_frame_end(__restore) + +ENTRY_PRIVATE(__restore_rt) +.L__restore_rt_START: + movl $__NR_rt_sigreturn, %eax + int $0x80 +.L__restore_rt_END: +END(__restore_rt) +cfi_signal_frame_start(__restore_rt) + cfi_def_cfa(OFFSET_ESP + 160) + cfi_offset(DW_x86_REG_EDI, OFFSET_EDI + 160) + cfi_offset(DW_x86_REG_ESI, OFFSET_ESI + 160) + cfi_offset(DW_x86_REG_EBP, OFFSET_EBP + 160) + cfi_offset(DW_x86_REG_EBX, OFFSET_EBX + 160) + cfi_offset(DW_x86_REG_EDX, OFFSET_EDX + 160) + cfi_offset(DW_x86_REG_ECX, OFFSET_ECX + 160) + cfi_offset(DW_x86_REG_EAX, OFFSET_EAX + 160) + cfi_offset(DW_x86_REG_EIP, OFFSET_EIP + 160) +cfi_signal_frame_end(__restore_rt) diff --git a/libc/arch-x86/bionic/__restore_rt.S b/libc/arch-x86/bionic/__restore_rt.S deleted file mode 100644 index 0cd808125..000000000 --- a/libc/arch-x86/bionic/__restore_rt.S +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -// This function must have exactly this instruction sequence for gdb and libunwind. -// This function must have exactly this name for gdb. -ENTRY(__restore_rt) - movl $__NR_rt_sigreturn, %eax - int $0x80 -END(__restore_rt) diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk index 905519745..d90b1ceec 100644 --- a/libc/arch-x86/x86.mk +++ b/libc/arch-x86/x86.mk @@ -26,7 +26,6 @@ libc_bionic_src_files_x86 += \ arch-x86/bionic/__bionic_clone.S \ arch-x86/bionic/_exit_with_stack_teardown.S \ arch-x86/bionic/libgcc_compat.c \ - arch-x86/bionic/__restore_rt.S \ arch-x86/bionic/__restore.S \ arch-x86/bionic/_setjmp.S \ arch-x86/bionic/setjmp.S \ diff --git a/libc/arch-x86_64/bionic/__restore_rt.S b/libc/arch-x86_64/bionic/__restore_rt.S index d84be219a..785b3b378 100644 --- a/libc/arch-x86_64/bionic/__restore_rt.S +++ b/libc/arch-x86_64/bionic/__restore_rt.S @@ -28,9 +28,116 @@ #include -// This function must have exactly this instruction sequence for gdb and libunwind. -// This function must have exactly this name for gdb. -ENTRY(__restore_rt) +// DWARF constants. +#define DW_CFA_def_cfa_expression 0x0f +#define DW_CFA_expression 0x10 +#define DW_EH_PE_pcrel 0x10 +#define DW_EH_PE_sdata4 0x0b +#define DW_OP_breg4 0x74 +#define DW_OP_breg7 0x77 +#define DW_OP_deref 0x06 + +// Offsets into struct ucontext_t of uc_mcontext.gregs[x]. +#define OFFSET_R8 40 +#define OFFSET_R9 48 +#define OFFSET_R10 56 +#define OFFSET_R11 64 +#define OFFSET_R12 72 +#define OFFSET_R13 80 +#define OFFSET_R14 88 +#define OFFSET_R15 96 +#define OFFSET_RDI 104 +#define OFFSET_RSI 112 +#define OFFSET_RBP 120 +#define OFFSET_RSP 160 +#define OFFSET_RBX 128 +#define OFFSET_RDX 136 +#define OFFSET_RAX 144 +#define OFFSET_RCX 152 +#define OFFSET_RIP 168 + +// Non-standard DWARF constants for the x86-64 registers. +#define DW_x86_64_RAX 0 +#define DW_x86_64_RDX 1 +#define DW_x86_64_RCX 2 +#define DW_x86_64_RBX 3 +#define DW_x86_64_RSI 4 +#define DW_x86_64_RDI 5 +#define DW_x86_64_RBP 6 +#define DW_x86_64_RSP 7 +#define DW_x86_64_R8 8 +#define DW_x86_64_R9 9 +#define DW_x86_64_R10 10 +#define DW_x86_64_R11 11 +#define DW_x86_64_R12 12 +#define DW_x86_64_R13 13 +#define DW_x86_64_R14 14 +#define DW_x86_64_R15 15 +#define DW_x86_64_RIP 16 + +#define cfi_signal_frame_start(f) \ +.section .eh_frame,"a",@progbits; \ +.L ## f ## _START_EH_FRAME: \ + .long 2f - 1f; /* CIE length. */ \ +1:.long 0; /* CIE ID. */ \ + .byte 1; /* Version. */ \ + .string "zRS"; /* Augmentation string. */ \ + .uleb128 1; /* Code alignment factor. */ \ + .sleb128 -8; /* Data alignment factor. */ \ + .uleb128 DW_x86_64_RIP; /* Return address register. */ \ + .uleb128 1; /* 1 byte of augmentation data. */ \ + .byte (DW_EH_PE_pcrel | DW_EH_PE_sdata4); /* FDE encoding. */ \ + .align 8; \ +2: \ + .long .L ## f ## _END_FDE - .L ## f ## _START_FDE; /* FDE length. */ \ +.L ## f ## _START_FDE: \ + .long .L ## f ## _START_FDE - .L ## f ## _START_EH_FRAME; /* CIE location. */ \ + .long (.L ## f ## _START - 1) - .; /* pcrel start address (see FDE encoding above). */ \ + .long .L ## f ## _END - (.L ## f ## _START - 1); /* Function this FDE applies to. */ \ + .uleb128 0; /* FDE augmentation length. */ \ + +#define cfi_signal_frame_end(f) \ +.L ## f ## _END_FDE: \ + +#define cfi_def_cfa(offset) \ + .byte DW_CFA_def_cfa_expression; \ + .uleb128 2f-1f; \ +1:.byte DW_OP_breg7; \ + .sleb128 offset; \ + .byte DW_OP_deref; \ +2: \ + +#define cfi_offset(reg_number,offset) \ + .byte DW_CFA_expression; \ + .uleb128 reg_number; \ + .uleb128 2f-1f; \ +1:.byte DW_OP_breg7; \ + .sleb128 offset; \ +2: \ + +ENTRY_PRIVATE(__restore_rt) +.L__restore_rt_START: mov $__NR_rt_sigreturn, %rax syscall +.L__restore_rt_END: END(__restore_rt) +cfi_signal_frame_start(__restore_rt) + cfi_def_cfa(OFFSET_RSP) + cfi_offset(DW_x86_64_R8, OFFSET_R8) + cfi_offset(DW_x86_64_R9, OFFSET_R9) + cfi_offset(DW_x86_64_R10, OFFSET_R10) + cfi_offset(DW_x86_64_R11, OFFSET_R11) + cfi_offset(DW_x86_64_R12, OFFSET_R12) + cfi_offset(DW_x86_64_R13, OFFSET_R13) + cfi_offset(DW_x86_64_R14, OFFSET_R14) + cfi_offset(DW_x86_64_R15, OFFSET_R15) + cfi_offset(DW_x86_64_RDI, OFFSET_RDI) + cfi_offset(DW_x86_64_RSI, OFFSET_RSI) + cfi_offset(DW_x86_64_RBP, OFFSET_RBP) + cfi_offset(DW_x86_64_RSP, OFFSET_RSP) + cfi_offset(DW_x86_64_RBX, OFFSET_RBX) + cfi_offset(DW_x86_64_RDX, OFFSET_RDX) + cfi_offset(DW_x86_64_RAX, OFFSET_RAX) + cfi_offset(DW_x86_64_RCX, OFFSET_RCX) + cfi_offset(DW_x86_64_RIP, OFFSET_RIP) +cfi_signal_frame_end(__restore_rt) diff --git a/tests/Android.mk b/tests/Android.mk index 23a2cb3ed..407f21bc5 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -88,6 +88,7 @@ libBionicStandardTests_src_files := \ search_test.cpp \ signal_test.cpp \ stack_protector_test.cpp \ + stack_unwinding_test.cpp \ stdatomic_test.cpp \ stdint_test.cpp \ stdio_test.cpp \ @@ -224,8 +225,6 @@ bionic-unit-tests_src_files := \ atexit_test.cpp \ dlext_test.cpp \ dlfcn_test.cpp \ - stack_unwinding_test.cpp \ - stack_unwinding_test_impl.c \ bionic-unit-tests_cflags := $(test_cflags) diff --git a/tests/ScopedSignalHandler.h b/tests/ScopedSignalHandler.h index 89a14a6b2..3ec23b0d8 100644 --- a/tests/ScopedSignalHandler.h +++ b/tests/ScopedSignalHandler.h @@ -21,9 +21,10 @@ class ScopedSignalHandler { public: - ScopedSignalHandler(int signal_number, void (*handler)(int)) : signal_number_(signal_number) { + ScopedSignalHandler(int signal_number, void (*handler)(int), int sa_flags = 0) + : signal_number_(signal_number) { sigemptyset(&action_.sa_mask); - action_.sa_flags = 0; + action_.sa_flags = sa_flags; action_.sa_handler = handler; sigaction(signal_number_, &action_, &old_action_); } diff --git a/tests/stack_unwinding_test.cpp b/tests/stack_unwinding_test.cpp index 017a5f2e8..3fc45c537 100644 --- a/tests/stack_unwinding_test.cpp +++ b/tests/stack_unwinding_test.cpp @@ -31,7 +31,8 @@ #include "ScopedSignalHandler.h" -#define noinline __attribute__((noinline)) +#define noinline __attribute__((__noinline__)) +#define __unused __attribute__((__unused__)) static _Unwind_Reason_Code FrameCounter(_Unwind_Context* ctx __unused, void* arg) { int* count_ptr = reinterpret_cast(arg); @@ -85,6 +86,7 @@ static void noinline UnwindSignalHandler(int) { } TEST(stack_unwinding, unwind_through_signal_frame) { + killer_count = handler_count = handler_one_deeper_count = 0; ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler); _Unwind_Backtrace(FrameCounter, &killer_count); @@ -92,11 +94,12 @@ TEST(stack_unwinding, unwind_through_signal_frame) { ASSERT_EQ(0, kill(getpid(), SIGUSR1)); } -extern "C" void unwind_through_frame_with_cleanup_function(); +// On LP32, the SA_SIGINFO flag gets you __restore_rt instead of __restore. +TEST(stack_unwinding, unwind_through_signal_frame_SA_SIGINFO) { + killer_count = handler_count = handler_one_deeper_count = 0; + ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler, SA_SIGINFO); -// We have to say "DeathTest" here so gtest knows to run this test (which exits) -// in its own process. -TEST(stack_unwinding_DeathTest, unwind_through_frame_with_cleanup_function) { - ::testing::FLAGS_gtest_death_test_style = "threadsafe"; - ASSERT_EXIT(unwind_through_frame_with_cleanup_function(), ::testing::ExitedWithCode(42), ""); + _Unwind_Backtrace(FrameCounter, &killer_count); + + ASSERT_EQ(0, kill(getpid(), SIGUSR1)); } diff --git a/tests/stack_unwinding_test_impl.c b/tests/stack_unwinding_test_impl.c deleted file mode 100644 index 2e0393847..000000000 --- a/tests/stack_unwinding_test_impl.c +++ /dev/null @@ -1,64 +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. - */ - -/* - * Contributed by: Intel Corporation - */ - -#include -#include -#include -#include -#include -#include -#include - -#define noinline __attribute__((__noinline__)) - -#ifndef __unused -#define __unused __attribute__((__unused__)) -#endif - -static noinline _Unwind_Reason_Code cleanup_unwind_fn(int a __unused, - _Unwind_Action action, - _Unwind_Exception_Class b __unused, - struct _Unwind_Exception* c __unused, - struct _Unwind_Context* ctx __unused, - void* e __unused) { - if ((action & _UA_END_OF_STACK) != 0) { - abort(); // We reached the end of the stack without executing foo_cleanup (which would have exited). Test failed. - } - return _URC_NO_REASON; -} - -static void noinline foo_cleanup(char* param __unused) { - exit(42); -} - -static void noinline function_with_cleanup_function() { - char c __attribute__((cleanup(foo_cleanup))) __unused; - *((int*) 1) = 0; -} - -static void noinline cleanup_sigsegv_handler(int param __unused) { - struct _Unwind_Exception* exception = (struct _Unwind_Exception*) calloc(1, sizeof(*exception)); - _Unwind_ForcedUnwind(exception, cleanup_unwind_fn, 0); -} - -void unwind_through_frame_with_cleanup_function() { - signal(SIGSEGV, &cleanup_sigsegv_handler); - function_with_cleanup_function(); -} From 28ea229bb29f3ee82991ca8b5ac5f7a9b7b89fdc Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 4 Sep 2014 13:54:42 -0700 Subject: [PATCH 7/9] Don't mask out SA_RESTORER from sa_flags. glibc doesn't do this, and we probably shouldn't either. Bug: 16703540 Bug: 17436734 (cherry picked from commit afe58ad9892de27a7acb0aaded6312ee0f958314) Change-Id: Iada5d0ae814f438cb276f056b2b5e3675f0e3666 --- libc/bionic/sigaction.cpp | 4 ---- tests/signal_test.cpp | 16 +++++++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/libc/bionic/sigaction.cpp b/libc/bionic/sigaction.cpp index 9038bd544..0633748bf 100644 --- a/libc/bionic/sigaction.cpp +++ b/libc/bionic/sigaction.cpp @@ -69,10 +69,6 @@ int sigaction(int signal, const struct sigaction* bionic_new_action, struct siga bionic_old_action->sa_mask = kernel_old_action.sa_mask; #if defined(SA_RESTORER) bionic_old_action->sa_restorer = kernel_old_action.sa_restorer; - - if (bionic_old_action->sa_restorer == &__rt_sigreturn) { - bionic_old_action->sa_flags &= ~SA_RESTORER; - } #endif } diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp index 89b808838..e53fd3af6 100644 --- a/tests/signal_test.cpp +++ b/tests/signal_test.cpp @@ -14,10 +14,10 @@ * limitations under the License. */ -#include +#include #include -#include +#include #include "ScopedSignalHandler.h" @@ -198,13 +198,19 @@ static void EmptySignalHandler(int) {} static void EmptySignalAction(int, siginfo_t*, void*) {} TEST(signal, sigaction) { + // Both bionic and glibc set SA_RESTORER when talking to the kernel on arm, + // arm64, x86, and x86-64. The version of glibc we're using also doesn't + // define SA_RESTORER, but luckily it's the same value everywhere, and mips + // doesn't use the bit for anything. + static const int sa_restorer = 0x4000000; + // See what's currently set for SIGALRM. struct sigaction original_sa; memset(&original_sa, 0, sizeof(original_sa)); ASSERT_EQ(0, sigaction(SIGALRM, NULL, &original_sa)); ASSERT_TRUE(original_sa.sa_handler == NULL); ASSERT_TRUE(original_sa.sa_sigaction == NULL); - ASSERT_TRUE(original_sa.sa_flags == 0); + ASSERT_EQ(0, original_sa.sa_flags & ~sa_restorer); // Set a traditional sa_handler signal handler. struct sigaction sa; @@ -219,7 +225,7 @@ TEST(signal, sigaction) { ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa)); ASSERT_TRUE(sa.sa_handler == EmptySignalHandler); ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler); - ASSERT_TRUE(sa.sa_flags == SA_ONSTACK); + ASSERT_EQ(SA_ONSTACK, sa.sa_flags & ~sa_restorer); // Set a new-style sa_sigaction signal handler. memset(&sa, 0, sizeof(sa)); @@ -233,7 +239,7 @@ TEST(signal, sigaction) { ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa)); ASSERT_TRUE(sa.sa_sigaction == EmptySignalAction); ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler); - ASSERT_TRUE(sa.sa_flags == (SA_ONSTACK | SA_SIGINFO)); + ASSERT_EQ((SA_ONSTACK | SA_SIGINFO), sa.sa_flags & ~sa_restorer); // Put everything back how it was. ASSERT_EQ(0, sigaction(SIGALRM, &original_sa, NULL)); From 43dc3a9aae7ad1f16a251e3c1e22dced82b811e3 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Tue, 23 Sep 2014 18:31:45 -0700 Subject: [PATCH 8/9] Remove the unnecessary generic-neon code. Bug: 18156619 (cherry picked from commit 2169e17482da91865e412e55b52b88d7c8db47f6) Change-Id: I4a7f5bb9ad4c27b274f3a3c86c1617ca0578b98f --- libc/arch-arm64/arm64.mk | 2 +- libc/arch-arm64/generic-neon/bionic/memcpy.S | 179 ------------------- libc/arch-arm64/generic-neon/generic-neon.mk | 13 -- 3 files changed, 1 insertion(+), 193 deletions(-) delete mode 100644 libc/arch-arm64/generic-neon/bionic/memcpy.S delete mode 100644 libc/arch-arm64/generic-neon/generic-neon.mk diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk index eb65cfd1f..692aaf606 100644 --- a/libc/arch-arm64/arm64.mk +++ b/libc/arch-arm64/arm64.mk @@ -52,7 +52,7 @@ ifeq ($(strip $(TARGET_CPU_VARIANT)),) endif cpu_variant_mk := $(LOCAL_PATH)/arch-arm64/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk ifeq ($(wildcard $(cpu_variant_mk)),) -$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, generic-neon, denver64. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.") +$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, denver64. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.") endif include $(cpu_variant_mk) libc_common_additional_dependencies += $(cpu_variank_mk) diff --git a/libc/arch-arm64/generic-neon/bionic/memcpy.S b/libc/arch-arm64/generic-neon/bionic/memcpy.S deleted file mode 100644 index 320f74896..000000000 --- a/libc/arch-arm64/generic-neon/bionic/memcpy.S +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright (c) 2012, 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 the Linaro nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - 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. -*/ - -/* Assumptions: - * - * ARMv8-a, AArch64 - * Unaligned accesses - * - */ - -#include - -#define dstin x0 -#define src x1 -#define count x2 -#define tmp1 x3 -#define tmp1w w3 -#define tmp2 x4 -#define tmp2w w4 -#define tmp3 x5 -#define tmp3w w5 -#define dst x6 - -#define A_l x7 -#define A_h x8 -#define B_l x9 -#define B_h x10 -#define C_l x11 -#define C_h x12 -#define D_l x13 -#define D_h x14 - -#define QA_l q0 -#define QA_h q1 -#define QB_l q2 -#define QB_h q3 - -ENTRY(memcpy) - - mov dst, dstin - cmp count, #64 - b.ge .Lcpy_not_short - cmp count, #15 - b.le .Ltail15tiny - - /* Deal with small copies quickly by dropping straight into the - * exit block. */ -.Ltail63: - /* Copy up to 48 bytes of data. At this point we only need the - * bottom 6 bits of count to be accurate. */ - ands tmp1, count, #0x30 - b.eq .Ltail15 - add dst, dst, tmp1 - add src, src, tmp1 - cmp tmp1w, #0x20 - b.eq 1f - b.lt 2f - ldp A_l, A_h, [src, #-48] - stp A_l, A_h, [dst, #-48] -1: - ldp A_l, A_h, [src, #-32] - stp A_l, A_h, [dst, #-32] -2: - ldp A_l, A_h, [src, #-16] - stp A_l, A_h, [dst, #-16] - -.Ltail15: - ands count, count, #15 - beq 1f - add src, src, count - ldp A_l, A_h, [src, #-16] - add dst, dst, count - stp A_l, A_h, [dst, #-16] -1: - ret - -.Ltail15tiny: - /* Copy up to 15 bytes of data. Does not assume additional data - being copied. */ - tbz count, #3, 1f - ldr tmp1, [src], #8 - str tmp1, [dst], #8 -1: - tbz count, #2, 1f - ldr tmp1w, [src], #4 - str tmp1w, [dst], #4 -1: - tbz count, #1, 1f - ldrh tmp1w, [src], #2 - strh tmp1w, [dst], #2 -1: - tbz count, #0, 1f - ldrb tmp1w, [src] - strb tmp1w, [dst] -1: - ret - -.Lcpy_not_short: - /* We don't much care about the alignment of DST, but we want SRC - * to be 128-bit (16 byte) aligned so that we don't cross cache line - * boundaries on both loads and stores. */ - neg tmp2, src - ands tmp2, tmp2, #15 /* Bytes to reach alignment. */ - b.eq 2f - sub count, count, tmp2 - /* Copy more data than needed; it's faster than jumping - * around copying sub-Quadword quantities. We know that - * it can't overrun. */ - ldp A_l, A_h, [src] - add src, src, tmp2 - stp A_l, A_h, [dst] - add dst, dst, tmp2 - /* There may be less than 63 bytes to go now. */ - cmp count, #63 - b.le .Ltail63 -2: - subs count, count, #128 - b.ge .Lcpy_body_large - /* Less than 128 bytes to copy, so handle 64 here and then jump - * to the tail. */ - ldp QA_l, QA_h, [src] - ldp QB_l, QB_h, [src, #32] - stp QA_l, QA_h, [dst] - stp QB_l, QB_h, [dst, #32] - tst count, #0x3f - add src, src, #64 - add dst, dst, #64 - b.ne .Ltail63 - ret - - /* Critical loop. Start at a new cache line boundary. Assuming - * 64 bytes per line this ensures the entire loop is in one line. */ - .p2align 6 -.Lcpy_body_large: - /* There are at least 128 bytes to copy. */ - ldp QA_l, QA_h, [src, #0] - sub dst, dst, #32 /* Pre-bias. */ - ldp QB_l, QB_h, [src, #32]! /* src += 64 - Pre-bias. */ -1: - stp QA_l, QA_h, [dst, #32] - ldp QA_l, QA_h, [src, #32] - stp QB_l, QB_h, [dst, #64]! - ldp QB_l, QB_h, [src, #64]! - - subs count, count, #64 - b.ge 1b - - stp QA_l, QA_h, [dst, #32] - stp QB_l, QB_h, [dst, #64] - add src, src, #32 - add dst, dst, #64 + 32 - tst count, #0x3f - b.ne .Ltail63 - ret -END(memcpy) diff --git a/libc/arch-arm64/generic-neon/generic-neon.mk b/libc/arch-arm64/generic-neon/generic-neon.mk deleted file mode 100644 index 77e3861ea..000000000 --- a/libc/arch-arm64/generic-neon/generic-neon.mk +++ /dev/null @@ -1,13 +0,0 @@ -libc_bionic_src_files_arm64 += \ - arch-arm64/generic/bionic/memchr.S \ - arch-arm64/generic/bionic/memcmp.S \ - arch-arm64/generic/bionic/memmove.S \ - arch-arm64/generic/bionic/memset.S \ - arch-arm64/generic/bionic/stpcpy.S \ - arch-arm64/generic/bionic/strchr.S \ - arch-arm64/generic/bionic/strcmp.S \ - arch-arm64/generic/bionic/strcpy.S \ - arch-arm64/generic/bionic/strlen.S \ - arch-arm64/generic/bionic/strncmp.S \ - arch-arm64/generic/bionic/strnlen.S \ - arch-arm64/generic-neon/bionic/memcpy.S \ From 22e2c9d963e0dde19e5876ab8dfc3576efc42ccc Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 4 Sep 2014 15:43:10 -0700 Subject: [PATCH 9/9] Fix mips signed/unsigned signal_test.cpp build breakage. (cherry picked from commit aa13e839f06231b9299bb683a71abd954294b49b) Bug: 17436734 Change-Id: I167fc5d74c49cca7031c5739bc53fdf3bde71887 --- tests/signal_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp index e53fd3af6..8fd8b72f7 100644 --- a/tests/signal_test.cpp +++ b/tests/signal_test.cpp @@ -202,7 +202,7 @@ TEST(signal, sigaction) { // arm64, x86, and x86-64. The version of glibc we're using also doesn't // define SA_RESTORER, but luckily it's the same value everywhere, and mips // doesn't use the bit for anything. - static const int sa_restorer = 0x4000000; + static const unsigned sa_restorer = 0x4000000; // See what's currently set for SIGALRM. struct sigaction original_sa; @@ -210,7 +210,7 @@ TEST(signal, sigaction) { ASSERT_EQ(0, sigaction(SIGALRM, NULL, &original_sa)); ASSERT_TRUE(original_sa.sa_handler == NULL); ASSERT_TRUE(original_sa.sa_sigaction == NULL); - ASSERT_EQ(0, original_sa.sa_flags & ~sa_restorer); + ASSERT_EQ(0U, original_sa.sa_flags & ~sa_restorer); // Set a traditional sa_handler signal handler. struct sigaction sa; @@ -225,7 +225,7 @@ TEST(signal, sigaction) { ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa)); ASSERT_TRUE(sa.sa_handler == EmptySignalHandler); ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler); - ASSERT_EQ(SA_ONSTACK, sa.sa_flags & ~sa_restorer); + ASSERT_EQ(static_cast(SA_ONSTACK), sa.sa_flags & ~sa_restorer); // Set a new-style sa_sigaction signal handler. memset(&sa, 0, sizeof(sa)); @@ -239,7 +239,7 @@ TEST(signal, sigaction) { ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa)); ASSERT_TRUE(sa.sa_sigaction == EmptySignalAction); ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler); - ASSERT_EQ((SA_ONSTACK | SA_SIGINFO), sa.sa_flags & ~sa_restorer); + ASSERT_EQ(static_cast(SA_ONSTACK | SA_SIGINFO), sa.sa_flags & ~sa_restorer); // Put everything back how it was. ASSERT_EQ(0, sigaction(SIGALRM, &original_sa, NULL));