summaryrefslogtreecommitdiff
path: root/libsigsegv/src
diff options
context:
space:
mode:
Diffstat (limited to 'libsigsegv/src')
-rw-r--r--libsigsegv/src/Makefile.am104
-rw-r--r--libsigsegv/src/Makefile.in591
-rw-r--r--libsigsegv/src/dispatcher.c255
-rw-r--r--libsigsegv/src/fault-aix3-powerpc.h20
-rw-r--r--libsigsegv/src/fault-aix3.h20
-rw-r--r--libsigsegv/src/fault-aix5-powerpc.h20
-rw-r--r--libsigsegv/src/fault-aix5.h18
-rw-r--r--libsigsegv/src/fault-beos-i386.h22
-rw-r--r--libsigsegv/src/fault-beos.h19
-rw-r--r--libsigsegv/src/fault-bsd.h19
-rw-r--r--libsigsegv/src/fault-freebsd-i386.h27
-rw-r--r--libsigsegv/src/fault-hpux-hppa.h46
-rw-r--r--libsigsegv/src/fault-hpux.h19
-rw-r--r--libsigsegv/src/fault-hurd.h20
-rw-r--r--libsigsegv/src/fault-irix-mips.h20
-rw-r--r--libsigsegv/src/fault-irix.h20
-rw-r--r--libsigsegv/src/fault-linux-alpha.h22
-rw-r--r--libsigsegv/src/fault-linux-arm.h26
-rw-r--r--libsigsegv/src/fault-linux-cris.h22
-rw-r--r--libsigsegv/src/fault-linux-hppa.h27
-rw-r--r--libsigsegv/src/fault-linux-i386-old.h23
-rw-r--r--libsigsegv/src/fault-linux-i386.h21
-rw-r--r--libsigsegv/src/fault-linux-ia64.h29
-rw-r--r--libsigsegv/src/fault-linux-m68k.c44
-rw-r--r--libsigsegv/src/fault-linux-m68k.h24
-rw-r--r--libsigsegv/src/fault-linux-mips.h22
-rw-r--r--libsigsegv/src/fault-linux-powerpc.h23
-rw-r--r--libsigsegv/src/fault-linux-s390.h22
-rw-r--r--libsigsegv/src/fault-linux-sh.h22
-rw-r--r--libsigsegv/src/fault-linux-sparc.h23
-rw-r--r--libsigsegv/src/fault-linux-x86_64.h22
-rw-r--r--libsigsegv/src/fault-linux.h22
-rw-r--r--libsigsegv/src/fault-macos-i386.h20
-rw-r--r--libsigsegv/src/fault-macosdarwin5-powerpc.c124
-rw-r--r--libsigsegv/src/fault-macosdarwin5-powerpc.h26
-rw-r--r--libsigsegv/src/fault-macosdarwin7-powerpc.c131
-rw-r--r--libsigsegv/src/fault-macosdarwin7-powerpc.h28
-rw-r--r--libsigsegv/src/fault-netbsd-alpha.c39
-rw-r--r--libsigsegv/src/fault-netbsd-alpha.h26
-rw-r--r--libsigsegv/src/fault-netbsd.h29
-rw-r--r--libsigsegv/src/fault-none.h17
-rw-r--r--libsigsegv/src/fault-openbsd-i386.h20
-rw-r--r--libsigsegv/src/fault-openbsd.h21
-rw-r--r--libsigsegv/src/fault-osf-alpha.h21
-rw-r--r--libsigsegv/src/fault-osf.h19
-rw-r--r--libsigsegv/src/fault-posix-ucontext.h23
-rw-r--r--libsigsegv/src/fault-posix.h21
-rw-r--r--libsigsegv/src/fault-solaris-i386.h20
-rw-r--r--libsigsegv/src/fault-solaris-sparc.h20
-rw-r--r--libsigsegv/src/fault-solaris.h18
-rw-r--r--libsigsegv/src/fault.h37
-rw-r--r--libsigsegv/src/handler-macos.c563
-rw-r--r--libsigsegv/src/handler-none.c49
-rw-r--r--libsigsegv/src/handler-unix.c542
-rw-r--r--libsigsegv/src/handler-win32.c317
-rw-r--r--libsigsegv/src/handler.c20
-rw-r--r--libsigsegv/src/leave-none.c18
-rw-r--r--libsigsegv/src/leave-nop.c23
-rw-r--r--libsigsegv/src/leave-setcontext.c38
-rw-r--r--libsigsegv/src/leave-sigaltstack.c39
-rw-r--r--libsigsegv/src/leave.c20
-rw-r--r--libsigsegv/src/leave.h18
-rw-r--r--libsigsegv/src/machfault-macos.h120
-rw-r--r--libsigsegv/src/machfault.h54
-rw-r--r--libsigsegv/src/signals-bsd.h21
-rw-r--r--libsigsegv/src/signals-hpux.h21
-rw-r--r--libsigsegv/src/signals-hurd.h21
-rw-r--r--libsigsegv/src/signals-macos.h24
-rw-r--r--libsigsegv/src/signals.h21
-rw-r--r--libsigsegv/src/sigsegv.h.in201
-rw-r--r--libsigsegv/src/sigsegv.h.msvc201
-rw-r--r--libsigsegv/src/stackvma-beos.c62
-rw-r--r--libsigsegv/src/stackvma-freebsd.c118
-rw-r--r--libsigsegv/src/stackvma-linux.c83
-rw-r--r--libsigsegv/src/stackvma-mach.c119
-rw-r--r--libsigsegv/src/stackvma-mincore.c275
-rw-r--r--libsigsegv/src/stackvma-none.c25
-rw-r--r--libsigsegv/src/stackvma-procfs.c188
-rw-r--r--libsigsegv/src/stackvma-rofile.c121
-rw-r--r--libsigsegv/src/stackvma-simple.c42
-rw-r--r--libsigsegv/src/stackvma.c20
-rw-r--r--libsigsegv/src/stackvma.h48
-rw-r--r--libsigsegv/src/version.c20
83 files changed, 5746 insertions, 0 deletions
diff --git a/libsigsegv/src/Makefile.am b/libsigsegv/src/Makefile.am
new file mode 100644
index 00000000..7e57dad2
--- /dev/null
+++ b/libsigsegv/src/Makefile.am
@@ -0,0 +1,104 @@
+## Makefile for libsigsegv/src.
+## Copyright (C) 2002-2006, 2008-2009 Bruno Haible <bruno@clisp.org>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+## USA.
+
+## Process this file with automake to produce Makefile.in.
+
+AUTOMAKE_OPTIONS = 1.5 gnits no-dependencies
+
+RM = rm -f
+
+lib_LTLIBRARIES = libsigsegv.la
+
+noinst_HEADERS = \
+ fault.h fault-aix3.h fault-aix3-powerpc.h fault-aix5.h fault-aix5-powerpc.h \
+ fault-beos.h fault-beos-i386.h \
+ fault-bsd.h fault-freebsd-i386.h \
+ fault-hpux.h fault-hpux-hppa.h fault-hurd.h fault-irix.h fault-irix-mips.h \
+ fault-linux.h fault-linux-alpha.h fault-linux-arm.h fault-linux-cris.h \
+ fault-linux-hppa.h fault-linux-i386.h fault-linux-i386-old.h \
+ fault-linux-ia64.h fault-linux-m68k.h fault-linux-m68k.c fault-linux-mips.h \
+ fault-linux-powerpc.h fault-linux-s390.h fault-linux-sh.h \
+ fault-linux-sparc.h fault-linux-x86_64.h \
+ fault-macos-i386.h \
+ fault-macosdarwin5-powerpc.h fault-macosdarwin5-powerpc.c \
+ fault-macosdarwin7-powerpc.h fault-macosdarwin7-powerpc.c \
+ fault-netbsd.h fault-netbsd-alpha.h fault-netbsd-alpha.c \
+ fault-none.h \
+ fault-openbsd.h fault-openbsd-i386.h \
+ fault-osf.h fault-osf-alpha.h \
+ fault-posix.h fault-posix-ucontext.h \
+ fault-solaris.h fault-solaris-i386.h fault-solaris-sparc.h \
+ machfault.h machfault-macos.h \
+ signals.h signals-bsd.h signals-hpux.h signals-hurd.h signals-macos.h \
+ leave.h \
+ stackvma.h
+
+EXTRA_DIST = \
+ handler-none.c handler-unix.c handler-macos.c handler-win32.c \
+ stackvma-none.c stackvma-simple.c stackvma-linux.c stackvma-freebsd.c \
+ stackvma-procfs.c stackvma-beos.c stackvma-mach.c stackvma-mincore.c \
+ stackvma-rofile.c \
+ leave-none.c leave-nop.c leave-sigaltstack.c leave-setcontext.c \
+ sigsegv.h.msvc
+
+INCLUDES = -I. -I$(srcdir)
+DEFS = @DEFS@
+
+libsigsegv_la_SOURCES = handler.c stackvma.c leave.c dispatcher.c version.c
+
+libsigsegv_la_LDFLAGS = \
+ -rpath $(libdir) \
+ -version-info $(LIBSIGSEGV_VERSION_INFO) \
+ -lc -no-undefined
+
+# Before making a release, change this according to the libtool documentation,
+# section "Library interface versions".
+LIBSIGSEGV_VERSION_INFO = 1:0:0
+
+# Dependencies.
+handler.$(OBJEXT) : ../config.h sigsegv.h @CFG_HANDLER@ $(noinst_HEADERS)
+stackvma.$(OBJEXT) : ../config.h @CFG_STACKVMA@ stackvma.h
+leave.$(OBJEXT) : ../config.h @CFG_LEAVE@
+dispatcher.$(OBJEXT) : sigsegv.h
+
+
+# Special rules for installing sigsegv.h.
+
+install-data-local:
+ $(mkinstalldirs) $(DESTDIR)$(includedir)
+ $(INSTALL_DATA) sigsegv.h $(DESTDIR)$(includedir)/sigsegv.h
+
+installdirs-local:
+ $(mkinstalldirs) $(DESTDIR)$(includedir)
+
+uninstall-local:
+ $(RM) $(DESTDIR)$(includedir)/sigsegv.h
+
+
+DISTCLEANFILES = sigsegv.h
+
+
+# Rules for "make dist".
+
+sigsegv.h.msvc : sigsegv.h.in
+ sed -e 's/@''FAULT_CONTEXT_INCLUDE''@/#include <windows.h>/' \
+ -e 's/@''FAULT_CONTEXT''@/CONTEXT/' \
+ -e 's/@''HAVE_SIGSEGV_RECOVERY''@/1/' \
+ -e 's/@''HAVE_STACK_OVERFLOW_RECOVERY''@/1/' \
+ < $(srcdir)/sigsegv.h.in > $@
+
diff --git a/libsigsegv/src/Makefile.in b/libsigsegv/src/Makefile.in
new file mode 100644
index 00000000..8f18748d
--- /dev/null
+++ b/libsigsegv/src/Makefile.in
@@ -0,0 +1,591 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/sigsegv.h.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/bold.m4 \
+ $(top_srcdir)/m4/fault.m4 $(top_srcdir)/m4/getpagesize.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/mmap-anon.m4 \
+ $(top_srcdir)/m4/relocatable.m4 \
+ $(top_srcdir)/m4/sigaltstack-longjmp.m4 \
+ $(top_srcdir)/m4/sigaltstack-siglongjmp.m4 \
+ $(top_srcdir)/m4/sigaltstack.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = sigsegv.h
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libsigsegv_la_LIBADD =
+am_libsigsegv_la_OBJECTS = handler.lo stackvma.lo leave.lo \
+ dispatcher.lo version.lo
+libsigsegv_la_OBJECTS = $(am_libsigsegv_la_OBJECTS)
+libsigsegv_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libsigsegv_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libsigsegv_la_SOURCES)
+DIST_SOURCES = $(libsigsegv_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFG_HANDLER = @CFG_HANDLER@
+CFG_LEAVE = @CFG_LEAVE@
+CFG_STACKVMA = @CFG_STACKVMA@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAULT_CONTEXT = @FAULT_CONTEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_SIGSEGV_RECOVERY = @HAVE_SIGSEGV_RECOVERY@
+HAVE_STACK_OVERFLOW_RECOVERY = @HAVE_STACK_OVERFLOW_RECOVERY@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PLATFORM = @PLATFORM@
+RANLIB = @RANLIB@
+RELOCATABLE = @RELOCATABLE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = 1.5 gnits no-dependencies
+RM = rm -f
+lib_LTLIBRARIES = libsigsegv.la
+noinst_HEADERS = \
+ fault.h fault-aix3.h fault-aix3-powerpc.h fault-aix5.h fault-aix5-powerpc.h \
+ fault-beos.h fault-beos-i386.h \
+ fault-bsd.h fault-freebsd-i386.h \
+ fault-hpux.h fault-hpux-hppa.h fault-hurd.h fault-irix.h fault-irix-mips.h \
+ fault-linux.h fault-linux-alpha.h fault-linux-arm.h fault-linux-cris.h \
+ fault-linux-hppa.h fault-linux-i386.h fault-linux-i386-old.h \
+ fault-linux-ia64.h fault-linux-m68k.h fault-linux-m68k.c fault-linux-mips.h \
+ fault-linux-powerpc.h fault-linux-s390.h fault-linux-sh.h \
+ fault-linux-sparc.h fault-linux-x86_64.h \
+ fault-macos-i386.h \
+ fault-macosdarwin5-powerpc.h fault-macosdarwin5-powerpc.c \
+ fault-macosdarwin7-powerpc.h fault-macosdarwin7-powerpc.c \
+ fault-netbsd.h fault-netbsd-alpha.h fault-netbsd-alpha.c \
+ fault-none.h \
+ fault-openbsd.h fault-openbsd-i386.h \
+ fault-osf.h fault-osf-alpha.h \
+ fault-posix.h fault-posix-ucontext.h \
+ fault-solaris.h fault-solaris-i386.h fault-solaris-sparc.h \
+ machfault.h machfault-macos.h \
+ signals.h signals-bsd.h signals-hpux.h signals-hurd.h signals-macos.h \
+ leave.h \
+ stackvma.h
+
+EXTRA_DIST = \
+ handler-none.c handler-unix.c handler-macos.c handler-win32.c \
+ stackvma-none.c stackvma-simple.c stackvma-linux.c stackvma-freebsd.c \
+ stackvma-procfs.c stackvma-beos.c stackvma-mach.c stackvma-mincore.c \
+ stackvma-rofile.c \
+ leave-none.c leave-nop.c leave-sigaltstack.c leave-setcontext.c \
+ sigsegv.h.msvc
+
+INCLUDES = -I. -I$(srcdir)
+libsigsegv_la_SOURCES = handler.c stackvma.c leave.c dispatcher.c version.c
+libsigsegv_la_LDFLAGS = \
+ -rpath $(libdir) \
+ -version-info $(LIBSIGSEGV_VERSION_INFO) \
+ -lc -no-undefined
+
+
+# Before making a release, change this according to the libtool documentation,
+# section "Library interface versions".
+LIBSIGSEGV_VERSION_INFO = 1:0:0
+DISTCLEANFILES = sigsegv.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnits src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+sigsegv.h: $(top_builddir)/config.status $(srcdir)/sigsegv.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libsigsegv.la: $(libsigsegv_la_OBJECTS) $(libsigsegv_la_DEPENDENCIES)
+ $(libsigsegv_la_LINK) -rpath $(libdir) $(libsigsegv_la_OBJECTS) $(libsigsegv_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+.c.o:
+ $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs: installdirs-local
+ for dir in "$(DESTDIR)$(libdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES uninstall-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-data-local install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-libLTLIBRARIES install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-local \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-libLTLIBRARIES uninstall-local
+
+
+# Dependencies.
+handler.$(OBJEXT) : ../config.h sigsegv.h @CFG_HANDLER@ $(noinst_HEADERS)
+stackvma.$(OBJEXT) : ../config.h @CFG_STACKVMA@ stackvma.h
+leave.$(OBJEXT) : ../config.h @CFG_LEAVE@
+dispatcher.$(OBJEXT) : sigsegv.h
+
+# Special rules for installing sigsegv.h.
+
+install-data-local:
+ $(mkinstalldirs) $(DESTDIR)$(includedir)
+ $(INSTALL_DATA) sigsegv.h $(DESTDIR)$(includedir)/sigsegv.h
+
+installdirs-local:
+ $(mkinstalldirs) $(DESTDIR)$(includedir)
+
+uninstall-local:
+ $(RM) $(DESTDIR)$(includedir)/sigsegv.h
+
+# Rules for "make dist".
+
+sigsegv.h.msvc : sigsegv.h.in
+ sed -e 's/@''FAULT_CONTEXT_INCLUDE''@/#include <windows.h>/' \
+ -e 's/@''FAULT_CONTEXT''@/CONTEXT/' \
+ -e 's/@''HAVE_SIGSEGV_RECOVERY''@/1/' \
+ -e 's/@''HAVE_STACK_OVERFLOW_RECOVERY''@/1/' \
+ < $(srcdir)/sigsegv.h.in > $@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libsigsegv/src/dispatcher.c b/libsigsegv/src/dispatcher.c
new file mode 100644
index 00000000..2619e65d
--- /dev/null
+++ b/libsigsegv/src/dispatcher.c
@@ -0,0 +1,255 @@
+/* Dispatch signal to right virtual memory area.
+ Copyright (C) 1993-1999, 2002-2003 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "sigsegv.h"
+
+#include <stddef.h> /* needed for NULL on SunOS4 */
+#include <stdlib.h>
+#ifdef _WIN32
+#include <malloc.h>
+#endif
+
+/*
+ * A dispatcher contains an AVL tree of non-empty intervals, sorted according
+ * to their starting address.
+ */
+typedef
+struct node_t
+{
+ /* AVL tree management. */
+ struct node_t *left;
+ struct node_t *right;
+ unsigned int height;
+ /* Representation of interval. */
+ unsigned long address;
+ unsigned long len;
+ /* User handler. */
+ sigsegv_area_handler_t handler;
+ void *handler_arg;
+}
+node_t;
+
+#define empty ((node_t *) 0)
+#define heightof(tree) ((tree) == empty ? 0 : (tree)->height)
+#define MAXHEIGHT 41
+
+static void
+rebalance (node_t ***nodeplaces_ptr, unsigned int count)
+{
+ if (count > 0)
+ do
+ {
+ node_t **nodeplace = *--nodeplaces_ptr;
+ node_t *node = *nodeplace;
+ node_t *nodeleft = node->left;
+ node_t *noderight = node->right;
+ unsigned int heightleft = heightof (nodeleft);
+ unsigned int heightright = heightof (noderight);
+ if (heightright + 1 < heightleft)
+ {
+ node_t *nodeleftleft = nodeleft->left;
+ node_t *nodeleftright = nodeleft->right;
+ unsigned int heightleftright = heightof (nodeleftright);
+ if (heightof (nodeleftleft) >= heightleftright)
+ {
+ node->left = nodeleftright; nodeleft->right = node;
+ nodeleft->height = 1 + (node->height = 1 + heightleftright);
+ *nodeplace = nodeleft;
+ }
+ else
+ {
+ nodeleft->right = nodeleftright->left;
+ node->left = nodeleftright->right;
+ nodeleftright->left = nodeleft;
+ nodeleftright->right = node;
+ nodeleft->height = node->height = heightleftright;
+ nodeleftright->height = heightleft;
+ *nodeplace = nodeleftright;
+ }
+ }
+ else if (heightleft + 1 < heightright)
+ {
+ node_t *noderightright = noderight->right;
+ node_t *noderightleft = noderight->left;
+ unsigned int heightrightleft = heightof (noderightleft);
+ if (heightof (noderightright) >= heightrightleft)
+ {
+ node->right = noderightleft; noderight->left = node;
+ noderight->height = 1 + (node->height = 1 + heightrightleft);
+ *nodeplace = noderight;
+ }
+ else
+ {
+ noderight->left = noderightleft->right;
+ node->right = noderightleft->left;
+ noderightleft->right = noderight;
+ noderightleft->left = node;
+ noderight->height = node->height = heightrightleft;
+ noderightleft->height = heightright;
+ *nodeplace = noderightleft;
+ }
+ }
+ else
+ {
+ unsigned int height =
+ (heightleft<heightright ? heightright : heightleft) + 1;
+ if (height == node->height)
+ break;
+ node->height = height;
+ }
+ }
+ while (--count > 0);
+}
+
+static node_t *
+insert (node_t *new_node, node_t *tree)
+{
+ unsigned long key = new_node->address;
+ node_t **nodeplace = &tree;
+ node_t **stack[MAXHEIGHT];
+ unsigned int stack_count = 0;
+ node_t ***stack_ptr = &stack[0];
+ for (;;)
+ {
+ node_t *node = *nodeplace;
+ if (node == empty)
+ break;
+ *stack_ptr++ = nodeplace; stack_count++;
+ if (key < node->address)
+ nodeplace = &node->left;
+ else
+ nodeplace = &node->right;
+ }
+ new_node->left = empty;
+ new_node->right = empty;
+ new_node->height = 1;
+ *nodeplace = new_node;
+ rebalance (stack_ptr, stack_count);
+ return tree;
+}
+
+static node_t *
+delete (node_t *node_to_delete, node_t *tree)
+{
+ unsigned long key = node_to_delete->address;
+ node_t **nodeplace = &tree;
+ node_t **stack[MAXHEIGHT];
+ unsigned int stack_count = 0;
+ node_t ***stack_ptr = &stack[0];
+ for (;;)
+ {
+ node_t *node = *nodeplace;
+ if (node == empty)
+ return tree;
+ *stack_ptr++ = nodeplace; stack_count++;
+ if (key == node->address)
+ {
+ if (node != node_to_delete)
+ abort ();
+ break;
+ }
+ if (key < node->address)
+ nodeplace = &node->left;
+ else
+ nodeplace = &node->right;
+ }
+ {
+ node_t **nodeplace_to_delete = nodeplace;
+ if (node_to_delete->left == empty)
+ {
+ *nodeplace_to_delete = node_to_delete->right;
+ stack_ptr--; stack_count--;
+ }
+ else
+ {
+ node_t ***stack_ptr_to_delete = stack_ptr;
+ node_t **nodeplace = &node_to_delete->left;
+ node_t *node;
+ for (;;)
+ {
+ node = *nodeplace;
+ if (node->right == empty)
+ break;
+ *stack_ptr++ = nodeplace; stack_count++;
+ nodeplace = &node->right;
+ }
+ *nodeplace = node->left;
+ node->left = node_to_delete->left;
+ node->right = node_to_delete->right;
+ node->height = node_to_delete->height;
+ *nodeplace_to_delete = node;
+ *stack_ptr_to_delete = &node->left;
+ }
+ }
+ rebalance (stack_ptr, stack_count);
+ return tree;
+}
+
+void
+sigsegv_init (sigsegv_dispatcher *dispatcher)
+{
+ dispatcher->tree = empty;
+}
+
+void *
+sigsegv_register (sigsegv_dispatcher *dispatcher,
+ void *address, unsigned long len,
+ sigsegv_area_handler_t handler, void *handler_arg)
+{
+ if (len == 0)
+ return NULL;
+ else
+ {
+ node_t *new_node = (node_t *) malloc (sizeof (node_t));
+ new_node->address = (unsigned long) address;
+ new_node->len = len;
+ new_node->handler = handler;
+ new_node->handler_arg = handler_arg;
+ dispatcher->tree = insert (new_node, (node_t *) dispatcher->tree);
+ return new_node;
+ }
+}
+
+void
+sigsegv_unregister (sigsegv_dispatcher *dispatcher, void *ticket)
+{
+ if (ticket != NULL)
+ {
+ node_t *node_to_delete = (node_t *) ticket;
+ dispatcher->tree = delete (node_to_delete, (node_t *) dispatcher->tree);
+ free (node_to_delete);
+ }
+}
+
+int
+sigsegv_dispatch (sigsegv_dispatcher *dispatcher, void *fault_address)
+{
+ unsigned long key = (unsigned long) fault_address;
+ node_t *tree = (node_t *) dispatcher->tree;
+ for (;;)
+ {
+ if (tree == empty)
+ return 0;
+ if (key < tree->address)
+ tree = tree->left;
+ else if (key - tree->address >= tree->len)
+ tree = tree->right;
+ else
+ break;
+ }
+ return (*tree->handler) (fault_address, tree->handler_arg);
+}
diff --git a/libsigsegv/src/fault-aix3-powerpc.h b/libsigsegv/src/fault-aix3-powerpc.h
new file mode 100644
index 00000000..057846ce
--- /dev/null
+++ b/libsigsegv/src/fault-aix3-powerpc.h
@@ -0,0 +1,20 @@
+/* Fault handler information. AIX3/PowerPC and AIX4/PowerPC version.
+ Copyright (C) 2002-2005 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "fault-aix3.h"
+
+#define SIGSEGV_FAULT_STACKPOINTER scp->sc_jmpbuf.jmp_context.gpr[1]
diff --git a/libsigsegv/src/fault-aix3.h b/libsigsegv/src/fault-aix3.h
new file mode 100644
index 00000000..2c91bc99
--- /dev/null
+++ b/libsigsegv/src/fault-aix3.h
@@ -0,0 +1,20 @@
+/* Fault handler information. AIX 3 and AIX 4 version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
+#define SIGSEGV_FAULT_ADDRESS scp->sc_jmpbuf.jmp_context.o_vaddr
+#define SIGSEGV_FAULT_CONTEXT scp
diff --git a/libsigsegv/src/fault-aix5-powerpc.h b/libsigsegv/src/fault-aix5-powerpc.h
new file mode 100644
index 00000000..bfc1a905
--- /dev/null
+++ b/libsigsegv/src/fault-aix5-powerpc.h
@@ -0,0 +1,20 @@
+/* Fault handler information. AIX5/PowerPC version.
+ Copyright (C) 2005 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "fault-aix5.h"
+
+#define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.jmp_context.gpr[1]
diff --git a/libsigsegv/src/fault-aix5.h b/libsigsegv/src/fault-aix5.h
new file mode 100644
index 00000000..a915a852
--- /dev/null
+++ b/libsigsegv/src/fault-aix5.h
@@ -0,0 +1,18 @@
+/* Fault handler information. AIX 5 version.
+ Copyright (C) 2005, 2009 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "fault-posix-ucontext.h"
diff --git a/libsigsegv/src/fault-beos-i386.h b/libsigsegv/src/fault-beos-i386.h
new file mode 100644
index 00000000..af030db4
--- /dev/null
+++ b/libsigsegv/src/fault-beos-i386.h
@@ -0,0 +1,22 @@
+/* Fault handler information. BeOS/i386 version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <OS.h>
+
+#include "fault-beos.h"
+
+#define SIGSEGV_FAULT_STACKPOINTER vrp->esp
diff --git a/libsigsegv/src/fault-beos.h b/libsigsegv/src/fault-beos.h
new file mode 100644
index 00000000..29e27daf
--- /dev/null
+++ b/libsigsegv/src/fault-beos.h
@@ -0,0 +1,19 @@
+/* Fault handler information. BeOS version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, void *userdata, struct vregs *vrp
+#define SIGSEGV_FAULT_CONTEXT vrp
diff --git a/libsigsegv/src/fault-bsd.h b/libsigsegv/src/fault-bsd.h
new file mode 100644
index 00000000..5e91845c
--- /dev/null
+++ b/libsigsegv/src/fault-bsd.h
@@ -0,0 +1,19 @@
+/* Fault handler information. BSD Unix version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, void *scp, void *addr
+#define SIGSEGV_FAULT_ADDRESS addr
diff --git a/libsigsegv/src/fault-freebsd-i386.h b/libsigsegv/src/fault-freebsd-i386.h
new file mode 100644
index 00000000..ffc1b6af
--- /dev/null
+++ b/libsigsegv/src/fault-freebsd-i386.h
@@ -0,0 +1,27 @@
+/* Fault handler information. FreeBSD/i386 version.
+ Copyright (C) 2002, 2007 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp, void *addr
+#define SIGSEGV_FAULT_ADDRESS addr
+#define SIGSEGV_FAULT_CONTEXT scp
+#if defined __x86_64__
+/* 64 bit registers */
+#define SIGSEGV_FAULT_STACKPOINTER scp->sc_rsp
+#else
+/* 32 bit registers */
+#define SIGSEGV_FAULT_STACKPOINTER scp->sc_esp
+#endif
diff --git a/libsigsegv/src/fault-hpux-hppa.h b/libsigsegv/src/fault-hpux-hppa.h
new file mode 100644
index 00000000..cbdf5a8b
--- /dev/null
+++ b/libsigsegv/src/fault-hpux-hppa.h
@@ -0,0 +1,46 @@
+/* Fault handler information. HP-UX HPPA version.
+ Copyright (C) 2002 Paolo Bonzini <bonzini@gnu.org>
+ Copyright (C) 2002-2003, 2009 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define USE_64BIT_REGS(mc) \
+ (((mc).ss_flags & SS_WIDEREGS) && ((mc).ss_flags & SS_NARROWISINVALID))
+
+/* Extract the cr21 register from an mcontext_t.
+ See the comments in /usr/include/machine/save_state.h. */
+#define GET_CR21(mc) \
+ (USE_64BIT_REGS(mc) ? (mc).ss_wide.ss_64.ss_cr21 : (mc).ss_narrow.ss_cr21)
+
+/* Extract the stack pointer from an mcontext_t.
+ See the comments in /usr/include/machine/save_state.h. */
+#define GET_SP(mc) \
+ (USE_64BIT_REGS(mc) ? (mc).ss_wide.ss_64.ss_sp : (mc).ss_narrow.ss_sp)
+
+/* Both of these alternatives work on HP-UX 10.20 and HP-UX 11.00. */
+#if 1
+
+#include "fault-hpux.h"
+
+#define SIGSEGV_FAULT_ADDRESS GET_CR21 (scp->sc_sl.sl_ss)
+#define SIGSEGV_FAULT_STACKPOINTER GET_SP (scp->sc_ctxt.sl.sl_ss)
+
+#else
+
+#include "fault-posix-ucontext.h"
+
+#define SIGSEGV_FAULT_STACKPOINTER GET_SP (((ucontext_t *) ucp)->uc_mcontext)
+
+#endif
diff --git a/libsigsegv/src/fault-hpux.h b/libsigsegv/src/fault-hpux.h
new file mode 100644
index 00000000..632e0de3
--- /dev/null
+++ b/libsigsegv/src/fault-hpux.h
@@ -0,0 +1,19 @@
+/* Fault handler information. HP-UX version.
+ Copyright (C) 2002 Paolo Bonzini <bonzini@gnu.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
+#define SIGSEGV_FAULT_CONTEXT scp
diff --git a/libsigsegv/src/fault-hurd.h b/libsigsegv/src/fault-hurd.h
new file mode 100644
index 00000000..d0272218
--- /dev/null
+++ b/libsigsegv/src/fault-hurd.h
@@ -0,0 +1,20 @@
+/* Fault handler information. Hurd version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
+#define SIGSEGV_FAULT_ADDRESS (unsigned long) code
+#define SIGSEGV_FAULT_CONTEXT scp
diff --git a/libsigsegv/src/fault-irix-mips.h b/libsigsegv/src/fault-irix-mips.h
new file mode 100644
index 00000000..2051e6e8
--- /dev/null
+++ b/libsigsegv/src/fault-irix-mips.h
@@ -0,0 +1,20 @@
+/* Fault handler information. IRIX MIPS version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "fault-irix.h"
+
+#define SIGSEGV_FAULT_STACKPOINTER scp->sc_regs[29]
diff --git a/libsigsegv/src/fault-irix.h b/libsigsegv/src/fault-irix.h
new file mode 100644
index 00000000..239a8604
--- /dev/null
+++ b/libsigsegv/src/fault-irix.h
@@ -0,0 +1,20 @@
+/* Fault handler information. IRIX version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
+#define SIGSEGV_FAULT_ADDRESS (unsigned long) scp->sc_badvaddr
+#define SIGSEGV_FAULT_CONTEXT scp
diff --git a/libsigsegv/src/fault-linux-alpha.h b/libsigsegv/src/fault-linux-alpha.h
new file mode 100644
index 00000000..0b49da0c
--- /dev/null
+++ b/libsigsegv/src/fault-linux-alpha.h
@@ -0,0 +1,22 @@
+/* Fault handler information. Linux/Alpha version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <asm/sigcontext.h>
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
+#define SIGSEGV_FAULT_CONTEXT scp
+#define SIGSEGV_FAULT_STACKPOINTER scp->sc_regs[30]
diff --git a/libsigsegv/src/fault-linux-arm.h b/libsigsegv/src/fault-linux-arm.h
new file mode 100644
index 00000000..08c92c1f
--- /dev/null
+++ b/libsigsegv/src/fault-linux-arm.h
@@ -0,0 +1,26 @@
+/* Fault handler information. Linux/ARM version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* This file supports only kernels >= 2.2.14 or >= 2.3.35. Support for older
+ kernels would be more complicated, see file
+ glibc/sysdeps/unix/sysv/linux/arm/bits/armsigctx.h. */
+
+#include <asm/sigcontext.h>
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int r1, int r2, int r3, struct sigcontext sc
+#define SIGSEGV_FAULT_CONTEXT &sc
+#define SIGSEGV_FAULT_STACKPOINTER sc.arm_sp
diff --git a/libsigsegv/src/fault-linux-cris.h b/libsigsegv/src/fault-linux-cris.h
new file mode 100644
index 00000000..b12b046c
--- /dev/null
+++ b/libsigsegv/src/fault-linux-cris.h
@@ -0,0 +1,22 @@
+/* Fault handler information. Linux/cris version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <asm/sigcontext.h>
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int r11, int r12, int r13, struct sigcontext sc
+#define SIGSEGV_FAULT_CONTEXT (&sc)
+#define SIGSEGV_FAULT_STACKPOINTER sc.usp
diff --git a/libsigsegv/src/fault-linux-hppa.h b/libsigsegv/src/fault-linux-hppa.h
new file mode 100644
index 00000000..4b83a0d0
--- /dev/null
+++ b/libsigsegv/src/fault-linux-hppa.h
@@ -0,0 +1,27 @@
+/* Fault handler information. Linux/HPPA version.
+ Copyright (C) 2002-2003 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <ucontext.h>
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *ucp
+#define SIGSEGV_FAULT_ADDRESS sip->si_ptr
+#define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
+
+#if 0
+#define SIGSEGV_FAULT_CONTEXT ((ucontext_t *) ucp)
+#define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs.g_regs[30]
+#endif
diff --git a/libsigsegv/src/fault-linux-i386-old.h b/libsigsegv/src/fault-linux-i386-old.h
new file mode 100644
index 00000000..fc949860
--- /dev/null
+++ b/libsigsegv/src/fault-linux-i386-old.h
@@ -0,0 +1,23 @@
+/* Fault handler information. Linux/i386 version, supports old kernels.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Don't include <asm/sigcontext.h> here, because some older kernels don't
+ have it or don't define `struct sigcontext' in it. */
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, unsigned long more
+#define SIGSEGV_FAULT_ADDRESS ((unsigned long *) &more) [21]
+#define SIGSEGV_FAULT_CONTEXT ((struct sigcontext *) &more)
+#define SIGSEGV_FAULT_STACKPOINTER ((unsigned long *) &more) [7]
diff --git a/libsigsegv/src/fault-linux-i386.h b/libsigsegv/src/fault-linux-i386.h
new file mode 100644
index 00000000..709ca3a1
--- /dev/null
+++ b/libsigsegv/src/fault-linux-i386.h
@@ -0,0 +1,21 @@
+/* Fault handler information. Linux/i386 version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, struct sigcontext sc
+#define SIGSEGV_FAULT_ADDRESS sc.cr2
+#define SIGSEGV_FAULT_CONTEXT (&sc)
+#define SIGSEGV_FAULT_STACKPOINTER sc.esp /* same value as sc.esp_at_signal */
diff --git a/libsigsegv/src/fault-linux-ia64.h b/libsigsegv/src/fault-linux-ia64.h
new file mode 100644
index 00000000..f9cf6b12
--- /dev/null
+++ b/libsigsegv/src/fault-linux-ia64.h
@@ -0,0 +1,29 @@
+/* Fault handler information. Linux/IA-64 version.
+ Copyright (C) 2002-2003 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, struct sigcontext *scp
+#define SIGSEGV_FAULT_ADDRESS sip->si_addr
+#define SIGSEGV_FAULT_CONTEXT scp
+
+/* IA-64 has two stack pointers, one that grows down, called $r12, and one
+ that grows up, called $bsp/$bspstore. */
+#define SIGSEGV_FAULT_STACKPOINTER scp->sc_gr[12]
+
+/* It would be better to access $bspstore instead of $bsp but I don't know
+ where to find it in 'struct sigcontext'. Anyway, it doesn't matter
+ because $bsp and $bspstore never differ by more than ca. 1 KB. */
+#define SIGSEGV_FAULT_BSP_POINTER scp->sc_ar_bsp
diff --git a/libsigsegv/src/fault-linux-m68k.c b/libsigsegv/src/fault-linux-m68k.c
new file mode 100644
index 00000000..8562e30e
--- /dev/null
+++ b/libsigsegv/src/fault-linux-m68k.c
@@ -0,0 +1,44 @@
+/* Fault handler information subroutine. Linux/m68k version.
+ * Taken from gcc-3.2/boehm-gc/os_dep.c.
+ *
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+static void *
+get_fault_addr (struct sigcontext *scp)
+{
+ int format = (scp->sc_formatvec >> 12) & 0xf;
+ unsigned long *framedata = (unsigned long *) (scp + 1);
+ unsigned long ea;
+
+ switch (format)
+ {
+ case 10: case 11: /* 68020/030 */
+ ea = framedata[2];
+ return (void *) ea;
+ case 7: /* 68040 */
+ ea = framedata[3];
+ break;
+ case 4: /* 68060 */
+ ea = framedata[0];
+ break;
+ default:
+ return (void *) 0;
+ }
+ if (framedata[1] & 0x08000000)
+ /* Correct addr on misaligned access. */
+ ea = (ea + 4095) & ~4095;
+ return (void *) ea;
+}
diff --git a/libsigsegv/src/fault-linux-m68k.h b/libsigsegv/src/fault-linux-m68k.h
new file mode 100644
index 00000000..4623d902
--- /dev/null
+++ b/libsigsegv/src/fault-linux-m68k.h
@@ -0,0 +1,24 @@
+/* Fault handler information. Linux/m68k version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <asm/sigcontext.h>
+#include "fault-linux-m68k.c"
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
+#define SIGSEGV_FAULT_ADDRESS (unsigned long) get_fault_addr (scp)
+#define SIGSEGV_FAULT_CONTEXT scp
+#define SIGSEGV_FAULT_STACKPOINTER scp->sc_usp
diff --git a/libsigsegv/src/fault-linux-mips.h b/libsigsegv/src/fault-linux-mips.h
new file mode 100644
index 00000000..fa80dc3e
--- /dev/null
+++ b/libsigsegv/src/fault-linux-mips.h
@@ -0,0 +1,22 @@
+/* Fault handler information. Linux/MIPS version
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <asm/sigcontext.h>
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
+#define SIGSEGV_FAULT_CONTEXT scp
+#define SIGSEGV_FAULT_STACKPOINTER scp->sc_regs[29]
diff --git a/libsigsegv/src/fault-linux-powerpc.h b/libsigsegv/src/fault-linux-powerpc.h
new file mode 100644
index 00000000..ea398f00
--- /dev/null
+++ b/libsigsegv/src/fault-linux-powerpc.h
@@ -0,0 +1,23 @@
+/* Fault handler information. Linux/PowerPC version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <asm/sigcontext.h>
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, struct sigcontext *scp
+#define SIGSEGV_FAULT_ADDRESS scp->regs->dar
+#define SIGSEGV_FAULT_CONTEXT scp
+#define SIGSEGV_FAULT_STACKPOINTER scp->regs->gpr[1]
diff --git a/libsigsegv/src/fault-linux-s390.h b/libsigsegv/src/fault-linux-s390.h
new file mode 100644
index 00000000..29056ffc
--- /dev/null
+++ b/libsigsegv/src/fault-linux-s390.h
@@ -0,0 +1,22 @@
+/* Fault handler information. Linux/S390 version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <asm/sigcontext.h>
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, struct sigcontext *scp
+#define SIGSEGV_FAULT_CONTEXT scp
+#define SIGSEGV_FAULT_STACKPOINTER scp->sregs->regs.gprs[15]
diff --git a/libsigsegv/src/fault-linux-sh.h b/libsigsegv/src/fault-linux-sh.h
new file mode 100644
index 00000000..3db1aee1
--- /dev/null
+++ b/libsigsegv/src/fault-linux-sh.h
@@ -0,0 +1,22 @@
+/* Fault handler information. Linux/SH version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <asm/sigcontext.h>
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int r1, int r2, int r3, struct sigcontext sc
+#define SIGSEGV_FAULT_CONTEXT (&sc)
+#define SIGSEGV_FAULT_STACKPOINTER sc.sc_regs[15]
diff --git a/libsigsegv/src/fault-linux-sparc.h b/libsigsegv/src/fault-linux-sparc.h
new file mode 100644
index 00000000..fcc77933
--- /dev/null
+++ b/libsigsegv/src/fault-linux-sparc.h
@@ -0,0 +1,23 @@
+/* Fault handler information. Linux/SPARC version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <asm/sigcontext.h>
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp, void *addr /* FIXME */
+#define SIGSEGV_FAULT_ADDRESS addr /* in case of SunOS4 signal frames */
+#define SIGSEGV_FAULT_CONTEXT scp
+#define SIGSEGV_FAULT_STACKPOINTER scp->sigc_sp /* FIXME: not scp->si_regs.u_regs[14] ? */
diff --git a/libsigsegv/src/fault-linux-x86_64.h b/libsigsegv/src/fault-linux-x86_64.h
new file mode 100644
index 00000000..70b08f08
--- /dev/null
+++ b/libsigsegv/src/fault-linux-x86_64.h
@@ -0,0 +1,22 @@
+/* Fault handler information. Linux/x86_64 version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <asm/sigcontext.h>
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, struct sigcontext sc
+#define SIGSEGV_FAULT_CONTEXT (&sc)
+#define SIGSEGV_FAULT_STACKPOINTER sc.rsp
diff --git a/libsigsegv/src/fault-linux.h b/libsigsegv/src/fault-linux.h
new file mode 100644
index 00000000..b7cf9dbc
--- /dev/null
+++ b/libsigsegv/src/fault-linux.h
@@ -0,0 +1,22 @@
+/* Fault handler information. Linux stub version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* For SIGSEGV_FAULT_HANDLER_ARGLIST, see the definition of SIGCONTEXT in
+ glibc/sysdeps/unix/sysv/linux/<cpu>/sigcontextinfo.h. */
+
+/* For SIGSEGV_FAULT_STACKPOINTER, see the definition of GET_STACK in
+ glibc/sysdeps/unix/sysv/linux/<cpu>/sigcontextinfo.h. */
diff --git a/libsigsegv/src/fault-macos-i386.h b/libsigsegv/src/fault-macos-i386.h
new file mode 100644
index 00000000..83d40cb5
--- /dev/null
+++ b/libsigsegv/src/fault-macos-i386.h
@@ -0,0 +1,20 @@
+/* Fault handler information. MacOSX/i386 version.
+ Copyright (C) 2003 Paolo Bonzini <bonzini@gnu.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
+#define SIGSEGV_FAULT_CONTEXT scp
+#define SIGSEGV_FAULT_STACKPOINTER scp->sc_esp
diff --git a/libsigsegv/src/fault-macosdarwin5-powerpc.c b/libsigsegv/src/fault-macosdarwin5-powerpc.c
new file mode 100644
index 00000000..a2f59d8f
--- /dev/null
+++ b/libsigsegv/src/fault-macosdarwin5-powerpc.c
@@ -0,0 +1,124 @@
+/* Fault handler information subroutine. MacOSX/Darwin5/PowerPC version.
+ * Taken from gcc-3.2/boehm-gc/os_dep.c.
+ *
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* Decodes the machine instruction which was responsible for the sending of the
+ SIGBUS signal. Sadly this is the only way to find the faulting address
+ because the signal handler doesn't get it directly from the kernel (although
+ it is available on the Mach level, but dropped by the BSD personality before
+ it calls our signal handler...)
+ This code should be able to deal correctly with all PPCs starting from the
+ 601 up to and including the G4s (including Velocity Engine). */
+#define EXTRACT_OP1(iw) (((iw) & 0xFC000000) >> 26)
+#define EXTRACT_OP2(iw) (((iw) & 0x000007FE) >> 1)
+#define EXTRACT_REGA(iw) (((iw) & 0x001F0000) >> 16)
+#define EXTRACT_REGB(iw) (((iw) & 0x03E00000) >> 21)
+#define EXTRACT_REGC(iw) (((iw) & 0x0000F800) >> 11)
+#define EXTRACT_DISP(iw) ((short *) &(iw))[1]
+
+static void *
+get_fault_addr (struct sigcontext *scp)
+{
+ unsigned int instr = *((unsigned int *) scp->sc_ir);
+ unsigned int *regs = &((unsigned int *) scp->sc_regs)[2];
+ int disp = 0;
+ int tmp;
+ unsigned int baseA = 0;
+ unsigned int baseB = 0;
+ unsigned int addr;
+ unsigned int alignmask = 0xFFFFFFFF;
+
+ switch (EXTRACT_OP1 (instr))
+ {
+ case 38: /* stb */
+ case 39: /* stbu */
+ case 54: /* stfd */
+ case 55: /* stfdu */
+ case 52: /* stfs */
+ case 53: /* stfsu */
+ case 44: /* sth */
+ case 45: /* sthu */
+ case 47: /* stmw */
+ case 36: /* stw */
+ case 37: /* stwu */
+ tmp = EXTRACT_REGA (instr);
+ if (tmp > 0)
+ baseA = regs[tmp];
+ disp = EXTRACT_DISP (instr);
+ break;
+ case 31:
+ switch (EXTRACT_OP2 (instr))
+ {
+ case 86: /* dcbf */
+ case 54: /* dcbst */
+ case 1014: /* dcbz */
+ case 247: /* stbux */
+ case 215: /* stbx */
+ case 759: /* stfdux */
+ case 727: /* stfdx */
+ case 983: /* stfiwx */
+ case 695: /* stfsux */
+ case 663: /* stfsx */
+ case 918: /* sthbrx */
+ case 439: /* sthux */
+ case 407: /* sthx */
+ case 661: /* stswx */
+ case 662: /* stwbrx */
+ case 150: /* stwcx. */
+ case 183: /* stwux */
+ case 151: /* stwx */
+ case 135: /* stvebx */
+ case 167: /* stvehx */
+ case 199: /* stvewx */
+ case 231: /* stvx */
+ case 487: /* stvxl */
+ tmp = EXTRACT_REGA (instr);
+ if (tmp > 0)
+ baseA = regs[tmp];
+ baseB = regs[EXTRACT_REGC (instr)];
+ /* Determine Altivec alignment mask. */
+ switch (EXTRACT_OP2 (instr))
+ {
+ case 167: /* stvehx */
+ alignmask = 0xFFFFFFFE;
+ break;
+ case 199: /* stvewx */
+ alignmask = 0xFFFFFFFC;
+ break;
+ case 231: /* stvx */
+ case 487: /* stvxl */
+ alignmask = 0xFFFFFFF0;
+ break;
+ }
+ break;
+ case 725: /* stswi */
+ tmp = EXTRACT_REGA (instr);
+ if (tmp > 0)
+ baseA = regs[tmp];
+ break;
+ default: /* ignore instruction */
+ return (void *) 0;
+ }
+ break;
+ default: /* ignore instruction */
+ return (void *) 0;
+ }
+
+ addr = (baseA + baseB) + disp;
+ addr &= alignmask;
+ return (void *) addr;
+}
diff --git a/libsigsegv/src/fault-macosdarwin5-powerpc.h b/libsigsegv/src/fault-macosdarwin5-powerpc.h
new file mode 100644
index 00000000..9998061c
--- /dev/null
+++ b/libsigsegv/src/fault-macosdarwin5-powerpc.h
@@ -0,0 +1,26 @@
+/* Fault handler information. MacOSX/Darwin5/PowerPC version.
+ Copyright (C) 2002-2004 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "fault-macosdarwin5-powerpc.c"
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
+#define SIGSEGV_FAULT_ADDRESS (unsigned long) get_fault_addr (scp)
+#define SIGSEGV_FAULT_CONTEXT scp
+#if 0
+#define SIGSEGV_FAULT_STACKPOINTER (&((unsigned int *) scp->sc_regs)[2])[1]
+#endif
+#define SIGSEGV_FAULT_STACKPOINTER (scp->sc_regs ? ((unsigned int *) scp->sc_regs)[3] : scp->sc_sp)
diff --git a/libsigsegv/src/fault-macosdarwin7-powerpc.c b/libsigsegv/src/fault-macosdarwin7-powerpc.c
new file mode 100644
index 00000000..e8e9337a
--- /dev/null
+++ b/libsigsegv/src/fault-macosdarwin7-powerpc.c
@@ -0,0 +1,131 @@
+/* Fault handler information subroutine. MacOSX/Darwin7/PowerPC version.
+ * Taken from gcc-3.2/boehm-gc/os_dep.c.
+ *
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#include <ucontext.h>
+
+/* Decodes the machine instruction which was responsible for the sending of the
+ SIGBUS signal. Sadly this is the only way to find the faulting address
+ because the signal handler doesn't get it directly from the kernel (although
+ it is available on the Mach level, but dropped by the BSD personality before
+ it calls our signal handler...)
+ This code should be able to deal correctly with all PPCs starting from the
+ 601 up to and including the G4s (including Velocity Engine). */
+#define EXTRACT_OP1(iw) (((iw) & 0xFC000000) >> 26)
+#define EXTRACT_OP2(iw) (((iw) & 0x000007FE) >> 1)
+#define EXTRACT_REGA(iw) (((iw) & 0x001F0000) >> 16)
+#define EXTRACT_REGB(iw) (((iw) & 0x03E00000) >> 21)
+#define EXTRACT_REGC(iw) (((iw) & 0x0000F800) >> 11)
+#define EXTRACT_DISP(iw) ((short *) &(iw))[1]
+
+static void *
+get_fault_addr (siginfo_t *sip, ucontext_t *ucp)
+{
+ unsigned int instr = *(unsigned int *) sip->si_addr;
+ unsigned int *regs =
+#if __DARWIN_UNIX03
+ &ucp->uc_mcontext->ss.__r0; /* r0..r31 */
+#else
+ &ucp->uc_mcontext->ss.r0; /* r0..r31 */
+#endif
+ int disp = 0;
+ int tmp;
+ unsigned int baseA = 0;
+ unsigned int baseB = 0;
+ unsigned int addr;
+ unsigned int alignmask = 0xFFFFFFFF;
+
+ switch (EXTRACT_OP1 (instr))
+ {
+ case 38: /* stb */
+ case 39: /* stbu */
+ case 54: /* stfd */
+ case 55: /* stfdu */
+ case 52: /* stfs */
+ case 53: /* stfsu */
+ case 44: /* sth */
+ case 45: /* sthu */
+ case 47: /* stmw */
+ case 36: /* stw */
+ case 37: /* stwu */
+ tmp = EXTRACT_REGA (instr);
+ if (tmp > 0)
+ baseA = regs[tmp];
+ disp = EXTRACT_DISP (instr);
+ break;
+ case 31:
+ switch (EXTRACT_OP2 (instr))
+ {
+ case 86: /* dcbf */
+ case 54: /* dcbst */
+ case 1014: /* dcbz */
+ case 247: /* stbux */
+ case 215: /* stbx */
+ case 759: /* stfdux */
+ case 727: /* stfdx */
+ case 983: /* stfiwx */
+ case 695: /* stfsux */
+ case 663: /* stfsx */
+ case 918: /* sthbrx */
+ case 439: /* sthux */
+ case 407: /* sthx */
+ case 661: /* stswx */
+ case 662: /* stwbrx */
+ case 150: /* stwcx. */
+ case 183: /* stwux */
+ case 151: /* stwx */
+ case 135: /* stvebx */
+ case 167: /* stvehx */
+ case 199: /* stvewx */
+ case 231: /* stvx */
+ case 487: /* stvxl */
+ tmp = EXTRACT_REGA (instr);
+ if (tmp > 0)
+ baseA = regs[tmp];
+ baseB = regs[EXTRACT_REGC (instr)];
+ /* Determine Altivec alignment mask. */
+ switch (EXTRACT_OP2 (instr))
+ {
+ case 167: /* stvehx */
+ alignmask = 0xFFFFFFFE;
+ break;
+ case 199: /* stvewx */
+ alignmask = 0xFFFFFFFC;
+ break;
+ case 231: /* stvx */
+ case 487: /* stvxl */
+ alignmask = 0xFFFFFFF0;
+ break;
+ }
+ break;
+ case 725: /* stswi */
+ tmp = EXTRACT_REGA (instr);
+ if (tmp > 0)
+ baseA = regs[tmp];
+ break;
+ default: /* ignore instruction */
+ return (void *) 0;
+ }
+ break;
+ default: /* ignore instruction */
+ return (void *) 0;
+ }
+
+ addr = (baseA + baseB) + disp;
+ addr &= alignmask;
+ return (void *) addr;
+}
diff --git a/libsigsegv/src/fault-macosdarwin7-powerpc.h b/libsigsegv/src/fault-macosdarwin7-powerpc.h
new file mode 100644
index 00000000..02a26bd8
--- /dev/null
+++ b/libsigsegv/src/fault-macosdarwin7-powerpc.h
@@ -0,0 +1,28 @@
+/* Fault handler information. MacOSX/Darwin7/PowerPC version.
+ Copyright (C) 2002-2004, 2007 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "fault-macosdarwin7-powerpc.c"
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, ucontext_t *ucp
+#define SIGSEGV_FAULT_ADDRESS (unsigned long) get_fault_addr (sip, ucp)
+#define SIGSEGV_FAULT_CONTEXT ucp
+#define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
+#if __DARWIN_UNIX03
+#define SIGSEGV_FAULT_STACKPOINTER ucp->uc_mcontext->ss.__r1
+#else
+#define SIGSEGV_FAULT_STACKPOINTER ucp->uc_mcontext->ss.r1
+#endif
diff --git a/libsigsegv/src/fault-netbsd-alpha.c b/libsigsegv/src/fault-netbsd-alpha.c
new file mode 100644
index 00000000..6ca67bc1
--- /dev/null
+++ b/libsigsegv/src/fault-netbsd-alpha.c
@@ -0,0 +1,39 @@
+/* Fault handler information subroutine. NetBSD/Alpha version.
+ * Taken from gcc-3.3/boehm-gc/os_dep.c.
+ *
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
+ * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* Decodes the machine instruction which was responsible for the sending of the
+ SIGBUS signal. Luckily this is much easier than, say, on the PowerPC. */
+
+static void *
+get_fault_addr (struct sigcontext *scp)
+{
+ unsigned int instr = *((unsigned int *)(scp->sc_pc));
+ unsigned long faultaddr;
+
+ /* Instructions which access memory have operands of the form ARG_MEM or
+ ARG_FMEM, consisting of
+ - a base register specification (PRB) in bits 20..16,
+ - a memory displacement (MDISP) in bits 15..0,
+ - an general register specification (RA) or a floating-point register
+ specification (FA) in bits 25..21.
+ See binutils-2.13.90.0.16/opcodes/alpha-opc.c. */
+
+ faultaddr = scp->sc_regs[(instr >> 16) & 0x1f];
+ faultaddr += (unsigned long) (long) (((int)instr << 16) >> 16);
+ return (void *) faultaddr;
+}
diff --git a/libsigsegv/src/fault-netbsd-alpha.h b/libsigsegv/src/fault-netbsd-alpha.h
new file mode 100644
index 00000000..595faf57
--- /dev/null
+++ b/libsigsegv/src/fault-netbsd-alpha.h
@@ -0,0 +1,26 @@
+/* Fault handler information. NetBSD/Alpha version.
+ Copyright (C) 2003 Paolo Bonzini <bonzini@gnu.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* NetBSD's sc_sp field depends on machine/reg.h's definition of R_SP. */
+#include <machine/reg.h>
+
+#include "fault-netbsd-alpha.c"
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
+#define SIGSEGV_FAULT_ADDRESS ((unsigned long) get_fault_addr (scp))
+#define SIGSEGV_FAULT_CONTEXT scp
+#define SIGSEGV_FAULT_STACKPOINTER ((unsigned int *) scp->sc_sp)
diff --git a/libsigsegv/src/fault-netbsd.h b/libsigsegv/src/fault-netbsd.h
new file mode 100644
index 00000000..a9f2b17c
--- /dev/null
+++ b/libsigsegv/src/fault-netbsd.h
@@ -0,0 +1,29 @@
+/* Fault handler information. NetBSD version.
+ Copyright (C) 2006, 2009 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "fault-posix-ucontext.h"
+
+/* _UC_MACHINE_SP is a platform independent macro.
+ Defined in <machine/mcontext.h>, see
+ http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/$arch/include/mcontext.h
+ Supported on alpha, amd64, i386, ia64, m68k, mips, powerpc, sparc since
+ NetBSD 2.0.
+ On i386, _UC_MACHINE_SP is the same as ->uc_mcontext.__gregs[_REG_UESP],
+ and apparently the same value as ->uc_mcontext.__gregs[_REG_ESP]. */
+#ifdef _UC_MACHINE_SP
+#define SIGSEGV_FAULT_STACKPOINTER _UC_MACHINE_SP ((ucontext_t *) ucp)
+#endif
diff --git a/libsigsegv/src/fault-none.h b/libsigsegv/src/fault-none.h
new file mode 100644
index 00000000..064a3f0c
--- /dev/null
+++ b/libsigsegv/src/fault-none.h
@@ -0,0 +1,17 @@
+/* Fault handler information. Version for platforms lacking support,
+ or with a self-contained handler.c.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
diff --git a/libsigsegv/src/fault-openbsd-i386.h b/libsigsegv/src/fault-openbsd-i386.h
new file mode 100644
index 00000000..23339eda
--- /dev/null
+++ b/libsigsegv/src/fault-openbsd-i386.h
@@ -0,0 +1,20 @@
+/* Fault handler information. OpenBSD/i386 version.
+ Copyright (C) 2003 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "fault-openbsd.h"
+
+#define SIGSEGV_FAULT_STACKPOINTER scp->sc_esp
diff --git a/libsigsegv/src/fault-openbsd.h b/libsigsegv/src/fault-openbsd.h
new file mode 100644
index 00000000..c784023e
--- /dev/null
+++ b/libsigsegv/src/fault-openbsd.h
@@ -0,0 +1,21 @@
+/* Fault handler information. OpenBSD version.
+ Copyright (C) 2003 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, struct sigcontext *scp
+#define SIGSEGV_FAULT_ADDRESS sip->si_addr
+#define SIGSEGV_FAULT_CONTEXT scp
+#define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
diff --git a/libsigsegv/src/fault-osf-alpha.h b/libsigsegv/src/fault-osf-alpha.h
new file mode 100644
index 00000000..e56a6539
--- /dev/null
+++ b/libsigsegv/src/fault-osf-alpha.h
@@ -0,0 +1,21 @@
+/* Fault handler information. OSF/1 Alpha version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "fault-osf.h"
+
+#define SIGSEGV_FAULT_ADDRESS scp->sc_traparg_a0
+#define SIGSEGV_FAULT_STACKPOINTER scp->sc_regs[30]
diff --git a/libsigsegv/src/fault-osf.h b/libsigsegv/src/fault-osf.h
new file mode 100644
index 00000000..8b939578
--- /dev/null
+++ b/libsigsegv/src/fault-osf.h
@@ -0,0 +1,19 @@
+/* Fault handler information. OSF/1 version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
+#define SIGSEGV_FAULT_CONTEXT scp
diff --git a/libsigsegv/src/fault-posix-ucontext.h b/libsigsegv/src/fault-posix-ucontext.h
new file mode 100644
index 00000000..78bdd976
--- /dev/null
+++ b/libsigsegv/src/fault-posix-ucontext.h
@@ -0,0 +1,23 @@
+/* Fault handler information. POSIX:2001 (= SUSV3 = XPG 6) version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <ucontext.h>
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *ucp
+#define SIGSEGV_FAULT_ADDRESS sip->si_addr
+#define SIGSEGV_FAULT_CONTEXT ((ucontext_t *) ucp)
+#define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
diff --git a/libsigsegv/src/fault-posix.h b/libsigsegv/src/fault-posix.h
new file mode 100644
index 00000000..85cd7df5
--- /dev/null
+++ b/libsigsegv/src/fault-posix.h
@@ -0,0 +1,21 @@
+/* Fault handler information. POSIX:2008 (XPG 7) version.
+ Copyright (C) 2002, 2009 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *context
+#define SIGSEGV_FAULT_ADDRESS sip->si_addr
+#define SIGSEGV_FAULT_CONTEXT context
+#define SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
diff --git a/libsigsegv/src/fault-solaris-i386.h b/libsigsegv/src/fault-solaris-i386.h
new file mode 100644
index 00000000..40035c70
--- /dev/null
+++ b/libsigsegv/src/fault-solaris-i386.h
@@ -0,0 +1,20 @@
+/* Fault handler information. Solaris/i386 version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "fault-solaris.h"
+
+#define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[ESP]
diff --git a/libsigsegv/src/fault-solaris-sparc.h b/libsigsegv/src/fault-solaris-sparc.h
new file mode 100644
index 00000000..878fe849
--- /dev/null
+++ b/libsigsegv/src/fault-solaris-sparc.h
@@ -0,0 +1,20 @@
+/* Fault handler information. Solaris/SPARC version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "fault-solaris.h"
+
+#define SIGSEGV_FAULT_STACKPOINTER ((ucontext_t *) ucp)->uc_mcontext.gregs[REG_O6]
diff --git a/libsigsegv/src/fault-solaris.h b/libsigsegv/src/fault-solaris.h
new file mode 100644
index 00000000..76135671
--- /dev/null
+++ b/libsigsegv/src/fault-solaris.h
@@ -0,0 +1,18 @@
+/* Fault handler information. Solaris version.
+ Copyright (C) 2002, 2009 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "fault-posix-ucontext.h"
diff --git a/libsigsegv/src/fault.h b/libsigsegv/src/fault.h
new file mode 100644
index 00000000..060c83c4
--- /dev/null
+++ b/libsigsegv/src/fault.h
@@ -0,0 +1,37 @@
+/* Fault handler information.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* The included file defines:
+
+ SIGSEGV_FAULT_HANDLER_ARGLIST
+ is the argument list for the actual fault handler.
+
+ SIGSEGV_FAULT_ADDRESS
+ is a macro for fetching the fault address.
+
+ and if available (optional):
+
+ SIGSEGV_FAULT_CONTEXT
+ is a macro giving a pointer to the entire fault context (i.e.
+ the register set etc.).
+
+ SIGSEGV_FAULT_STACKPOINTER
+ is a macro for fetching the stackpointer at the moment the fault
+ occurred.
+ */
+
+#include CFG_FAULT
diff --git a/libsigsegv/src/handler-macos.c b/libsigsegv/src/handler-macos.c
new file mode 100644
index 00000000..3a39e727
--- /dev/null
+++ b/libsigsegv/src/handler-macos.c
@@ -0,0 +1,563 @@
+/* Fault handler information. MacOSX version.
+ Copyright (C) 1993-1999, 2002-2003, 2007-2008 Bruno Haible <bruno@clisp.org>
+ Copyright (C) 2003 Paolo Bonzini <bonzini@gnu.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "sigsegv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#if HAVE_SYS_SIGNAL_H
+# include <sys/signal.h>
+#endif
+
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <mach/thread_status.h>
+#include <mach/exception.h>
+#include <mach/task.h>
+#include <pthread.h>
+
+/* For MacOSX. */
+#ifndef SS_DISABLE
+#define SS_DISABLE SA_DISABLE
+#endif
+
+/* In the header files of MacOS X >= 10.5, when compiling with flags that lead
+ to __DARWIN_UNIX03=1 (see <sys/cdefs.h>), the register names are prefixed
+ with '__'. To test for MacOS X >= 10.5 versus < 10.5, we cannot use a
+ predefined macro such as __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+ because that does not change when a cross-compile via -isysroot is
+ activated. Instead use some macro defined inside the header files and which
+ changed in 10.5, such as
+ File Macro 10.4 10.5
+ <mach/machine/exception.h> EXC_TYPES_COUNT 10 11
+ <mach/exception_types.h> EXC_CRASH -- 10
+ <mach/mach_vm.h> mach_vm_MSG_COUNT 18 19
+ <mach/machine.h> CPU_TYPE_ARM -- ...
+ <mach/memory_object_control.h> memory_object_control_MSG_COUNT 11 12
+ <mach/memory_object_types.h> UPL_ABORT_REFERENCE -- 0x80
+ <mach/message.h> MACH_RCV_TRAILER_AV -- 8
+ <mach/port.h> MACH_PORT_RIGHT_LABELH -- ...
+ <mach/thread_policy.h> THREAD_AFFINITY_POLICY -- 4
+ <mach/vm_region.h> VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 ...
+ */
+#if EXC_TYPES_COUNT >= 11
+# define MacOS_X_10_5_HEADERS 1
+#endif
+
+#include "machfault.h"
+
+/* The following sources were used as a *reference* for this exception handling
+ code:
+ 1. Apple's mach/xnu documentation
+ 2. Timothy J. Wood's "Mach Exception Handlers 101" post to the
+ omnigroup's macosx-dev list.
+ www.omnigroup.com/mailman/archive/macosx-dev/2000-June/002030.html */
+
+/* This is not defined in any header, although documented. */
+
+/* http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/exc_server.html says:
+ The exc_server function is the MIG generated server handling function
+ to handle messages from the kernel relating to the occurrence of an
+ exception in a thread. Such messages are delivered to the exception port
+ set via thread_set_exception_ports or task_set_exception_ports. When an
+ exception occurs in a thread, the thread sends an exception message to its
+ exception port, blocking in the kernel waiting for the receipt of a reply.
+ The exc_server function performs all necessary argument handling for this
+ kernel message and calls catch_exception_raise, catch_exception_raise_state
+ or catch_exception_raise_state_identity, which should handle the exception.
+ If the called routine returns KERN_SUCCESS, a reply message will be sent,
+ allowing the thread to continue from the point of the exception; otherwise,
+ no reply message is sent and the called routine must have dealt with the
+ exception thread directly. */
+extern boolean_t
+ exc_server (mach_msg_header_t *request_msg,
+ mach_msg_header_t *reply_msg);
+
+
+/* http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/catch_exception_raise.html
+ These functions are defined in this file, and called by exc_server.
+ FIXME: What needs to be done when this code is put into a shared library? */
+kern_return_t
+catch_exception_raise (mach_port_t exception_port,
+ mach_port_t thread,
+ mach_port_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t code_count);
+kern_return_t
+catch_exception_raise_state (mach_port_t exception_port,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t code_count,
+ thread_state_flavor_t *flavor,
+ thread_state_t in_state,
+ mach_msg_type_number_t in_state_count,
+ thread_state_t out_state,
+ mach_msg_type_number_t *out_state_count);
+kern_return_t
+catch_exception_raise_state_identity (mach_port_t exception_port,
+ mach_port_t thread,
+ mach_port_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t codeCnt,
+ thread_state_flavor_t *flavor,
+ thread_state_t in_state,
+ mach_msg_type_number_t in_state_count,
+ thread_state_t out_state,
+ mach_msg_type_number_t *out_state_count);
+
+
+/* Our exception thread. */
+static mach_port_t our_exception_thread;
+
+/* The exception port on which our thread listens. */
+static mach_port_t our_exception_port;
+
+
+/* mach_initialize() status:
+ 0: not yet called
+ 1: called and succeeded
+ -1: called and failed */
+static int mach_initialized = 0;
+
+/* Communication area for the exception state and thread state. */
+static SIGSEGV_THREAD_STATE_TYPE save_thread_state;
+
+/* Check for reentrant signals. */
+static int emergency = -1;
+
+/* User's stack overflow handler. */
+static stackoverflow_handler_t stk_user_handler = (stackoverflow_handler_t)NULL;
+static unsigned long stk_extra_stack;
+static unsigned long stk_extra_stack_size;
+
+/* User's fault handler. */
+static sigsegv_handler_t user_handler = (sigsegv_handler_t)NULL;
+
+/* Thread that signalled the exception. Only set while user_handler is being
+ invoked. */
+static mach_port_t signalled_thread = (mach_port_t) 0;
+
+/* A handler that is called in the faulting thread. It terminates the thread. */
+static void
+terminating_handler ()
+{
+ /* Dump core. */
+ raise (SIGSEGV);
+
+ /* Seriously. */
+ abort ();
+}
+
+/* A handler that is called in the faulting thread, on an alternate stack.
+ It calls the user installed stack overflow handler. */
+static void
+altstack_handler ()
+{
+ /* We arrive here when the user refused to handle a fault. */
+
+ /* Check if it is plausibly a stack overflow, and the user installed
+ a stack overflow handler. */
+ if (stk_user_handler)
+ {
+ emergency++;
+ /* Call user's handler. */
+ (*stk_user_handler) (emergency, &save_thread_state);
+ }
+
+ /* Else, terminate the thread. */
+ terminating_handler ();
+}
+
+
+/* Handle an exception by invoking the user's fault handler and/or forwarding
+ the duty to the previously installed handlers. */
+kern_return_t
+catch_exception_raise (mach_port_t exception_port,
+ mach_port_t thread,
+ mach_port_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t code_count)
+{
+#ifdef SIGSEGV_EXC_STATE_TYPE
+ SIGSEGV_EXC_STATE_TYPE exc_state;
+#endif
+ SIGSEGV_THREAD_STATE_TYPE thread_state;
+ mach_msg_type_number_t state_count;
+ unsigned long addr;
+ unsigned long sp;
+
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "Exception: 0x%x Code: 0x%x 0x%x in catch....\n",
+ exception,
+ code_count > 0 ? code[0] : -1,
+ code_count > 1 ? code[1] : -1);
+#endif
+
+ /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_get_state.html. */
+#ifdef SIGSEGV_EXC_STATE_TYPE
+ state_count = SIGSEGV_EXC_STATE_COUNT;
+ if (thread_get_state (thread, SIGSEGV_EXC_STATE_FLAVOR,
+ (void *) &exc_state, &state_count)
+ != KERN_SUCCESS)
+ {
+ /* The thread is supposed to be suspended while the exception handler
+ is called. This shouldn't fail. */
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "thread_get_state failed for exception state\n");
+#endif
+ return KERN_FAILURE;
+ }
+#endif
+
+ state_count = SIGSEGV_THREAD_STATE_COUNT;
+ if (thread_get_state (thread, SIGSEGV_THREAD_STATE_FLAVOR,
+ (void *) &thread_state, &state_count)
+ != KERN_SUCCESS)
+ {
+ /* The thread is supposed to be suspended while the exception handler
+ is called. This shouldn't fail. */
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "thread_get_state failed for thread state\n");
+#endif
+ return KERN_FAILURE;
+ }
+
+ addr = (unsigned long) (SIGSEGV_FAULT_ADDRESS (thread_state, exc_state));
+ sp = (unsigned long) (SIGSEGV_STACK_POINTER (thread_state));
+
+ /* Got the thread's state. Now extract the address that caused the
+ fault and invoke the user's handler. */
+ save_thread_state = thread_state;
+
+ /* If the fault address is near the stack pointer, it's a stack overflow.
+ Otherwise, treat it like a normal SIGSEGV. */
+ if (addr <= sp + 4096 && sp <= addr + 4096)
+ {
+ unsigned long new_safe_esp;
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "Treating as stack overflow, sp = 0x%lx\n", (char *) sp);
+#endif
+ new_safe_esp =
+#if STACK_DIRECTION < 0
+ stk_extra_stack + stk_extra_stack_size - 256;
+#else
+ stk_extra_stack + 256;
+#endif
+#if defined __x86_64__ || defined __i386__
+ new_safe_esp &= -16; /* align */
+ new_safe_esp -= sizeof (void *); /* make room for (unused) return address slot */
+#endif
+ SIGSEGV_STACK_POINTER (thread_state) = new_safe_esp;
+ /* Continue handling this fault in the faulting thread. (We cannot longjmp while
+ in the exception handling thread, so we need to mimic what signals do!) */
+ SIGSEGV_PROGRAM_COUNTER (thread_state) = (unsigned long) altstack_handler;
+ }
+ else
+ {
+ if (user_handler)
+ {
+ int done;
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "Calling user handler, addr = 0x%lx\n", (char *) addr);
+#endif
+ signalled_thread = thread;
+ done = (*user_handler) ((void *) addr, 1);
+ signalled_thread = (mach_port_t) 0;
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "Back from user handler\n");
+#endif
+ if (done)
+ return KERN_SUCCESS;
+ }
+ SIGSEGV_PROGRAM_COUNTER (thread_state) = (unsigned long) terminating_handler;
+ }
+
+ /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_set_state.html. */
+ if (thread_set_state (thread, SIGSEGV_THREAD_STATE_FLAVOR,
+ (void *) &thread_state, state_count)
+ != KERN_SUCCESS)
+ {
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "thread_set_state failed for altstack state\n");
+#endif
+ return KERN_FAILURE;
+ }
+ return KERN_SUCCESS;
+}
+
+
+/* The main function of the thread listening for exceptions. */
+static void *
+mach_exception_thread (void *arg)
+{
+ /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_thread_self.html. */
+ our_exception_thread = mach_thread_self ();
+
+ for (;;)
+ {
+ /* These two structures contain some private kernel data. We don't need
+ to access any of it so we don't bother defining a proper struct. The
+ correct definitions are in the xnu source code. */
+ /* Buffer for a message to be received. */
+ struct
+ {
+ mach_msg_header_t head;
+ mach_msg_body_t msgh_body;
+ char data[1024];
+ }
+ msg;
+ /* Buffer for a reply message. */
+ struct
+ {
+ mach_msg_header_t head;
+ char data[1024];
+ }
+ reply;
+
+ mach_msg_return_t retval;
+
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "Exception thread going to sleep\n");
+#endif
+
+ /* Wait for a message on the exception port. */
+ retval = mach_msg (&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0,
+ sizeof (msg), our_exception_port,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "Exception thread woke up\n");
+#endif
+ if (retval != MACH_MSG_SUCCESS)
+ {
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "mach_msg receive failed with %d %s\n",
+ (int) retval, mach_error_string (retval));
+#endif
+ abort ();
+ }
+
+ /* Handle the message: Call exc_server, which will call
+ catch_exception_raise and produce a reply message. */
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "Calling exc_server\n");
+#endif
+ exc_server (&msg.head, &reply.head);
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "Finished exc_server\n");
+#endif
+
+ /* Send the reply. */
+ if (mach_msg (&reply.head, MACH_SEND_MSG, reply.head.msgh_size,
+ 0, MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL)
+ != MACH_MSG_SUCCESS)
+ {
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "mach_msg send failed\n");
+#endif
+ abort ();
+ }
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "Reply successful\n");
+#endif
+ }
+}
+
+
+/* Initialize the Mach exception handler thread.
+ Return 0 if OK, -1 on error. */
+static int
+mach_initialize ()
+{
+ mach_port_t self;
+ exception_mask_t mask;
+ pthread_attr_t attr;
+ pthread_t thread;
+
+ self = mach_task_self ();
+
+ /* Allocate a port on which the thread shall listen for exceptions. */
+ if (mach_port_allocate (self, MACH_PORT_RIGHT_RECEIVE, &our_exception_port)
+ != KERN_SUCCESS)
+ return -1;
+
+ /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html. */
+ if (mach_port_insert_right (self, our_exception_port, our_exception_port,
+ MACH_MSG_TYPE_MAKE_SEND)
+ != KERN_SUCCESS)
+ return -1;
+
+ /* The exceptions we want to catch. Only EXC_BAD_ACCESS is interesting
+ for us (see above in function catch_exception_raise). */
+ mask = EXC_MASK_BAD_ACCESS;
+
+ /* Create the thread listening on the exception port. */
+ if (pthread_attr_init (&attr) != 0)
+ return -1;
+ if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) != 0)
+ return -1;
+ if (pthread_create (&thread, &attr, mach_exception_thread, NULL) != 0)
+ return -1;
+ pthread_attr_destroy (&attr);
+
+ /* Replace the exception port info for these exceptions with our own.
+ Note that we replace the exception port for the entire task, not only
+ for a particular thread. This has the effect that when our exception
+ port gets the message, the thread specific exception port has already
+ been asked, and we don't need to bother about it.
+ See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html. */
+ if (task_set_exception_ports (self, mask, our_exception_port,
+ EXCEPTION_DEFAULT, MACHINE_THREAD_STATE)
+ != KERN_SUCCESS)
+ return -1;
+
+ return 0;
+}
+
+
+int
+sigsegv_install_handler (sigsegv_handler_t handler)
+{
+ if (!mach_initialized)
+ mach_initialized = (mach_initialize () >= 0 ? 1 : -1);
+ if (mach_initialized < 0)
+ return -1;
+
+ user_handler = handler;
+
+ return 0;
+}
+
+void
+sigsegv_deinstall_handler (void)
+{
+ user_handler = (sigsegv_handler_t)NULL;
+}
+
+int
+sigsegv_leave_handler (void (*continuation) (void*, void*, void*),
+ void* cont_arg1, void* cont_arg2, void* cont_arg3)
+{
+ emergency--;
+ if (mach_thread_self () == our_exception_thread)
+ {
+ /* Inside user_handler invocation. */
+ mach_port_t thread;
+ SIGSEGV_THREAD_STATE_TYPE thread_state;
+ mach_msg_type_number_t state_count;
+
+ thread = signalled_thread;
+ if (thread == (mach_port_t) 0)
+ {
+ /* The variable signalled_thread was supposed to be set! */
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "sigsegv_leave_handler: signalled_thread not set\n");
+#endif
+ return 0;
+ }
+
+ /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_get_state.html. */
+ state_count = SIGSEGV_THREAD_STATE_COUNT;
+ if (thread_get_state (thread, SIGSEGV_THREAD_STATE_FLAVOR,
+ (void *) &thread_state, &state_count)
+ != KERN_SUCCESS)
+ {
+ /* The thread was supposed to be suspended! */
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "sigsegv_leave_handler: thread_get_state failed for thread state\n");
+#endif
+ return 0;
+ }
+
+#if defined __ppc64__ || defined __ppc__ || defined __x86_64__
+ /* Store arguments in registers. */
+ SIGSEGV_INTEGER_ARGUMENT_1 (thread_state) = (unsigned long) cont_arg1;
+ SIGSEGV_INTEGER_ARGUMENT_2 (thread_state) = (unsigned long) cont_arg2;
+ SIGSEGV_INTEGER_ARGUMENT_3 (thread_state) = (unsigned long) cont_arg3;
+#endif
+#if defined __x86_64__
+ /* Align stack. */
+ {
+ unsigned long new_esp = SIGSEGV_STACK_POINTER (thread_state);
+ new_esp &= -16; /* align */
+ new_esp -= sizeof (void *); *(void **)new_esp = SIGSEGV_FRAME_POINTER (thread_state); /* push %rbp */
+ SIGSEGV_STACK_POINTER (thread_state) = new_esp;
+ SIGSEGV_FRAME_POINTER (thread_state) = new_esp; /* mov %rsp,%rbp */
+ }
+#elif defined __i386__
+ /* Push arguments onto the stack. */
+ {
+ unsigned long new_esp = SIGSEGV_STACK_POINTER (thread_state);
+ new_esp &= -16; /* align */
+ new_esp -= sizeof (void *); /* unused room, alignment */
+ new_esp -= sizeof (void *); *(void **)new_esp = cont_arg3;
+ new_esp -= sizeof (void *); *(void **)new_esp = cont_arg2;
+ new_esp -= sizeof (void *); *(void **)new_esp = cont_arg1;
+ new_esp -= sizeof (void *); /* make room for (unused) return address slot */
+ SIGSEGV_STACK_POINTER (thread_state) = new_esp;
+ }
+#endif
+ /* Point program counter to continuation to be executed. */
+ SIGSEGV_PROGRAM_COUNTER (thread_state) = (unsigned long) continuation;
+
+ /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_set_state.html. */
+ if (thread_set_state (thread, SIGSEGV_THREAD_STATE_FLAVOR,
+ (void *) &thread_state, state_count)
+ != KERN_SUCCESS)
+ {
+#ifdef DEBUG_EXCEPTION_HANDLING
+ fprintf (stderr, "sigsegv_leave_handler: thread_set_state failed\n");
+#endif
+ return 0;
+ }
+
+ return 1;
+ }
+ else
+ {
+ /* Inside stk_user_handler invocation. Stay in the same thread. */
+ (*continuation) (cont_arg1, cont_arg2, cont_arg3);
+ return 1;
+ }
+}
+
+int
+stackoverflow_install_handler (stackoverflow_handler_t handler,
+ void *extra_stack, unsigned long extra_stack_size)
+{
+ if (!mach_initialized)
+ mach_initialized = (mach_initialize () >= 0 ? 1 : -1);
+ if (mach_initialized < 0)
+ return -1;
+
+ stk_user_handler = handler;
+ stk_extra_stack = (unsigned long) extra_stack;
+ stk_extra_stack_size = extra_stack_size;
+ return 0;
+}
+
+void
+stackoverflow_deinstall_handler (void)
+{
+ stk_user_handler = (stackoverflow_handler_t) NULL;
+}
diff --git a/libsigsegv/src/handler-none.c b/libsigsegv/src/handler-none.c
new file mode 100644
index 00000000..51a13f6f
--- /dev/null
+++ b/libsigsegv/src/handler-none.c
@@ -0,0 +1,49 @@
+/* Fault handler information.
+ Copyright (C) 1993-1999, 2002, 2008 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "sigsegv.h"
+
+int
+sigsegv_install_handler (sigsegv_handler_t handler)
+{
+ return -1;
+}
+
+void
+sigsegv_deinstall_handler (void)
+{
+}
+
+int
+sigsegv_leave_handler (void (*continuation) (void*, void*, void*),
+ void* cont_arg1, void* cont_arg2, void* cont_arg3)
+{
+ (*continuation) (cont_arg1, cont_arg2, cont_arg3);
+ return 1;
+}
+
+int
+stackoverflow_install_handler (stackoverflow_handler_t handler,
+ void *extra_stack, unsigned long extra_stack_size)
+{
+ return -1;
+}
+
+void
+stackoverflow_deinstall_handler (void)
+{
+}
diff --git a/libsigsegv/src/handler-unix.c b/libsigsegv/src/handler-unix.c
new file mode 100644
index 00000000..3718eb98
--- /dev/null
+++ b/libsigsegv/src/handler-unix.c
@@ -0,0 +1,542 @@
+/* Fault handler information. Unix version.
+ Copyright (C) 1993-1999, 2002-2003, 2006, 2008 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "sigsegv.h"
+
+/* On the average Unix platform, we define
+
+ HAVE_SIGSEGV_RECOVERY
+ if there is a fault-*.h include file which defines
+ SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_ADDRESS.
+
+ HAVE_STACK_OVERFLOW_RECOVERY
+ if HAVE_SIGALTSTACK is set and
+ at least two of the following are true:
+ A) There is a fault-*.h include file which defines
+ SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_ADDRESS.
+ B) There is a fault-*.h include file which defines
+ SIGSEGV_FAULT_HANDLER_ARGLIST and SIGSEGV_FAULT_STACKPOINTER.
+ C) There is a stackvma-*.c, other than stackvma-none.c, which
+ defines sigsegv_get_vma.
+
+ Why? Obviously, to catch stack overflow, we need an alternate signal
+ stack; this requires kernel support. But we also need to distinguish
+ (with a reasonable confidence) a stack overflow from a regular SIGSEGV.
+ If we have A) and B), we use the
+ Heuristic AB: If the fault address is near the stack pointer, it's a
+ stack overflow.
+ If we have A) and C), we use the
+ Heuristic AC: If the fault address is near and beyond the bottom of
+ the stack's virtual memory area, it's a stack overflow.
+ If we have B) and C), we use the
+ Heuristic BC: If the stack pointer is near the bottom of the stack's
+ virtual memory area, it's a stack overflow.
+ This heuristic comes in two flavours: On OSes which let the stack's
+ VMA grow continuously, we determine the bottom by use of getrlimit().
+ On OSes which preallocate the stack's VMA with its maximum size
+ (like BeOS), we use the stack's VMA directly.
+ */
+
+#include <stddef.h> /* needed for NULL on SunOS4 */
+#include <stdlib.h>
+#include <signal.h>
+#if HAVE_SYS_SIGNAL_H
+# include <sys/signal.h>
+#endif
+#include <errno.h>
+
+/* For MacOSX. */
+#ifndef SS_DISABLE
+#define SS_DISABLE SA_DISABLE
+#endif
+
+#include "fault.h"
+#include CFG_SIGNALS
+
+#if HAVE_STACK_OVERFLOW_RECOVERY
+
+#include <stdio.h> /* perror */
+
+#if HAVE_GETRLIMIT
+# include <sys/types.h>
+# include <sys/time.h>
+# include <sys/resource.h> /* declares struct rlimit */
+#endif
+
+/* Platform dependent:
+ Determine the virtual memory area of a given address. */
+#include "stackvma.h"
+
+/* Platform dependent:
+ Leaving a signal handler executing on the alternate stack. */
+#include "leave.h"
+
+#if HAVE_STACKVMA
+
+/* Address of the last byte belonging to the stack vma. */
+static unsigned long stack_top = 0;
+
+/* Needs to be called once only. */
+static void
+remember_stack_top (void *some_variable_on_stack)
+{
+ struct vma_struct vma;
+
+ if (sigsegv_get_vma ((unsigned long) some_variable_on_stack, &vma) >= 0)
+ stack_top = vma.end - 1;
+}
+
+#endif /* HAVE_STACKVMA */
+
+static stackoverflow_handler_t stk_user_handler = (stackoverflow_handler_t)NULL;
+static unsigned long stk_extra_stack;
+static unsigned long stk_extra_stack_size;
+
+#endif /* HAVE_STACK_OVERFLOW_RECOVERY */
+
+#if HAVE_SIGSEGV_RECOVERY
+
+/* User's SIGSEGV handler. */
+static sigsegv_handler_t user_handler = (sigsegv_handler_t)NULL;
+
+#endif /* HAVE_SIGSEGV_RECOVERY */
+
+
+/* Our SIGSEGV handler, with OS dependent argument list. */
+
+#if HAVE_SIGSEGV_RECOVERY
+
+static void
+sigsegv_handler (SIGSEGV_FAULT_HANDLER_ARGLIST)
+{
+ void *address = (void *) (SIGSEGV_FAULT_ADDRESS);
+
+#if HAVE_STACK_OVERFLOW_RECOVERY
+#if !(HAVE_STACKVMA || defined SIGSEGV_FAULT_STACKPOINTER)
+#error "Insufficient heuristics for detecting a stack overflow. Either define CFG_STACKVMA and HAVE_STACKVMA correctly, or define SIGSEGV_FAULT_STACKPOINTER correctly, or undefine HAVE_STACK_OVERFLOW_RECOVERY!"
+#endif
+
+ /* Call user's handler. */
+ if (user_handler && (*user_handler) (address, 0))
+ {
+ /* Handler successful. */
+ }
+ else
+ {
+ /* Handler declined responsibility. */
+
+ /* Did the user install a stack overflow handler? */
+ if (stk_user_handler)
+ {
+ /* See whether it was a stack overflow. If so, longjump away. */
+#ifdef SIGSEGV_FAULT_STACKPOINTER
+ unsigned long old_sp = (unsigned long) (SIGSEGV_FAULT_STACKPOINTER);
+#ifdef __ia64
+ unsigned long old_bsp = (unsigned long) (SIGSEGV_FAULT_BSP_POINTER);
+#endif
+#endif
+
+#if HAVE_STACKVMA
+ /* Were we able to determine the stack top? */
+ if (stack_top)
+ {
+ /* Determine stack bounds. */
+ int saved_errno;
+ struct vma_struct vma;
+ int ret;
+
+ saved_errno = errno;
+ ret = sigsegv_get_vma (stack_top, &vma);
+ errno = saved_errno;
+ if (ret >= 0)
+ {
+ /* Heuristic AC: If the fault_address is nearer to the stack
+ segment's [start,end] than to the previous segment, we
+ consider it a stack overflow.
+ In the case of IA-64, we know that the previous segment
+ is the up-growing bsp segment, and either of the two
+ stacks can overflow. */
+ unsigned long addr = (unsigned long) address;
+
+#ifdef __ia64
+ if (addr >= vma.prev_end && addr <= vma.end - 1)
+#else
+#if STACK_DIRECTION < 0
+ if (addr >= vma.start
+ ? (addr <= vma.end - 1)
+ : vma.is_near_this (addr, &vma))
+#else
+ if (addr <= vma.end - 1
+ ? (addr >= vma.start)
+ : vma.is_near_this (addr, &vma))
+#endif
+#endif
+#else
+ /* Heuristic AB: If the fault address is near the stack pointer,
+ it's a stack overflow. */
+ unsigned long addr = (unsigned long) address;
+
+ if ((addr <= old_sp + 4096 && old_sp <= addr + 4096)
+#ifdef __ia64
+ || (addr <= old_bsp + 4096 && old_bsp <= addr + 4096)
+#endif
+ )
+ {
+ {
+#endif
+ {
+#ifdef SIGSEGV_FAULT_STACKPOINTER
+ int emergency =
+ (old_sp >= stk_extra_stack
+ && old_sp <= stk_extra_stack + stk_extra_stack_size);
+ stackoverflow_context_t context = (SIGSEGV_FAULT_CONTEXT);
+#else
+ int emergency = 0;
+ stackoverflow_context_t context = (void *) 0;
+#endif
+ /* Call user's handler. */
+ (*stk_user_handler) (emergency, context);
+ }
+ }
+ }
+ }
+#endif /* HAVE_STACK_OVERFLOW_RECOVERY */
+
+ if (user_handler && (*user_handler) (address, 1))
+ {
+ /* Handler successful. */
+ }
+ else
+ {
+ /* Handler declined responsibility for real. */
+
+ /* Remove ourselves and dump core. */
+ SIGSEGV_FOR_ALL_SIGNALS (sig, signal (sig, SIG_DFL);)
+ }
+
+#if HAVE_STACK_OVERFLOW_RECOVERY
+ }
+#endif /* HAVE_STACK_OVERFLOW_RECOVERY */
+}
+
+#elif HAVE_STACK_OVERFLOW_RECOVERY
+
+static void
+#ifdef SIGSEGV_FAULT_STACKPOINTER
+sigsegv_handler (SIGSEGV_FAULT_HANDLER_ARGLIST)
+#else
+sigsegv_handler (int sig)
+#endif
+{
+#if !((HAVE_GETRLIMIT && defined RLIMIT_STACK) || defined SIGSEGV_FAULT_STACKPOINTER)
+#error "Insufficient heuristics for detecting a stack overflow. Either define SIGSEGV_FAULT_STACKPOINTER correctly, or undefine HAVE_STACK_OVERFLOW_RECOVERY!"
+#endif
+
+ /* Did the user install a handler? */
+ if (stk_user_handler)
+ {
+ /* See whether it was a stack overflow. If so, longjump away. */
+#ifdef SIGSEGV_FAULT_STACKPOINTER
+ unsigned long old_sp = (unsigned long) (SIGSEGV_FAULT_STACKPOINTER);
+#endif
+
+ /* Were we able to determine the stack top? */
+ if (stack_top)
+ {
+ /* Determine stack bounds. */
+ int saved_errno;
+ struct vma_struct vma;
+
+ saved_errno = errno;
+ if (sigsegv_get_vma (stack_top, &vma) >= 0)
+ {
+#if HAVE_GETRLIMIT && defined RLIMIT_STACK
+ /* Heuristic BC: If the stack size has reached its maximal size,
+ and old_sp is near the low end, we consider it a stack
+ overflow. */
+ struct rlimit rl;
+
+ if (getrlimit (RLIMIT_STACK, &rl) >= 0)
+ {
+ unsigned long current_stack_size = vma.end - vma.start;
+ unsigned long max_stack_size = rl.rlim_cur;
+ if (current_stack_size <= max_stack_size + 4096
+ && max_stack_size <= current_stack_size + 4096
+#else
+ {
+ if (1
+#endif
+#ifdef SIGSEGV_FAULT_STACKPOINTER
+ /* Heuristic BC: If we know old_sp, and it is neither
+ near the low end, nor in the alternate stack, then
+ it's probably not a stack overflow. */
+ && ((old_sp >= stk_extra_stack
+ && old_sp <= stk_extra_stack + stk_extra_stack_size)
+#if STACK_DIRECTION < 0
+ || (old_sp <= vma.start + 4096
+ && vma.start <= old_sp + 4096))
+#else
+ || (old_sp <= vma.end + 4096
+ && vma.end <= old_sp + 4096))
+#endif
+#endif
+ )
+ {
+#ifdef SIGSEGV_FAULT_STACKPOINTER
+ int emergency =
+ (old_sp >= stk_extra_stack
+ && old_sp <= stk_extra_stack + stk_extra_stack_size);
+ stackoverflow_context_t context = (SIGSEGV_FAULT_CONTEXT);
+#else
+ int emergency = 0;
+ stackoverflow_context_t context = (void *) 0;
+#endif
+ /* Call user's handler. */
+ (*stk_user_handler)(emergency,context);
+ }
+ }
+ }
+ errno = saved_errno;
+ }
+ }
+
+ /* Remove ourselves and dump core. */
+ SIGSEGV_FOR_ALL_SIGNALS (sig, signal (sig, SIG_DFL);)
+}
+
+#endif
+
+
+static void
+install_for (int sig)
+{
+ struct sigaction action;
+
+#ifdef SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
+ action.sa_sigaction = &sigsegv_handler;
+#else
+ action.sa_handler = (void (*) (int)) &sigsegv_handler;
+#endif
+ /* Block most signals while SIGSEGV is being handled. */
+ /* Signals SIGKILL, SIGSTOP cannot be blocked. */
+ /* Signals SIGCONT, SIGTSTP, SIGTTIN, SIGTTOU are not blocked because
+ dealing with these signals seems dangerous. */
+ /* Signals SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGTRAP, SIGIOT, SIGEMT, SIGBUS,
+ SIGSYS, SIGSTKFLT are not blocked because these are synchronous signals,
+ which may require immediate intervention, otherwise the process may
+ starve. */
+ sigemptyset (&action.sa_mask);
+#ifdef SIGHUP
+ sigaddset (&action.sa_mask,SIGHUP);
+#endif
+#ifdef SIGINT
+ sigaddset (&action.sa_mask,SIGINT);
+#endif
+#ifdef SIGQUIT
+ sigaddset (&action.sa_mask,SIGQUIT);
+#endif
+#ifdef SIGPIPE
+ sigaddset (&action.sa_mask,SIGPIPE);
+#endif
+#ifdef SIGALRM
+ sigaddset (&action.sa_mask,SIGALRM);
+#endif
+#ifdef SIGTERM
+ sigaddset (&action.sa_mask,SIGTERM);
+#endif
+#ifdef SIGUSR1
+ sigaddset (&action.sa_mask,SIGUSR1);
+#endif
+#ifdef SIGUSR2
+ sigaddset (&action.sa_mask,SIGUSR2);
+#endif
+#ifdef SIGCHLD
+ sigaddset (&action.sa_mask,SIGCHLD);
+#endif
+#ifdef SIGCLD
+ sigaddset (&action.sa_mask,SIGCLD);
+#endif
+#ifdef SIGURG
+ sigaddset (&action.sa_mask,SIGURG);
+#endif
+#ifdef SIGIO
+ sigaddset (&action.sa_mask,SIGIO);
+#endif
+#ifdef SIGPOLL
+ sigaddset (&action.sa_mask,SIGPOLL);
+#endif
+#ifdef SIGXCPU
+ sigaddset (&action.sa_mask,SIGXCPU);
+#endif
+#ifdef SIGXFSZ
+ sigaddset (&action.sa_mask,SIGXFSZ);
+#endif
+#ifdef SIGVTALRM
+ sigaddset (&action.sa_mask,SIGVTALRM);
+#endif
+#ifdef SIGPROF
+ sigaddset (&action.sa_mask,SIGPROF);
+#endif
+#ifdef SIGPWR
+ sigaddset (&action.sa_mask,SIGPWR);
+#endif
+#ifdef SIGLOST
+ sigaddset (&action.sa_mask,SIGLOST);
+#endif
+#ifdef SIGWINCH
+ sigaddset (&action.sa_mask,SIGWINCH);
+#endif
+ /* Note that sigaction() implicitly adds sig itself to action.sa_mask. */
+ /* Ask the OS to provide a structure siginfo_t to the handler. */
+#ifdef SIGSEGV_FAULT_ADDRESS_FROM_SIGINFO
+ action.sa_flags = SA_SIGINFO;
+#else
+ action.sa_flags = 0;
+#endif
+#if HAVE_STACK_OVERFLOW_RECOVERY && HAVE_SIGALTSTACK /* not BeOS */
+ /* Work around Linux 2.2.5 bug: If SA_ONSTACK is specified but sigaltstack()
+ has not been called, the kernel will busy loop, eating CPU time. So
+ avoid setting SA_ONSTACK until the user has requested stack overflow
+ handling. */
+ if (stk_user_handler)
+ action.sa_flags |= SA_ONSTACK;
+#endif
+ sigaction (sig, &action, (struct sigaction *) NULL);
+}
+
+int
+sigsegv_install_handler (sigsegv_handler_t handler)
+{
+#if HAVE_SIGSEGV_RECOVERY
+ user_handler = handler;
+
+ SIGSEGV_FOR_ALL_SIGNALS (sig, install_for (sig);)
+
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+void
+sigsegv_deinstall_handler (void)
+{
+#if HAVE_SIGSEGV_RECOVERY
+ user_handler = (sigsegv_handler_t)NULL;
+
+#if HAVE_STACK_OVERFLOW_RECOVERY
+ if (!stk_user_handler)
+#endif
+ {
+ SIGSEGV_FOR_ALL_SIGNALS (sig, signal (sig, SIG_DFL);)
+ }
+#endif
+}
+
+int
+sigsegv_leave_handler (void (*continuation) (void*, void*, void*),
+ void* cont_arg1, void* cont_arg2, void* cont_arg3)
+{
+#if HAVE_STACK_OVERFLOW_RECOVERY
+ /*
+ * Reset the system's knowledge that we are executing on the alternate
+ * stack. If we didn't do that, siglongjmp would be needed instead of
+ * longjmp to leave the signal handler.
+ */
+ sigsegv_reset_onstack_flag ();
+#endif
+ (*continuation) (cont_arg1, cont_arg2, cont_arg3);
+ return 1;
+}
+
+int
+stackoverflow_install_handler (stackoverflow_handler_t handler,
+ void *extra_stack, unsigned long extra_stack_size)
+{
+#if HAVE_STACK_OVERFLOW_RECOVERY
+#if HAVE_STACKVMA
+ if (!stack_top)
+ {
+ int dummy;
+ remember_stack_top (&dummy);
+ if (!stack_top)
+ return -1;
+ }
+#endif
+
+ stk_user_handler = handler;
+ stk_extra_stack = (unsigned long) extra_stack;
+ stk_extra_stack_size = extra_stack_size;
+#ifdef __BEOS__
+ set_signal_stack (extra_stack, extra_stack_size);
+#else /* HAVE_SIGALTSTACK */
+ {
+ stack_t ss;
+#if SIGALTSTACK_SS_REVERSED
+ ss.ss_sp = (char *) extra_stack + extra_stack_size - sizeof (void *);
+ ss.ss_size = extra_stack_size - sizeof (void *);
+#else
+ ss.ss_sp = extra_stack;
+ ss.ss_size = extra_stack_size;
+#endif
+ ss.ss_flags = 0; /* no SS_DISABLE */
+ if (sigaltstack (&ss, (stack_t*)0) < 0)
+ return -1;
+ }
+#endif
+
+ /* Install the signal handlers with SA_ONSTACK. */
+ SIGSEGV_FOR_ALL_SIGNALS (sig, install_for (sig);)
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+void
+stackoverflow_deinstall_handler (void)
+{
+#if HAVE_STACK_OVERFLOW_RECOVERY
+ stk_user_handler = (stackoverflow_handler_t) NULL;
+
+#if HAVE_SIGSEGV_RECOVERY
+ if (user_handler)
+ {
+ /* Reinstall the signal handlers without SA_ONSTACK, to avoid Linux
+ bug. */
+ SIGSEGV_FOR_ALL_SIGNALS (sig, install_for (sig);)
+ }
+ else
+#endif
+ {
+ SIGSEGV_FOR_ALL_SIGNALS (sig, signal (sig, SIG_DFL);)
+ }
+
+#ifdef __BEOS__
+ /* We cannot undo the effect of set_signal_stack. */
+ fprintf (stderr, "libsigsegv (stackoverflow_deinstall_handler): not supported on this platform\n");
+#else /* HAVE_SIGALTSTACK */
+ {
+ stack_t ss;
+ ss.ss_flags = SS_DISABLE;
+ if (sigaltstack (&ss, (stack_t *) 0) < 0)
+ perror ("libsigsegv (stackoverflow_deinstall_handler)");
+ }
+#endif
+
+#endif
+}
diff --git a/libsigsegv/src/handler-win32.c b/libsigsegv/src/handler-win32.c
new file mode 100644
index 00000000..479bd030
--- /dev/null
+++ b/libsigsegv/src/handler-win32.c
@@ -0,0 +1,317 @@
+/* Fault handler information. Woe32 version.
+ Copyright (C) 1993-1999, 2002-2003, 2007-2008 Bruno Haible <bruno@clisp.org>
+ Copyright (C) 2003 Paolo Bonzini <bonzini@gnu.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "sigsegv.h"
+
+#define WIN32_LEAN_AND_MEAN /* avoid including junk */
+#include <windows.h>
+#include <winerror.h>
+/*
+ * extern LPTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter (LPTOP_LEVEL_EXCEPTION_FILTER TopLevelExceptionFilter);
+ * extern DWORD VirtualQuery (LPCVOID Address, PMEMORY_BASIC_INFORMATION Buffer, DWORD Length);
+ * extern BOOL VirtualProtect (LPVOID Address, DWORD Size, DWORD NewProtect, PDWORD OldProtect);
+ * extern DWORD GetLastError (void);
+ */
+
+/* User's SIGSEGV handler. */
+static sigsegv_handler_t user_handler = (sigsegv_handler_t) NULL;
+
+/* Stack overflow handling is tricky:
+ First, we must catch a STATUS_STACK_OVERFLOW exception. This is signalled
+ when the guard page at the end of the stack has been touched. The operating
+ system remaps the page with protection PAGE_READWRITE and only then calls
+ our exception handler. Actually, it's even more complicated: The stack has
+ the following layout:
+
+ | |guard|----------stack-----------|
+
+ and when the guard page is touched, the system maps it PAGE_READWRITE and
+ allocates a new guard page below it:
+
+ | |guard|-------------stack--------------|
+
+ Only when no new guard page can be allocated (because the maximum stack
+ size has been reached), will we see an exception.
+
+ |guard|-------------------------stack--------------------------|
+
+ Second, we must reinstall the guard page. Otherwise, on the next stack
+ overflow, the application will simply crash (on WinNT: silently, on Win95:
+ with an error message box and freezing the system).
+ But since we don't know where %esp points to during the exception handling,
+ we must first leave the exception handler, before we can restore the guard
+ page. And %esp must be made to point to a reasonable value before we do
+ this.
+
+ Note: On WinNT, the guard page has protection PAGE_READWRITE|PAGE_GUARD.
+ On Win95, which doesn't know PAGE_GUARD, it has protection PAGE_NOACCESS.
+ */
+
+static stackoverflow_handler_t stk_user_handler =
+ (stackoverflow_handler_t) NULL;
+static unsigned long stk_extra_stack;
+static unsigned long stk_extra_stack_size;
+
+static void
+stack_overflow_handler (unsigned long faulting_page_address, stackoverflow_context_t context)
+{
+ MEMORY_BASIC_INFORMATION info;
+ DWORD oldprot;
+ unsigned long base;
+ unsigned long address;
+
+ /* First get stack's base address. */
+ if (VirtualQuery ((void*) faulting_page_address, &info, sizeof (info))
+ != sizeof (info))
+ goto failed;
+ base = (unsigned long) info.AllocationBase;
+
+ /* Now search for the first existing page. */
+ address = base;
+ for (;;)
+ {
+ if (VirtualQuery ((void*) address, &info, sizeof (info)) != sizeof (info))
+ goto failed;
+ if (address != (unsigned long) info.BaseAddress)
+ goto failed;
+ if (info.State != MEM_FREE)
+ {
+ if ((unsigned long) info.AllocationBase != base)
+ goto failed;
+ if (info.State == MEM_COMMIT)
+ break;
+ }
+ address = (unsigned long) info.BaseAddress + info.RegionSize;
+ }
+
+ /* Now add the PAGE_GUARD bit to the first existing page. */
+ /* On WinNT this works... */
+ if (VirtualProtect (info.BaseAddress, 0x1000, info.Protect | PAGE_GUARD,
+ &oldprot))
+ goto ok;
+ if (GetLastError () == ERROR_INVALID_PARAMETER)
+ /* ... but on Win95 we need this: */
+ if (VirtualProtect (info.BaseAddress, 0x1000, PAGE_NOACCESS, &oldprot))
+ goto ok;
+ failed:
+ for (;;)
+ (*stk_user_handler) (1, context);
+ ok:
+ for (;;)
+ (*stk_user_handler) (0, context);
+}
+
+/* This is the stack overflow and page fault handler. */
+static LONG WINAPI
+main_exception_filter (EXCEPTION_POINTERS *ExceptionInfo)
+{
+ if ((stk_user_handler
+ && ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW
+ )
+ ||
+ (user_handler != (sigsegv_handler_t)NULL
+ && ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
+ ))
+ {
+#if 0 /* for debugging only */
+ printf ("Exception!\n");
+ printf ("Code = 0x%x\n",
+ ExceptionInfo->ExceptionRecord->ExceptionCode);
+ printf ("Flags = 0x%x\n",
+ ExceptionInfo->ExceptionRecord->ExceptionFlags);
+ printf ("Address = 0x%x\n",
+ ExceptionInfo->ExceptionRecord->ExceptionAddress);
+ printf ("Params:");
+ {
+ DWORD i;
+ for (i = 0; i < ExceptionInfo->ExceptionRecord->NumberParameters; i++)
+ printf (" 0x%x,",
+ ExceptionInfo->ExceptionRecord->ExceptionInformation[i]);
+ }
+ printf ("\n");
+ printf ("Registers:\n");
+ printf ("eip = 0x%x\n", ExceptionInfo->ContextRecord->Eip);
+ printf ("eax = 0x%x, ", ExceptionInfo->ContextRecord->Eax);
+ printf ("ebx = 0x%x, ", ExceptionInfo->ContextRecord->Ebx);
+ printf ("ecx = 0x%x, ", ExceptionInfo->ContextRecord->Ecx);
+ printf ("edx = 0x%x\n", ExceptionInfo->ContextRecord->Edx);
+ printf ("esi = 0x%x, ", ExceptionInfo->ContextRecord->Esi);
+ printf ("edi = 0x%x, ", ExceptionInfo->ContextRecord->Edi);
+ printf ("ebp = 0x%x, ", ExceptionInfo->ContextRecord->Ebp);
+ printf ("esp = 0x%x\n", ExceptionInfo->ContextRecord->Esp);
+#endif
+ if (ExceptionInfo->ExceptionRecord->NumberParameters == 2)
+ {
+ if (stk_user_handler
+ && ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW)
+ {
+ char *address = (char *) ExceptionInfo->ExceptionRecord->ExceptionInformation[1];
+ /* Restart the program, giving it a sane value for %esp.
+ At the same time, copy the contents of
+ ExceptionInfo->ContextRecord (which, on Windows XP, happens
+ to be allocated in the guard page, where it will be
+ inaccessible as soon as we restore the PAGE_GUARD bit!) to
+ this new stack. */
+ unsigned long faulting_page_address = (unsigned long)address & -0x1000;
+ unsigned long new_safe_esp = ((stk_extra_stack + stk_extra_stack_size) & -16);
+ CONTEXT *orig_context = ExceptionInfo->ContextRecord;
+ CONTEXT *safe_context = (CONTEXT *) (new_safe_esp -= sizeof (CONTEXT)); /* make room */
+ memcpy (safe_context, orig_context, sizeof (CONTEXT));
+ new_safe_esp -= 8; /* make room for arguments */
+ new_safe_esp &= -16; /* align */
+ new_safe_esp -= 4; /* make room for (unused) return address slot */
+ ExceptionInfo->ContextRecord->Esp = new_safe_esp;
+ /* Call stack_overflow_handler(faulting_page_address,safe_context). */
+ ExceptionInfo->ContextRecord->Eip = (unsigned long)&stack_overflow_handler;
+ *(unsigned long *)(new_safe_esp + 4) = faulting_page_address;
+ *(unsigned long *)(new_safe_esp + 8) = (unsigned long) safe_context;
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ if (user_handler != (sigsegv_handler_t) NULL
+ && ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
+ {
+ /* ExceptionInfo->ExceptionRecord->ExceptionInformation[0] is 1
+ if it's a write access, 0 if it's a read access. But we don't
+ need this info because we don't have it on Unix either. */
+ void *address = (void *) ExceptionInfo->ExceptionRecord->ExceptionInformation[1];
+ if ((*user_handler) (address, 1))
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ }
+ }
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+#if defined __CYGWIN__ && defined __i386__
+
+/* In Cygwin programs, SetUnhandledExceptionFilter has no effect because Cygwin
+ installs a global exception handler. We have to dig deep in order to install
+ our main_exception_filter. */
+
+/* Data structures for the current thread's exception handler chain.
+ On the x86 Windows uses register fs, offset 0 to point to the current
+ exception handler; Cygwin mucks with it, so we must do the same... :-/ */
+
+/* Magic taken from winsup/cygwin/include/exceptions.h. */
+
+struct exception_list
+ {
+ struct exception_list *prev;
+ int (*handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
+ };
+typedef struct exception_list exception_list;
+
+/* Magic taken from winsup/cygwin/exceptions.cc. */
+
+__asm__ (".equ __except_list,0");
+
+extern exception_list *_except_list __asm__ ("%fs:__except_list");
+
+/* For debugging. _except_list is not otherwise accessible from gdb. */
+static exception_list *
+debug_get_except_list ()
+{
+ return _except_list;
+}
+
+/* Cygwin's original exception handler. */
+static int (*cygwin_exception_handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
+
+/* Our exception handler. */
+static int
+libsigsegv_exception_handler (EXCEPTION_RECORD *exception, void *frame, CONTEXT *context, void *dispatch)
+{
+ EXCEPTION_POINTERS ExceptionInfo;
+ ExceptionInfo.ExceptionRecord = exception;
+ ExceptionInfo.ContextRecord = context;
+ if (main_exception_filter (&ExceptionInfo) == EXCEPTION_CONTINUE_SEARCH)
+ return cygwin_exception_handler (exception, frame, context, dispatch);
+ else
+ return 0;
+}
+
+static void
+do_install_main_exception_filter ()
+{
+ /* We cannot insert any handler into the chain, because such handlers
+ must lie on the stack (?). Instead, we have to replace(!) Cygwin's
+ global exception handler. */
+ cygwin_exception_handler = _except_list->handler;
+ _except_list->handler = libsigsegv_exception_handler;
+}
+
+#else
+
+static void
+do_install_main_exception_filter ()
+{
+ SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER) &main_exception_filter);
+}
+
+#endif
+
+static void
+install_main_exception_filter ()
+{
+ static int main_exception_filter_installed = 0;
+
+ if (!main_exception_filter_installed)
+ {
+ do_install_main_exception_filter ();
+ main_exception_filter_installed = 1;
+ }
+}
+
+int
+sigsegv_install_handler (sigsegv_handler_t handler)
+{
+ user_handler = handler;
+ install_main_exception_filter ();
+ return 0;
+}
+
+void
+sigsegv_deinstall_handler (void)
+{
+ user_handler = (sigsegv_handler_t) NULL;
+}
+
+int
+sigsegv_leave_handler (void (*continuation) (void*, void*, void*),
+ void* cont_arg1, void* cont_arg2, void* cont_arg3)
+{
+ (*continuation) (cont_arg1, cont_arg2, cont_arg3);
+ return 1;
+}
+
+int
+stackoverflow_install_handler (stackoverflow_handler_t handler,
+ void *extra_stack, unsigned long extra_stack_size)
+{
+ stk_user_handler = handler;
+ stk_extra_stack = (unsigned long) extra_stack;
+ stk_extra_stack_size = extra_stack_size;
+ install_main_exception_filter ();
+ return 0;
+}
+
+void
+stackoverflow_deinstall_handler (void)
+{
+ stk_user_handler = (stackoverflow_handler_t) NULL;
+}
diff --git a/libsigsegv/src/handler.c b/libsigsegv/src/handler.c
new file mode 100644
index 00000000..4fd1cbac
--- /dev/null
+++ b/libsigsegv/src/handler.c
@@ -0,0 +1,20 @@
+/* Fault handler information.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+
+#include CFG_HANDLER
diff --git a/libsigsegv/src/leave-none.c b/libsigsegv/src/leave-none.c
new file mode 100644
index 00000000..deeb7b89
--- /dev/null
+++ b/libsigsegv/src/leave-none.c
@@ -0,0 +1,18 @@
+/* Leaving a signal handler executing on the alternate stack.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* No need to define sigsegv_reset_onstack_flag() on this platform. */
diff --git a/libsigsegv/src/leave-nop.c b/libsigsegv/src/leave-nop.c
new file mode 100644
index 00000000..88674bda
--- /dev/null
+++ b/libsigsegv/src/leave-nop.c
@@ -0,0 +1,23 @@
+/* Leaving a signal handler executing on the alternate stack.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+void
+sigsegv_reset_onstack_flag (void)
+{
+ /* Nothing to do. sigaltstack() simply looks at the stack pointer,
+ therefore SS_ONSTACK is not sticky. */
+}
diff --git a/libsigsegv/src/leave-setcontext.c b/libsigsegv/src/leave-setcontext.c
new file mode 100644
index 00000000..e383cf96
--- /dev/null
+++ b/libsigsegv/src/leave-setcontext.c
@@ -0,0 +1,38 @@
+/* Leaving a signal handler executing on the alternate stack.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <signal.h>
+#include <ucontext.h>
+
+void
+sigsegv_reset_onstack_flag (void)
+{
+ ucontext_t uc;
+
+ if (getcontext (&uc) >= 0)
+ /* getcontext returns twice. We are interested in the returned context
+ only the first time, i.e. when the SS_ONSTACK bit is set. */
+ if (uc.uc_stack.ss_flags & SS_ONSTACK)
+ {
+ uc.uc_stack.ss_flags &= ~SS_ONSTACK;
+ /* Note that setcontext() does not refill uc. Therefore if
+ setcontext() keeps SS_ONSTACK set in the kernel, either
+ setcontext() will return -1 or getcontext() will return a
+ second time, with the SS_ONSTACK bit being cleared. */
+ setcontext (&uc);
+ }
+}
diff --git a/libsigsegv/src/leave-sigaltstack.c b/libsigsegv/src/leave-sigaltstack.c
new file mode 100644
index 00000000..39749a55
--- /dev/null
+++ b/libsigsegv/src/leave-sigaltstack.c
@@ -0,0 +1,39 @@
+/* Leaving a signal handler executing on the alternate stack.
+ Copyright (C) 2002-2003 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <stddef.h>
+#include <signal.h>
+#if HAVE_SYS_SIGNAL_H
+# include <sys/signal.h>
+#endif
+
+/* For MacOSX. */
+#ifndef SS_ONSTACK
+#define SS_ONSTACK SA_ONSTACK
+#endif
+
+void
+sigsegv_reset_onstack_flag (void)
+{
+ stack_t ss;
+
+ if (sigaltstack (NULL, &ss) >= 0)
+ {
+ ss.ss_flags &= ~SS_ONSTACK;
+ sigaltstack (&ss, NULL);
+ }
+}
diff --git a/libsigsegv/src/leave.c b/libsigsegv/src/leave.c
new file mode 100644
index 00000000..e7d7024a
--- /dev/null
+++ b/libsigsegv/src/leave.c
@@ -0,0 +1,20 @@
+/* Leaving a signal handler executing on the alternate stack.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+
+#include CFG_LEAVE
diff --git a/libsigsegv/src/leave.h b/libsigsegv/src/leave.h
new file mode 100644
index 00000000..9a279c76
--- /dev/null
+++ b/libsigsegv/src/leave.h
@@ -0,0 +1,18 @@
+/* Leaving a signal handler executing on the alternate stack.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+extern void sigsegv_reset_onstack_flag (void);
diff --git a/libsigsegv/src/machfault-macos.h b/libsigsegv/src/machfault-macos.h
new file mode 100644
index 00000000..3fb49d7b
--- /dev/null
+++ b/libsigsegv/src/machfault-macos.h
@@ -0,0 +1,120 @@
+/* Fault handler information. MacOSX version (both PowerPC and i386).
+ Copyright (C) 2003-2004, 2006-2008 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#if defined __ppc__ || defined __ppc64__
+
+#if defined __ppc64__
+/* 64 bit registers */
+
+#define SIGSEGV_EXC_STATE_TYPE ppc_exception_state64_t
+#define SIGSEGV_EXC_STATE_FLAVOR PPC_EXCEPTION_STATE64
+#define SIGSEGV_EXC_STATE_COUNT PPC_EXCEPTION_STATE64_COUNT
+#define SIGSEGV_THREAD_STATE_TYPE ppc_thread_state64_t
+#define SIGSEGV_THREAD_STATE_FLAVOR PPC_THREAD_STATE64
+#define SIGSEGV_THREAD_STATE_COUNT PPC_THREAD_STATE64_COUNT
+
+#else
+/* 32 bit registers */
+
+#define SIGSEGV_EXC_STATE_TYPE ppc_exception_state_t
+#define SIGSEGV_EXC_STATE_FLAVOR PPC_EXCEPTION_STATE
+#define SIGSEGV_EXC_STATE_COUNT PPC_EXCEPTION_STATE_COUNT
+#define SIGSEGV_THREAD_STATE_TYPE ppc_thread_state_t
+#define SIGSEGV_THREAD_STATE_FLAVOR PPC_THREAD_STATE
+#define SIGSEGV_THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT
+
+#endif
+
+#if MacOS_X_10_5_HEADERS && __DARWIN_UNIX03
+#define SIGSEGV_FAULT_ADDRESS(thr_state,exc_state) (exc_state).__dar
+#define SIGSEGV_STACK_POINTER(thr_state) (thr_state).__r1
+#define SIGSEGV_PROGRAM_COUNTER(thr_state) (thr_state).__srr0
+#define SIGSEGV_INTEGER_ARGUMENT_1(thr_state) (thr_state).__r3
+#define SIGSEGV_INTEGER_ARGUMENT_2(thr_state) (thr_state).__r4
+#define SIGSEGV_INTEGER_ARGUMENT_3(thr_state) (thr_state).__r5
+#else
+#define SIGSEGV_FAULT_ADDRESS(thr_state,exc_state) (exc_state).dar
+#define SIGSEGV_STACK_POINTER(thr_state) (thr_state).r1
+#define SIGSEGV_PROGRAM_COUNTER(thr_state) (thr_state).srr0
+#define SIGSEGV_INTEGER_ARGUMENT_1(thr_state) (thr_state).r3
+#define SIGSEGV_INTEGER_ARGUMENT_2(thr_state) (thr_state).r4
+#define SIGSEGV_INTEGER_ARGUMENT_3(thr_state) (thr_state).r5
+#endif
+
+#endif
+
+#if defined __i386__ || defined __x86_64__
+
+#if defined __x86_64__
+/* 64 bit registers */
+
+#define SIGSEGV_THREAD_STATE_TYPE x86_thread_state64_t
+#define SIGSEGV_THREAD_STATE_FLAVOR x86_THREAD_STATE64
+#define SIGSEGV_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
+#define SIGSEGV_EXC_STATE_TYPE x86_exception_state64_t
+#define SIGSEGV_EXC_STATE_FLAVOR x86_EXCEPTION_STATE64
+#define SIGSEGV_EXC_STATE_COUNT x86_EXCEPTION_STATE64_COUNT
+#if MacOS_X_10_5_HEADERS && __DARWIN_UNIX03
+#define SIGSEGV_FAULT_ADDRESS(thr_state,exc_state) (exc_state).__faultvaddr
+#define SIGSEGV_STACK_POINTER(thr_state) (thr_state).__rsp
+#define SIGSEGV_PROGRAM_COUNTER(thr_state) (thr_state).__rip
+#define SIGSEGV_FRAME_POINTER(thr_state) (thr_state).__rbp
+#define SIGSEGV_INTEGER_ARGUMENT_1(thr_state) (thr_state).__rdi
+#define SIGSEGV_INTEGER_ARGUMENT_2(thr_state) (thr_state).__rsi
+#define SIGSEGV_INTEGER_ARGUMENT_3(thr_state) (thr_state).__rdx
+#else
+#define SIGSEGV_FAULT_ADDRESS(thr_state,exc_state) (exc_state).faultvaddr
+#define SIGSEGV_STACK_POINTER(thr_state) (thr_state).rsp
+#define SIGSEGV_PROGRAM_COUNTER(thr_state) (thr_state).rip
+#define SIGSEGV_FRAME_POINTER(thr_state) (thr_state).rbp
+#define SIGSEGV_INTEGER_ARGUMENT_1(thr_state) (thr_state).rdi
+#define SIGSEGV_INTEGER_ARGUMENT_2(thr_state) (thr_state).rsi
+#define SIGSEGV_INTEGER_ARGUMENT_3(thr_state) (thr_state).rdx
+#endif
+
+#else
+/* 32 bit registers */
+
+#if defined x86_THREAD_STATE32
+/* MacOS X 10.5 or newer introduces the new names and deprecates the old ones */
+#define SIGSEGV_THREAD_STATE_TYPE x86_thread_state32_t
+#define SIGSEGV_THREAD_STATE_FLAVOR x86_THREAD_STATE32
+#define SIGSEGV_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT
+#define SIGSEGV_EXC_STATE_TYPE x86_exception_state32_t
+#define SIGSEGV_EXC_STATE_FLAVOR x86_EXCEPTION_STATE32
+#define SIGSEGV_EXC_STATE_COUNT x86_EXCEPTION_STATE32_COUNT
+#else
+#define SIGSEGV_THREAD_STATE_TYPE i386_thread_state_t
+#define SIGSEGV_THREAD_STATE_FLAVOR i386_THREAD_STATE
+#define SIGSEGV_THREAD_STATE_COUNT i386_THREAD_STATE_COUNT
+#define SIGSEGV_EXC_STATE_TYPE i386_exception_state_t
+#define SIGSEGV_EXC_STATE_FLAVOR i386_EXCEPTION_STATE
+#define SIGSEGV_EXC_STATE_COUNT i386_EXCEPTION_STATE_COUNT
+#endif
+#if MacOS_X_10_5_HEADERS && __DARWIN_UNIX03
+#define SIGSEGV_FAULT_ADDRESS(thr_state,exc_state) (exc_state).__faultvaddr
+#define SIGSEGV_STACK_POINTER(thr_state) (thr_state).__esp
+#define SIGSEGV_PROGRAM_COUNTER(thr_state) (thr_state).__eip
+#else
+#define SIGSEGV_FAULT_ADDRESS(thr_state,exc_state) (exc_state).faultvaddr
+#define SIGSEGV_STACK_POINTER(thr_state) (thr_state).esp
+#define SIGSEGV_PROGRAM_COUNTER(thr_state) (thr_state).eip
+#endif
+
+#endif
+
+#endif
diff --git a/libsigsegv/src/machfault.h b/libsigsegv/src/machfault.h
new file mode 100644
index 00000000..fd182a05
--- /dev/null
+++ b/libsigsegv/src/machfault.h
@@ -0,0 +1,54 @@
+/* Fault handler information.
+ Copyright (C) 2004 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* The included file defines:
+
+ SIGSEGV_EXC_STATE_TYPE
+ is a type containing state describing details of an exception,
+ excluding the thread state.
+ SIGSEGV_EXC_STATE_FLAVOR
+ is a macro expanding to a constant int value denoting the
+ SIGSEGV_EXC_STATE_TYPE type.
+ SIGSEGV_EXC_STATE_COUNT
+ is a macro expanding to the number of words of the
+ SIGSEGV_EXC_STATE_TYPE type.
+
+ SIGSEGV_THREAD_STATE_TYPE
+ is a type containing the state of a (stopped or interrupted) thread.
+ SIGSEGV_THREAD_STATE_FLAVOR
+ is a macro expanding to a constant int value denoting the
+ SIGSEGV_THREAD_STATE_TYPE type.
+ SIGSEGV_THREAD_STATE_COUNT
+ is a macro expanding to the number of words of the
+ SIGSEGV_THREAD_STATE_TYPE type.
+
+ SIGSEGV_FAULT_ADDRESS(thr_state, exc_state)
+ is a macro for fetching the fault address.
+
+ SIGSEGV_STACK_POINTER(thr_state)
+ is a macro, expanding to an lvalue, for fetching the stackpointer at
+ the moment the fault occurred, and for setting the stackpointer in
+ effect when the thread continues.
+
+ SIGSEGV_PROGRAM_COUNTER(thr_state)
+ is a macro, expanding to an lvalue, for fetching the program counter
+ (= instruction pointer) at the moment the fault occurred, and for
+ setting the program counter before letting the thread continue.
+
+ */
+
+#include CFG_MACHFAULT
diff --git a/libsigsegv/src/signals-bsd.h b/libsigsegv/src/signals-bsd.h
new file mode 100644
index 00000000..4b57f069
--- /dev/null
+++ b/libsigsegv/src/signals-bsd.h
@@ -0,0 +1,21 @@
+/* List of signals. BSD version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* List of signals that are sent when an invalid virtual memory address
+ is accessed, or when the stack overflows. */
+#define SIGSEGV_FOR_ALL_SIGNALS(var,body) \
+ { int var; var = SIGSEGV; { body } var = SIGBUS; { body } }
diff --git a/libsigsegv/src/signals-hpux.h b/libsigsegv/src/signals-hpux.h
new file mode 100644
index 00000000..0061d21c
--- /dev/null
+++ b/libsigsegv/src/signals-hpux.h
@@ -0,0 +1,21 @@
+/* List of signals. HP-UX version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* List of signals that are sent when an invalid virtual memory address
+ is accessed, or when the stack overflows. */
+#define SIGSEGV_FOR_ALL_SIGNALS(var,body) \
+ { int var; var = SIGSEGV; { body } var = SIGBUS; { body } }
diff --git a/libsigsegv/src/signals-hurd.h b/libsigsegv/src/signals-hurd.h
new file mode 100644
index 00000000..b191fe4d
--- /dev/null
+++ b/libsigsegv/src/signals-hurd.h
@@ -0,0 +1,21 @@
+/* List of signals. Hurd version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* List of signals that are sent when an invalid virtual memory address
+ is accessed, or when the stack overflows. */
+#define SIGSEGV_FOR_ALL_SIGNALS(var,body) \
+ { int var; var = SIGSEGV; { body } var = SIGBUS; { body } }
diff --git a/libsigsegv/src/signals-macos.h b/libsigsegv/src/signals-macos.h
new file mode 100644
index 00000000..a9fc9a81
--- /dev/null
+++ b/libsigsegv/src/signals-macos.h
@@ -0,0 +1,24 @@
+/* List of signals. MacOSX version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+ Copyright (C) 2003 Paolo Bonzini <bonzini@gnu.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* List of signals that are sent when an invalid virtual memory address
+ is accessed, or when the stack overflows.
+ On MacOS X, accessing an invalid memory address gives a SIGBUS, but a
+ stack overflow gives a SIGSEGV. */
+#define SIGSEGV_FOR_ALL_SIGNALS(var,body) \
+ { int var; var = SIGSEGV; { body } var = SIGBUS; { body } }
diff --git a/libsigsegv/src/signals.h b/libsigsegv/src/signals.h
new file mode 100644
index 00000000..b6203ee5
--- /dev/null
+++ b/libsigsegv/src/signals.h
@@ -0,0 +1,21 @@
+/* List of signals. Generic Unix version.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* List of signals that are sent when an invalid virtual memory address
+ is accessed, or when the stack overflows. */
+#define SIGSEGV_FOR_ALL_SIGNALS(var,body) \
+ { int var; var = SIGSEGV; { body } }
diff --git a/libsigsegv/src/sigsegv.h.in b/libsigsegv/src/sigsegv.h.in
new file mode 100644
index 00000000..e6689d28
--- /dev/null
+++ b/libsigsegv/src/sigsegv.h.in
@@ -0,0 +1,201 @@
+/* Page fault handling library.
+ Copyright (C) 1998-1999, 2002, 2004-2008 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _SIGSEGV_H
+#define _SIGSEGV_H
+
+@FAULT_CONTEXT_INCLUDE@
+
+/* HAVE_SIGSEGV_RECOVERY
+ is defined if the system supports catching SIGSEGV. */
+#if @HAVE_SIGSEGV_RECOVERY@
+# define HAVE_SIGSEGV_RECOVERY 1
+#endif
+
+/* HAVE_STACK_OVERFLOW_RECOVERY
+ is defined if stack overflow can be caught. */
+#if @HAVE_STACK_OVERFLOW_RECOVERY@
+# define HAVE_STACK_OVERFLOW_RECOVERY 1
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBSIGSEGV_VERSION 0x0206 /* version number: (major<<8) + minor */
+extern int libsigsegv_version; /* Likewise */
+
+/* -------------------------------------------------------------------------- */
+
+/*
+ * The type of a global SIGSEGV handler.
+ * The fault address is passed as argument.
+ * The access type (read access or write access) is not passed; your handler
+ * has to know itself how to distinguish these two cases.
+ * The second argument is 0, meaning it could also be a stack overflow, or 1,
+ * meaning the handler should seriously try to fix the fault.
+ * The return value should be nonzero if the handler has done its job
+ * and no other handler should be called, or 0 if the handler declines
+ * responsibility for the given address.
+ *
+ * The handler is run at a moment when nothing about the global state of the
+ * program is known. Therefore it cannot use facilities that manipulate global
+ * variables or locks. In particular, it cannot use malloc(); use mmap()
+ * instead. It cannot use fopen(); use open() instead. Etc. All global
+ * variables that are accessed by the handler should be marked 'volatile'.
+ */
+typedef int (*sigsegv_handler_t) (void* fault_address, int serious);
+
+/*
+ * Installs a global SIGSEGV handler.
+ * This should be called once only, and it ignores any previously installed
+ * SIGSEGV handler.
+ * Returns 0 on success, or -1 if the system doesn't support catching SIGSEGV.
+ */
+extern int sigsegv_install_handler (sigsegv_handler_t handler);
+
+/*
+ * Deinstalls the global SIGSEGV handler.
+ * This goes back to the state where no SIGSEGV handler is installed.
+ */
+extern void sigsegv_deinstall_handler (void);
+
+#if LIBSIGSEGV_VERSION >= 0x0206
+/*
+ * Prepares leaving a SIGSEGV handler (through longjmp or similar means).
+ * Control is transferred by calling CONTINUATION with CONT_ARG1, CONT_ARG2,
+ * CONT_ARG3 as arguments.
+ * CONTINUATION must not return.
+ * The sigsegv_leave_handler function may return if called from a SIGSEGV
+ * handler; its return value should be used as the handler's return value.
+ * The sigsegv_leave_handler function does not return if called from a
+ * stack overflow handler.
+ */
+extern int sigsegv_leave_handler (void (*continuation) (void*, void*, void*), void* cont_arg1, void* cont_arg2, void* cont_arg3);
+#else /* older versions of libsigsegv */
+/*
+ * Prepares leaving a SIGSEGV handler (through longjmp or similar means).
+ * Limitation: This function could only be called once on MacOS X.
+ */
+extern void sigsegv_leave_handler (void);
+#endif
+
+/*
+ * The type of a context passed to a stack overflow handler.
+ * This type is system dependent; on some platforms it is an 'ucontext_t *',
+ * on some platforms it is a 'struct sigcontext *', on others merely an
+ * opaque 'void *'.
+ */
+typedef @FAULT_CONTEXT@ *stackoverflow_context_t;
+
+/*
+ * The type of a stack overflow handler.
+ * Such a handler should perform a longjmp call in order to reduce the amount
+ * of stack needed. It must not return.
+ * The emergency argument is 0 when the stack could be repared, or 1 if the
+ * application should better save its state and exit now.
+ *
+ * The handler is run at a moment when nothing about the global state of the
+ * program is known. Therefore it cannot use facilities that manipulate global
+ * variables or locks. In particular, it cannot use malloc(); use mmap()
+ * instead. It cannot use fopen(); use open() instead. Etc. All global
+ * variables that are accessed by the handler should be marked 'volatile'.
+ */
+typedef void (*stackoverflow_handler_t) (int emergency, stackoverflow_context_t scp);
+
+/*
+ * Installs a stack overflow handler.
+ * The extra_stack argument is a pointer to a pre-allocated area used as a
+ * stack for executing the handler. It is typically allocated by use of
+ * `alloca' during `main'. Its size should be sufficiently large.
+ * The following code determines an appropriate size:
+ * #include <signal.h>
+ * #ifndef SIGSTKSZ / * glibc defines SIGSTKSZ for this purpose * /
+ * # define SIGSTKSZ 16384 / * on most platforms, 16 KB are sufficient * /
+ * #endif
+ * Returns 0 on success, or -1 if the system doesn't support catching stack
+ * overflow.
+ */
+extern int stackoverflow_install_handler (stackoverflow_handler_t handler,
+ void* extra_stack, unsigned long extra_stack_size);
+
+/*
+ * Deinstalls the stack overflow handler.
+ */
+extern void stackoverflow_deinstall_handler (void);
+
+/* -------------------------------------------------------------------------- */
+
+/*
+ * The following structure and functions permit to define different SIGSEGV
+ * policies on different address ranges.
+ */
+
+/*
+ * The type of a local SIGSEGV handler.
+ * The fault address is passed as argument.
+ * The second argument is fixed arbitrary user data.
+ * The return value should be nonzero if the handler has done its job
+ * and no other handler should be called, or 0 if the handler declines
+ * responsibility for the given address.
+ */
+typedef int (*sigsegv_area_handler_t) (void* fault_address, void* user_arg);
+
+/*
+ * This structure represents a table of memory areas (address range intervals),
+ * with an local SIGSEGV handler for each.
+ */
+typedef
+struct sigsegv_dispatcher {
+ void* tree;
+}
+sigsegv_dispatcher;
+
+/*
+ * Initializes a sigsegv_dispatcher structure.
+ */
+extern void sigsegv_init (sigsegv_dispatcher* dispatcher);
+
+/*
+ * Adds a local SIGSEGV handler to a sigsegv_dispatcher structure.
+ * It will cover the interval [address..address+len-1].
+ * Returns a "ticket" that can be used to remove the handler later.
+ */
+extern void* sigsegv_register (sigsegv_dispatcher* dispatcher,
+ void* address, unsigned long len,
+ sigsegv_area_handler_t handler, void* handler_arg);
+
+/*
+ * Removes a local SIGSEGV handler.
+ */
+extern void sigsegv_unregister (sigsegv_dispatcher* dispatcher, void* ticket);
+
+/*
+ * Call the local SIGSEGV handler responsible for the given fault address.
+ * Return the handler's return value. 0 means that no handler has been found,
+ * or that a handler was found but declined responsibility.
+ */
+extern int sigsegv_dispatch (sigsegv_dispatcher* dispatcher, void* fault_address);
+
+/* -------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SIGSEGV_H */
diff --git a/libsigsegv/src/sigsegv.h.msvc b/libsigsegv/src/sigsegv.h.msvc
new file mode 100644
index 00000000..a586b48a
--- /dev/null
+++ b/libsigsegv/src/sigsegv.h.msvc
@@ -0,0 +1,201 @@
+/* Page fault handling library.
+ Copyright (C) 1998-1999, 2002, 2004-2008 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _SIGSEGV_H
+#define _SIGSEGV_H
+
+#include <windows.h>
+
+/* HAVE_SIGSEGV_RECOVERY
+ is defined if the system supports catching SIGSEGV. */
+#if 1
+# define HAVE_SIGSEGV_RECOVERY 1
+#endif
+
+/* HAVE_STACK_OVERFLOW_RECOVERY
+ is defined if stack overflow can be caught. */
+#if 1
+# define HAVE_STACK_OVERFLOW_RECOVERY 1
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBSIGSEGV_VERSION 0x0206 /* version number: (major<<8) + minor */
+extern int libsigsegv_version; /* Likewise */
+
+/* -------------------------------------------------------------------------- */
+
+/*
+ * The type of a global SIGSEGV handler.
+ * The fault address is passed as argument.
+ * The access type (read access or write access) is not passed; your handler
+ * has to know itself how to distinguish these two cases.
+ * The second argument is 0, meaning it could also be a stack overflow, or 1,
+ * meaning the handler should seriously try to fix the fault.
+ * The return value should be nonzero if the handler has done its job
+ * and no other handler should be called, or 0 if the handler declines
+ * responsibility for the given address.
+ *
+ * The handler is run at a moment when nothing about the global state of the
+ * program is known. Therefore it cannot use facilities that manipulate global
+ * variables or locks. In particular, it cannot use malloc(); use mmap()
+ * instead. It cannot use fopen(); use open() instead. Etc. All global
+ * variables that are accessed by the handler should be marked 'volatile'.
+ */
+typedef int (*sigsegv_handler_t) (void* fault_address, int serious);
+
+/*
+ * Installs a global SIGSEGV handler.
+ * This should be called once only, and it ignores any previously installed
+ * SIGSEGV handler.
+ * Returns 0 on success, or -1 if the system doesn't support catching SIGSEGV.
+ */
+extern int sigsegv_install_handler (sigsegv_handler_t handler);
+
+/*
+ * Deinstalls the global SIGSEGV handler.
+ * This goes back to the state where no SIGSEGV handler is installed.
+ */
+extern void sigsegv_deinstall_handler (void);
+
+#if LIBSIGSEGV_VERSION >= 0x0206
+/*
+ * Prepares leaving a SIGSEGV handler (through longjmp or similar means).
+ * Control is transferred by calling CONTINUATION with CONT_ARG1, CONT_ARG2,
+ * CONT_ARG3 as arguments.
+ * CONTINUATION must not return.
+ * The sigsegv_leave_handler function may return if called from a SIGSEGV
+ * handler; its return value should be used as the handler's return value.
+ * The sigsegv_leave_handler function does not return if called from a
+ * stack overflow handler.
+ */
+extern int sigsegv_leave_handler (void (*continuation) (void*, void*, void*), void* cont_arg1, void* cont_arg2, void* cont_arg3);
+#else /* older versions of libsigsegv */
+/*
+ * Prepares leaving a SIGSEGV handler (through longjmp or similar means).
+ * Limitation: This function could only be called once on MacOS X.
+ */
+extern void sigsegv_leave_handler (void);
+#endif
+
+/*
+ * The type of a context passed to a stack overflow handler.
+ * This type is system dependent; on some platforms it is an 'ucontext_t *',
+ * on some platforms it is a 'struct sigcontext *', on others merely an
+ * opaque 'void *'.
+ */
+typedef CONTEXT *stackoverflow_context_t;
+
+/*
+ * The type of a stack overflow handler.
+ * Such a handler should perform a longjmp call in order to reduce the amount
+ * of stack needed. It must not return.
+ * The emergency argument is 0 when the stack could be repared, or 1 if the
+ * application should better save its state and exit now.
+ *
+ * The handler is run at a moment when nothing about the global state of the
+ * program is known. Therefore it cannot use facilities that manipulate global
+ * variables or locks. In particular, it cannot use malloc(); use mmap()
+ * instead. It cannot use fopen(); use open() instead. Etc. All global
+ * variables that are accessed by the handler should be marked 'volatile'.
+ */
+typedef void (*stackoverflow_handler_t) (int emergency, stackoverflow_context_t scp);
+
+/*
+ * Installs a stack overflow handler.
+ * The extra_stack argument is a pointer to a pre-allocated area used as a
+ * stack for executing the handler. It is typically allocated by use of
+ * `alloca' during `main'. Its size should be sufficiently large.
+ * The following code determines an appropriate size:
+ * #include <signal.h>
+ * #ifndef SIGSTKSZ / * glibc defines SIGSTKSZ for this purpose * /
+ * # define SIGSTKSZ 16384 / * on most platforms, 16 KB are sufficient * /
+ * #endif
+ * Returns 0 on success, or -1 if the system doesn't support catching stack
+ * overflow.
+ */
+extern int stackoverflow_install_handler (stackoverflow_handler_t handler,
+ void* extra_stack, unsigned long extra_stack_size);
+
+/*
+ * Deinstalls the stack overflow handler.
+ */
+extern void stackoverflow_deinstall_handler (void);
+
+/* -------------------------------------------------------------------------- */
+
+/*
+ * The following structure and functions permit to define different SIGSEGV
+ * policies on different address ranges.
+ */
+
+/*
+ * The type of a local SIGSEGV handler.
+ * The fault address is passed as argument.
+ * The second argument is fixed arbitrary user data.
+ * The return value should be nonzero if the handler has done its job
+ * and no other handler should be called, or 0 if the handler declines
+ * responsibility for the given address.
+ */
+typedef int (*sigsegv_area_handler_t) (void* fault_address, void* user_arg);
+
+/*
+ * This structure represents a table of memory areas (address range intervals),
+ * with an local SIGSEGV handler for each.
+ */
+typedef
+struct sigsegv_dispatcher {
+ void* tree;
+}
+sigsegv_dispatcher;
+
+/*
+ * Initializes a sigsegv_dispatcher structure.
+ */
+extern void sigsegv_init (sigsegv_dispatcher* dispatcher);
+
+/*
+ * Adds a local SIGSEGV handler to a sigsegv_dispatcher structure.
+ * It will cover the interval [address..address+len-1].
+ * Returns a "ticket" that can be used to remove the handler later.
+ */
+extern void* sigsegv_register (sigsegv_dispatcher* dispatcher,
+ void* address, unsigned long len,
+ sigsegv_area_handler_t handler, void* handler_arg);
+
+/*
+ * Removes a local SIGSEGV handler.
+ */
+extern void sigsegv_unregister (sigsegv_dispatcher* dispatcher, void* ticket);
+
+/*
+ * Call the local SIGSEGV handler responsible for the given fault address.
+ * Return the handler's return value. 0 means that no handler has been found,
+ * or that a handler was found but declined responsibility.
+ */
+extern int sigsegv_dispatch (sigsegv_dispatcher* dispatcher, void* fault_address);
+
+/* -------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SIGSEGV_H */
diff --git a/libsigsegv/src/stackvma-beos.c b/libsigsegv/src/stackvma-beos.c
new file mode 100644
index 00000000..3bcebac2
--- /dev/null
+++ b/libsigsegv/src/stackvma-beos.c
@@ -0,0 +1,62 @@
+/* Determine the virtual memory area of a given address. BeOS version.
+ Copyright (C) 2002, 2006 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "stackvma.h"
+#include <OS.h>
+
+#include "stackvma-simple.c"
+
+int
+sigsegv_get_vma (unsigned long address, struct vma_struct *vma)
+{
+ area_info info;
+ int32 cookie;
+ unsigned long start, end;
+#if STACK_DIRECTION < 0
+ unsigned long prev;
+#endif
+
+#if STACK_DIRECTION < 0
+ prev = 0;
+#endif
+ cookie = 0;
+ while (get_next_area_info (0, &cookie, &info) == B_OK)
+ {
+ start = (unsigned long) info.address;
+ end = start + info.size;
+ if (address >= start && address <= end - 1)
+ {
+ vma->start = start;
+ vma->end = end;
+#if STACK_DIRECTION < 0
+ vma->prev_end = prev;
+#else
+ if (get_next_area_info (0, &cookie, &info) == B_OK)
+ vma->next_start = (unsigned long) info.address;
+ else
+ vma->next_start = 0;
+#endif
+ vma->is_near_this = simple_is_near_this;
+ return 0;
+ }
+#if STACK_DIRECTION < 0
+ prev = end;
+#endif
+ }
+
+ return -1;
+}
diff --git a/libsigsegv/src/stackvma-freebsd.c b/libsigsegv/src/stackvma-freebsd.c
new file mode 100644
index 00000000..fd04ba85
--- /dev/null
+++ b/libsigsegv/src/stackvma-freebsd.c
@@ -0,0 +1,118 @@
+/* Determine the virtual memory area of a given address. FreeBSD version.
+ Copyright (C) 2002-2003, 2006, 2008 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "stackvma.h"
+#include <stdio.h>
+
+#include "stackvma-simple.c"
+#include "stackvma-rofile.c"
+
+#if HAVE_MINCORE
+# define sigsegv_get_vma mincore_get_vma
+# define STATIC static
+# include "stackvma-mincore.c"
+# undef sigsegv_get_vma
+#endif
+
+int
+sigsegv_get_vma (unsigned long address, struct vma_struct *vma)
+{
+ struct rofile rof;
+ int c;
+ /* The stack appears as multiple adjacents segments, therefore we
+ merge adjacent segments. */
+ unsigned long next_start, next_end, curr_start, curr_end;
+#if STACK_DIRECTION < 0
+ unsigned long prev_end;
+#endif
+
+ /* Open the current process' maps file. It describes one VMA per line. */
+ if (rof_open (&rof, "/proc/curproc/map") < 0)
+ goto failed;
+
+#if STACK_DIRECTION < 0
+ prev_end = 0;
+#endif
+ for (curr_start = curr_end = 0; ;)
+ {
+ if (!(rof_getchar (&rof) == '0'
+ && rof_getchar (&rof) == 'x'
+ && rof_scanf_lx (&rof, &next_start) >= 0))
+ break;
+ while (c = rof_peekchar (&rof), c == ' ' || c == '\t')
+ rof_getchar (&rof);
+ if (!(rof_getchar (&rof) == '0'
+ && rof_getchar (&rof) == 'x'
+ && rof_scanf_lx (&rof, &next_end) >= 0))
+ break;
+ while (c = rof_getchar (&rof), c != -1 && c != '\n')
+ continue;
+ if (next_start == curr_end)
+ {
+ /* Merge adjacent segments. */
+ curr_end = next_end;
+ }
+ else
+ {
+ if (curr_start < curr_end
+ && address >= curr_start && address <= curr_end-1)
+ goto found;
+#if STACK_DIRECTION < 0
+ prev_end = curr_end;
+#endif
+ curr_start = next_start; curr_end = next_end;
+ }
+ }
+ if (address >= curr_start && address <= curr_end-1)
+ found:
+ {
+ vma->start = curr_start;
+ vma->end = curr_end;
+#if STACK_DIRECTION < 0
+ vma->prev_end = prev_end;
+#else
+ if (rof_getchar (&rof) == '0'
+ && rof_getchar (&rof) == 'x'
+ && rof_scanf_lx (&rof, &vma->next_start) >= 0)
+ {
+ while (c = rof_peekchar (&rof), c == ' ' || c == '\t')
+ rof_getchar (&rof);
+ if (rof_getchar (&rof) == '0'
+ && rof_getchar (&rof) == 'x'
+ && rof_scanf_lx (&rof, &next_end) >= 0)
+ ;
+ else
+ vma->next_start = 0;
+ }
+ else
+ vma->next_start = 0;
+#endif
+ rof_close (&rof);
+ vma->is_near_this = simple_is_near_this;
+ return 0;
+ }
+ rof_close (&rof);
+ failed:
+#if HAVE_MINCORE
+ /* FreeBSD 6.[01] doesn't allow to distinguish unmapped pages from
+ mapped but swapped-out pages. See whether it's fixed. */
+ if (!is_mapped (0))
+ /* OK, mincore() appears to work as expected. */
+ return mincore_get_vma (address, vma);
+#endif
+ return -1;
+}
diff --git a/libsigsegv/src/stackvma-linux.c b/libsigsegv/src/stackvma-linux.c
new file mode 100644
index 00000000..33842287
--- /dev/null
+++ b/libsigsegv/src/stackvma-linux.c
@@ -0,0 +1,83 @@
+/* Determine the virtual memory area of a given address. Linux version.
+ Copyright (C) 2002, 2006, 2008 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "stackvma.h"
+#include <stdio.h>
+
+#include "stackvma-simple.c"
+#include "stackvma-rofile.c"
+
+#if HAVE_MINCORE
+# define sigsegv_get_vma mincore_get_vma
+# define STATIC static
+# include "stackvma-mincore.c"
+# undef sigsegv_get_vma
+#endif
+
+int
+sigsegv_get_vma (unsigned long address, struct vma_struct *vma)
+{
+ struct rofile rof;
+ int c;
+ unsigned long start, end;
+#if STACK_DIRECTION < 0
+ unsigned long prev;
+#endif
+
+ /* Open the current process' maps file. It describes one VMA per line. */
+ if (rof_open (&rof, "/proc/self/maps") < 0)
+ goto failed;
+
+#if STACK_DIRECTION < 0
+ prev = 0;
+#endif
+ for (;;)
+ {
+ if (!(rof_scanf_lx (&rof, &start) >= 0
+ && rof_getchar (&rof) == '-'
+ && rof_scanf_lx (&rof, &end) >= 0))
+ break;
+ while (c = rof_getchar (&rof), c != -1 && c != '\n')
+ continue;
+ if (address >= start && address <= end - 1)
+ {
+ vma->start = start;
+ vma->end = end;
+#if STACK_DIRECTION < 0
+ vma->prev_end = prev;
+#else
+ if (!(rof_scanf_lx (&rof, &vma->next_start) >= 0
+ && rof_getchar (&rof) == '-'
+ && rof_scanf_lx (&rof, &end) >= 0))
+ vma->next_start = 0;
+#endif
+ rof_close (&rof);
+ vma->is_near_this = simple_is_near_this;
+ return 0;
+ }
+#if STACK_DIRECTION < 0
+ prev = end;
+#endif
+ }
+ rof_close (&rof);
+ failed:
+#if HAVE_MINCORE
+ return mincore_get_vma (address, vma);
+#else
+ return -1;
+#endif
+}
diff --git a/libsigsegv/src/stackvma-mach.c b/libsigsegv/src/stackvma-mach.c
new file mode 100644
index 00000000..ae309a60
--- /dev/null
+++ b/libsigsegv/src/stackvma-mach.c
@@ -0,0 +1,119 @@
+/* Determine the virtual memory area of a given address. Mach version.
+ Copyright (C) 2003, 2006 Paolo Bonzini <bonzini@gnu.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "stackvma.h"
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <libc.h>
+#include <nlist.h>
+#include <mach/mach.h>
+#ifndef NeXT
+#include <mach/machine/vm_param.h>
+#endif
+
+#include "stackvma-simple.c"
+
+int
+sigsegv_get_vma (unsigned long req_address, struct vma_struct *vma)
+{
+ unsigned long prev_address = 0, prev_size = 0;
+ unsigned long join_address = 0, join_size = 0;
+ int more = 1;
+ vm_address_t address;
+ vm_size_t size;
+ mach_port_t object_name;
+#ifdef VM_REGION_BASIC_INFO
+ task_t task = mach_task_self ();
+ struct vm_region_basic_info info;
+ mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
+#else
+ task_t task = task_self ();
+ vm_prot_t protection, max_protection;
+ vm_inherit_t inheritance;
+ boolean_t shared;
+ vm_offset_t offset;
+#endif
+
+ for (address = VM_MIN_ADDRESS; more; address += size)
+ {
+#ifdef VM_REGION_BASIC_INFO
+ more = (vm_region (task, &address, &size, VM_REGION_BASIC_INFO,
+ (vm_region_info_t)&info, &info_count, &object_name)
+ == KERN_SUCCESS);
+#else
+ more = (vm_region (task, &address, &size, &protection, &max_protection,
+ &inheritance, &shared, &object_name, &offset)
+ == KERN_SUCCESS);
+#endif
+ if (!more)
+ {
+ address = join_address + join_size;
+ size = 0;
+ }
+
+ if ((unsigned long) address == join_address + join_size)
+ join_size += size;
+ else
+ {
+ prev_address = join_address;
+ prev_size = join_size;
+ join_address = (unsigned long) address;
+ join_size = size;
+ }
+
+#ifdef VM_REGION_BASIC_INFO
+ if (object_name != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), object_name);
+ info_count = VM_REGION_BASIC_INFO_COUNT;
+#endif
+
+#if STACK_DIRECTION < 0
+ if (join_address <= req_address && join_address + join_size > req_address)
+ {
+ vma->start = join_address;
+ vma->end = join_address + join_size;
+ vma->prev_end = prev_address + prev_size;
+ vma->is_near_this = simple_is_near_this;
+ return 0;
+ }
+#else
+ if (prev_address <= req_address && prev_address + prev_size > req_address)
+ {
+ vma->start = prev_address;
+ vma->end = prev_address + prev_size;
+ vma->next_start = join_address;
+ vma->is_near_this = simple_is_near_this;
+ return 0;
+ }
+#endif
+ }
+
+#if STACK_DIRECTION > 0
+ if (join_address <= req_address && join_address + size > req_address)
+ {
+ vma->start = prev_address;
+ vma->end = prev_address + prev_size;
+ vma->next_start = ~0UL;
+ vma->is_near_this = simple_is_near_this;
+ return 0;
+ }
+#endif
+
+ return -1;
+}
diff --git a/libsigsegv/src/stackvma-mincore.c b/libsigsegv/src/stackvma-mincore.c
new file mode 100644
index 00000000..1b51ef23
--- /dev/null
+++ b/libsigsegv/src/stackvma-mincore.c
@@ -0,0 +1,275 @@
+/* Determine the virtual memory area of a given address.
+ Copyright (C) 2006, 2008 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* mincore() is a system call that allows to inquire the status of a
+ range of pages of virtual memory. In particular, it allows to inquire
+ whether a page is mapped at all.
+ As of 2006, mincore() is supported by: possible bits:
+ - Linux, since Linux 2.4 and glibc 2.2, 1
+ - Solaris, since Solaris 9, 1
+ - MacOS X, since MacOS X 10.3 (at least), 1
+ - FreeBSD, since FreeBSD 6.0, MINCORE_{INCORE,REFERENCED,MODIFIED}
+ - NetBSD, since NetBSD 3.0 (at least), 1
+ - OpenBSD, since OpenBSD 2.6 (at least), 1
+ However, while the API allows to easily determine the bounds of mapped
+ virtual memory, it does not make it easy the bounds of _unmapped_ virtual
+ memory ranges. We try to work around this, but it may still be slow. */
+
+#include "stackvma.h"
+#include <limits.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/mman.h>
+
+/* Cache for getpagesize(). */
+static unsigned long pagesize;
+
+/* Initialize pagesize. */
+static void
+init_pagesize (void)
+{
+#if HAVE_GETPAGESIZE
+ pagesize = getpagesize ();
+#elif HAVE_SYSCONF_PAGESIZE
+ pagesize = sysconf (_SC_PAGESIZE);
+#else
+ pagesize = PAGESIZE;
+#endif
+}
+
+/* Test whether the page starting at ADDR is among the address range.
+ ADDR must be a multiple of pagesize. */
+static int
+is_mapped (unsigned long addr)
+{
+ char vec[1];
+ return mincore ((void *) addr, pagesize, vec) >= 0;
+}
+
+/* Assuming that the page starting at ADDR is among the address range,
+ return the start of its virtual memory range.
+ ADDR must be a multiple of pagesize. */
+static unsigned long
+mapped_range_start (unsigned long addr)
+{
+ /* Use a moderately sized VEC here, small enough that it fits on the stack
+ (without requiring malloc). */
+ char vec[2048];
+ unsigned long stepsize = sizeof (vec);
+
+ for (;;)
+ {
+ unsigned long max_remaining;
+
+ if (addr == 0)
+ return addr;
+
+ max_remaining = addr / pagesize;
+ if (stepsize > max_remaining)
+ stepsize = max_remaining;
+ if (mincore ((void *) (addr - stepsize * pagesize),
+ stepsize * pagesize, vec) < 0)
+ /* Time to search in smaller steps. */
+ break;
+ /* The entire range exists. Continue searching in large steps. */
+ addr -= stepsize * pagesize;
+ }
+ for (;;)
+ {
+ unsigned long halfstepsize1;
+ unsigned long halfstepsize2;
+
+ if (stepsize == 1)
+ return addr;
+
+ /* Here we know that less than stepsize pages exist starting at addr. */
+ halfstepsize1 = (stepsize + 1) / 2;
+ halfstepsize2 = stepsize / 2;
+ /* halfstepsize1 + halfstepsize2 = stepsize. */
+
+ if (mincore ((void *) (addr - halfstepsize1 * pagesize),
+ halfstepsize1 * pagesize, vec) < 0)
+ stepsize = halfstepsize1;
+ else
+ {
+ addr -= halfstepsize1 * pagesize;
+ stepsize = halfstepsize2;
+ }
+ }
+}
+
+/* Assuming that the page starting at ADDR is among the address range,
+ return the end of its virtual memory range + 1.
+ ADDR must be a multiple of pagesize. */
+static unsigned long
+mapped_range_end (unsigned long addr)
+{
+ /* Use a moderately sized VEC here, small enough that it fits on the stack
+ (without requiring malloc). */
+ char vec[2048];
+ unsigned long stepsize = sizeof (vec);
+
+ addr += pagesize;
+ for (;;)
+ {
+ unsigned long max_remaining;
+
+ if (addr == 0) /* wrapped around? */
+ return addr;
+
+ max_remaining = (- addr) / pagesize;
+ if (stepsize > max_remaining)
+ stepsize = max_remaining;
+ if (mincore ((void *) addr, stepsize * pagesize, vec) < 0)
+ /* Time to search in smaller steps. */
+ break;
+ /* The entire range exists. Continue searching in large steps. */
+ addr += stepsize * pagesize;
+ }
+ for (;;)
+ {
+ unsigned long halfstepsize1;
+ unsigned long halfstepsize2;
+
+ if (stepsize == 1)
+ return addr;
+
+ /* Here we know that less than stepsize pages exist starting at addr. */
+ halfstepsize1 = (stepsize + 1) / 2;
+ halfstepsize2 = stepsize / 2;
+ /* halfstepsize1 + halfstepsize2 = stepsize. */
+
+ if (mincore ((void *) addr, halfstepsize1 * pagesize, vec) < 0)
+ stepsize = halfstepsize1;
+ else
+ {
+ addr += halfstepsize1 * pagesize;
+ stepsize = halfstepsize2;
+ }
+ }
+}
+
+/* Determine whether an address range [ADDR1..ADDR2] is completely unmapped.
+ ADDR1 must be <= ADDR2. */
+static int
+is_unmapped (unsigned long addr1, unsigned long addr2)
+{
+ unsigned long count;
+ unsigned long stepsize;
+
+ /* Round addr1 down. */
+ addr1 = (addr1 / pagesize) * pagesize;
+ /* Round addr2 up and turn it into an exclusive bound. */
+ addr2 = ((addr2 / pagesize) + 1) * pagesize;
+
+ /* This is slow: mincore() does not provide a way to determine the bounds
+ of the gaps directly. So we have to use mincore() on individual pages
+ over and over again. Only after we've verified that all pages are
+ unmapped, we know that the range is completely unmapped.
+ If we were to traverse the pages from bottom to top or from top to bottom,
+ it would be slow even in the average case. To speed up the search, we
+ exploit the fact that mapped memory ranges are larger than one page on
+ average, therefore we have good chances of hitting a mapped area if we
+ traverse only every second, or only fourth page, etc. This doesn't
+ decrease the worst-case runtime, only the average runtime. */
+ count = (addr2 - addr1) / pagesize;
+ /* We have to test is_mapped (addr1 + i * pagesize) for 0 <= i < count. */
+ for (stepsize = 1; stepsize < count; )
+ stepsize = 2 * stepsize;
+ for (;;)
+ {
+ unsigned long addr_stepsize;
+ unsigned long i;
+ unsigned long addr;
+
+ stepsize = stepsize / 2;
+ if (stepsize == 0)
+ break;
+ addr_stepsize = stepsize * pagesize;
+ for (i = stepsize, addr = addr1 + addr_stepsize;
+ i < count;
+ i += 2 * stepsize, addr += 2 * addr_stepsize)
+ /* Here addr = addr1 + i * pagesize. */
+ if (is_mapped (addr))
+ return 0;
+ }
+ return 1;
+}
+
+#if STACK_DIRECTION < 0
+
+/* Info about the gap between this VMA and the previous one.
+ addr must be < vma->start. */
+static int
+mincore_is_near_this (unsigned long addr, struct vma_struct *vma)
+{
+ /* vma->start - addr <= (vma->start - vma->prev_end) / 2
+ is mathematically equivalent to
+ vma->prev_end <= 2 * addr - vma->start
+ <==> is_unmapped (2 * addr - vma->start, vma->start - 1).
+ But be careful about overflow: if 2 * addr - vma->start is negative,
+ we consider a tiny "guard page" mapping [0, 0] to be present around
+ NULL; it intersects the range (2 * addr - vma->start, vma->start - 1),
+ therefore return false. */
+ unsigned long testaddr = addr - (vma->start - addr);
+ if (testaddr > addr) /* overflow? */
+ return 0;
+ /* Here testaddr <= addr < vma->start. */
+ return is_unmapped (testaddr, vma->start - 1);
+}
+
+#endif
+#if STACK_DIRECTION > 0
+
+/* Info about the gap between this VMA and the next one.
+ addr must be > vma->end - 1. */
+static int
+mincore_is_near_this (unsigned long addr, struct vma_struct *vma)
+{
+ /* addr - vma->end < (vma->next_start - vma->end) / 2
+ is mathematically equivalent to
+ vma->next_start > 2 * addr - vma->end
+ <==> is_unmapped (vma->end, 2 * addr - vma->end).
+ But be careful about overflow: if 2 * addr - vma->end is > ~0UL,
+ we consider a tiny "guard page" mapping [0, 0] to be present around
+ NULL; it intersects the range (vma->end, 2 * addr - vma->end),
+ therefore return false. */
+ unsigned long testaddr = addr + (addr - vma->end);
+ if (testaddr < addr) /* overflow? */
+ return 0;
+ /* Here vma->end - 1 < addr <= testaddr. */
+ return is_unmapped (vma->end, testaddr);
+}
+
+#endif
+
+#ifdef STATIC
+STATIC
+#endif
+int
+sigsegv_get_vma (unsigned long address, struct vma_struct *vma)
+{
+ if (pagesize == 0)
+ init_pagesize ();
+ address = (address / pagesize) * pagesize;
+ vma->start = mapped_range_start (address);
+ vma->end = mapped_range_end (address);
+ vma->is_near_this = mincore_is_near_this;
+ return 0;
+}
diff --git a/libsigsegv/src/stackvma-none.c b/libsigsegv/src/stackvma-none.c
new file mode 100644
index 00000000..3ffeb8e3
--- /dev/null
+++ b/libsigsegv/src/stackvma-none.c
@@ -0,0 +1,25 @@
+/* Determine the virtual memory area of a given address.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "stackvma.h"
+
+int
+sigsegv_get_vma (unsigned long address, struct vma_struct *vma)
+{
+ /* No way. */
+ return -1;
+}
diff --git a/libsigsegv/src/stackvma-procfs.c b/libsigsegv/src/stackvma-procfs.c
new file mode 100644
index 00000000..24c90a1a
--- /dev/null
+++ b/libsigsegv/src/stackvma-procfs.c
@@ -0,0 +1,188 @@
+/* Determine the virtual memory area of a given address.
+ Copyright (C) 2002, 2006, 2008 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "stackvma.h"
+#include <unistd.h> /* open, close */
+#include <fcntl.h> /* open */
+#include <sys/types.h>
+#include <sys/mman.h> /* mmap, munmap */
+#include <sys/procfs.h> /* PIOC*, prmap_t */
+
+#include "stackvma-simple.c"
+
+#if HAVE_MINCORE
+# define sigsegv_get_vma mincore_get_vma
+# define STATIC static
+# include "stackvma-mincore.c"
+# undef sigsegv_get_vma
+#else
+/* Cache for getpagesize(). */
+static unsigned long pagesize;
+/* Initialize pagesize. */
+static void
+init_pagesize (void)
+{
+ pagesize = getpagesize ();
+}
+#endif
+
+int
+sigsegv_get_vma (unsigned long address, struct vma_struct *vma)
+{
+ char fnamebuf[6+10+1];
+ char *fname;
+ int fd;
+ int nmaps;
+ size_t memneed;
+#if HAVE_MMAP_ANON
+# define zero_fd -1
+# define map_flags MAP_ANON
+#elif HAVE_MMAP_ANONYMOUS
+# define zero_fd -1
+# define map_flags MAP_ANONYMOUS
+#else
+ int zero_fd;
+# define map_flags 0
+#endif
+ void *auxmap;
+ unsigned long auxmap_start;
+ unsigned long auxmap_end;
+ prmap_t* maps;
+ prmap_t* mp;
+ unsigned long start, end;
+#if STACK_DIRECTION < 0
+ unsigned long prev;
+#endif
+
+ if (pagesize == 0)
+ init_pagesize ();
+
+ /* Construct fname = sprintf (fnamebuf+i, "/proc/%u", getpid ()). */
+ fname = fnamebuf + sizeof (fnamebuf) - 1;
+ *fname = '\0';
+ {
+ unsigned int value = getpid ();
+ do
+ *--fname = (value % 10) + '0';
+ while ((value = value / 10) > 0);
+ }
+ fname -= 6;
+ memcpy (fname, "/proc/", 6);
+
+ fd = open (fname, O_RDONLY);
+ if (fd < 0)
+ goto failed;
+
+ if (ioctl (fd, PIOCNMAP, &nmaps) < 0)
+ goto fail2;
+
+ memneed = (nmaps + 10) * sizeof (prmap_t);
+ /* Allocate memneed bytes of memory.
+ We cannot use alloca here, because we are low on stack space.
+ We also cannot use malloc here, because a malloc() call may have been
+ interrupted.
+ So use mmap(), and ignore the resulting VMA. */
+ memneed = ((memneed - 1) / pagesize + 1) * pagesize;
+#if !(HAVE_MMAP_ANON || HAVE_MMAP_ANONYMOUS)
+ zero_fd = open ("/dev/zero", O_RDONLY, 0644);
+ if (zero_fd < 0)
+ goto fail2;
+#endif
+ auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE, map_flags | MAP_PRIVATE, zero_fd, 0);
+#if !(HAVE_MMAP_ANON || HAVE_MMAP_ANONYMOUS)
+ close (zero_fd);
+#endif
+ if (auxmap == (void *) -1)
+ goto fail2;
+ auxmap_start = (unsigned long) auxmap;
+ auxmap_end = auxmap_start + memneed;
+ maps = (prmap_t *) auxmap;
+
+ if (ioctl (fd, PIOCMAP, maps) < 0)
+ goto fail1;
+
+#if STACK_DIRECTION < 0
+ prev = 0;
+#endif
+ for (mp = maps;;)
+ {
+ start = (unsigned long) mp->pr_vaddr;
+ end = start + mp->pr_size;
+ if (start == 0 && end == 0)
+ break;
+ mp++;
+ if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
+ {
+ /* Consider [start,end-1] \ [auxmap_start,auxmap_end-1]
+ = [start,auxmap_start-1] u [auxmap_end,end-1]. */
+ if (start != auxmap_start)
+ {
+ if (address >= start && address <= auxmap_start - 1)
+ {
+ end = auxmap_start;
+ goto found;
+ }
+#if STACK_DIRECTION < 0
+ prev = auxmap_start;
+#endif
+ }
+ if (end != auxmap_end)
+ {
+ if (address >= auxmap_end && address <= end - 1)
+ {
+ start = auxmap_end;
+ goto found;
+ }
+#if STACK_DIRECTION < 0
+ prev = end;
+#endif
+ }
+ }
+ else
+ {
+ if (address >= start && address <= end - 1)
+ goto found;
+#if STACK_DIRECTION < 0
+ prev = end;
+#endif
+ }
+ }
+
+ fail1:
+ munmap (auxmap, memneed);
+ fail2:
+ close (fd);
+ failed:
+#if HAVE_MINCORE
+ return mincore_get_vma (address, vma);
+#else
+ return -1;
+#endif
+
+ found:
+ vma->start = start;
+ vma->end = end;
+#if STACK_DIRECTION < 0
+ vma->prev_end = prev;
+#else
+ vma->next_start = (unsigned long) mp->pr_vaddr;
+#endif
+ munmap (auxmap, memneed);
+ close (fd);
+ vma->is_near_this = simple_is_near_this;
+ return 0;
+}
diff --git a/libsigsegv/src/stackvma-rofile.c b/libsigsegv/src/stackvma-rofile.c
new file mode 100644
index 00000000..d6d19394
--- /dev/null
+++ b/libsigsegv/src/stackvma-rofile.c
@@ -0,0 +1,121 @@
+/* Buffered read-only streams.
+ Copyright (C) 2008 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <errno.h> /* errno, EINTR */
+#include <fcntl.h> /* O_RDONLY */
+#include <stddef.h> /* size_t */
+#include <unistd.h> /* read, close */
+
+/* Buffered read-only streams.
+ We cannot use <stdio.h> here, because fopen() calls malloc(), and a malloc()
+ call may have been interrupted. */
+
+struct rofile
+ {
+ int fd;
+ size_t position;
+ size_t filled;
+ int eof_seen;
+ char buffer[4096];
+ };
+
+/* Open a read-only file stream. */
+static int
+rof_open (struct rofile *rof, const char *filename)
+{
+ int fd = open (filename, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ rof->fd = fd;
+ rof->position = 0;
+ rof->filled = 0;
+ rof->eof_seen = 0;
+ return 0;
+}
+
+/* Return the next byte from a read-only file stream without consuming it,
+ or -1 at EOF. */
+static int
+rof_peekchar (struct rofile *rof)
+{
+ if (rof->position == rof->filled)
+ {
+ if (rof->eof_seen)
+ return -1;
+ else
+ for (;;)
+ {
+ int n = read (rof->fd, rof->buffer, sizeof (rof->buffer));
+#ifdef EINTR
+ if (n < 0 && errno == EINTR)
+ continue;
+#endif
+ if (n <= 0)
+ {
+ rof->eof_seen = 1;
+ return -1;
+ }
+ rof->filled = n;
+ rof->position = 0;
+ break;
+ }
+ }
+ return (unsigned char) rof->buffer[rof->position];
+}
+
+/* Return the next byte from a read-only file stream, or -1 at EOF. */
+static int
+rof_getchar (struct rofile *rof)
+{
+ int c = rof_peekchar (rof);
+ if (c >= 0)
+ rof->position++;
+ return c;
+}
+
+/* Parse an unsigned hexadecimal number from a read-only file stream. */
+static int
+rof_scanf_lx (struct rofile *rof, unsigned long *valuep)
+{
+ unsigned long value = 0;
+ unsigned int numdigits = 0;
+ for (;;)
+ {
+ int c = rof_peekchar (rof);
+ if (c >= '0' && c <= '9')
+ value = (value << 4) + (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ value = (value << 4) + (c - 'A' + 10);
+ else if (c >= 'a' && c <= 'f')
+ value = (value << 4) + (c - 'a' + 10);
+ else
+ break;
+ rof_getchar (rof);
+ numdigits++;
+ }
+ if (numdigits == 0)
+ return -1;
+ *valuep = value;
+ return 0;
+}
+
+/* Close a read-only file stream. */
+static void
+rof_close (struct rofile *rof)
+{
+ close (rof->fd);
+}
diff --git a/libsigsegv/src/stackvma-simple.c b/libsigsegv/src/stackvma-simple.c
new file mode 100644
index 00000000..3e800373
--- /dev/null
+++ b/libsigsegv/src/stackvma-simple.c
@@ -0,0 +1,42 @@
+/* Determine the virtual memory area of a given address.
+ Copyright (C) 2006 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* This file contains the proximity test function for the simple cases, where
+ the OS has an API for enumerating the mapped ranges of virtual memory. */
+
+#if STACK_DIRECTION < 0
+
+/* Info about the gap between this VMA and the previous one.
+ addr must be < vma->start. */
+static int
+simple_is_near_this (unsigned long addr, struct vma_struct *vma)
+{
+ return (vma->start - addr <= (vma->start - vma->prev_end) / 2);
+}
+
+#endif
+#if STACK_DIRECTION > 0
+
+/* Info about the gap between this VMA and the next one.
+ addr must be > vma->end - 1. */
+static int
+simple_is_near_this (unsigned long addr, struct vma_struct *vma)
+{
+ return (addr - vma->end < (vma->next_start - vma->end) / 2);
+}
+
+#endif
diff --git a/libsigsegv/src/stackvma.c b/libsigsegv/src/stackvma.c
new file mode 100644
index 00000000..17fd8e51
--- /dev/null
+++ b/libsigsegv/src/stackvma.c
@@ -0,0 +1,20 @@
+/* Determine the virtual memory area of a given address.
+ Copyright (C) 2002 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+
+#include CFG_STACKVMA
diff --git a/libsigsegv/src/stackvma.h b/libsigsegv/src/stackvma.h
new file mode 100644
index 00000000..cc475d51
--- /dev/null
+++ b/libsigsegv/src/stackvma.h
@@ -0,0 +1,48 @@
+/* Determine the virtual memory area of a given address.
+ Copyright (C) 2002, 2006 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _STACKVMA_H
+#define _STACKVMA_H
+
+/* Describes a virtual memory area, with some info about the gap between
+ it and the next or previous virtual memory area. */
+struct vma_struct
+{
+ unsigned long start;
+ unsigned long end;
+#if STACK_DIRECTION < 0
+ /* Info about the gap between this VMA and the previous one.
+ addr must be < vma->start. */
+ int (*is_near_this) (unsigned long addr, struct vma_struct *vma);
+ /* Private field, not provided by all sigsegv_get_vma implementations. */
+ unsigned long prev_end;
+#endif
+#if STACK_DIRECTION > 0
+ /* Info about the gap between this VMA and the next one.
+ addr must be > vma->end - 1. */
+ int (*is_near_this) (unsigned long addr, struct vma_struct *vma);
+ /* Private field, not provided by all sigsegv_get_vma implementations. */
+ unsigned long next_start;
+#endif
+};
+
+/* Determines the virtual memory area to which a given address belongs,
+ and returns 0. Returns -1 if it cannot be determined.
+ This function is used to determine the stack extent when a fault occurs. */
+extern int sigsegv_get_vma (unsigned long address, struct vma_struct *vma);
+
+#endif /* _STACKVMA_H */
diff --git a/libsigsegv/src/version.c b/libsigsegv/src/version.c
new file mode 100644
index 00000000..80bffce2
--- /dev/null
+++ b/libsigsegv/src/version.c
@@ -0,0 +1,20 @@
+/* Version number.
+ Copyright (C) 2005 Bruno Haible <bruno@clisp.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include "sigsegv.h"
+
+int libsigsegv_version = LIBSIGSEGV_VERSION;