Subject: Re: bin/30143: gdb does not work with threaded programs
To: None <nathanw@netbsd.org, gnats-admin@netbsd.org,>
From: Nathan J. Williams <nathanw@wasabisystems.com>
List: netbsd-bugs
Date: 05/06/2005 02:23:02
The following reply was made to PR kern/30143; it has been noted by GNATS.

From: "Nathan J. Williams" <nathanw@wasabisystems.com>
To: gnats-bugs@netbsd.org
Cc: chs@netbsd.org
Subject: Re: bin/30143: gdb does not work with threaded programs
Date: 05 May 2005 21:41:05 -0400

 This is a problem in the core-dumping code. Specifically, a region
 without read permission but otherwise dumpable will generate EFAULT
 when coredump_writesegs() tries to write it out. The following program
 will demonstrate this, without libpthread linked in:
 
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/param.h>
 #include <unistd.h>
 
 int
 test(int *x)
 {
         return *x;
 }
 
 int
 main(int argc, char **argv)
 {
         int local;
         vaddr_t stackaddr;
         size_t pagesize;
 
         pagesize = (size_t)sysconf(_SC_PAGESIZE);
 
         stackaddr = (vaddr_t)&local & ~(pagesize -1);
         stackaddr -= pagesize;
         mprotect((caddr_t)stackaddr, pagesize, PROT_NONE);
 
         return test(0);
 }
 
 
 (libpthread does something similar to generate a red zone on the main
 stack, which is why this problem appears when libpthread is linked
 in).
 
 The following patch to uvm_glue.c seems to fix this by adding read
 permission if it's not there already. There might be a better way to
 do this, or it might be better to mark unreadable regions as
 undumpable.
 
         - Nathan
 
 Index: uvm_glue.c
 ===================================================================
 RCS file: /cvsroot/src/sys/uvm/uvm_glue.c,v
 retrieving revision 1.84
 diff -u -r1.84 uvm_glue.c
 --- uvm_glue.c	1 Apr 2005 11:59:38 -0000	1.84
 +++ uvm_glue.c	6 May 2005 01:32:39 -0000
 @@ -766,7 +766,13 @@
  		if (state.start >= (vaddr_t)vm->vm_maxsaddr) {
  			state.flags |= UVM_COREDUMP_STACK;
  		}
 -
 +		if (((state.flags & UVM_COREDUMP_NODUMP) == 0) && 
 +		    (entry->protection & VM_PROT_READ) == 0) {
 +			entry->protection |= VM_PROT_READ;
 +			state.prot = entry->protection;
 +			pmap_protect(map->pmap, entry->start, entry->end, entry->protection);
 +			pmap_update(map->pmap);
 +		}
  		vm_map_unlock_read(map);
  		error = (*func)(p, vp, cred, &state);
  		if (error)