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

Jordan R AW via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 19 14:02:08 PST 2023


================
@@ -2974,6 +2966,39 @@ 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), and provided under
+  // the Apache License 2.0.
+
+  // Align to 8-bytes.
+  const auto alignedAddr = addr & ~pint_t{7};
+  const auto sigsetAddr = reinterpret_cast<sigset_t *>(alignedAddr);
+  // We have to check that addr is nullptr because sigprocmask allows that
+  // as an argument without failure.
+  if (!sigsetAddr)
+    return false;
+
+  // We MUST use the raw sigprocmask syscall here, as wrappers may try to
+  // access sigsetAddr which may cause a SIGSEGV. The raw syscall however is
+  // safe. Additionally, we need to pass the kernel_sigset_size, which is
+  // different from libc sizeof(sigset_t). Some archs have sigset_t
+  // defined as unsigned long, so let's use that.
+  const auto approxKernelSigsetSize = sizeof(unsigned long);
----------------
ajordanr-google wrote:

Looking at linux-6.6.7 source code, we have some minor variety on `sigset_t` size...

TL;DR: They are almost all `_NSIG` bits long, which is 64 bits or, in the case of MIPS, maybe 128? There are two exceptions to this, where they are not a struct of size `_NSIG/_NSIG_BPW * sizeof(unsigned long)` but rather just `unsigned long`. I assume `_NSIG_BPW == sizeof(long) == sizeof(unsigned long)`, which seems reasonable given the comments (and not `_NSIG_BPW == sizeof(int)`).

---

`sigset_t` is almost always defined as:

```
typedef struct {
        unsigned long sig[_NSIG_WORDS];
} sigset_t;
```

Where:

```
arch/parisc/include/asm/signal.h-7-#define _NSIG                64
arch/parisc/include/asm/signal.h-8-/* bits-per-word, where word apparently means 'long' not 'int' */
arch/parisc/include/asm/signal.h-9-#define _NSIG_BPW    BITS_PER_LONG
arch/parisc/include/asm/signal.h:10:#define _NSIG_WORDS (_NSIG / _NSIG_BPW)

// or

arch/xtensa/include/uapi/asm/signal.h-18-#define _NSIG          64
arch/xtensa/include/uapi/asm/signal.h-19-#define _NSIG_BPW      32
arch/xtensa/include/uapi/asm/signal.h:20:#define _NSIG_WORDS    (_NSIG / _NSIG_BPW)

// or

arch/ia64/include/asm/signal.h-15-#define _NSIG         64
arch/ia64/include/asm/signal.h-16-#define _NSIG_BPW     64
arch/ia64/include/asm/signal.h:17:#define _NSIG_WORDS   (_NSIG / _NSIG_BPW)

// or

arch/alpha/include/asm/signal.h-10-#define _NSIG                64
arch/alpha/include/asm/signal.h-11-#define _NSIG_BPW    64
arch/alpha/include/asm/signal.h:12:#define _NSIG_WORDS  (_NSIG / _NSIG_BPW)

// or

arch/arm/include/asm/signal.h-10-#define _NSIG          64
arch/arm/include/asm/signal.h-11-#define _NSIG_BPW      32
arch/arm/include/asm/signal.h:12:#define _NSIG_WORDS    (_NSIG / _NSIG_BPW)

// or

arch/s390/include/asm/signal.h-12-/* Most things should be clean enough to redefine this at will, if care
arch/s390/include/asm/signal.h-13-   is taken to make libc match.  */
arch/s390/include/asm/signal.h-14-#include <asm/sigcontext.h>
arch/s390/include/asm/signal.h-15-#define _NSIG           _SIGCONTEXT_NSIG
arch/s390/include/asm/signal.h-16-#define _NSIG_BPW       _SIGCONTEXT_NSIG_BPW
arch/s390/include/asm/signal.h:17:#define _NSIG_WORDS     _SIGCONTEXT_NSIG_WORDS
arch/s390/include/uapi/asm/sigcontext.h:30:/* Has to be at least _NSIG_WORDS from asm/signal.h */
arch/s390/include/uapi/asm/sigcontext.h-31-#define _SIGCONTEXT_NSIG     64
arch/s390/include/uapi/asm/sigcontext.h-32-#define _SIGCONTEXT_NSIG_BPW 64

// or

arch/x86/include/asm/signal.h-11-#define _NSIG          64
arch/x86/include/asm/signal.h-12-
arch/x86/include/asm/signal.h-13-#ifdef __i386__
arch/x86/include/asm/signal.h-14-# define _NSIG_BPW     32
arch/x86/include/asm/signal.h-15-#else
arch/x86/include/asm/signal.h-16-# define _NSIG_BPW     64
arch/x86/include/asm/signal.h-17-#endif
arch/x86/include/asm/signal.h-18-
arch/x86/include/asm/signal.h:19:#define _NSIG_WORDS    (_NSIG / _NSIG_BPW)

// or

arch/m68k/include/asm/signal.h-10-#define _NSIG         64
arch/m68k/include/asm/signal.h-11-#define _NSIG_BPW     32
arch/m68k/include/asm/signal.h:12:#define _NSIG_WORDS   (_NSIG / _NSIG_BPW)

// or (quite weirdly)

arch/mips/include/uapi/asm/signal.h-15-#define _NSIG            128
arch/mips/include/uapi/asm/signal.h-16-#define _NSIG_BPW        (sizeof(unsigned long) * 8)
arch/mips/include/uapi/asm/signal.h:17:#define _NSIG_WORDS      (_NSIG / _NSIG_BPW)

// or

arch/sparc/include/uapi/asm/signal.h-81-#define __NEW_NSIG      64
arch/sparc/include/uapi/asm/signal.h-82-#ifdef __arch64__
arch/sparc/include/uapi/asm/signal.h-83-#define _NSIG_BPW       64
arch/sparc/include/uapi/asm/signal.h-84-#else
arch/sparc/include/uapi/asm/signal.h-85-#define _NSIG_BPW       32
arch/sparc/include/uapi/asm/signal.h-86-#endif
arch/sparc/include/uapi/asm/signal.h:87:#define _NSIG_WORDS     (__NEW_NSIG / _NSIG_BPW)

// or

arch/powerpc/include/uapi/asm/signal.h-7-#define _NSIG          64
arch/powerpc/include/uapi/asm/signal.h-8-#ifdef __powerpc64__
arch/powerpc/include/uapi/asm/signal.h-9-#define _NSIG_BPW      64
arch/powerpc/include/uapi/asm/signal.h-10-#else
arch/powerpc/include/uapi/asm/signal.h-11-#define _NSIG_BPW     32
arch/powerpc/include/uapi/asm/signal.h-12-#endif
arch/powerpc/include/uapi/asm/signal.h:13:#define _NSIG_WORDS   (_NSIG / _NSIG_BPW)

// or (finally)

include/uapi/asm-generic/signal.h-7-#define _NSIG               64
include/uapi/asm-generic/signal.h-8-#define _NSIG_BPW   __BITS_PER_LONG
include/uapi/asm-generic/signal.h:9:#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
```

Here are the two exceptions to that (and their line numbers):

```
arch/x86/include/uapi/asm/signal.h:17:typedef unsigned long sigset_t;
arch/alpha/include/uapi/asm/signal.h:14:typedef unsigned long sigset_t;
```

There were also various `old_sigset_t` and `__kernel_sigset_t`, which were defined like:

```
arch/ia64/include/asm/signal.h:24:typedef unsigned long old_sigset_t;
arch/alpha/include/asm/signal.h:14:typedef unsigned long old_sigset_t;          /* at least 32 bits */
arch/m68k/include/asm/signal.h:14:typedef unsigned long old_sigset_t;           /* at least 32 bits */
arch/s390/include/asm/signal.h:19:typedef unsigned long old_sigset_t;             /* at least 32 bits */
arch/x86/include/asm/signal.h:21:typedef unsigned long old_sigset_t;            /* at least 32 bits */
arch/parisc/include/asm/signal.h:17:typedef unsigned long old_sigset_t;         /* at least 32 bits */
arch/mips/include/uapi/asm/signal.h:23:typedef unsigned long old_sigset_t;              /* at least 32 bits */
arch/powerpc/include/uapi/asm/signal.h:15:typedef unsigned long old_sigset_t;           /* at least 32 bits */
```

and

```
arch/ia64/include/uapi/asm/posix_types.h:5:typedef unsigned long        __kernel_sigset_t;      /* at least 32 bits */
arch/s390/include/uapi/asm/posix_types.h:46:typedef unsigned long   __kernel_sigset_t;      /* at least 32 bits */
arch/alpha/include/uapi/asm/posix_types.h:14:typedef unsigned long      __kernel_sigset_t;      /* at least 32 bits */
```

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


More information about the cfe-commits mailing list