]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix an assertion in the address space manager. BZ #345887.
authorFlorian Krohm <florian@eich-krohm.de>
Thu, 23 Apr 2015 15:20:00 +0000 (15:20 +0000)
committerFlorian Krohm <florian@eich-krohm.de>
Thu, 23 Apr 2015 15:20:00 +0000 (15:20 +0000)
The VG_(extend_stack) call needs to be properly guarded because the
passed-in address is not necessarily part of an extensible stack
segment. And an extensible stack segment is the only thing that
function should have to deal with.
Previously, the function VG_(am_addr_is_in_extensible_client_stack)
was introduced to guard VG_(extend_stack) but it was not added in all
places it should have been.

Also, extending the client stack during signal delivery (in sigframe-common.c)
was simply calling VG_(extend_stack) hoping it would do the right thing.
But that was not always the case. The new testcase
none/tests/linux/pthread-stack.c exercises this (3.10.1 errors out on it).

Renamed ML_(sf_extend_stack) to ML_(sf_maybe_extend_stack) and add
proper guard logic for VG_(extend_stack).

Testcases none/tests/{amd64|x86}-linux/bug345887.c by Ivo Raisr.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15138

33 files changed:
NEWS
configure.ac
coregrind/m_sigframe/priv_sigframe.h
coregrind/m_sigframe/sigframe-amd64-darwin.c
coregrind/m_sigframe/sigframe-amd64-linux.c
coregrind/m_sigframe/sigframe-arm-linux.c
coregrind/m_sigframe/sigframe-arm64-linux.c
coregrind/m_sigframe/sigframe-common.c
coregrind/m_sigframe/sigframe-mips32-linux.c
coregrind/m_sigframe/sigframe-mips64-linux.c
coregrind/m_sigframe/sigframe-ppc32-linux.c
coregrind/m_sigframe/sigframe-ppc64-linux.c
coregrind/m_sigframe/sigframe-s390x-linux.c
coregrind/m_sigframe/sigframe-tilegx-linux.c
coregrind/m_sigframe/sigframe-x86-darwin.c
coregrind/m_sigframe/sigframe-x86-linux.c
coregrind/m_signals.c
none/tests/Makefile.am
none/tests/amd64-linux/Makefile.am [new file with mode: 0644]
none/tests/amd64-linux/bug345887.c [new file with mode: 0644]
none/tests/amd64-linux/bug345887.stderr.exp [new file with mode: 0644]
none/tests/amd64-linux/bug345887.vgtest [new file with mode: 0644]
none/tests/amd64-linux/filter_minimal [new file with mode: 0755]
none/tests/amd64-linux/filter_stderr [new file with mode: 0755]
none/tests/linux/Makefile.am
none/tests/linux/pthread-stack.c [new file with mode: 0644]
none/tests/linux/pthread-stack.stderr.exp [new file with mode: 0644]
none/tests/linux/pthread-stack.vgtest [new file with mode: 0644]
none/tests/x86-linux/Makefile.am
none/tests/x86-linux/bug345887.c [new file with mode: 0644]
none/tests/x86-linux/bug345887.stderr.exp [new file with mode: 0644]
none/tests/x86-linux/bug345887.vgtest [new file with mode: 0644]
none/tests/x86-linux/filter_minimal [new file with mode: 0755]

diff --git a/NEWS b/NEWS
index 9fdc7952509be91dabc38b495dc6b46bb48947fe..2a61168449ee81a0ec883df7f15cb4f21fadcf6a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -151,6 +151,7 @@ where XXXXXX is the bug number as listed below.
 345016  helgrind/tests/locked_vs_unlocked2 is failing sometimes
 345394  Fix memcheck/tests/strchr on OS X
 345637  Fix memcheck/tests/sendmsg on OS X
+345887  Fix an assertion in the address space manager
 346307  fuse filesystem syscall deadlocks
 n-i-bz  Provide implementations of certain compiler builtins to support
         compilers who may not provide those
index a5aa96403f590a3e31f2528692492ef150294d99..d03aa5c0c4e7fc045b826523d4106d84fdbca145 100644 (file)
@@ -3033,6 +3033,7 @@ AC_CONFIG_FILES([
    none/tests/tilegx/Makefile
    none/tests/linux/Makefile
    none/tests/darwin/Makefile
+   none/tests/amd64-linux/Makefile
    none/tests/x86-linux/Makefile
    exp-sgcheck/Makefile
    exp-sgcheck/tests/Makefile
index a81f4d005a7e8f13d84b9a8abdf3899b96630a00..74351852ee3c57c7bd8fab98f853d9c0f0e9ca8d 100644 (file)
@@ -37,7 +37,8 @@
 
 /* --------------- Implemented in sigframe-common.c ---------------*/
 
-Bool ML_(sf_extend_stack)( const ThreadState *tst, Addr addr, SizeT size );
+Bool ML_(sf_maybe_extend_stack)( const ThreadState *tst, Addr addr,
+                                 SizeT size, UInt flags );
 
 #endif   // __PRIV_SIGFRAME_H
 
index 77752beda9838c1dc2dc5e7d434d13c5f9da5bd9..38682f318e780c48ecf9f24b885e2dbd85602f6a 100644 (file)
@@ -109,7 +109,7 @@ void VG_(sigframe_create) ( ThreadId tid,
                 entry to a function. */
 
    tst = VG_(get_ThreadState)(tid);
-   if (! ML_(sf_extend_stack)(tst, rsp, sp_top_of_frame - rsp))
+   if (! ML_(sf_maybe_extend_stack)(tst, rsp, sp_top_of_frame - rsp, flags))
       return;
 
    vg_assert(VG_IS_16_ALIGNED(rsp+8));
index a2b79e5adba49382256ffd8638482ace18880ff4..e0154016c7b63162e88750ce5bf1976ea50ab577 100644 (file)
@@ -412,7 +412,7 @@ static Addr build_rt_sigframe(ThreadState *tst,
    rsp = VG_ROUNDDN(rsp, 16) - 8;
    frame = (struct rt_sigframe *)rsp;
 
-   if (! ML_(sf_extend_stack)(tst, rsp, sizeof(*frame)))
+   if (! ML_(sf_maybe_extend_stack)(tst, rsp, sizeof(*frame), flags))
       return rsp_top_of_frame;
 
    /* retaddr, siginfo, uContext fields are to be written */
index dbbebc34da366bf1b517b4d07ed0a00b1a6da627..7ae7f07291719f7fdbb294e352b4a2b5a504ac61 100644 (file)
@@ -185,7 +185,7 @@ void VG_(sigframe_create)( ThreadId tid,
    sp -= size;
    sp = VG_ROUNDDN(sp, 16);
 
-   if(! ML_(sf_extend_stack)(tst, sp, size))
+   if (! ML_(sf_maybe_extend_stack)(tst, sp, size, flags))
       I_die_here; // XXX Incorrect behavior
 
 
index 1b09696d0fa7e7a90910b06f8b2e372ee553696d..1a7c984e9be52a58487d1bd09905e4d668484001 100644 (file)
@@ -173,7 +173,7 @@ void VG_(sigframe_create)( ThreadId tid,
    sp -= size;
    sp = VG_ROUNDDN(sp, 16);
 
-   if (! ML_(sf_extend_stack)(tst, sp, size))
+   if (! ML_(sf_maybe_extend_stack)(tst, sp, size, flags))
       return; // Give up.  No idea if this is correct
 
    struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
index 59b34ee68aa2b444d90e64e6256d596ec6a85f2a..12ef1ed8cef96d3fef72ba07f683e0a62b7440a9 100644 (file)
@@ -54,16 +54,31 @@ static void track_frame_memory ( Addr addr, SizeT size, ThreadId tid )
 /* Extend the stack segment downwards if needed so as to ensure the
    new signal frames are mapped to something.  Return a Bool
    indicating whether or not the operation was successful. */
-Bool ML_(sf_extend_stack) ( const ThreadState *tst, Addr addr, SizeT size )
+Bool ML_(sf_maybe_extend_stack) ( const ThreadState *tst, Addr addr,
+                                  SizeT size, UInt flags )
 {
    ThreadId        tid = tst->tid;
    const NSegment *stackseg = NULL;
 
-   if (VG_(extend_stack)(tid, addr)) {
+   if (flags & VKI_SA_ONSTACK) {
+      /* If the sigframe is allocated on an alternate stack, then we cannot
+         extend that stack. Nothing to do here. */
       stackseg = VG_(am_find_nsegment)(addr);
-      if (0 && stackseg)
-        VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
-                    addr, stackseg->start, stackseg->end);
+   } else if (VG_(am_addr_is_in_extensible_client_stack)(addr)) {
+      if (VG_(extend_stack)(tid, addr)) {
+         stackseg = VG_(am_find_nsegment)(addr);
+         if (0 && stackseg)
+            VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
+                        addr, stackseg->start, stackseg->end);
+      }
+   } else if ((stackseg = VG_(am_find_nsegment)(addr)) &&
+              VG_(am_is_valid_for_client)(addr, 1,
+                                          VKI_PROT_READ | VKI_PROT_WRITE)) {
+      /* We come here for explicitly defined pthread-stacks which can be
+         located in any client segment. */
+   } else {
+      /* Something unexpected */
+      stackseg = NULL;
    }
 
    if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
index 6f09e4d2fc9027f2fd8086504caae32cface7289..0e27e01d99f031251738b1a5e2bd30c013c1de0b 100644 (file)
@@ -148,7 +148,7 @@ void VG_(sigframe_create)( ThreadId tid,
     }
 
   tst = VG_(get_ThreadState)(tid);
-  if (! ML_(sf_extend_stack)(tst, sp, sp_top_of_frame - sp))
+  if (! ML_(sf_maybe_extend_stack)(tst, sp, sp_top_of_frame - sp, flags))
     return;
 
   vg_assert(VG_IS_8_ALIGNED(sp));
index fa6615b248e8dc79eb37d8a853eec02d4f5c413f..cacf9ce7d0a32d4878d83c5195f1b0c112780d9f 100644 (file)
@@ -135,7 +135,7 @@ void VG_(sigframe_create) ( ThreadId tid,
    sp = sp_top_of_frame - sizeof(struct rt_sigframe);
 
    tst = VG_(get_ThreadState)(tid);
-   if (! ML_(sf_extend_stack)(tst, sp, sp_top_of_frame - sp))
+   if (! ML_(sf_maybe_extend_stack)(tst, sp, sp_top_of_frame - sp, flags))
       return;
 
    sp = VG_ROUNDDN(sp, 16);
index 346abb229c06afec8375b17233da7671b7f8e01c..467814dc5c1b165356aeb4f0a14fcd9c9d7b2c43 100644 (file)
@@ -650,7 +650,7 @@ void VG_(sigframe_create)( ThreadId tid,
 
    tst = VG_(get_ThreadState)(tid);
 
-   if (! ML_(sf_extend_stack)(tst, sp, sp_top_of_frame - sp))
+   if (! ML_(sf_maybe_extend_stack)(tst, sp, sp_top_of_frame - sp, flags))
       return;
 
    vg_assert(VG_IS_16_ALIGNED(sp));
index 8a6bcb3ebbc80626fad175d1bd8115c905c41084..5e90e54aea36093635a48dac2fcdadf2fe56e8ed 100644 (file)
@@ -158,7 +158,7 @@ void VG_(sigframe_create)( ThreadId tid,
    sp = sp_top_of_frame - sizeof(struct rt_sigframe);
 
    tst = VG_(get_ThreadState)(tid);
-   if (! ML_(sf_extend_stack)(tst, sp, sp_top_of_frame - sp))
+   if (! ML_(sf_maybe_extend_stack)(tst, sp, sp_top_of_frame - sp, flags))
       return;
 
    vg_assert(VG_IS_16_ALIGNED(sp));
index b3ca4aebf0b4380b738f73d3640be7aa0037b97f..05689227270fa31d14cbab7ead5148819105f521 100644 (file)
@@ -298,7 +298,7 @@ static Addr build_sigframe(ThreadState *tst,
    sp -= sizeof(*frame);
    frame = (struct sigframe *)sp;
 
-   if (! ML_(sf_extend_stack)(tst, sp, sizeof(*frame)))
+   if (! ML_(sf_maybe_extend_stack)(tst, sp, sizeof(*frame), flags))
       return sp_top_of_frame;
 
    /* retcode, sigNo, sc, sregs fields are to be written */
@@ -358,7 +358,7 @@ static Addr build_rt_sigframe(ThreadState *tst,
    sp -= sizeof(*frame);
    frame = (struct rt_sigframe *)sp;
 
-   if (! ML_(sf_extend_stack)(tst, sp, sizeof(*frame)))
+   if (! ML_(sf_maybe_extend_stack)(tst, sp, sizeof(*frame), flags))
       return sp_top_of_frame;
 
    /* retcode, sigNo, sc, sregs fields are to be written */
index 48d0859693818c521e49d679211e8da97ebb8d84..b9de920aa5ef58e1911e5931e7cfb06ab10d5664 100644 (file)
@@ -158,7 +158,7 @@ void VG_(sigframe_create)( ThreadId tid,
   sp = sp_top_of_frame - sizeof(struct rt_sigframe);
 
   tst = VG_(get_ThreadState)(tid);
-  if (! ML_(sf_extend_stack)(tst, sp, sizeof(struct rt_sigframe)))
+  if (! ML_(sf_maybe_extend_stack)(tst, sp, sizeof(struct rt_sigframe), flags))
     return;
 
   vg_assert(VG_IS_8_ALIGNED(sp));
index 6c2c1efc2ed9bf2cd8ce36ae9c8d724e7e80cd7c..e3da65d034ad266a0470b3151b538b661d59082b 100644 (file)
@@ -112,7 +112,7 @@ void VG_(sigframe_create) ( ThreadId tid,
                 entry to a function. */
 
    tst = VG_(get_ThreadState)(tid);
-   if (! ML_(sf_extend_stack)(tst, esp, sp_top_of_frame - esp))
+   if (! ML_(sf_maybe_extend_stack)(tst, esp, sp_top_of_frame - esp, flags))
       return;
 
    vg_assert(VG_IS_16_ALIGNED(esp+4));
index d6597b6c967466cbf810fe5e8cda9f7ff5f30227..a09aaf2e545f20c904af385984d72c36972a9df5 100644 (file)
@@ -434,7 +434,7 @@ static Addr build_sigframe(ThreadState *tst,
    esp = VG_ROUNDDN(esp, 16);
    frame = (struct sigframe *)esp;
 
-   if (! ML_(sf_extend_stack)(tst, esp, sizeof(*frame)))
+   if (! ML_(sf_maybe_extend_stack)(tst, esp, sizeof(*frame), flags))
       return esp_top_of_frame;
 
    /* retaddr, sigNo, siguContext fields are to be written */
@@ -491,7 +491,7 @@ static Addr build_rt_sigframe(ThreadState *tst,
    esp = VG_ROUNDDN(esp, 16);
    frame = (struct rt_sigframe *)esp;
 
-   if (! ML_(sf_extend_stack)(tst, esp, sizeof(*frame)))
+   if (! ML_(sf_maybe_extend_stack)(tst, esp, sizeof(*frame), flags))
       return esp_top_of_frame;
 
    /* retaddr, sigNo, pSiginfo, puContext fields are to be written */
index 5dc5f2f57469e3e6e95c442f92c0bedae3c62f6a..47a345f703866f65fc7a2ed6223dab3418c5cb0d 100644 (file)
@@ -1737,7 +1737,8 @@ static void default_action(const vki_siginfo_t *info, ThreadId tid)
          if (tid == 1) {           // main thread
             Addr esp  = VG_(get_SP)(tid);
             Addr base = VG_PGROUNDDN(esp - VG_STACK_REDZONE_SZB);
-            if (VG_(extend_stack)(tid, base)) {
+            if (VG_(am_addr_is_in_extensible_client_stack)(base) &&
+                VG_(extend_stack)(tid, base)) {
                if (VG_(clo_trace_signals))
                   VG_(dmsg)("       -> extended stack base to %#lx\n",
                             VG_PGROUNDDN(esp));
@@ -2462,7 +2463,8 @@ static Bool extend_stack_if_appropriate(ThreadId tid, vki_siginfo_t* info)
          then extend the stack segment. 
        */
       Addr base = VG_PGROUNDDN(esp - VG_STACK_REDZONE_SZB);
-      if (VG_(extend_stack)(tid, base)) {
+      if (VG_(am_addr_is_in_extensible_client_stack)(base) &&
+          VG_(extend_stack)(tid, base)) {
          if (VG_(clo_trace_signals))
             VG_(dmsg)("       -> extended stack base to %#lx\n",
                       VG_PGROUNDDN(fault));
index 89970645017fc138a036bbab4f8a36aff1974a24..4edbeaa52d5e44afb5b59742ed1dd1b28dae0c94 100644 (file)
@@ -45,12 +45,15 @@ SUBDIRS += darwin
 endif
 
 # Platform-specific tests
+if VGCONF_PLATFORMS_INCLUDE_AMD64_LINUX
+SUBDIRS += amd64-linux
+endif
 if VGCONF_PLATFORMS_INCLUDE_X86_LINUX
 SUBDIRS += x86-linux
 endif
 
 DIST_SUBDIRS = x86 amd64 ppc32 ppc64 arm arm64 s390x mips32 mips64 tilegx \
-               linux darwin x86-linux scripts .
+               linux darwin amd64-linux x86-linux scripts .
 
 dist_noinst_SCRIPTS = \
        filter_cmdline0 \
diff --git a/none/tests/amd64-linux/Makefile.am b/none/tests/amd64-linux/Makefile.am
new file mode 100644 (file)
index 0000000..39d7bac
--- /dev/null
@@ -0,0 +1,15 @@
+
+include $(top_srcdir)/Makefile.tool-tests.am
+
+dist_noinst_SCRIPTS = \
+       filter_stderr filter_minimal
+
+EXTRA_DIST = \
+       bug345887.stderr.exp bug345887.vgtest
+
+check_PROGRAMS = \
+       bug345887
+
+AM_CFLAGS    += @FLAG_M64@
+AM_CXXFLAGS  += @FLAG_M64@
+AM_CCASFLAGS += @FLAG_M64@
diff --git a/none/tests/amd64-linux/bug345887.c b/none/tests/amd64-linux/bug345887.c
new file mode 100644 (file)
index 0000000..0f9237d
--- /dev/null
@@ -0,0 +1,42 @@
+/* This test used to cause an assertion in the address space manager */
+
+__attribute__((noinline))
+static void inner(void)
+{
+   /* Set registers to apriori known values. */
+   __asm__ __volatile__(
+      "movq $0x101, %%rax\n"
+      "movq $0x102, %%rbx\n"
+      "movq $0x103, %%rcx\n"
+      "movq $0x104, %%rdx\n"
+      "movq $0x105, %%rsi\n"
+      "movq $0x106, %%rdi\n"
+      "movq $0x107, %%r8\n"
+      "movq $0x108, %%r9\n"
+      "movq $0x109, %%r10\n"
+      "movq $0x10a, %%r11\n"
+      "movq $0x10b, %%r12\n"
+      "movq $0x10c, %%r13\n"
+      "movq $0x10d, %%r14\n"
+      "movq $0x10e, %%r15\n"
+      // not %rbp as mdb is then not able to reconstruct stack trace
+      "movq $0x10f, %%rsp\n"
+      "movq $0x1234, (%%rax)\n"  // should cause SEGV here
+      "ud2"                      // should never get here
+      : // no output registers
+      : // no input registers
+      : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",
+        "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rsp");
+}
+
+__attribute__((noinline))
+static void outer(void)
+{
+   inner();
+}
+
+int main(int argc, const char *argv[])
+{
+   outer();
+   return 0;
+}
diff --git a/none/tests/amd64-linux/bug345887.stderr.exp b/none/tests/amd64-linux/bug345887.stderr.exp
new file mode 100644 (file)
index 0000000..129193c
--- /dev/null
@@ -0,0 +1,9 @@
+
+Process terminating with default action of signal 11 (SIGSEGV)
+ Access not within mapped region at address 0x........
+   at 0x........: inner (bug345887.c:7)
+ If you believe this happened as a result of a stack
+ overflow in your program's main thread (unlikely but
+ possible), you can try to increase the size of the
+ main thread stack using the --main-stacksize= flag.
+ The main thread stack size used in this run was ....
diff --git a/none/tests/amd64-linux/bug345887.vgtest b/none/tests/amd64-linux/bug345887.vgtest
new file mode 100644 (file)
index 0000000..c014423
--- /dev/null
@@ -0,0 +1,4 @@
+prog: bug345887
+vgopts: -q
+stderr_filter: filter_minimal
+cleanup: rm -f vgcore.*
diff --git a/none/tests/amd64-linux/filter_minimal b/none/tests/amd64-linux/filter_minimal
new file mode 100755 (executable)
index 0000000..e69398c
--- /dev/null
@@ -0,0 +1,20 @@
+#! /bin/sh
+
+dir=`dirname $0`
+
+# Remove ==pid== and **pid** strings 
+perl -p -e 's/(==|\*\*)[0-9]{1,7}\1 //' |
+
+perl -p -e 's/0x[0-9A-Fa-f]+/0x......../g' |
+
+# Older bash versions print abnormal termination messages on the stderr
+# of the bash process. Newer bash versions redirect such messages properly.
+# Suppress any redirected abnormal termination messages. You can find the
+# complete list of messages in the bash source file siglist.c.
+perl -n -e 'print if !/^(Segmentation fault|Alarm clock|Aborted|Bus error)( \(core dumped\))?$/' |
+
+# Remove the size in "The main thread stack size..." message.
+sed "s/The main thread stack size used in this run was [0-9]*/The main thread stack size used in this run was .../"
+
+# NOTE: it is essential for the bug345887 testcase that the stderr
+#       filtering does *not* remove lines beginning with --
diff --git a/none/tests/amd64-linux/filter_stderr b/none/tests/amd64-linux/filter_stderr
new file mode 100755 (executable)
index 0000000..587754a
--- /dev/null
@@ -0,0 +1,11 @@
+#! /bin/sh
+
+dir=`dirname $0`
+
+# Remove ==pid== and --pid-- and **pid** strings 
+perl -p -e 's/(==|--|\*\*)[0-9]{1,7}\1 //' |
+
+perl -p -e 's/0x[0-9A-Fa-f]+/0x......../g'
+
+# NOTE: it is essential for the bug345887 testcase that the stderr
+#       filtering does *not* remove lines beginning with --
index 87f780ccfaabcf674ae55edd626bd7f82e56adba..0ac75dacf684c3448b1e2bd1663658b35af84fe1 100644 (file)
@@ -9,6 +9,7 @@ EXTRA_DIST = \
            mremap.vgtest \
        mremap2.stderr.exp mremap2.stdout.exp mremap2.vgtest \
        mremap3.stderr.exp mremap3.stdout.exp mremap3.vgtest \
+       pthread-stack.stderr.exp pthread-stack.vgtest \
        stack-overflow.stderr.exp stack-overflow.vgtest
 
 check_PROGRAMS = \
@@ -16,8 +17,12 @@ check_PROGRAMS = \
        mremap \
        mremap2 \
        mremap3 \
+       pthread-stack \
        stack-overflow
 
 
 AM_CFLAGS   += $(AM_FLAG_M3264_PRI)
 AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
+
+# Special needs
+pthread_stack_LDADD = -lpthread
diff --git a/none/tests/linux/pthread-stack.c b/none/tests/linux/pthread-stack.c
new file mode 100644 (file)
index 0000000..4b7a953
--- /dev/null
@@ -0,0 +1,109 @@
+/* This test causes an error in 3.10.1 and earlier versions like so:
+
+==8336== Can't extend stack to 0x4033f98 during signal delivery for thread 2:
+==8336==   no stack segment
+
+  The reason was that only AnonC segments were considered as stack
+  segments. */
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+static volatile char *lowest_j;
+static jmp_buf goback;
+
+static void sigsegv_handler(int signr)
+{
+   longjmp(goback, 1);
+}
+
+static void bad_things_till_guard_page(void)
+{
+   fprintf(stderr, "... doing bad things till guard page\n");
+   char j = 0;
+   char *p = &j;
+
+   for (;;) {
+      j = j + *p;
+      p = p - 400;
+      lowest_j = p;
+   }
+}
+
+static void say_something(void)
+{
+  fprintf(stderr, "plugh\n");
+}
+
+static void* child_func ( void* arg )
+{
+   if (setjmp(goback)) {
+      say_something();
+   } else
+      bad_things_till_guard_page();
+
+   return NULL;
+}
+
+int main(int argc, const char** argv)
+{
+   int r, fd;
+
+   /* We will discover the thread guard page using SEGV.
+      So, prepare an handler. */
+   struct sigaction sa;
+   sa.sa_handler = sigsegv_handler;
+   sigemptyset(&sa.sa_mask);
+   sa.sa_flags = 0;
+   if (sigaction (SIGSEGV, &sa, NULL) != 0)
+      perror("sigaction");
+
+   pthread_t child;
+
+   /* Create a file that will be used as stack for a pthread.  */
+   const size_t file_size = 1024 * 1024;
+   const char file_name[] = "FILE";
+   fd = open(file_name, O_CREAT|O_WRONLY, 
+             S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+   assert(fd > 0);
+   void *p = malloc(file_size);
+   assert(p != 0);
+   memset(p, 0, file_size);
+   int written = write(fd, p, file_size);
+   assert(written == file_size);
+   close(fd);
+
+   /* Create a file-based stack for the child */
+   fd = open(file_name, O_CREAT|O_RDWR, 
+             S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+   assert(fd > 0);
+   const size_t stack_size = 256 * 1024;
+   assert(stack_size < file_size);
+   void *stack = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, 
+                      MAP_PRIVATE, fd, 0);
+   assert(stack != (void *)-1);
+   pthread_attr_t attr;
+   pthread_attr_init(&attr);
+   r = pthread_attr_setstack(&attr, stack, stack_size);
+   assert(r == 0);
+   
+   /* Create child run */
+   r = pthread_create(&child, &attr, child_func, NULL);
+   assert(r == 0);
+   r = pthread_join(child, NULL);
+   assert(r == 0);
+
+   /* Remove file */
+   unlink(file_name);
+   return 0;
+}
+
diff --git a/none/tests/linux/pthread-stack.stderr.exp b/none/tests/linux/pthread-stack.stderr.exp
new file mode 100644 (file)
index 0000000..391e60c
--- /dev/null
@@ -0,0 +1,2 @@
+... doing bad things till guard page
+plugh
diff --git a/none/tests/linux/pthread-stack.vgtest b/none/tests/linux/pthread-stack.vgtest
new file mode 100644 (file)
index 0000000..50cafcb
--- /dev/null
@@ -0,0 +1,2 @@
+prog: pthread-stack
+vgopts: -q
index 8592f1d72a86d45354be4c1861dd9476d43e3a8b..4fa0fac2f5125dfd83b43dbbd3930c6c9c5d34b2 100644 (file)
@@ -2,14 +2,16 @@
 include $(top_srcdir)/Makefile.tool-tests.am
 
 dist_noinst_SCRIPTS = \
-       filter_stderr
+       filter_stderr filter_minimal
 
 EXTRA_DIST = \
+       bug345887.stderr.exp bug345887.vgtest \
        hang.stderr.exp hang.vgtest \
        seg_override.stderr.exp seg_override.stdout.exp seg_override.vgtest \
        sigcontext.stdout.exp sigcontext.stderr.exp sigcontext.vgtest
 
 check_PROGRAMS = \
+       bug345887 \
        hang \
        seg_override \
        sigcontext
@@ -17,5 +19,3 @@ check_PROGRAMS = \
 AM_CFLAGS    += @FLAG_M32@ $(FLAG_MMMX) $(FLAG_MSSE)
 AM_CXXFLAGS  += @FLAG_M32@ $(FLAG_MMMX) $(FLAG_MSSE)
 AM_CCASFLAGS += @FLAG_M32@
-
-
diff --git a/none/tests/x86-linux/bug345887.c b/none/tests/x86-linux/bug345887.c
new file mode 100644 (file)
index 0000000..f2e8a8d
--- /dev/null
@@ -0,0 +1,33 @@
+/* This test used to cause an assertion in the address space manager */
+
+__attribute__((noinline))
+static void inner(void)
+{
+   /* Set other registers to apriori known values. */
+   __asm__ __volatile__(
+      "movl $0x101, %%eax\n"
+      "movl $0x102, %%ebx\n"
+      "movl $0x103, %%ecx\n"
+      "movl $0x104, %%edx\n"
+      "movl $0x105, %%esi\n"
+      "movl $0x106, %%edi\n"
+      // not %ebp as mdb is then not able to reconstruct stack trace
+      "movl $0x108, %%esp\n"
+      "movl $0x1234, (%%eax)\n"  // should cause SEGV here
+      "ud2"                      // should never get here
+      : // no output registers
+      : // no input registers
+      : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%esp");
+}
+
+__attribute__((noinline))
+static void outer(void)
+{
+   inner();
+}
+
+int main(int argc, const char *argv[])
+{
+   outer();
+   return 0;
+}
diff --git a/none/tests/x86-linux/bug345887.stderr.exp b/none/tests/x86-linux/bug345887.stderr.exp
new file mode 100644 (file)
index 0000000..129193c
--- /dev/null
@@ -0,0 +1,9 @@
+
+Process terminating with default action of signal 11 (SIGSEGV)
+ Access not within mapped region at address 0x........
+   at 0x........: inner (bug345887.c:7)
+ If you believe this happened as a result of a stack
+ overflow in your program's main thread (unlikely but
+ possible), you can try to increase the size of the
+ main thread stack using the --main-stacksize= flag.
+ The main thread stack size used in this run was ....
diff --git a/none/tests/x86-linux/bug345887.vgtest b/none/tests/x86-linux/bug345887.vgtest
new file mode 100644 (file)
index 0000000..c014423
--- /dev/null
@@ -0,0 +1,4 @@
+prog: bug345887
+vgopts: -q
+stderr_filter: filter_minimal
+cleanup: rm -f vgcore.*
diff --git a/none/tests/x86-linux/filter_minimal b/none/tests/x86-linux/filter_minimal
new file mode 100755 (executable)
index 0000000..e69398c
--- /dev/null
@@ -0,0 +1,20 @@
+#! /bin/sh
+
+dir=`dirname $0`
+
+# Remove ==pid== and **pid** strings 
+perl -p -e 's/(==|\*\*)[0-9]{1,7}\1 //' |
+
+perl -p -e 's/0x[0-9A-Fa-f]+/0x......../g' |
+
+# Older bash versions print abnormal termination messages on the stderr
+# of the bash process. Newer bash versions redirect such messages properly.
+# Suppress any redirected abnormal termination messages. You can find the
+# complete list of messages in the bash source file siglist.c.
+perl -n -e 'print if !/^(Segmentation fault|Alarm clock|Aborted|Bus error)( \(core dumped\))?$/' |
+
+# Remove the size in "The main thread stack size..." message.
+sed "s/The main thread stack size used in this run was [0-9]*/The main thread stack size used in this run was .../"
+
+# NOTE: it is essential for the bug345887 testcase that the stderr
+#       filtering does *not* remove lines beginning with --