2020#include < stdlib.h>
2121#include < sys/syscall.h>
2222#include < sys/types.h>
23+ #include < sys/utsname.h>
2324#include < unistd.h>
2425
2526#include " base/check_op.h"
@@ -69,6 +70,7 @@ enum class CrashType : uint32_t {
6970 kSimulated ,
7071 kBuiltinTrap ,
7172 kInfiniteRecursion ,
73+ kSegvWithTagBits ,
7274};
7375
7476struct StartHandlerForSelfTestOptions {
@@ -170,6 +172,10 @@ void ValidateExtraMemory(const StartHandlerForSelfTestOptions& options,
170172 }
171173 }
172174 EXPECT_EQ (pc_found, options.gather_indirectly_referenced_memory );
175+
176+ if (options.crash_type == CrashType::kSegvWithTagBits ) {
177+ EXPECT_EQ (exception->ExceptionAddress (), 0xefull << 56 );
178+ }
173179}
174180
175181void ValidateDump (const StartHandlerForSelfTestOptions& options,
@@ -213,6 +219,12 @@ void ValidateDump(const StartHandlerForSelfTestOptions& options,
213219
214220#pragma clang diagnostic push
215221#pragma clang diagnostic ignored "-Winfinite-recursion"
222+ // Clang (masquerading as gcc) is too smart, and removes the recursion
223+ // otherwise. May need to change if either clang or another compiler becomes
224+ // smarter.
225+ #if defined(COMPILER_GCC)
226+ __attribute__ ((noinline))
227+ #endif
216228int RecurseInfinitely (int * ptr) {
217229 int buf[1 << 20 ];
218230 return *ptr + RecurseInfinitely (buf);
@@ -236,16 +248,28 @@ void DoCrash(const StartHandlerForSelfTestOptions& options,
236248 }
237249
238250 switch (options.crash_type ) {
239- case CrashType::kSimulated :
251+ case CrashType::kSimulated : {
240252 CRASHPAD_SIMULATE_CRASH ();
241253 break ;
254+ }
242255
243- case CrashType::kBuiltinTrap :
256+ case CrashType::kBuiltinTrap : {
244257 __builtin_trap ();
258+ }
245259
246- case CrashType::kInfiniteRecursion :
260+ case CrashType::kInfiniteRecursion : {
247261 int val = 42 ;
248262 exit (RecurseInfinitely (&val));
263+ }
264+
265+ case CrashType::kSegvWithTagBits : {
266+ volatile char * x = nullptr ;
267+ #ifdef __aarch64__
268+ x += 0xefull << 56 ;
269+ #endif // __aarch64__
270+ *x;
271+ break ;
272+ }
249273 }
250274}
251275
@@ -268,7 +292,7 @@ class ScopedAltSignalStack {
268292
269293 void Initialize () {
270294 ScopedMmap local_stack_mem;
271- constexpr size_t stack_size = MINSIGSTKSZ;
295+ const size_t stack_size = MINSIGSTKSZ;
272296 ASSERT_TRUE (local_stack_mem.ResetMmap (nullptr ,
273297 stack_size,
274298 PROT_READ | PROT_WRITE,
@@ -410,6 +434,9 @@ class StartHandlerForSelfInChildTest : public MultiprocessExec {
410434 SetExpectedChildTermination (TerminationReason::kTerminationSignal ,
411435 SIGSEGV);
412436 break ;
437+ case CrashType::kSegvWithTagBits :
438+ SetExpectedChildTermination (TerminationReason::kTerminationSignal ,
439+ SIGSEGV);
413440 }
414441 }
415442 }
@@ -486,6 +513,27 @@ TEST_P(StartHandlerForSelfTest, StartHandlerInChild) {
486513 GTEST_SKIP ();
487514 }
488515#endif // defined(ADDRESS_SANITIZER)
516+
517+ if (Options ().crash_type == CrashType::kSegvWithTagBits ) {
518+ #if !defined(ARCH_CPU_ARM64)
519+ GTEST_SKIP () << " Testing for tag bits only exists on aarch64." ;
520+ #else
521+ struct utsname uname_info;
522+ ASSERT_EQ (uname (&uname_info), 0 );
523+ ASSERT_NE (uname_info.release , nullptr );
524+
525+ char * release = uname_info.release ;
526+ unsigned major = strtoul (release, &release, 10 );
527+ ASSERT_EQ (*release++, ' .' );
528+ unsigned minor = strtoul (release, nullptr , 10 );
529+
530+ if (major < 5 || (major == 5 && minor < 11 )) {
531+ GTEST_SKIP () << " Linux kernel v" << uname_info.release
532+ << " does not support SA_EXPOSE_TAGBITS" ;
533+ }
534+ #endif // !defined(ARCH_CPU_ARM64)
535+ }
536+
489537 StartHandlerForSelfInChildTest test (Options ());
490538 test.Run ();
491539}
@@ -500,7 +548,8 @@ INSTANTIATE_TEST_SUITE_P(
500548 testing::Bool(),
501549 testing::Values(CrashType::kSimulated ,
502550 CrashType::kBuiltinTrap ,
503- CrashType::kInfiniteRecursion )));
551+ CrashType::kInfiniteRecursion ,
552+ CrashType::kSegvWithTagBits )));
504553
505554// Test state for starting the handler for another process.
506555class StartHandlerForClientTest {
0 commit comments