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
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
/* --------------- 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
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));
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 */
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
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;
/* 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) {
}
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));
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);
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));
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));
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 */
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 */
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));
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));
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 */
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 */
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));
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));
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 \
--- /dev/null
+
+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@
--- /dev/null
+/* 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;
+}
--- /dev/null
+
+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 ....
--- /dev/null
+prog: bug345887
+vgopts: -q
+stderr_filter: filter_minimal
+cleanup: rm -f vgcore.*
--- /dev/null
+#! /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 --
--- /dev/null
+#! /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 --
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 = \
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
--- /dev/null
+/* 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;
+}
+
--- /dev/null
+... doing bad things till guard page
+plugh
--- /dev/null
+prog: pthread-stack
+vgopts: -q
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
AM_CFLAGS += @FLAG_M32@ $(FLAG_MMMX) $(FLAG_MSSE)
AM_CXXFLAGS += @FLAG_M32@ $(FLAG_MMMX) $(FLAG_MSSE)
AM_CCASFLAGS += @FLAG_M32@
-
-
--- /dev/null
+/* 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;
+}
--- /dev/null
+
+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 ....
--- /dev/null
+prog: bug345887
+vgopts: -q
+stderr_filter: filter_minimal
+cleanup: rm -f vgcore.*
--- /dev/null
+#! /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 --