diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index f20c64d..3a7cf7f 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -1045,7 +1045,7 @@ generic_elf_coredump(struct lwp *lp, int sig, struct file *fp, off_t limit) target.buf = kmalloc(target.off_max, M_TEMP, M_WAITOK|M_ZERO); error = elf_corehdr(lp, sig, fp, cred, seginfo.count, &target); - +kprintf("xxx: generic_elf_coredump: did elf_corehdr: %d\n", error); /* Write the contents of all of the writable segments. */ if (error == 0) { Elf_Phdr *php; @@ -1056,6 +1056,7 @@ generic_elf_coredump(struct lwp *lp, int sig, struct file *fp, off_t limit) for (i = 0; i < seginfo.count; i++) { error = fp_write(fp, (caddr_t)php->p_vaddr, php->p_filesz, &nbytes, UIO_USERSPACE); +kprintf("xxx: generic_elf_coredump: did fp_write: %d\n", error); if (error != 0) break; php++; @@ -1296,11 +1297,13 @@ elf_corehdr(struct lwp *lp, int sig, struct file *fp, struct ucred *cred, * it may not be restored from the same file handle. */ error = elf_puthdr(lp, target, sig, WRITE, numsegs, fp); +kprintf("xxx: elf_corehdr: did elf_puthdr: %d\n", error); /* Write it to the core file. */ if (error == 0) { error = fp_write(fp, target->buf, target->off, &nbytes, UIO_SYSSPACE); +kprintf("xxx: elf_corehdr: did fp_write: %d\n", error); } return error; } @@ -1323,6 +1326,7 @@ elf_puthdr(struct lwp *lp, elf_buf_t target, int sig, enum putmode mode, phdr = target_reserve(target, (numsegs + 1) * sizeof(Elf_Phdr), &error); noteoff = target->off; +/* XXX SJG - why wouldn't error = 0 here? */ if (error == 0) elf_putallnotes(lp, target, sig, mode); notesz = target->off - noteoff; @@ -1414,10 +1418,12 @@ elf_putallnotes(struct lwp *corelp, elf_buf_t target, int sig, prstatus_t status; prfpregset_t fpregs; prpsinfo_t psinfo; + prsavetls_t tls; } *tmpdata; prstatus_t *status; prfpregset_t *fpregs; prpsinfo_t *psinfo; + prsavetls_t *tls; struct lwp *lp; /* @@ -1428,11 +1434,13 @@ elf_putallnotes(struct lwp *corelp, elf_buf_t target, int sig, status = &tmpdata->status; fpregs = &tmpdata->fpregs; psinfo = &tmpdata->psinfo; + tls = &tmpdata->tls; } else { tmpdata = NULL; status = NULL; fpregs = NULL; psinfo = NULL; + tls = NULL; } /* @@ -1463,6 +1471,7 @@ elf_putallnotes(struct lwp *corelp, elf_buf_t target, int sig, status->pr_statussz = sizeof(prstatus_t); status->pr_gregsetsz = sizeof(gregset_t); status->pr_fpregsetsz = sizeof(fpregset_t); + status->pr_savetlssz = sizeof(prsavetls_t); status->pr_osreldate = osreldate; status->pr_cursig = sig; /* @@ -1473,6 +1482,9 @@ elf_putallnotes(struct lwp *corelp, elf_buf_t target, int sig, status->pr_pid = corelp->lwp_tid; fill_regs(corelp, &status->pr_reg); fill_fpregs(corelp, fpregs); +// XXX SJG fill_segdescrs(corelp, segdescrs); +kprintf("xxx - saving out tls data for first thread\n"); +bcopy(&corelp->lwp_thread->td_tls, tls, sizeof *tls); } error = elf_putnote(target, "CORE", NT_PRSTATUS, status, sizeof *status); @@ -1482,6 +1494,10 @@ elf_putallnotes(struct lwp *corelp, elf_buf_t target, int sig, elf_putnote(target, "CORE", NT_FPREGSET, fpregs, sizeof *fpregs); if (error) goto exit; + error = + elf_putnote(target, "CORE", NT_TLS, tls, sizeof *tls); + if (error) + goto exit; /* * Then append notes for other LWPs. @@ -1496,6 +1512,9 @@ elf_putallnotes(struct lwp *corelp, elf_buf_t target, int sig, status->pr_pid = lp->lwp_tid; fill_regs(lp, &status->pr_reg); fill_fpregs(lp, fpregs); +// XXX SJG +kprintf("xxx - saving out tls data for another thread\n"); +bcopy(&lp->lwp_thread->td_tls, tls, sizeof *tls); } error = elf_putnote(target, "CORE", NT_PRSTATUS, status, sizeof *status); @@ -1505,6 +1524,10 @@ elf_putallnotes(struct lwp *corelp, elf_buf_t target, int sig, fpregs, sizeof *fpregs); if (error) goto exit; + error = elf_putnote(target, "CORE", NT_TLS, + tls, sizeof *tls); + if (error) + goto exit; } exit: @@ -1540,6 +1563,7 @@ elf_putnote(elf_buf_t target, const char *name, int type, if (dst != NULL) bcopy(desc, dst, note.n_descsz); target->off = roundup2(target->off, sizeof(Elf_Word)); +kprintf("xxx: elf_putnote returning with: %d\n", error); return(error); } diff --git a/sys/kern/kern_checkpoint.c b/sys/kern/kern_checkpoint.c index a24e9ed..4815e8e 100644 --- a/sys/kern/kern_checkpoint.c +++ b/sys/kern/kern_checkpoint.c @@ -77,9 +77,10 @@ static int elf_loadphdrs(struct file *fp, Elf_Phdr *phdr, int numsegs); static int elf_getnotes(struct lwp *lp, struct file *fp, size_t notesz); static int elf_demarshalnotes(void *src, prpsinfo_t *psinfo, - prstatus_t *status, prfpregset_t *fpregset, int nthreads); + prstatus_t *status, prfpregset_t *fpregset, prsavetls_t *tls, + int nthreads); static int elf_loadnotes(struct lwp *, prpsinfo_t *, prstatus_t *, - prfpregset_t *); + prfpregset_t *, prsavetls_t *); static int elf_getsigs(struct lwp *lp, struct file *fp); static int elf_getfiles(struct lwp *lp, struct file *fp); static int elf_gettextvp(struct proc *p, struct file *fp); @@ -184,6 +185,7 @@ elf_getnotes(struct lwp *lp, struct file *fp, size_t notesz) prpsinfo_t *psinfo; prstatus_t *status; prfpregset_t *fpregset; + prsavetls_t *tls; nthreads = (notesz - sizeof(prpsinfo_t))/(sizeof(prstatus_t) + sizeof(prfpregset_t)); @@ -194,17 +196,18 @@ elf_getnotes(struct lwp *lp, struct file *fp, size_t notesz) psinfo = kmalloc(sizeof(prpsinfo_t), M_TEMP, M_ZERO | M_WAITOK); status = kmalloc(nthreads*sizeof(prstatus_t), M_TEMP, M_WAITOK); fpregset = kmalloc(nthreads*sizeof(prfpregset_t), M_TEMP, M_WAITOK); + tls = kmalloc(nthreads*sizeof(prsavetls_t), M_TEMP, M_WAITOK); note = kmalloc(notesz, M_TEMP, M_WAITOK); PRINTF(("reading notes section\n")); if ((error = read_check(fp, note, notesz)) != 0) goto done; - error = elf_demarshalnotes(note, psinfo, status, fpregset, nthreads); + error = elf_demarshalnotes(note, psinfo, status, fpregset, tls, nthreads); if (error) goto done; /* fetch register state from notes */ - error = elf_loadnotes(lp, psinfo, status, fpregset); + error = elf_loadnotes(lp, psinfo, status, fpregset, tls); done: if (psinfo) kfree(psinfo, M_TEMP); @@ -212,6 +215,8 @@ elf_getnotes(struct lwp *lp, struct file *fp, size_t notesz) kfree(status, M_TEMP); if (fpregset) kfree(fpregset, M_TEMP); + if (tls) + kfree(tls, M_TEMP); if (note) kfree(note, M_TEMP); return error; @@ -285,7 +290,7 @@ done: static int elf_loadnotes(struct lwp *lp, prpsinfo_t *psinfo, prstatus_t *status, - prfpregset_t *fpregset) + prfpregset_t *fpregset, prsavetls_t *tls) { struct proc *p = lp->lwp_proc; int error; @@ -306,6 +311,9 @@ elf_loadnotes(struct lwp *lp, prpsinfo_t *psinfo, prstatus_t *status, if ((error = set_regs(lp, &status->pr_reg)) != 0) goto done; error = set_fpregs(lp, fpregset); +/* XXX SJG */ +kprintf("xxx: restoring TLS-fu\n"); +bcopy(tls, &lp->lwp_thread->td_tls, sizeof *tls); strlcpy(p->p_comm, psinfo->pr_fname, sizeof(p->p_comm)); /* XXX psinfo->pr_psargs not yet implemented */ done: @@ -356,7 +364,7 @@ elf_getnote(void *src, size_t *off, const char *name, unsigned int type, static int elf_demarshalnotes(void *src, prpsinfo_t *psinfo, prstatus_t *status, - prfpregset_t *fpregset, int nthreads) + prfpregset_t *fpregset, prsavetls_t *tls, int nthreads) { int i; int error; @@ -375,6 +383,10 @@ elf_demarshalnotes(void *src, prpsinfo_t *psinfo, prstatus_t *status, (void **)&fpregset, sizeof(prfpregset_t)); if (error) goto done; + error = elf_getnote(src, &off, "CORE", NT_TLS, + (void **)&tls, sizeof(prsavetls_t)); + if (error) + goto done; /* * The remaining portion needs to be an integer multiple @@ -390,6 +402,10 @@ elf_demarshalnotes(void *src, prpsinfo_t *psinfo, prstatus_t *status, (void **)&fpregset, sizeof(prfpregset_t)); if (error) goto done; + error = elf_getnote(src, &off, "CORE", NT_TLS, + (void **)&tls, sizeof(prsavetls_t)); + if (error) + goto done; } done: @@ -699,6 +715,7 @@ ckpt_freeze_proc(struct lwp *lp, struct file *fp) while (p->p_nstopped < p->p_nthreads - 1) tsleep(&p->p_nstopped, 0, "freeze", 1); error = generic_elf_coredump(lp, SIGCKPT, fp, limit); +PRINTF(("xxx: generic_elf_coredump returned: %d\n", error)); proc_unstop(p); } else { error = ERANGE; diff --git a/sys/sys/ckpt.h b/sys/sys/ckpt.h index 1fe0f0c..a745fb8 100644 --- a/sys/sys/ckpt.h +++ b/sys/sys/ckpt.h @@ -1,3 +1,4 @@ +#define DEBUG 1 /*- * Copyright (c) 2003 Kip Macy All rights reserved. * diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index fa200ad..693db6d 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -385,6 +385,7 @@ typedef struct { #define NT_PRSTATUS 1 /* Process status. */ #define NT_FPREGSET 2 /* Floating point registers. */ #define NT_PRPSINFO 3 /* Process state info. */ +#define NT_TLS 4 /* TLS data. */ /* Symbol Binding - ELFNN_ST_BIND - st_info */ #define STB_LOCAL 0 /* Local symbol */ diff --git a/sys/sys/procfs.h b/sys/sys/procfs.h index de6a4dd..7b90398 100644 --- a/sys/sys/procfs.h +++ b/sys/sys/procfs.h @@ -30,8 +30,15 @@ #ifndef _SYS_PROCFS_H_ #define _SYS_PROCFS_H_ +#ifndef _SYS_PARAM_H_ #include +#endif +#ifndef _SYS_REG_H_ #include +#endif +#ifndef _MACHINE_SEGMENTS_H_ +#include +#endif typedef struct reg gregset_t; typedef struct fpreg fpregset_t; @@ -53,21 +60,23 @@ typedef struct fpreg fpregset_t; * for which each element exists in the structure. */ -#define PRSTATUS_VERSION 1 /* Current version of prstatus_t */ +#define PRSTATUS_VERSION 2 /* Current version of prstatus_t */ typedef struct prstatus { - int pr_version; /* Version number of struct (1) */ - size_t pr_statussz; /* sizeof(prstatus_t) (1) */ - size_t pr_gregsetsz; /* sizeof(gregset_t) (1) */ - size_t pr_fpregsetsz; /* sizeof(fpregset_t) (1) */ - int pr_osreldate; /* Kernel version (1) */ - int pr_cursig; /* Current signal (1) */ - pid_t pr_pid; /* Process ID (1) */ - gregset_t pr_reg; /* General purpose registers (1) */ + int pr_version; /* Version number of struct (1) */ + size_t pr_statussz; /* sizeof(prstatus_t) (1) */ + size_t pr_gregsetsz; /* sizeof(gregset_t) (1) */ + size_t pr_fpregsetsz; /* sizeof(fpregset_t) (1) */ + size_t pr_savetlssz; /* sizeof(struct savetls) (2) */ + int pr_osreldate; /* Kernel version (1) */ + int pr_cursig; /* Current signal (1) */ + pid_t pr_pid; /* Process ID (1) */ + gregset_t pr_reg; /* General purpose registers (1) */ } prstatus_t; typedef gregset_t prgregset_t[1]; typedef fpregset_t prfpregset_t; +typedef struct savetls prsavetls_t; #define PRARGSZ 80 /* Maximum argument bytes saved */