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)