From 9d3d254a8b3b6bbb7a554db7491d4585dd12d47b Mon Sep 17 00:00:00 2001 From: Florian Krohm Date: Thu, 23 Apr 2015 15:20:00 +0000 Subject: [PATCH] Fix an assertion in the address space manager. BZ #345887. 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 --- NEWS | 1 + configure.ac | 1 + coregrind/m_sigframe/priv_sigframe.h | 3 +- coregrind/m_sigframe/sigframe-amd64-darwin.c | 2 +- coregrind/m_sigframe/sigframe-amd64-linux.c | 2 +- coregrind/m_sigframe/sigframe-arm-linux.c | 2 +- coregrind/m_sigframe/sigframe-arm64-linux.c | 2 +- coregrind/m_sigframe/sigframe-common.c | 25 ++++- coregrind/m_sigframe/sigframe-mips32-linux.c | 2 +- coregrind/m_sigframe/sigframe-mips64-linux.c | 2 +- coregrind/m_sigframe/sigframe-ppc32-linux.c | 2 +- coregrind/m_sigframe/sigframe-ppc64-linux.c | 2 +- coregrind/m_sigframe/sigframe-s390x-linux.c | 4 +- coregrind/m_sigframe/sigframe-tilegx-linux.c | 2 +- coregrind/m_sigframe/sigframe-x86-darwin.c | 2 +- coregrind/m_sigframe/sigframe-x86-linux.c | 4 +- coregrind/m_signals.c | 6 +- none/tests/Makefile.am | 5 +- none/tests/amd64-linux/Makefile.am | 15 +++ none/tests/amd64-linux/bug345887.c | 42 +++++++ none/tests/amd64-linux/bug345887.stderr.exp | 9 ++ none/tests/amd64-linux/bug345887.vgtest | 4 + none/tests/amd64-linux/filter_minimal | 20 ++++ none/tests/amd64-linux/filter_stderr | 11 ++ none/tests/linux/Makefile.am | 5 + none/tests/linux/pthread-stack.c | 109 +++++++++++++++++++ none/tests/linux/pthread-stack.stderr.exp | 2 + none/tests/linux/pthread-stack.vgtest | 2 + none/tests/x86-linux/Makefile.am | 6 +- none/tests/x86-linux/bug345887.c | 33 ++++++ none/tests/x86-linux/bug345887.stderr.exp | 9 ++ none/tests/x86-linux/bug345887.vgtest | 4 + none/tests/x86-linux/filter_minimal | 20 ++++ 33 files changed, 334 insertions(+), 26 deletions(-) create mode 100644 none/tests/amd64-linux/Makefile.am create mode 100644 none/tests/amd64-linux/bug345887.c create mode 100644 none/tests/amd64-linux/bug345887.stderr.exp create mode 100644 none/tests/amd64-linux/bug345887.vgtest create mode 100755 none/tests/amd64-linux/filter_minimal create mode 100755 none/tests/amd64-linux/filter_stderr create mode 100644 none/tests/linux/pthread-stack.c create mode 100644 none/tests/linux/pthread-stack.stderr.exp create mode 100644 none/tests/linux/pthread-stack.vgtest create mode 100644 none/tests/x86-linux/bug345887.c create mode 100644 none/tests/x86-linux/bug345887.stderr.exp create mode 100644 none/tests/x86-linux/bug345887.vgtest create mode 100755 none/tests/x86-linux/filter_minimal diff --git a/NEWS b/NEWS index 9fdc795250..2a61168449 100644 --- 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 diff --git a/configure.ac b/configure.ac index a5aa96403f..d03aa5c0c4 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/coregrind/m_sigframe/priv_sigframe.h b/coregrind/m_sigframe/priv_sigframe.h index a81f4d005a..74351852ee 100644 --- a/coregrind/m_sigframe/priv_sigframe.h +++ b/coregrind/m_sigframe/priv_sigframe.h @@ -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 diff --git a/coregrind/m_sigframe/sigframe-amd64-darwin.c b/coregrind/m_sigframe/sigframe-amd64-darwin.c index 77752beda9..38682f318e 100644 --- a/coregrind/m_sigframe/sigframe-amd64-darwin.c +++ b/coregrind/m_sigframe/sigframe-amd64-darwin.c @@ -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)); diff --git a/coregrind/m_sigframe/sigframe-amd64-linux.c b/coregrind/m_sigframe/sigframe-amd64-linux.c index a2b79e5adb..e0154016c7 100644 --- a/coregrind/m_sigframe/sigframe-amd64-linux.c +++ b/coregrind/m_sigframe/sigframe-amd64-linux.c @@ -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 */ diff --git a/coregrind/m_sigframe/sigframe-arm-linux.c b/coregrind/m_sigframe/sigframe-arm-linux.c index dbbebc34da..7ae7f07291 100644 --- a/coregrind/m_sigframe/sigframe-arm-linux.c +++ b/coregrind/m_sigframe/sigframe-arm-linux.c @@ -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 diff --git a/coregrind/m_sigframe/sigframe-arm64-linux.c b/coregrind/m_sigframe/sigframe-arm64-linux.c index 1b09696d0f..1a7c984e9b 100644 --- a/coregrind/m_sigframe/sigframe-arm64-linux.c +++ b/coregrind/m_sigframe/sigframe-arm64-linux.c @@ -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; diff --git a/coregrind/m_sigframe/sigframe-common.c b/coregrind/m_sigframe/sigframe-common.c index 59b34ee68a..12ef1ed8ce 100644 --- a/coregrind/m_sigframe/sigframe-common.c +++ b/coregrind/m_sigframe/sigframe-common.c @@ -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) { diff --git a/coregrind/m_sigframe/sigframe-mips32-linux.c b/coregrind/m_sigframe/sigframe-mips32-linux.c index 6f09e4d2fc..0e27e01d99 100644 --- a/coregrind/m_sigframe/sigframe-mips32-linux.c +++ b/coregrind/m_sigframe/sigframe-mips32-linux.c @@ -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)); diff --git a/coregrind/m_sigframe/sigframe-mips64-linux.c b/coregrind/m_sigframe/sigframe-mips64-linux.c index fa6615b248..cacf9ce7d0 100644 --- a/coregrind/m_sigframe/sigframe-mips64-linux.c +++ b/coregrind/m_sigframe/sigframe-mips64-linux.c @@ -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); diff --git a/coregrind/m_sigframe/sigframe-ppc32-linux.c b/coregrind/m_sigframe/sigframe-ppc32-linux.c index 346abb229c..467814dc5c 100644 --- a/coregrind/m_sigframe/sigframe-ppc32-linux.c +++ b/coregrind/m_sigframe/sigframe-ppc32-linux.c @@ -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)); diff --git a/coregrind/m_sigframe/sigframe-ppc64-linux.c b/coregrind/m_sigframe/sigframe-ppc64-linux.c index 8a6bcb3ebb..5e90e54aea 100644 --- a/coregrind/m_sigframe/sigframe-ppc64-linux.c +++ b/coregrind/m_sigframe/sigframe-ppc64-linux.c @@ -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)); diff --git a/coregrind/m_sigframe/sigframe-s390x-linux.c b/coregrind/m_sigframe/sigframe-s390x-linux.c index b3ca4aebf0..0568922727 100644 --- a/coregrind/m_sigframe/sigframe-s390x-linux.c +++ b/coregrind/m_sigframe/sigframe-s390x-linux.c @@ -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 */ diff --git a/coregrind/m_sigframe/sigframe-tilegx-linux.c b/coregrind/m_sigframe/sigframe-tilegx-linux.c index 48d0859693..b9de920aa5 100644 --- a/coregrind/m_sigframe/sigframe-tilegx-linux.c +++ b/coregrind/m_sigframe/sigframe-tilegx-linux.c @@ -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)); diff --git a/coregrind/m_sigframe/sigframe-x86-darwin.c b/coregrind/m_sigframe/sigframe-x86-darwin.c index 6c2c1efc2e..e3da65d034 100644 --- a/coregrind/m_sigframe/sigframe-x86-darwin.c +++ b/coregrind/m_sigframe/sigframe-x86-darwin.c @@ -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)); diff --git a/coregrind/m_sigframe/sigframe-x86-linux.c b/coregrind/m_sigframe/sigframe-x86-linux.c index d6597b6c96..a09aaf2e54 100644 --- a/coregrind/m_sigframe/sigframe-x86-linux.c +++ b/coregrind/m_sigframe/sigframe-x86-linux.c @@ -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 */ diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index 5dc5f2f574..47a345f703 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -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)); diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am index 8997064501..4edbeaa52d 100644 --- a/none/tests/Makefile.am +++ b/none/tests/Makefile.am @@ -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 index 0000000000..39d7bac13e --- /dev/null +++ b/none/tests/amd64-linux/Makefile.am @@ -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 index 0000000000..0f9237df54 --- /dev/null +++ b/none/tests/amd64-linux/bug345887.c @@ -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 index 0000000000..129193cd83 --- /dev/null +++ b/none/tests/amd64-linux/bug345887.stderr.exp @@ -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 index 0000000000..c0144230c6 --- /dev/null +++ b/none/tests/amd64-linux/bug345887.vgtest @@ -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 index 0000000000..e69398ce8a --- /dev/null +++ b/none/tests/amd64-linux/filter_minimal @@ -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 index 0000000000..587754a136 --- /dev/null +++ b/none/tests/amd64-linux/filter_stderr @@ -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 -- diff --git a/none/tests/linux/Makefile.am b/none/tests/linux/Makefile.am index 87f780ccfa..0ac75dacf6 100644 --- a/none/tests/linux/Makefile.am +++ b/none/tests/linux/Makefile.am @@ -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 index 0000000000..4b7a9532af --- /dev/null +++ b/none/tests/linux/pthread-stack.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 index 0000000000..391e60c396 --- /dev/null +++ b/none/tests/linux/pthread-stack.stderr.exp @@ -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 index 0000000000..50cafcb6d8 --- /dev/null +++ b/none/tests/linux/pthread-stack.vgtest @@ -0,0 +1,2 @@ +prog: pthread-stack +vgopts: -q diff --git a/none/tests/x86-linux/Makefile.am b/none/tests/x86-linux/Makefile.am index 8592f1d72a..4fa0fac2f5 100644 --- a/none/tests/x86-linux/Makefile.am +++ b/none/tests/x86-linux/Makefile.am @@ -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 index 0000000000..f2e8a8ddec --- /dev/null +++ b/none/tests/x86-linux/bug345887.c @@ -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 index 0000000000..129193cd83 --- /dev/null +++ b/none/tests/x86-linux/bug345887.stderr.exp @@ -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 index 0000000000..c0144230c6 --- /dev/null +++ b/none/tests/x86-linux/bug345887.vgtest @@ -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 index 0000000000..e69398ce8a --- /dev/null +++ b/none/tests/x86-linux/filter_minimal @@ -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 -- -- 2.47.3