diff options
| -rw-r--r-- | build/Android.common_test.mk | 7 | ||||
| -rw-r--r-- | build/Android.gtest.mk | 1 | ||||
| -rw-r--r-- | runtime/arch/arm64/instruction_set_features_arm64.cc | 1 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 4 | ||||
| -rw-r--r-- | sigchainlib/Android.bp | 30 | ||||
| -rw-r--r-- | sigchainlib/sigchain.cc | 199 | ||||
| -rw-r--r-- | sigchainlib/sigchain_test.cc | 187 | ||||
| -rw-r--r-- | sigchainlib/version-script32.txt | 2 | ||||
| -rw-r--r-- | sigchainlib/version-script64.txt | 2 | ||||
| -rw-r--r-- | test/004-SignalTest/signaltest.cc | 18 | ||||
| -rw-r--r-- | test/115-native-bridge/expected.txt | 2 | ||||
| -rw-r--r-- | test/115-native-bridge/nativebridge.cc | 16 | ||||
| -rw-r--r-- | test/1926-missed-frame-pop/src/art/Test1926.java | 27 | ||||
| -rw-r--r-- | test/983-source-transform-verify/source_transform_slicer.cc | 7 | ||||
| -rw-r--r-- | test/ti-stress/stress.cc | 21 |
15 files changed, 433 insertions, 91 deletions
diff --git a/build/Android.common_test.mk b/build/Android.common_test.mk index 7fae7f6200..c508fe7e9e 100644 --- a/build/Android.common_test.mk +++ b/build/Android.common_test.mk @@ -20,14 +20,11 @@ ART_ANDROID_COMMON_TEST_MK = true include art/build/Android.common_path.mk # Directory used for temporary test files on the host. -ifneq ($(TMPDIR),) -ART_HOST_TEST_DIR := $(TMPDIR)/test-art-$(shell echo $$PPID) -else # Use a BSD checksum calculated from CWD and USER as one of the path # components for the test output. This should allow us to run tests from # multiple repositories at the same time. -ART_HOST_TEST_DIR := /tmp/test-art-$(shell echo $$CWD-${USER} | sum | cut -d ' ' -f1) -endif +ART_TMPDIR := $(if $(TMPDIR),$(TMPDIR),/tmp) +ART_HOST_TEST_DIR := $(ART_TMPDIR)/test-art-$(shell echo $$CWD-${USER} | sum | cut -d ' ' -f1) # List of known broken tests that we won't attempt to execute. The test name must be the full # rule name such as test-art-host-oat-optimizing-HelloWorld64. diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index 4a35ccfa13..388ff061a9 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -339,6 +339,7 @@ ART_TEST_MODULES := \ art_profman_tests \ art_runtime_tests \ art_runtime_compiler_tests \ + art_sigchain_tests \ ART_TARGET_GTEST_FILES := $(foreach m,$(ART_TEST_MODULES),\ $(ART_TEST_LIST_device_$(TARGET_ARCH)_$(m))) diff --git a/runtime/arch/arm64/instruction_set_features_arm64.cc b/runtime/arch/arm64/instruction_set_features_arm64.cc index 9e9cb16008..42c9a846d0 100644 --- a/runtime/arch/arm64/instruction_set_features_arm64.cc +++ b/runtime/arch/arm64/instruction_set_features_arm64.cc @@ -54,6 +54,7 @@ Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromVariant( "cortex-a35", "exynos-m1", "exynos-m2", + "exynos-m3", "denver64", "kryo" }; diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 856e538ad6..f18e0b412c 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -267,7 +267,9 @@ static void WrapExceptionInInitializer(Handle<mirror::Class> klass) // cannot in general be guaranteed, but in all likelihood leads to breakage down the line. if (klass->GetClassLoader() == nullptr && !Runtime::Current()->IsAotCompiler()) { std::string tmp; - LOG(kIsDebugBuild ? FATAL : WARNING) << klass->GetDescriptor(&tmp) << " failed initialization"; + LOG(kIsDebugBuild ? FATAL : WARNING) << klass->GetDescriptor(&tmp) + << " failed initialization: " + << self->GetException()->Dump(); } env->ExceptionClear(); diff --git a/sigchainlib/Android.bp b/sigchainlib/Android.bp index 7aab726be7..1f490cd3b9 100644 --- a/sigchainlib/Android.bp +++ b/sigchainlib/Android.bp @@ -16,15 +16,24 @@ cc_library { name: "libsigchain", + cpp_std: "gnu++17", + host_supported: true, defaults: ["art_defaults"], - shared: { - srcs: ["sigchain_dummy.cc"], - }, - static: { - srcs: ["sigchain.cc"], - }, target: { + linux: { + shared: { + srcs: ["sigchain_dummy.cc"], + }, + static: { + srcs: ["sigchain.cc"], + }, + }, + + darwin: { + srcs: ["sigchain_dummy.cc"], + }, + android: { shared_libs: ["liblog"], }, @@ -51,3 +60,12 @@ cc_library_static { }, }, } + +art_cc_test { + name: "art_sigchain_tests", + defaults: [ + "art_gtest_defaults", + ], + srcs: ["sigchain_test.cc"], + whole_static_libs: ["libsigchain"], +} diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc index b8ab51b629..61346b1487 100644 --- a/sigchainlib/sigchain.cc +++ b/sigchainlib/sigchain.cc @@ -29,8 +29,10 @@ #include <stdlib.h> #include <string.h> +#include <algorithm> #include <initializer_list> #include <mutex> +#include <type_traits> #include <utility> #include "sigchain.h" @@ -78,9 +80,28 @@ static void log(const char* format, ...) { #define fatal(...) log(__VA_ARGS__); abort() -static int sigorset(sigset_t* dest, sigset_t* left, sigset_t* right) { +#if defined(__BIONIC__) && !defined(__LP64__) +static int sigismember(const sigset64_t* sigset, int signum) { + return sigismember64(sigset, signum); +} + +static int sigemptyset(sigset64_t* sigset) { + return sigemptyset64(sigset); +} + +static int sigaddset(sigset64_t* sigset, int signum) { + return sigaddset64(sigset, signum); +} + +static int sigdelset(sigset64_t* sigset, int signum) { + return sigdelset64(sigset, signum); +} +#endif + +template<typename SigsetType> +static int sigorset(SigsetType* dest, SigsetType* left, SigsetType* right) { sigemptyset(dest); - for (size_t i = 0; i < sizeof(sigset_t) * CHAR_BIT; ++i) { + for (size_t i = 0; i < sizeof(SigsetType) * CHAR_BIT; ++i) { if (sigismember(left, i) == 1 || sigismember(right, i) == 1) { sigaddset(dest, i); } @@ -93,35 +114,36 @@ namespace art { static decltype(&sigaction) linked_sigaction; static decltype(&sigprocmask) linked_sigprocmask; +#if defined(__BIONIC__) +static decltype(&sigaction64) linked_sigaction64; +static decltype(&sigprocmask64) linked_sigprocmask64; +#endif + +template<typename T> +static void lookup_next_symbol(T* output, T wrapper, const char* name) { + void* sym = dlsym(RTLD_NEXT, name); + if (sym == nullptr) { + sym = dlsym(RTLD_DEFAULT, name); + if (sym == wrapper || sym == sigaction) { + fatal("Unable to find next %s in signal chain", name); + } + } + *output = reinterpret_cast<T>(sym); +} + __attribute__((constructor)) static void InitializeSignalChain() { static std::once_flag once; std::call_once(once, []() { - void* linked_sigaction_sym = dlsym(RTLD_NEXT, "sigaction"); - if (linked_sigaction_sym == nullptr) { - linked_sigaction_sym = dlsym(RTLD_DEFAULT, "sigaction"); - if (linked_sigaction_sym == nullptr || - linked_sigaction_sym == reinterpret_cast<void*>(sigaction)) { - fatal("Unable to find next sigaction in signal chain"); - } - } - - void* linked_sigprocmask_sym = dlsym(RTLD_NEXT, "sigprocmask"); - if (linked_sigprocmask_sym == nullptr) { - linked_sigprocmask_sym = dlsym(RTLD_DEFAULT, "sigprocmask"); - if (linked_sigprocmask_sym == nullptr || - linked_sigprocmask_sym == reinterpret_cast<void*>(sigprocmask)) { - fatal("Unable to find next sigprocmask in signal chain"); - } - } + lookup_next_symbol(&linked_sigaction, sigaction, "sigaction"); + lookup_next_symbol(&linked_sigprocmask, sigprocmask, "sigprocmask"); - linked_sigaction = - reinterpret_cast<decltype(linked_sigaction)>(linked_sigaction_sym); - linked_sigprocmask = - reinterpret_cast<decltype(linked_sigprocmask)>(linked_sigprocmask_sym); +#if defined(__BIONIC__) + lookup_next_symbol(&linked_sigaction64, sigaction64, "sigaction64"); + lookup_next_symbol(&linked_sigprocmask64, sigprocmask64, "sigprocmask64"); +#endif }); } - static pthread_key_t GetHandlingSignalKey() { static pthread_key_t key; static std::once_flag once; @@ -175,19 +197,51 @@ class SignalChain { // Register the signal chain with the kernel if needed. void Register(int signo) { +#if defined(__BIONIC__) + struct sigaction64 handler_action = {}; + sigfillset64(&handler_action.sa_mask); +#else struct sigaction handler_action = {}; + sigfillset(&handler_action.sa_mask); +#endif + handler_action.sa_sigaction = SignalChain::Handler; handler_action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; - sigfillset(&handler_action.sa_mask); + +#if defined(__BIONIC__) + linked_sigaction64(signo, &handler_action, &action_); +#else linked_sigaction(signo, &handler_action, &action_); +#endif } - void SetAction(const struct sigaction* action) { - action_ = *action; + template <typename SigactionType> + SigactionType GetAction() { + if constexpr (std::is_same_v<decltype(action_), SigactionType>) { + return action_; + } else { + SigactionType result; + result.sa_flags = action_.sa_flags; + result.sa_handler = action_.sa_handler; + result.sa_restorer = action_.sa_restorer; + memcpy(&result.sa_mask, &action_.sa_mask, + std::min(sizeof(action_.sa_mask), sizeof(result.sa_mask))); + return result; + } } - struct sigaction GetAction() { - return action_; + template <typename SigactionType> + void SetAction(const SigactionType* new_action) { + if constexpr (std::is_same_v<decltype(action_), SigactionType>) { + action_ = *new_action; + } else { + action_.sa_flags = new_action->sa_flags; + action_.sa_handler = new_action->sa_handler; + action_.sa_restorer = new_action->sa_restorer; + sigemptyset(&action_.sa_mask); + memcpy(&action_.sa_mask, &new_action->sa_mask, + std::min(sizeof(action_.sa_mask), sizeof(new_action->sa_mask))); + } } void AddSpecialHandler(SigchainAction* sa) { @@ -222,11 +276,17 @@ class SignalChain { private: bool claimed_; +#if defined(__BIONIC__) + struct sigaction64 action_; +#else struct sigaction action_; +#endif SigchainAction special_handlers_[2]; }; -static SignalChain chains[_NSIG]; +// _NSIG is 1 greater than the highest valued signal, but signals start from 1. +// Leave an empty element at index 0 for convenience. +static SignalChain chains[_NSIG + 1]; void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) { // Try the special handlers first. @@ -260,12 +320,22 @@ void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) { // Forward to the user's signal handler. int handler_flags = chains[signo].action_.sa_flags; ucontext_t* ucontext = static_cast<ucontext_t*>(ucontext_raw); +#if defined(__BIONIC__) + sigset64_t mask; + sigorset(&mask, &ucontext->uc_sigmask64, &chains[signo].action_.sa_mask); +#else sigset_t mask; sigorset(&mask, &ucontext->uc_sigmask, &chains[signo].action_.sa_mask); +#endif if (!(handler_flags & SA_NODEFER)) { sigaddset(&mask, signo); } + +#if defined(__BIONIC__) + linked_sigprocmask64(SIG_SETMASK, &mask, nullptr); +#else linked_sigprocmask(SIG_SETMASK, &mask, nullptr); +#endif if ((handler_flags & SA_SIGINFO)) { chains[signo].action_.sa_sigaction(signo, siginfo, ucontext_raw); @@ -281,20 +351,22 @@ void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) { } } -extern "C" int sigaction(int signal, const struct sigaction* new_action, struct sigaction* old_action) { - InitializeSignalChain(); - +template <typename SigactionType> +static int __sigaction(int signal, const SigactionType* new_action, + SigactionType* old_action, + int (*linked)(int, const SigactionType*, + SigactionType*)) { // If this signal has been claimed as a signal chain, record the user's // action but don't pass it on to the kernel. // Note that we check that the signal number is in range here. An out of range signal // number should behave exactly as the libc sigaction. - if (signal < 0 || signal >= _NSIG) { + if (signal <= 0 || signal >= _NSIG) { errno = EINVAL; return -1; } if (chains[signal].IsClaimed()) { - struct sigaction saved_action = chains[signal].GetAction(); + SigactionType saved_action = chains[signal].GetAction<SigactionType>(); if (new_action != nullptr) { chains[signal].SetAction(new_action); } @@ -306,13 +378,27 @@ extern "C" int sigaction(int signal, const struct sigaction* new_action, struct // Will only get here if the signal chain has not been claimed. We want // to pass the sigaction on to the kernel via the real sigaction in libc. - return linked_sigaction(signal, new_action, old_action); + return linked(signal, new_action, old_action); +} + +extern "C" int sigaction(int signal, const struct sigaction* new_action, + struct sigaction* old_action) { + InitializeSignalChain(); + return __sigaction(signal, new_action, old_action, linked_sigaction); +} + +#if defined(__BIONIC__) +extern "C" int sigaction64(int signal, const struct sigaction64* new_action, + struct sigaction64* old_action) { + InitializeSignalChain(); + return __sigaction(signal, new_action, old_action, linked_sigaction64); } +#endif extern "C" sighandler_t signal(int signo, sighandler_t handler) { InitializeSignalChain(); - if (signo < 0 || signo > _NSIG) { + if (signo <= 0 || signo >= _NSIG) { errno = EINVAL; return SIG_ERR; } @@ -326,7 +412,8 @@ extern "C" sighandler_t signal(int signo, sighandler_t handler) { // If this signal has been claimed as a signal chain, record the user's // action but don't pass it on to the kernel. if (chains[signo].IsClaimed()) { - oldhandler = reinterpret_cast<sighandler_t>(chains[signo].GetAction().sa_handler); + oldhandler = reinterpret_cast<sighandler_t>( + chains[signo].GetAction<struct sigaction>().sa_handler); chains[signo].SetAction(&sa); return oldhandler; } @@ -348,23 +435,23 @@ extern "C" sighandler_t bsd_signal(int signo, sighandler_t handler) { } #endif -extern "C" int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bionic_old_set) { - InitializeSignalChain(); - +template <typename SigsetType> +int __sigprocmask(int how, const SigsetType* new_set, SigsetType* old_set, + int (*linked)(int, const SigsetType*, SigsetType*)) { // When inside a signal handler, forward directly to the actual sigprocmask. if (GetHandlingSignal()) { - return linked_sigprocmask(how, bionic_new_set, bionic_old_set); + return linked(how, new_set, old_set); } - const sigset_t* new_set_ptr = bionic_new_set; - sigset_t tmpset; - if (bionic_new_set != nullptr) { - tmpset = *bionic_new_set; + const SigsetType* new_set_ptr = new_set; + SigsetType tmpset; + if (new_set != nullptr) { + tmpset = *new_set; - if (how == SIG_BLOCK) { + if (how == SIG_BLOCK || how == SIG_SETMASK) { // Don't allow claimed signals in the mask. If a signal chain has been claimed // we can't allow the user to block that signal. - for (int i = 0 ; i < _NSIG; ++i) { + for (int i = 1; i < _NSIG; ++i) { if (chains[i].IsClaimed() && sigismember(&tmpset, i)) { sigdelset(&tmpset, i); } @@ -373,9 +460,23 @@ extern "C" int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bi new_set_ptr = &tmpset; } - return linked_sigprocmask(how, new_set_ptr, bionic_old_set); + return linked(how, new_set_ptr, old_set); } +extern "C" int sigprocmask(int how, const sigset_t* new_set, + sigset_t* old_set) { + InitializeSignalChain(); + return __sigprocmask(how, new_set, old_set, linked_sigprocmask); +} + +#if defined(__BIONIC__) +extern "C" int sigprocmask64(int how, const sigset64_t* new_set, + sigset64_t* old_set) { + InitializeSignalChain(); + return __sigprocmask(how, new_set, old_set, linked_sigprocmask64); +} +#endif + extern "C" void AddSpecialSignalHandlerFn(int signal, SigchainAction* sa) { InitializeSignalChain(); diff --git a/sigchainlib/sigchain_test.cc b/sigchainlib/sigchain_test.cc new file mode 100644 index 0000000000..9f338ad3a2 --- /dev/null +++ b/sigchainlib/sigchain_test.cc @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2018 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 <signal.h> +#include <sys/syscall.h> + +#include <functional> + +#include <gtest/gtest.h> + +#include "sigchain.h" + +#if !defined(__BIONIC__) +typedef sigset_t sigset64_t; + +static int sigemptyset64(sigset64_t* set) { + return sigemptyset(set); +} + +static int sigismember64(sigset64_t* set, int member) { + return sigismember(set, member); +} +#endif + +static int RealSigprocmask(int how, const sigset64_t* new_sigset, sigset64_t* old_sigset) { + // glibc's sigset_t is overly large, so sizeof(*new_sigset) doesn't work. + return syscall(__NR_rt_sigprocmask, how, new_sigset, old_sigset, 8); +} + +class SigchainTest : public ::testing::Test { + void SetUp() final { + art::AddSpecialSignalHandlerFn(SIGSEGV, &action); + } + + void TearDown() final { + art::RemoveSpecialSignalHandlerFn(SIGSEGV, action.sc_sigaction); + } + + art::SigchainAction action = { + .sc_sigaction = [](int, siginfo_t*, void*) { return true; }, + .sc_mask = {}, + .sc_flags = 0, + }; +}; + + +static void TestSignalBlocking(std::function<void()> fn) { + // Unblock SIGSEGV, make sure it stays unblocked. + sigset64_t mask; + sigemptyset64(&mask); + ASSERT_EQ(0, RealSigprocmask(SIG_SETMASK, &mask, nullptr)) << strerror(errno); + + fn(); + + if (testing::Test::HasFatalFailure()) return; + ASSERT_EQ(0, RealSigprocmask(SIG_SETMASK, nullptr, &mask)); + ASSERT_FALSE(sigismember64(&mask, SIGSEGV)); +} + +TEST_F(SigchainTest, sigprocmask_setmask) { + TestSignalBlocking([]() { + sigset_t mask; + sigfillset(&mask); + ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &mask, nullptr)); + }); +} + +TEST_F(SigchainTest, sigprocmask_block) { + TestSignalBlocking([]() { + sigset_t mask; + sigfillset(&mask); + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &mask, nullptr)); + }); +} + +// bionic-only wide variants for LP32. +#if defined(__BIONIC__) +TEST_F(SigchainTest, sigprocmask64_setmask) { + TestSignalBlocking([]() { + sigset64_t mask; + sigfillset64(&mask); + ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &mask, nullptr)); + }); +} + +TEST_F(SigchainTest, sigprocmask64_block) { + TestSignalBlocking([]() { + sigset64_t mask; + sigfillset64(&mask); + ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &mask, nullptr)); + }); +} + +TEST_F(SigchainTest, pthread_sigmask64_setmask) { + TestSignalBlocking([]() { + sigset64_t mask; + sigfillset64(&mask); + ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &mask, nullptr)); + }); +} + +TEST_F(SigchainTest, pthread_sigmask64_block) { + TestSignalBlocking([]() { + sigset64_t mask; + sigfillset64(&mask); + ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &mask, nullptr)); + }); +} +#endif + +// glibc doesn't implement most of these in terms of sigprocmask, which we rely on. +#if defined(__BIONIC__) +TEST_F(SigchainTest, pthread_sigmask_setmask) { + TestSignalBlocking([]() { + sigset_t mask; + sigfillset(&mask); + ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &mask, nullptr)); + }); +} + +TEST_F(SigchainTest, pthread_sigmask_block) { + TestSignalBlocking([]() { + sigset_t mask; + sigfillset(&mask); + ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &mask, nullptr)); + }); +} + +TEST_F(SigchainTest, sigset_mask) { + TestSignalBlocking([]() { + sigset(SIGSEGV, SIG_HOLD); + }); +} + +TEST_F(SigchainTest, sighold) { + TestSignalBlocking([]() { + sighold(SIGSEGV); + }); +} + +#if defined(__BIONIC__) +// Not exposed via headers, but the symbols are available if you declare them yourself. +extern "C" int sigblock(int); +extern "C" int sigsetmask(int); +#endif + +TEST_F(SigchainTest, sigblock) { + TestSignalBlocking([]() { + int mask = ~0U; + ASSERT_EQ(0, sigblock(mask)); + }); +} + +TEST_F(SigchainTest, sigsetmask) { + TestSignalBlocking([]() { + int mask = ~0U; + ASSERT_EQ(0, sigsetmask(mask)); + }); +} + +#endif diff --git a/sigchainlib/version-script32.txt b/sigchainlib/version-script32.txt index 2340785c42..e8a18e772c 100644 --- a/sigchainlib/version-script32.txt +++ b/sigchainlib/version-script32.txt @@ -5,8 +5,10 @@ global: RemoveSpecialSignalHandlerFn; bsd_signal; sigaction; + sigaction64; signal; sigprocmask; + sigprocmask64; local: *; }; diff --git a/sigchainlib/version-script64.txt b/sigchainlib/version-script64.txt index acf36309ea..72c86a1ba8 100644 --- a/sigchainlib/version-script64.txt +++ b/sigchainlib/version-script64.txt @@ -4,8 +4,10 @@ global: AddSpecialSignalHandlerFn; RemoveSpecialSignalHandlerFn; sigaction; + sigaction64; signal; sigprocmask; + sigprocmask64; local: *; }; diff --git a/test/004-SignalTest/signaltest.cc b/test/004-SignalTest/signaltest.cc index a58a0752c9..67118d5e63 100644 --- a/test/004-SignalTest/signaltest.cc +++ b/test/004-SignalTest/signaltest.cc @@ -99,6 +99,15 @@ static void signalhandler(int sig ATTRIBUTE_UNUSED, siginfo_t* info ATTRIBUTE_UN static struct sigaction oldaction; +bool compare_sigaction(const struct sigaction* lhs, const struct sigaction* rhs) { + // bionic's definition of `struct sigaction` has internal padding bytes, so we can't just do a + // naive memcmp of the entire struct. + return memcmp(&lhs->sa_mask, &rhs->sa_mask, sizeof(lhs->sa_mask)) == 0 && + lhs->sa_sigaction == rhs->sa_sigaction && + lhs->sa_flags == rhs->sa_flags && + lhs->sa_restorer == rhs->sa_restorer; +} + extern "C" JNIEXPORT void JNICALL Java_Main_initSignalTest(JNIEnv*, jclass) { struct sigaction action; action.sa_sigaction = signalhandler; @@ -112,8 +121,15 @@ extern "C" JNIEXPORT void JNICALL Java_Main_initSignalTest(JNIEnv*, jclass) { sigaction(SIGSEGV, &action, &oldaction); struct sigaction check; sigaction(SIGSEGV, nullptr, &check); - if (memcmp(&action, &check, sizeof(action)) != 0) { + if (!compare_sigaction(&check, &action)) { printf("sigaction returned different value\n"); + printf("action.sa_mask = %p, check.sa_mask = %p\n", + *reinterpret_cast<void**>(&action.sa_mask), + *reinterpret_cast<void**>(&check.sa_mask)); + printf("action.sa_sigaction = %p, check.sa_sigaction = %p\n", + action.sa_sigaction, check.sa_sigaction); + printf("action.sa_flags = %x, check.sa_flags = %x\n", + action.sa_flags, check.sa_flags); } signal(BLOCKED_SIGNAL, blocked_signal); signal(UNBLOCKED_SIGNAL, unblocked_signal); diff --git a/test/115-native-bridge/expected.txt b/test/115-native-bridge/expected.txt index 343a76247e..06f5979f3e 100644 --- a/test/115-native-bridge/expected.txt +++ b/test/115-native-bridge/expected.txt @@ -63,6 +63,8 @@ trampoline_Java_Main_testNewStringObject called! Getting trampoline for Java_Main_testSignal with shorty I. NB signal handler with signal 11. NB signal handler with signal 4. +NB signal handler with signal 11. +NB signal handler with signal 4. Loading invalid library 'libinvalid.so' from Java, which will fail. Checking for support. Was to load 'libinvalid.so', force fail. diff --git a/test/115-native-bridge/nativebridge.cc b/test/115-native-bridge/nativebridge.cc index a049b97adc..3b352096df 100644 --- a/test/115-native-bridge/nativebridge.cc +++ b/test/115-native-bridge/nativebridge.cc @@ -224,6 +224,22 @@ static jint trampoline_Java_Main_testSignal(JNIEnv*, jclass) { sigaction(SIGILL, &tmp, nullptr); kill(getpid(), SIGILL); +#if defined(__BIONIC__) + // Do the same again, but with sigaction64. + struct sigaction64 tmp2; + sigemptyset64(&tmp2.sa_mask); + tmp2.sa_sigaction = test_sigaction_handler; + tmp2.sa_restorer = nullptr; + + sigaction64(SIGSEGV, &tmp2, nullptr); + sigaction64(SIGILL, &tmp2, nullptr); +#endif + + // Reraise SIGSEGV/SIGILL even on non-bionic, so that the expected output is + // the same. + raise_sigsegv(); + kill(getpid(), SIGILL); + return 1234; } diff --git a/test/1926-missed-frame-pop/src/art/Test1926.java b/test/1926-missed-frame-pop/src/art/Test1926.java index cb210729a9..1c6c33a9e6 100644 --- a/test/1926-missed-frame-pop/src/art/Test1926.java +++ b/test/1926-missed-frame-pop/src/art/Test1926.java @@ -166,17 +166,22 @@ public class Test1926 { public static void doRecurTestWith(final int times, int watch_frame) throws Exception { final String target_method_name_start = "recurTimes"; final ThreadPauser safepoint = new ThreadPauser(); - Thread target = new Thread(() -> { - recurTimesA(times, () -> { - safepoint.run(); - disableFramePop(null); - }); - System.out.println("Ran recurTimes(" + times + ") without errors after disabling " + - "frame pop event!"); - System.out.println("renabling frame pop event with similar stack."); - recurTimesB(times, () -> { reenableFramePop(null); }); - System.out.println("Ran recurTimes(" + times + ") without errors!"); - }); + // We need to make the stack bigger since ASAN causes SOE if we don't. + Thread target = new Thread( + /*thread Group*/ null, + () -> { + recurTimesA(times, () -> { + safepoint.run(); + disableFramePop(null); + }); + System.out.println("Ran recurTimes(" + times + ") without errors after disabling " + + "frame pop event!"); + System.out.println("renabling frame pop event with similar stack."); + recurTimesB(times, () -> { reenableFramePop(null); }); + System.out.println("Ran recurTimes(" + times + ") without errors!"); + }, + "Test1926-Thread", + /*10 mb stack*/10 * 1024 * 1024); target.start(); safepoint.waitForOtherThreadToPause(); Suspension.suspend(target); diff --git a/test/983-source-transform-verify/source_transform_slicer.cc b/test/983-source-transform-verify/source_transform_slicer.cc index abf32e752e..34de625ed3 100644 --- a/test/983-source-transform-verify/source_transform_slicer.cc +++ b/test/983-source-transform-verify/source_transform_slicer.cc @@ -17,15 +17,10 @@ #include "source_transform.h" #pragma clang diagnostic push -// slicer defines its own CHECK. b/65422458 -#pragma push_macro("CHECK") -#undef CHECK - // Slicer's headers have code that triggers these warnings. b/65298177 #pragma clang diagnostic ignored "-Wsign-compare" -#include "reader.h" +#include "slicer/reader.h" -#pragma pop_macro("CHECK") #pragma clang diagnostic pop namespace art { diff --git a/test/ti-stress/stress.cc b/test/ti-stress/stress.cc index 7fc289faeb..d2da244397 100644 --- a/test/ti-stress/stress.cc +++ b/test/ti-stress/stress.cc @@ -29,22 +29,19 @@ #include "utils.h" #pragma clang diagnostic push -// slicer defines its own CHECK. b/65422458 -#pragma push_macro("CHECK") -#undef CHECK // Slicer's headers have code that triggers these warnings. b/65298177 #pragma clang diagnostic ignored "-Wunused-parameter" #pragma clang diagnostic ignored "-Wsign-compare" -#include "code_ir.h" -#include "control_flow_graph.h" -#include "dex_ir.h" -#include "dex_ir_builder.h" -#include "instrumentation.h" -#include "reader.h" -#include "writer.h" - -#pragma pop_macro("CHECK") + +#include "slicer/code_ir.h" +#include "slicer/control_flow_graph.h" +#include "slicer/dex_ir.h" +#include "slicer/dex_ir_builder.h" +#include "slicer/instrumentation.h" +#include "slicer/reader.h" +#include "slicer/writer.h" + #pragma clang diagnostic pop namespace art { |