Support the generation of coredumps for 32-bits binaries under

COMPAT_NETBSD32.  They haven't worked for 5 years.

Silently agreed by the tech-kern readers.

XXX sparc64 MD glue still lacking.
XXX The FPU registers on i386 are not dumped correctly, according to my
XXX tests.  It shouldn't be much work for someone who has the slightest
XXX idea of how that stuff is supposed to be laid out on i386.
This commit is contained in:
cube 2006-03-12 20:25:25 +00:00
parent b85c051fa8
commit 209be910b7
5 changed files with 159 additions and 29 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: netbsd32_machdep.c,v 1.20 2006/01/14 17:14:46 hamajima Exp $ */
/* $NetBSD: netbsd32_machdep.c,v 1.21 2006/03/12 20:25:25 cube Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.20 2006/01/14 17:14:46 hamajima Exp $");
__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.21 2006/03/12 20:25:25 cube Exp $");
#include "opt_compat_netbsd.h"
#include "opt_execfmt.h"
@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.20 2006/01/14 17:14:46 hamaji
#include <sys/buf.h>
#include <sys/vnode.h>
#include <sys/ras.h>
#include <sys/ptrace.h>
#include <machine/fpu.h>
#include <machine/frame.h>
@ -71,9 +72,6 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.20 2006/01/14 17:14:46 hamaji
const char machine32[] = "i386";
const char machine_arch32[] = "i386";
int process_read_fpregs32(struct lwp *, struct fpreg32 *);
int process_read_regs32(struct lwp *, struct reg32 *);
extern void (osyscall_return) __P((void));
static int x86_64_get_mtrr32(struct lwp *, void *, register_t *);
@ -436,12 +434,12 @@ cpu_coredump32(struct lwp *l, void *iocookie, struct core32 *chdr)
}
/* Save integer registers. */
error = process_read_regs32(l, &md_core.intreg);
error = netbsd32_process_read_regs(l, &md_core.intreg);
if (error)
return error;
/* Save floating point registers. */
error = process_read_fpregs32(l, &md_core.freg);
error = netbsd32_process_read_fpregs(l, &md_core.freg);
if (error)
return error;
@ -458,9 +456,8 @@ cpu_coredump32(struct lwp *l, void *iocookie, struct core32 *chdr)
sizeof(md_core));
}
int
process_read_regs32(struct lwp *l, struct reg32 *regs)
netbsd32_process_read_regs(struct lwp *l, struct reg32 *regs)
{
struct trapframe *tf = l->l_md.md_regs;
@ -485,21 +482,85 @@ process_read_regs32(struct lwp *l, struct reg32 *regs)
return (0);
}
int
process_read_fpregs32(struct lwp *l, struct fpreg32 *regs)
/*
* XXX-cube (20060311): This doesn't seem to work fine.
*/
static int
xmm_to_s87_tag(const uint8_t *fpac, int regno, uint8_t tw)
{
struct oldfsave frame;
static const uint8_t empty_significand[8] = { 0 };
int tag;
uint16_t exponent;
if (l->l_md.md_flags & MDP_USEDFPU) {
fpusave_lwp(l, 1);
} else {
memset(&frame, 0, sizeof(*regs));
frame.fs_control = __NetBSD_NPXCW__;
frame.fs_tag = 0xffff;
l->l_md.md_flags |= MDP_USEDFPU;
if (tw & (1U << regno)) {
exponent = fpac[8] | (fpac[9] << 8);
switch (exponent) {
case 0x7fff:
tag = 2;
break;
case 0x0000:
if (memcmp(empty_significand, fpac,
sizeof(empty_significand)) == 0)
tag = 1;
else
tag = 2;
break;
default:
if ((fpac[7] & 0x80) == 0)
tag = 2;
else
tag = 0;
break;
}
} else
tag = 3;
return (tag);
}
int
netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *regs)
{
struct savefpu *sf = &l->l_addr->u_pcb.pcb_savefpu;
struct fpreg regs64;
struct save87 *s87 = (struct save87 *)regs;
int error, i;
/*
* All that stuff makes no sense in i386 code :(
*/
error = process_read_fpregs(l, &regs64);
if (error)
return error;
s87->sv_env.en_cw = regs64.fxstate.fx_fcw;
s87->sv_env.en_sw = regs64.fxstate.fx_fsw;
s87->sv_env.en_fip = regs64.fxstate.fx_rip >> 16; /* XXX Order? */
s87->sv_env.en_fcs = regs64.fxstate.fx_rip & 0xffff;
s87->sv_env.en_opcode = regs64.fxstate.fx_fop;
s87->sv_env.en_foo = regs64.fxstate.fx_rdp >> 16; /* XXX See above */
s87->sv_env.en_fos = regs64.fxstate.fx_rdp & 0xffff;
s87->sv_env.en_tw = 0;
s87->sv_ex_tw = 0;
for (i = 0; i < 8; i++) {
s87->sv_env.en_tw |=
(xmm_to_s87_tag((uint8_t *)&regs64.fxstate.fx_st[i][0], i,
regs64.fxstate.fx_ftw) << (i * 2));
s87->sv_ex_tw |=
(xmm_to_s87_tag((uint8_t *)&regs64.fxstate.fx_st[i][0], i,
sf->fp_ex_tw) << (i * 2));
memcpy(&s87->sv_ac[i].fp_bytes, &regs64.fxstate.fx_st[i][0],
sizeof(s87->sv_ac[i].fp_bytes));
}
memcpy(regs, &frame, sizeof(*regs));
s87->sv_ex_sw = sf->fp_ex_sw;
return (0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: netbsd32_machdep.h,v 1.8 2005/12/11 12:16:25 christos Exp $ */
/* $NetBSD: netbsd32_machdep.h,v 1.9 2006/03/12 20:25:25 cube Exp $ */
#ifndef _MACHINE_NETBSD32_H_
#define _MACHINE_NETBSD32_H_
@ -130,6 +130,32 @@ struct x86_64_set_mtrr_args32 {
uint32_t n;
};
struct env87 {
int32_t en_cw;
int32_t en_sw;
int32_t en_tw;
int32_t en_fip;
uint16_t en_fcs;
uint16_t en_opcode;
int32_t en_foo;
int32_t en_fos;
} __attribute__((packed));
struct fpacc87 {
uint8_t fp_bytes[10];
} __attribute__((packed));
struct save87 {
struct env87 sv_env;
struct fpacc87 sv_ac[8];
int32_t sv_ex_sw;
int32_t sv_ex_tw;
uint8_t sv_pad[8 * 2 - 2 * 4];
} __attribute__((packed));
#define NETBSD32_MID_MACHINE MID_I386
int netbsd32_process_read_regs(struct lwp *, struct reg32 *);
int netbsd32_process_read_fpregs(struct lwp *, struct fpreg32 *);
#endif /* _MACHINE_NETBSD32_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: ptrace.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */
/* $NetBSD: ptrace.h,v 1.2 2006/03/12 20:25:25 cube Exp $ */
/*
* Copyright (c) 1993 Christopher G. Demetriou
@ -38,3 +38,17 @@
#define PT_SETREGS (PT_FIRSTMACH + 2)
#define PT_GETFPREGS (PT_FIRSTMACH + 3)
#define PT_SETFPREGS (PT_FIRSTMACH + 4)
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd32.h"
#ifdef COMPAT_NETBSD32
#include <machine/netbsd32_machdep.h>
#define process_read_regs32 netbsd32_process_read_regs
#define process_read_fpregs32 netbsd32_process_read_fpregs
#define process_reg32 struct reg32
#define process_fpreg32 struct fpreg32
#endif
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: core_elf32.c,v 1.22 2005/12/08 03:05:40 thorpej Exp $ */
/* $NetBSD: core_elf32.c,v 1.23 2006/03/12 20:25:26 cube Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.22 2005/12/08 03:05:40 thorpej Exp $");
__KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.23 2006/03/12 20:25:26 cube Exp $");
/* If not included by core_elf64.c, ELFSIZE won't be defined. */
#ifndef ELFSIZE
@ -83,6 +83,11 @@ static int ELFNAMEEND(coredump_note)(struct proc *, struct lwp *, void *,
#define ELFROUNDSIZE 4 /* XXX Should it be sizeof(Elf_Word)? */
#define elfround(x) roundup((x), ELFROUNDSIZE)
#define elf_process_read_regs CONCAT(process_read_regs, ELFSIZE)
#define elf_process_read_fpregs CONCAT(process_read_fpregs, ELFSIZE)
#define elf_reg CONCAT(process_reg, ELFSIZE)
#define elf_fpreg CONCAT(process_fpreg, ELFSIZE)
int
ELFNAMEEND(coredump)(struct lwp *l, void *cookie)
{
@ -395,9 +400,9 @@ ELFNAMEEND(coredump_note)(struct proc *p, struct lwp *l, void *iocookie,
int size, notesize, error;
int namesize;
char name[64+ELFROUNDSIZE];
struct reg intreg;
elf_reg intreg;
#ifdef PT_GETFPREGS
struct fpreg freg;
elf_fpreg freg;
#endif
size = 0;
@ -410,7 +415,7 @@ ELFNAMEEND(coredump_note)(struct proc *p, struct lwp *l, void *iocookie,
notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(intreg));
if (iocookie) {
PHOLD(l);
error = process_read_regs(l, &intreg);
error = elf_process_read_regs(l, &intreg);
PRELE(l);
if (error)
return (error);
@ -431,7 +436,7 @@ ELFNAMEEND(coredump_note)(struct proc *p, struct lwp *l, void *iocookie,
notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(freg));
if (iocookie) {
PHOLD(l);
error = process_read_fpregs(l, &freg);
error = elf_process_read_fpregs(l, &freg);
PRELE(l);
if (error)
return (error);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ptrace.h,v 1.36 2006/03/05 07:21:38 christos Exp $ */
/* $NetBSD: ptrace.h,v 1.37 2006/03/12 20:25:26 cube Exp $ */
/*-
* Copyright (c) 1984, 1993
@ -82,9 +82,21 @@ struct ptrace_lwpinfo {
#if defined(PT_GETREGS) || defined(PT_SETREGS)
struct reg;
#ifndef process_reg32
#define process_reg32 struct reg
#endif
#ifndef process_reg64
#define process_reg64 struct reg
#endif
#endif
#if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
struct fpreg;
#ifndef process_fpreg32
#define process_fpreg32 struct fpreg
#endif
#ifndef process_fpreg64
#define process_fpreg64 struct fpreg
#endif
#endif
int process_doregs(struct lwp *, struct lwp *, struct uio *);
@ -101,9 +113,21 @@ void process_stoptrace(struct lwp *);
void proc_reparent(struct proc *, struct proc *);
#ifdef PT_GETFPREGS
int process_read_fpregs(struct lwp *, struct fpreg *);
#ifndef process_read_fpregs32
#define process_read_fpregs32 process_read_fpregs
#endif
#ifndef process_read_fpregs64
#define process_read_fpregs64 process_read_fpregs
#endif
#endif
#ifdef PT_GETREGS
int process_read_regs(struct lwp *, struct reg *);
#ifndef process_read_regs32
#define process_read_regs32 process_read_regs
#endif
#ifndef process_read_regs64
#define process_read_regs64 process_read_regs
#endif
#endif
int process_set_pc(struct lwp *, caddr_t);
int process_sstep(struct lwp *, int);