Start working through proper handling of pthreads when
debugging Linux core dumps.  Pthreads for active processes
is still not supported, nor are other systems.
diff --git a/src/libmach/elfcorelinux386.c b/src/libmach/elfcorelinux386.c
index 9e8d0aa..4c4aabc 100644
--- a/src/libmach/elfcorelinux386.c
+++ b/src/libmach/elfcorelinux386.c
@@ -34,6 +34,10 @@
 	UregLinux386	reg;
 	u32int	fpvalid;
 };
+enum
+{
+	StatusSize = sizeof(Status),
+};
 
 struct Psinfo
 {
@@ -51,6 +55,10 @@
 	char fname[16];
 	char psargs[80];
 };
+enum
+{
+	PsinfoSize = sizeof(Psinfo),
+};
 
 int
 coreregslinux386(Elf *elf, ElfNote *note, uchar **up)
@@ -65,8 +73,9 @@
 	}
 	s = (Status*)note->desc;
 	l = &s->reg;
-	if((u = _linux2ureg386(l)) == nil)
+	if((u = malloc(sizeof *u)) == nil)
 		return -1;
+	linux2ureg386(l, u);
 	*up = (uchar*)u;
 	return sizeof(Ureg);
 }
@@ -93,3 +102,101 @@
 	return 0;
 }
 
+#define dprint if(0)print
+
+void
+elfcorelinux386(Fhdr *fp, Elf *elf, ElfNote *note)
+{
+	int i;
+	Psinfo *ps;
+	Status *st;
+	Mach *m;
+	Ureg *u;
+
+	m = fp->mach;
+	dprint("%s ", note->name);
+	switch(note->type){
+	case ElfNotePrPsinfo:
+		ps = (Psinfo*)note->desc;
+		dprint("note info\n");
+		dprint("state=%d sname=%d zomb=%d nice=%d\n",
+			ps->state, ps->sname, ps->zomb, ps->nice);
+		dprint("flag=0x%ux uid=%ud gid=%ud pid=%ud ppid=%ud pgrp=%ud sid=%ud\n",
+			(uint)m->swap4(ps->flag),
+			(uint)m->swap2(ps->uid),
+			(uint)m->swap2(ps->gid),
+			(uint)m->swap4(ps->pid),
+			(uint)m->swap4(ps->ppid),
+			(uint)m->swap4(ps->pgrp),
+			(uint)m->swap4(ps->sid));
+		dprint("fname=%s psargs=%s\n", ps->fname, ps->psargs);
+		fp->pid = m->swap4(ps->pid);
+		if((fp->prog = strdup(ps->fname)) == nil)
+			fprint(2, "warning: out of memory saving core program name\n");
+		if((fp->cmdline = strdup(ps->psargs)) == nil)
+			fprint(2, "warning: out of memory saving core command line\n");
+		break;
+	case ElfNotePrTaskstruct:
+		dprint("note taskstruct\n");
+		break;
+	case ElfNotePrAuxv:
+		dprint("note auxv\n");
+		break;
+	case ElfNotePrStatus:
+		dprint("note status\n");
+		if(note->descsz < StatusSize){
+			dprint("too small\n");
+			break;
+		}
+		st = (Status*)note->desc;
+		dprint("sig=%ud code=%ud errno=%ud cursig=%ud sigpend=0x%ux sighold=0x%ux\n",
+			(uint)m->swap4(st->signo),
+			(uint)m->swap4(st->code),
+			(uint)m->swap4(st->errno),
+			(uint)m->swap4(st->cursig),
+			(uint)m->swap4(st->sigpend),
+			(uint)m->swap4(st->sighold));
+		dprint("pid=%ud ppid=%ud pgrp=%ud sid=%ud\n",
+			(uint)m->swap4(st->pid),
+			(uint)m->swap4(st->ppid),	
+			(uint)m->swap4(st->pgrp),
+			(uint)m->swap4(st->sid));
+		dprint("utime=%ud.%06ud stime=%ud.%06ud cutime=%ud.%06ud cstime=%ud.%06ud\n",
+			(uint)m->swap4(st->utime[0]),
+			(uint)m->swap4(st->utime[1]),
+			(uint)m->swap4(st->stime[0]),
+			(uint)m->swap4(st->stime[1]),
+			(uint)m->swap4(st->cutime[0]),
+			(uint)m->swap4(st->cutime[1]),
+			(uint)m->swap4(st->cstime[0]),
+			(uint)m->swap4(st->cstime[1]));
+		dprint("fpvalid=%ud\n",
+			(uint)m->swap4(st->fpvalid));
+		if((fp->thread = realloc(fp->thread, (1+fp->nthread)*sizeof(fp->thread[0]))) == nil){
+			fprint(2, "warning: out of memory saving thread info\n");
+			return;
+		}
+		i = fp->nthread;
+		fp->thread[i].id = m->swap4(st->pid);
+		u = malloc(sizeof *u);
+		if(u == nil){
+			fprint(2, "warning: out of memory saving thread info\n");
+			return;
+		}
+		fp->thread[i].ureg = u;
+		linux2ureg386(&st->reg, u);
+		fp->nthread++;
+		break;
+	case ElfNotePrFpreg:
+		dprint("note fpreg\n");
+		/* XXX maybe record floating-point registers eventually */
+		break;
+	case ElfNotePrXfpreg:
+		dprint("note xfpreg\n");
+		/* XXX maybe record floating-point registers eventually */
+		break;
+	default:
+		dprint("note %d\n", note->type);
+	}
+}
+