sigsegv on s390 only giving start address of page in segv handler
Bruno Haible
bruno at clisp.org
Sun Mar 13 11:18:35 UTC 2011
Hi Christoph,
> I guess it's
> preferred to just accepting a inexact address? Considering how to best
> build a fixed package. The 2 patches I'd consider attached. I'd prefer
> the first one at the moment.
> ...
> Now I'm wondering of software depending on libsigsegv won't work on s390
> or maybe the correct page is still enough information for dependencies
> like clisp to work
Looking at clisp's fault handler: In the usual case (SPVW_PURE_BLOCKS)
the fault handler will accept a page-aligned fault address just as well, and
likely the same in the other case, due to the way the bounds of the memory
areas are initialized.
In smalltalk as well, the handler uses only the page-aligned fault address.
In gawk and m4, the fault address is not used at all in the handler.
I guess that it's the same for other software that uses libsigsegv.
So I'm applying this patch. Find in
http://www.haible.de/bruno/gnu/libsigsegv-2.10-pre1.tar.gz
a new prerelease. Can you please test how it works on a Linux/S390 system,
and whether clisp then builds and runs fine?
Bruno
2011-03-13 Bruno Haible <bruno at clisp.org>
Support for Linux/S390.
* m4/fault.m4 (SV_TRY_FAULT): Define
SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS. On Linux/S390 systems, expect a
page-aligned fault address.
* src/sigsegv.h.in (SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS): New macro.
(sigsegv_register): Mention constraint about address and len arguments.
* tests/sigsegv1.c (handler): On Linux/S390 systems, expect a
page-aligned fault address.
* tests/sigsegv3.c (handler): Likewise.
* tests/sigsegv2.c: Add comment.
* NEWS: Document the change.
Reported by Christoph Egger <christoph at debian.org>.
diff --git a/NEWS b/NEWS
index 35ed934..9820c90 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,12 @@
New in 2.10:
+* Support for Linux/S390.
+ <sigsegv.h> now defines a macro SIGSEGV_FAULT_ADDRESS_ALIGNMENT.
+ It is either 1 or pagesize. Its meaning is that
+ - The fault address passed to a SIGSEGV handler has rounded down to a
+ multiple of SIGSEGV_FAULT_ADDRESS_ALIGNMENT.
+ - The address and length arguments of sigsegv_register function calls
+ must be multiples of SIGSEGV_FAULT_ADDRESS_ALIGNMENT.
* Faster distinction between stack overflow and other fault on OpenBSD.
New in 2.9:
diff --git a/m4/fault.m4 b/m4/fault.m4
index 2dd89f8..2a2d72b 100644
--- a/m4/fault.m4
+++ b/m4/fault.m4
@@ -1,5 +1,5 @@
-# fault.m4 serial 5 (libsigsegv-2.2)
-dnl Copyright (C) 2002-2003 Bruno Haible <bruno at clisp.org>
+# fault.m4 serial 6 (libsigsegv-2.10)
+dnl Copyright (C) 2002-2003, 2011 Bruno Haible <bruno at clisp.org>
dnl This file is free software, distributed under the terms of the GNU
dnl General Public License. As a special exception to the GNU General
dnl Public License, this file may be distributed as part of a program
@@ -43,6 +43,11 @@ $4
static int zero_fd;
# define map_flags MAP_FILE | MAP_PRIVATE
#endif
+#if defined __linux__ && (defined __s390__ || defined __s390x__)
+# define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS (0x1000UL - 1)
+#else
+# define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS 0UL
+#endif
unsigned long page;
int handler_called = 0;
void sigsegv_handler ($5)
@@ -51,7 +56,8 @@ void sigsegv_handler ($5)
handler_called++;
if (handler_called == 10)
exit (4);
- if (fault_address != (void*)(page + 0x678))
+ if (fault_address
+ != (void*)((page + 0x678) & ~SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS))
exit (3);
if (mprotect ((void *) page, 0x10000, PROT_READ | PROT_WRITE) < 0)
exit (2);
diff --git a/src/sigsegv.h.in b/src/sigsegv.h.in
index a21f6a0..5254641 100644
--- a/src/sigsegv.h.in
+++ b/src/sigsegv.h.in
@@ -1,5 +1,5 @@
/* Page fault handling library.
- Copyright (C) 1998-1999, 2002, 2004-2010 Bruno Haible <bruno at clisp.org>
+ Copyright (C) 1998-1999, 2002, 2004-2011 Bruno Haible <bruno at 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
@@ -43,8 +43,22 @@ extern int libsigsegv_version; /* Likewise */
/* -------------------------------------------------------------------------- */
/*
+ * The mask of bits that are set to zero in a fault address that gets passed
+ * to a global SIGSEGV handler.
+ * On some platforms, the precise fault address is not known, only the memory
+ * page into which the fault address falls. On these platforms,
+ * SIGSEGV_FAULT_ADDRESS_ALIGNMENT is greater than 1.
+ */
+#if defined __linux__ && (defined __s390__ || defined __s390x__)
+# define SIGSEGV_FAULT_ADDRESS_ALIGNMENT 0x1000UL
+#else
+# define SIGSEGV_FAULT_ADDRESS_ALIGNMENT 1UL
+#endif
+
+/*
* The type of a global SIGSEGV handler.
- * The fault address is passed as argument.
+ * The fault address, with the bits (SIGSEGV_FAULT_ADDRESS_ALIGNMENT - 1)
+ * cleared, 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,
@@ -176,6 +190,8 @@ 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].
+ * The address and len arguments must be multiples of
+ * SIGSEGV_FAULT_ADDRESS_ALIGNMENT.
* Returns a "ticket" that can be used to remove the handler later.
*/
extern void* sigsegv_register (sigsegv_dispatcher* dispatcher,
diff --git a/tests/sigsegv1.c b/tests/sigsegv1.c
index ce00642..e59018b 100644
--- a/tests/sigsegv1.c
+++ b/tests/sigsegv1.c
@@ -1,5 +1,5 @@
/* Test that the handler is called, with the right fault address.
- Copyright (C) 2002-2006, 2008 Bruno Haible <bruno at clisp.org>
+ Copyright (C) 2002-2006, 2008, 2011 Bruno Haible <bruno at 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
@@ -37,7 +37,8 @@ handler (void *fault_address, int serious)
handler_called++;
if (handler_called > 10)
abort ();
- if (fault_address != (void *)(page + 0x678))
+ if (fault_address
+ != (void *)((page + 0x678) & ~(SIGSEGV_FAULT_ADDRESS_ALIGNMENT - 1)))
abort ();
if (mprotect ((void *) page, 0x4000, PROT_READ_WRITE) == 0)
return 1;
diff --git a/tests/sigsegv2.c b/tests/sigsegv2.c
index 39961a6..775a56a 100644
--- a/tests/sigsegv2.c
+++ b/tests/sigsegv2.c
@@ -1,5 +1,5 @@
/* Test the dispatcher.
- Copyright (C) 2002-2006, 2008 Bruno Haible <bruno at clisp.org>
+ Copyright (C) 2002-2006, 2008, 2011 Bruno Haible <bruno at 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
@@ -32,6 +32,10 @@ static sigsegv_dispatcher dispatcher;
static volatile unsigned int logcount = 0;
static volatile unsigned long logdata[10];
+/* Note about SIGSEGV_FAULT_ADDRESS_ALIGNMENT: It does not matter whether
+ fault_address is rounded off here because all intervals that we pass to
+ sigsegv_register are page-aligned. */
+
static int
area_handler (void *fault_address, void *user_arg)
{
diff --git a/tests/sigsegv3.c b/tests/sigsegv3.c
index 1ea0ec4..397e356 100644
--- a/tests/sigsegv3.c
+++ b/tests/sigsegv3.c
@@ -1,5 +1,5 @@
/* Test that the handler can be exited multiple times.
- Copyright (C) 2002-2006, 2008 Bruno Haible <bruno at clisp.org>
+ Copyright (C) 2002-2006, 2008, 2011 Bruno Haible <bruno at 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
@@ -56,7 +56,8 @@ handler (void *fault_address, int serious)
handler_called++;
if (handler_called > 10)
abort ();
- if (fault_address != (void *)(page + 0x678 + 8 * pass))
+ if (fault_address != (void *)((page + 0x678 + 8 * pass)
+ & ~(SIGSEGV_FAULT_ADDRESS_ALIGNMENT - 1)))
abort ();
pass++;
printf ("Stack overflow %d caught.\n", pass);
--
In memoriam Odette Sansom <http://en.wikipedia.org/wiki/Odette_Hallowes>
More information about the pkg-common-lisp-devel
mailing list