[m-rev.] for review: Fix access to PC from signal handler context.
Peter Wang
novalazy at gmail.com
Tue Oct 13 13:33:24 AEDT 2020
configure.ac:
Deduplicate checks for how to access the program counter from a
signal handler context.
Check REG_RIP for x86-64 and REG_EIP for i386.
Define _GNU_SOURCE for the register constants (REG_RIP, etc.)
Drop support for accessing the PC on Alpha as it doesn't fit easily
into the "uc_mcontext.gregs[$reg]" pattern.
---
configure.ac | 110 ++++++++----------------------
runtime/mercury_memory_handlers.c | 5 ++
2 files changed, 32 insertions(+), 83 deletions(-)
diff --git a/configure.ac b/configure.ac
index 78567aac9..1367017cf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1538,7 +1538,9 @@ AC_CACHE_VAL(mercury_cv_siginfo_t,
AC_TRY_RUN(
[
#include <stdio.h>
+ #include <stdlib.h>
#include <signal.h>
+ #include <unistd.h>
#ifdef MR_HAVE_SYS_SIGINFO_H
#include <sys/siginfo.h>
#endif
@@ -1584,105 +1586,41 @@ if test "$mercury_cv_siginfo_t" = yes; then
AC_DEFINE(MR_HAVE_SIGINFO_T)
AC_DEFINE(MR_HAVE_SIGINFO)
- AC_MSG_CHECKING(for \`siginfo' pc access at signals)
+ AC_MSG_CHECKING(for PC access from signal handler context)
AC_CACHE_VAL(mercury_cv_pc_access,
mercury_cv_pc_access=no
+ mercury_cv_pc_access_greg=no
+ # Which register contains the program counter:
+ # x86-64 REG_RIP
+ # i386 REG_EIP
+ # SPARC REG_PC
+ # MIPS CTX_EPC
+ for try_reg in REG_RIP REG_EIP REG_PC CTX_EPC ; do
AC_TRY_RUN(
[
+ changequote(<<,>>)
+ #define _GNU_SOURCE /* for register constants */
#include <stdio.h>
+ #include <stdlib.h>
#include <signal.h>
+ #include <unistd.h>
#ifdef MR_HAVE_SYS_SIGINFO_H
#include <sys/siginfo.h>
#endif
- #ifdef MR_HAVE_UCONTEXT_H
- #include <ucontext.h>
- #else
- #include <sys/ucontext.h>
- #endif
- int save_signum = 0;
- int save_cause;
- int save_pc;
- extern void handler(int signum, siginfo_t *info, void *context);
- int main() {
- struct sigaction act;
- act.sa_flags = SA_SIGINFO;
- act.sa_sigaction = handler;
- if (sigemptyset(&act.sa_mask) != 0)
- exit(1);
- if (sigaction(SIGSEGV, &act, NULL) != 0)
- exit(1);
- if (kill(getpid(), SIGSEGV) != 0)
- exit(1);
- if (save_signum == 0)
- exit(1);
- exit(0);
- }
- void handler(int signum, siginfo_t *info, void *context) {
- save_signum = signum;
- save_cause = info->si_code;
- /* Don't use array indexing - the square brackets
- are autoconf quote characters */
- save_pc = *(((ucontext_t *) context)->uc_mcontext.gregs
- + REG_PC);
- }
- ],
- [mercury_cv_pc_access=REG_PC;mercury_cv_pc_access_greg=yes],
- [true])
- AC_TRY_RUN(
- [
- #include <stdio.h>
- #include <signal.h>
- #ifdef MR_HAVE_SYS_SIGINFO_H
- #include <sys/siginfo.h>
+ #ifdef MR_HAVE_SYS_SIGNAL_H
+ #include <sys/signal.h>
#endif
#ifdef MR_HAVE_UCONTEXT_H
#include <ucontext.h>
- #else
- #include <sys/ucontext.h>
- #endif
- int save_signum = 0;
- int save_cause;
- int save_pc;
- extern void handler(int signum, siginfo_t *info, void *context);
- int main() {
- struct sigaction act;
- act.sa_flags = SA_SIGINFO;
- act.sa_sigaction = handler;
- if (sigemptyset(&act.sa_mask) != 0)
- exit(1);
- if (sigaction(SIGSEGV, &act, NULL) != 0)
- exit(1);
- if (kill(getpid(), SIGSEGV) != 0)
- exit(1);
- if (save_signum == 0)
- exit(1);
- exit(0);
- }
- void handler(int signum, siginfo_t *info, void *context) {
- save_signum = signum;
- save_cause = info->si_code;
- save_pc = *(((ucontext_t *) context)->uc_mcontext.gregs
- + CTX_EPC);
- }
- ],
- [mercury_cv_pc_access=CTX_EPC;mercury_cv_pc_access_greg=yes],
- [true])
- AC_TRY_RUN(
- [
- #include <stdio.h>
- #include <signal.h>
- #ifdef MR_HAVE_SYS_SIGINFO_H
- #include <sys/siginfo.h>
#endif
- #ifdef MR_HAVE_UCONTEXT_H
- #include <ucontext.h>
- #else
+ #ifdef MR_HAVE_SYS_UCONTEXT_H
#include <sys/ucontext.h>
#endif
int save_signum = 0;
int save_cause;
int save_pc;
- extern void handler(int signum, siginfo_t *info, void *context);
+ extern void handler(int signum, siginfo_t *info,
+ void *context);
int main() {
struct sigaction act;
act.sa_flags = SA_SIGINFO;
@@ -1698,13 +1636,19 @@ if test "$mercury_cv_siginfo_t" = yes; then
exit(0);
}
void handler(int signum, siginfo_t *info, void *context) {
+ ucontext_t *uc = (ucontext_t *) context;
save_signum = signum;
save_cause = info->si_code;
- save_pc = ((ucontext_t *) context)->uc_mcontext.sc_pc;
+ save_pc = uc->uc_mcontext.gregs[$try_reg];
}
+ changequote([,])
],
- [mercury_cv_pc_access=sc_pc;mercury_cv_pc_access_greg=no],
+ [mercury_cv_pc_access=$try_reg;mercury_cv_pc_access_greg=yes],
[true])
+ if test "$mercury_cv_pc_access" != no; then
+ break
+ fi
+ done
)
AC_MSG_RESULT($mercury_cv_pc_access)
if test "$mercury_cv_pc_access" != no; then
diff --git a/runtime/mercury_memory_handlers.c b/runtime/mercury_memory_handlers.c
index 04592754a..40e76fe06 100644
--- a/runtime/mercury_memory_handlers.c
+++ b/runtime/mercury_memory_handlers.c
@@ -11,6 +11,11 @@
////////////////////////////////////////////////////////////////////////////
+#ifndef _GNU_SOURCE
+ // This must be defined for REG_RIP, etc.
+ #define _GNU_SOURCE
+#endif
+
#include "mercury_imp.h"
#ifdef MR_HAVE_UNISTD_H
--
2.28.0
More information about the reviews
mailing list