Date: Sun, 28 Mar 2004 14:44:41 -0800 (PST) From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 49851 for review Message-ID: <200403282244.i2SMiffN034641@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=49851 Change 49851 by marcel@marcel_nfs on 2004/03/28 14:44:06 Fix coredumps for multi-threaded applications that use 1:1 or M:N threading. When multiple kernel threads exist in a process, we want to dump the context of each thread so that the debugger has a chance to figure out where each of the bound or system scoped threads was and libthread_db has a chance to map user threads to system threads (if applicable). This change is dependent on kernel threads having IDs. Affected files ... .. //depot/projects/gdb/sys/kern/imgact_elf.c#4 edit Differences ... ==== //depot/projects/gdb/sys/kern/imgact_elf.c#4 (text+ko) ==== @@ -922,8 +922,7 @@ static void each_writable_segment(struct proc *, segment_callback, void *); static int __elfN(corehdr)(struct thread *, struct vnode *, struct ucred *, int, void *, size_t); -static void __elfN(puthdr)(struct proc *, void *, size_t *, - const prstatus_t *, const prfpregset_t *, const prpsinfo_t *, int); +static void __elfN(puthdr)(struct proc *, void *, size_t *, int); static void __elfN(putnote)(void *, size_t *, const char *, int, const void *, size_t); @@ -953,9 +952,7 @@ * size is calculated. */ hdrsize = 0; - __elfN(puthdr)((struct proc *)NULL, (void *)NULL, &hdrsize, - (const prstatus_t *)NULL, (const prfpregset_t *)NULL, - (const prpsinfo_t *)NULL, seginfo.count); + __elfN(puthdr)(p, (void *)NULL, &hdrsize, seginfo.count); if (hdrsize + seginfo.size >= limit) return (EFAULT); @@ -1115,48 +1112,14 @@ size_t hdrsize; void *hdr; { - struct { - prstatus_t status; - prfpregset_t fpregset; - prpsinfo_t psinfo; - } *tempdata; struct proc *p = td->td_proc; size_t off; - prstatus_t *status; - prfpregset_t *fpregset; - prpsinfo_t *psinfo; - - tempdata = malloc(sizeof(*tempdata), M_TEMP, M_ZERO | M_WAITOK); - status = &tempdata->status; - fpregset = &tempdata->fpregset; - psinfo = &tempdata->psinfo; - - /* Gather the information for the header. */ - status->pr_version = PRSTATUS_VERSION; - status->pr_statussz = sizeof(prstatus_t); - status->pr_gregsetsz = sizeof(gregset_t); - status->pr_fpregsetsz = sizeof(fpregset_t); - status->pr_osreldate = osreldate; - status->pr_cursig = p->p_sig; - status->pr_pid = p->p_pid; - fill_regs(td, &status->pr_reg); - fill_fpregs(td, fpregset); - - psinfo->pr_version = PRPSINFO_VERSION; - psinfo->pr_psinfosz = sizeof(prpsinfo_t); - strlcpy(psinfo->pr_fname, p->p_comm, sizeof(psinfo->pr_fname)); - - /* XXX - We don't fill in the command line arguments properly yet. */ - strlcpy(psinfo->pr_psargs, p->p_comm, sizeof(psinfo->pr_psargs)); - /* Fill in the header. */ bzero(hdr, hdrsize); off = 0; - __elfN(puthdr)(p, hdr, &off, status, fpregset, psinfo, numsegs); + __elfN(puthdr)(p, hdr, &off, numsegs); - free(tempdata, M_TEMP); - /* Write it to the core file. */ return (vn_rdwr_inchunks(UIO_WRITE, vp, hdr, hdrsize, (off_t)0, UIO_SYSSPACE, IO_UNIT | IO_DIRECT, cred, NOCRED, NULL, @@ -1164,13 +1127,18 @@ } static void -__elfN(puthdr)(struct proc *p, void *dst, size_t *off, const prstatus_t *status, - const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs) +__elfN(puthdr)(struct proc *p, void *dst, size_t *off, int numsegs) { - size_t ehoff; - size_t phoff; - size_t noteoff; - size_t notesz; + struct { + prstatus_t status; + prfpregset_t fpregset; + prpsinfo_t psinfo; + } *tempdata; + prstatus_t *status; + prfpregset_t *fpregset; + prpsinfo_t *psinfo; + struct thread *thr; + size_t ehoff, noteoff, notesz, phoff; ehoff = *off; *off += sizeof(Elf_Ehdr); @@ -1179,14 +1147,64 @@ *off += (numsegs + 1) * sizeof(Elf_Phdr); noteoff = *off; - __elfN(putnote)(dst, off, "FreeBSD", NT_PRSTATUS, status, - sizeof *status); - __elfN(putnote)(dst, off, "FreeBSD", NT_FPREGSET, fpregset, - sizeof *fpregset); + /* + * Don't allocate space for the notes if we're just calculating + * the size of the header. We also don't collect the data. + */ + if (dst != NULL) { + tempdata = malloc(sizeof(*tempdata), M_TEMP, M_ZERO|M_WAITOK); + status = &tempdata->status; + fpregset = &tempdata->fpregset; + psinfo = &tempdata->psinfo; + } else { + tempdata = NULL; + status = NULL; + fpregset = NULL; + psinfo = NULL; + } + + if (dst != NULL) { + psinfo->pr_version = PRPSINFO_VERSION; + psinfo->pr_psinfosz = sizeof(prpsinfo_t); + strlcpy(psinfo->pr_fname, p->p_comm, sizeof(psinfo->pr_fname)); + /* + * XXX - We don't fill in the command line arguments properly + * yet. + */ + strlcpy(psinfo->pr_psargs, p->p_comm, + sizeof(psinfo->pr_psargs)); + } __elfN(putnote)(dst, off, "FreeBSD", NT_PRPSINFO, psinfo, sizeof *psinfo); + + thr = TAILQ_FIRST(&p->p_threads); + while (thr != NULL) { + if (dst != NULL) { + status->pr_version = PRSTATUS_VERSION; + status->pr_statussz = sizeof(prstatus_t); + status->pr_gregsetsz = sizeof(gregset_t); + status->pr_fpregsetsz = sizeof(fpregset_t); + status->pr_osreldate = osreldate; + status->pr_cursig = p->p_sig; + status->pr_pid = thr->td_tid; + fill_regs(thr, &status->pr_reg); + fill_fpregs(thr, fpregset); + } + __elfN(putnote)(dst, off, "FreeBSD", NT_PRSTATUS, status, + sizeof *status); + __elfN(putnote)(dst, off, "FreeBSD", NT_FPREGSET, fpregset, + sizeof *fpregset); + /* + * XXX allow for MD specific notes. + */ + thr = TAILQ_NEXT(thr, td_plist); + } + notesz = *off - noteoff; + if (dst != NULL) + free(tempdata, M_TEMP); + /* Align up to a page boundary for the program segments. */ *off = round_page(*off);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200403282244.i2SMiffN034641>