[clang] [llvm] [libunwind] [clang-tools-extra] [libunwind] Replace process_vm_readv with SYS_rt_sigprocmask (PR #74791)

Fangrui Song via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 20 13:09:31 PST 2023


================
@@ -2974,6 +2966,37 @@ bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
                                          buf, bufLen, offset);
 }
 
+#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
+template <typename A, typename R>
+bool UnwindCursor<A, R>::isReadableAddr(const pint_t addr) const {
+  // This code is heavily based on Abseil's 'address_is_readable.cc',
+  // which is Copyright Abseil Authors (2017).
+
+  const auto sigsetAddr = reinterpret_cast<sigset_t *>(addr);
+  // We have to check that addr is nullptr because sigprocmask allows that
+  // as an argument without failure.
+  if (!sigsetAddr)
+    return false;
+  // We MUST use a raw syscall here, as wrappers may try to access
+  // sigsetAddr which may cause a SIGSEGV. A raw syscall however is
+  // safe. Additionally, we need to pass the kernel_sigset_size, which is
+  // different from libc sizeof(sigset_t). For the majority of architectures,
+  // it's 64 bits (_NSIG), and libc NSIG is _NSIG + 1.
+  const auto kernelSigsetSize = NSIG / 8;
+  const int Result = syscall(SYS_rt_sigprocmask, /*how=*/~0, sigsetAddr,
+                             nullptr, kernelSigsetSize);
+  (void)Result;
+  // Because our "how" is invalid, this syscall should always fail, and our
+  // errno should always be EINVAL or an EFAULT. EFAULT is not guaranteed
+  // by the POSIX standard. Additionally, this relies on the Linux kernel
----------------
MaskRay wrote:

"EFAULT is not guaranteed by the POSIX standard." should be removed since the whole function is Linux specific

https://github.com/llvm/llvm-project/pull/74791


More information about the cfe-commits mailing list