Add __elfN(dump_thread). This function is called from __elfN(coredump)

to allow dumping per-thread machine specific notes. On ia64 we use this
function to flush the dirty registers onto the backingstore before we
write out the PRSTATUS notes.

Tested on: alpha, amd64, i386, ia64 & sparc64
Not tested on: arm, powerpc
This commit is contained in:
Marcel Moolenaar 2004-08-11 02:35:06 +00:00
parent b505f47bef
commit 4da47b2fec
12 changed files with 121 additions and 78 deletions

View File

@ -106,6 +106,13 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
&freebsd_brand_oinfo);
void
elf64_dump_thread(struct thread *td __unused, void *dst __unused,
size_t *off __unused)
{
}
/* Process one elf relocation with addend. */
static int
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,

View File

@ -102,6 +102,14 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_oinfo);
void
elf64_dump_thread(struct thread *td __unused, void *dst __unused,
size_t *off __unused)
{
}
/* Process one elf relocation with addend. */
static int
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,

View File

@ -102,6 +102,14 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_oinfo);
void
elf32_dump_thread(struct thread *td __unused, void *dst __unused,
size_t *off __unused)
{
}
/* Process one elf relocation with addend. */
static int
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,

View File

@ -157,6 +157,14 @@ SYSINIT(oia32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&ia32_brand_oinfo);
void
elf32_dump_thread(struct thread *td __unused, void *dst __unused,
size_t *off __unused)
{
}
/* XXX may be freebsd32 MI */
static register_t *
ia32_copyout_strings(struct image_params *imgp)

View File

@ -102,6 +102,14 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_oinfo);
void
elf32_dump_thread(struct thread *td __unused, void *dst __unused,
size_t *off __unused)
{
}
/* Process one elf relocation with addend. */
static int
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,

View File

@ -49,7 +49,9 @@
#include <machine/md_var.h>
#include <machine/unwind.h>
static int ia64_coredump(struct thread *, struct vnode *, off_t);
Elf_Addr link_elf_get_gp(linker_file_t);
extern Elf_Addr fptr_storage[];
struct sysentvec elf64_freebsd_sysvec = {
SYS_MAXSYSCALL,
@ -66,7 +68,7 @@ struct sysentvec elf64_freebsd_sysvec = {
NULL, /* &szsigcode */
NULL,
"FreeBSD ELF64",
ia64_coredump,
__elfN(coredump),
NULL,
MINSIGSTKSZ,
PAGE_SIZE,
@ -81,67 +83,40 @@ struct sysentvec elf64_freebsd_sysvec = {
};
static Elf64_Brandinfo freebsd_brand_info = {
ELFOSABI_FREEBSD,
EM_IA_64,
"FreeBSD",
NULL,
"/libexec/ld-elf.so.1",
&elf64_freebsd_sysvec,
NULL,
};
ELFOSABI_FREEBSD,
EM_IA_64,
"FreeBSD",
NULL,
"/libexec/ld-elf.so.1",
&elf64_freebsd_sysvec,
NULL,
};
SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_info);
(sysinit_cfunc_t)elf64_insert_brand_entry, &freebsd_brand_info);
static Elf64_Brandinfo freebsd_brand_oinfo = {
ELFOSABI_FREEBSD,
EM_IA_64,
"FreeBSD",
NULL,
"/usr/libexec/ld-elf.so.1",
&elf64_freebsd_sysvec,
NULL,
};
ELFOSABI_FREEBSD,
EM_IA_64,
"FreeBSD",
NULL,
"/usr/libexec/ld-elf.so.1",
&elf64_freebsd_sysvec,
NULL,
};
SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_oinfo);
(sysinit_cfunc_t)elf64_insert_brand_entry, &freebsd_brand_oinfo);
Elf_Addr link_elf_get_gp(linker_file_t);
extern Elf_Addr fptr_storage[];
static int
ia64_coredump(struct thread *td, struct vnode *vp, off_t limit)
void
elf64_dump_thread(struct thread *td, void *dst, size_t *off __unused)
{
struct trapframe *tf;
uint64_t bspst, kstk, ndirty, rnat;
tf = td->td_frame;
ndirty = tf->tf_special.ndirty;
if (ndirty != 0) {
kstk = td->td_kstack + (tf->tf_special.bspstore & 0x1ffUL);
__asm __volatile("mov ar.rsc=0;;");
__asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
/* Make sure we have all the user registers written out. */
if (bspst - kstk < ndirty) {
__asm __volatile("flushrs;;");
__asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
}
__asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat));
__asm __volatile("mov ar.rsc=3");
copyout((void*)kstk, (void*)tf->tf_special.bspstore, ndirty);
kstk += ndirty;
tf->tf_special.bspstore += ndirty;
tf->tf_special.ndirty = 0;
tf->tf_special.rnat =
(bspst > kstk && (bspst & 0x1ffUL) < (kstk & 0x1ffUL))
? *(uint64_t*)(kstk | 0x1f8UL) : rnat;
}
return (elf64_coredump(td, vp, limit));
/* Flush the dirty registers onto the backingstore. */
if (dst == NULL)
ia64_flush_dirty(td, &td->td_frame->tf_special);
}
static Elf_Addr
lookup_fdesc(linker_file_t lf, Elf_Word symidx, elf_lookup_fn lookup)
{

View File

@ -1034,36 +1034,41 @@ makectx(struct trapframe *tf, struct pcb *pcb)
save_callee_saved_fp(&pcb->pcb_preserved_fp);
}
void
ia64_flush_dirty(struct thread *td, struct _special *r)
{
uint64_t bspst, kstk, rnat;
if (r->ndirty == 0)
return;
kstk = td->td_kstack + (r->bspstore & 0x1ffUL);
__asm __volatile("mov ar.rsc=0;;");
__asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
/* Make sure we have all the user registers written out. */
if (bspst - kstk < r->ndirty) {
__asm __volatile("flushrs;;");
__asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
}
__asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat));
__asm __volatile("mov ar.rsc=3");
copyout((void*)kstk, (void*)r->bspstore, r->ndirty);
kstk += r->ndirty;
r->rnat = (bspst > kstk && (bspst & 0x1ffUL) < (kstk & 0x1ffUL))
? *(uint64_t*)(kstk | 0x1f8UL) : rnat;
r->bspstore += r->ndirty;
r->ndirty = 0;
}
int
get_mcontext(struct thread *td, mcontext_t *mc, int flags)
{
struct trapframe *tf;
uint64_t bspst, kstk, rnat;
tf = td->td_frame;
bzero(mc, sizeof(*mc));
if (tf->tf_special.ndirty != 0) {
kstk = td->td_kstack + (tf->tf_special.bspstore & 0x1ffUL);
__asm __volatile("mov ar.rsc=0;;");
__asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
/* Make sure we have all the user registers written out. */
if (bspst - kstk < tf->tf_special.ndirty) {
__asm __volatile("flushrs;;");
__asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
}
__asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat));
__asm __volatile("mov ar.rsc=3");
copyout((void*)kstk, (void*)tf->tf_special.bspstore,
tf->tf_special.ndirty);
kstk += tf->tf_special.ndirty;
mc->mc_special = tf->tf_special;
mc->mc_special.rnat =
(bspst > kstk && (bspst & 0x1ffUL) < (kstk & 0x1ffUL))
? *(uint64_t*)(kstk | 0x1f8UL) : rnat;
mc->mc_special.bspstore += mc->mc_special.ndirty;
mc->mc_special.ndirty = 0;
} else
mc->mc_special = tf->tf_special;
mc->mc_special = tf->tf_special;
ia64_flush_dirty(td, &mc->mc_special);
if (tf->tf_flags & FRAME_SYSCALL) {
mc->mc_flags |= _MC_FLAGS_SYSCALL_CONTEXT;
mc->mc_scratch = tf->tf_scratch;

View File

@ -65,6 +65,7 @@ extern char esigcode[];
extern int szsigcode;
extern long Maxmem;
struct _special;
struct fpreg;
struct reg;
struct thread;
@ -75,6 +76,7 @@ int copyout_regstack(struct thread *, uint64_t *, uint64_t *);
void cpu_mp_add(u_int, u_int, u_int);
int do_ast(struct trapframe *);
int ia64_count_cpus(void);
void ia64_flush_dirty(struct thread *, struct _special *);
int ia64_highfp_drop(struct thread *);
int ia64_highfp_save(struct thread *);
void ia64_init(void);

View File

@ -1204,8 +1204,11 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs)
sizeof *status);
__elfN(putnote)(dst, off, "FreeBSD", NT_FPREGSET, fpregset,
sizeof *fpregset);
/* XXX allow for MD specific notes. */
/*
* Allow for MD specific notes, as well as any MD
* specific preparations for writing MI notes.
*/
__elfN(dump_thread)(thr, dst, off);
thr = (thr == td) ? TAILQ_FIRST(&p->p_threads) :
TAILQ_NEXT(thr, td_plist);

View File

@ -105,6 +105,14 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_oinfo);
void
elf32_dump_thread(struct thread *td __unused, void *dst __unused,
size_t *off __unused)
{
}
/* Process one elf relocation with addend. */
static int
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,

View File

@ -115,6 +115,14 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_oinfo);
void
elf64_dump_thread(struct thread *td __unused, void *dst __unused,
size_t *off __unused)
{
}
/*
* The following table holds for each relocation type:
* - the width in bits of the memory location the relocation

View File

@ -76,6 +76,9 @@ int __elfN(remove_brand_entry)(Elf_Brandinfo *entry);
int __elfN(freebsd_fixup)(register_t **, struct image_params *);
int __elfN(coredump)(struct thread *, struct vnode *, off_t);
/* Machine specific function to dump per-thread information. */
void __elfN(dump_thread)(struct thread *, void *, size_t *);
extern int __elfN(fallback_brand);
#endif /* _KERNEL */