Store a 32-bit PT_LWPINFO struct for 32-bit process core dumps.

Process core notes for a 32-bit process running on a 64-bit host need to
use 32-bit structures so that the note layout matches the layout of notes
of a core dump of a 32-bit process under a 32-bit kernel.

Reviewed by:	kib
Differential Revision:	https://reviews.freebsd.org/D11407
This commit is contained in:
jhb 2017-06-29 21:31:13 +00:00
parent f043fa948f
commit 131ea5a7f4
7 changed files with 121 additions and 59 deletions

View File

@ -35,44 +35,6 @@ struct sigaltstack32 {
int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */
};
union sigval32 {
int sival_int;
u_int32_t sival_ptr;
/* 6.0 compatibility */
int sigval_int;
u_int32_t sigval_ptr;
};
struct siginfo32 {
int si_signo; /* signal number */
int si_errno; /* errno association */
int si_code; /* signal code */
int32_t si_pid; /* sending process */
u_int32_t si_uid; /* sender's ruid */
int si_status; /* exit value */
u_int32_t si_addr; /* faulting instruction */
union sigval32 si_value; /* signal value */
union {
struct {
int _trapno;/* machine specific trap code */
} _fault;
struct {
int _timerid;
int _overrun;
} _timer;
struct {
int _mqd;
} _mesgq;
struct {
int _band; /* band event for SIGPOLL */
} _poll; /* was this ever used ? */
struct {
int __spare1__;
int __spare2__[7];
} __spare__;
} _reason;
};
struct osigevent32 {
int sigev_notify; /* Notification type */
union {

View File

@ -1875,6 +1875,7 @@ __elfN(putnote)(struct note_info *ninfo, struct sbuf *sb)
#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
#include <compat/freebsd32/freebsd32.h>
#include <compat/freebsd32/freebsd32_signal.h>
typedef struct prstatus32 elf_prstatus_t;
typedef struct prpsinfo32 elf_prpsinfo_t;
@ -2029,13 +2030,17 @@ __elfN(note_ptlwpinfo)(void *arg, struct sbuf *sb, size_t *sizep)
struct thread *td;
size_t size;
int structsize;
#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
struct ptrace_lwpinfo32 pl;
#else
struct ptrace_lwpinfo pl;
#endif
td = (struct thread *)arg;
size = sizeof(structsize) + sizeof(struct ptrace_lwpinfo);
size = sizeof(structsize) + sizeof(pl);
if (sb != NULL) {
KASSERT(*sizep == size, ("invalid size"));
structsize = sizeof(struct ptrace_lwpinfo);
structsize = sizeof(pl);
sbuf_bcat(sb, &structsize, sizeof(structsize));
bzero(&pl, sizeof(pl));
pl.pl_lwpid = td->td_tid;
@ -2045,11 +2050,15 @@ __elfN(note_ptlwpinfo)(void *arg, struct sbuf *sb, size_t *sizep)
if (td->td_si.si_signo != 0) {
pl.pl_event = PL_EVENT_SIGNAL;
pl.pl_flags |= PL_FLAG_SI;
#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
siginfo_to_siginfo32(&td->td_si, &pl.pl_siginfo);
#else
pl.pl_siginfo = td->td_si;
#endif
}
strcpy(pl.pl_tdname, td->td_name);
/* XXX TODO: supply more information in struct ptrace_lwpinfo*/
sbuf_bcat(sb, &pl, sizeof(struct ptrace_lwpinfo));
sbuf_bcat(sb, &pl, sizeof(pl));
}
*sizep = size;
}

View File

@ -87,20 +87,6 @@ struct ptrace_vm_entry32 {
u_int pve_fsid;
uint32_t pve_path;
};
struct ptrace_lwpinfo32 {
lwpid_t pl_lwpid; /* LWP described. */
int pl_event; /* Event that stopped the LWP. */
int pl_flags; /* LWP flags. */
sigset_t pl_sigmask; /* LWP signal mask */
sigset_t pl_siglist; /* LWP pending signal */
struct siginfo32 pl_siginfo; /* siginfo for signal */
char pl_tdname[MAXCOMLEN + 1]; /* LWP name. */
pid_t pl_child_pid; /* New child pid */
u_int pl_syscall_code;
u_int pl_syscall_narg;
};
#endif
/*

View File

@ -138,6 +138,21 @@ struct ptrace_lwpinfo {
u_int pl_syscall_narg;
};
#if defined(_WANT_LWPINFO32) || (defined(_KERNEL) && defined(__LP64__))
struct ptrace_lwpinfo32 {
lwpid_t pl_lwpid; /* LWP described. */
int pl_event; /* Event that stopped the LWP. */
int pl_flags; /* LWP flags. */
sigset_t pl_sigmask; /* LWP signal mask */
sigset_t pl_siglist; /* LWP pending signal */
struct siginfo32 pl_siginfo; /* siginfo for signal */
char pl_tdname[MAXCOMLEN + 1]; /* LWP name. */
pid_t pl_child_pid; /* New child pid */
u_int pl_syscall_code;
u_int pl_syscall_narg;
};
#endif
/* Argument structure for PT_VM_ENTRY. */
struct ptrace_vm_entry {
int pve_entry; /* Entry number used for iteration. */

View File

@ -174,6 +174,16 @@ union sigval {
int sigval_int;
void *sigval_ptr;
};
#if defined(_WANT_LWPINFO32) || (defined(_KERNEL) && defined(__LP64__))
union sigval32 {
int sival_int;
uint32_t sival_ptr;
/* 6.0 compatibility */
int sigval_int;
uint32_t sigval_ptr;
};
#endif
#endif
#if __POSIX_VISIBLE >= 199309
@ -256,6 +266,38 @@ typedef struct __siginfo {
#define si_mqd _reason._mesgq._mqd
#define si_band _reason._poll._band
#if defined(_WANT_LWPINFO32) || (defined(_KERNEL) && defined(__LP64__))
struct siginfo32 {
int si_signo; /* signal number */
int si_errno; /* errno association */
int si_code; /* signal code */
__pid_t si_pid; /* sending process */
__uid_t si_uid; /* sender's ruid */
int si_status; /* exit value */
uint32_t si_addr; /* faulting instruction */
union sigval32 si_value; /* signal value */
union {
struct {
int _trapno;/* machine specific trap code */
} _fault;
struct {
int _timerid;
int _overrun;
} _timer;
struct {
int _mqd;
} _mesgq;
struct {
int32_t _band; /* band event for SIGPOLL */
} _poll; /* was this ever used ? */
struct {
int32_t __spare1__;
int __spare2__[7];
} __spare__;
} _reason;
};
#endif
/** si_code **/
/* codes for SIGILL */
#define ILL_ILLOPC 1 /* Illegal opcode. */

View File

@ -5,6 +5,7 @@
#define __ELF_WORD_SIZE 32
#define _MACHINE_ELF_WANT_32BIT
#define _WANT_LWPINFO32
#include <sys/procfs.h>
@ -46,3 +47,42 @@ elf_convert_fpregset(elfcore_fpregset_t *rd, struct fpreg *rs)
#error Unsupported architecture
#endif
}
static void
elf_convert_siginfo(struct siginfo32 *sid, siginfo_t *sis)
{
bzero(sid, sizeof(*sid));
sid->si_signo = sis->si_signo;
sid->si_errno = sis->si_errno;
sid->si_code = sis->si_code;
sid->si_pid = sis->si_pid;
sid->si_uid = sis->si_uid;
sid->si_status = sis->si_status;
sid->si_addr = (uintptr_t)sis->si_addr;
#if _BYTE_ORDER == _BIG_ENDIAN
if (sis->si_value.sival_int == 0)
sid->si_value.sival_ptr = (uintptr_t)sis->si_value.sival_ptr;
else
#endif
sid->si_value.sival_int = sis->si_value.sival_int;
sid->si_timerid = sis->si_timerid;
sid->si_overrun = sis->si_overrun;
}
static void
elf_convert_lwpinfo(struct ptrace_lwpinfo32 *pld, struct ptrace_lwpinfo *pls)
{
pld->pl_lwpid = pls->pl_lwpid;
pld->pl_event = pls->pl_event;
pld->pl_flags = pls->pl_flags;
pld->pl_sigmask = pls->pl_sigmask;
pld->pl_siglist = pls->pl_siglist;
elf_convert_siginfo(&pld->pl_siginfo, &pls->pl_siginfo);
memcpy(pld->pl_tdname, pls->pl_tdname, sizeof(pld->pl_tdname));
pld->pl_child_pid = pls->pl_child_pid;
pld->pl_syscall_code = pls->pl_syscall_code;
pld->pl_syscall_narg = pls->pl_syscall_narg;
}

View File

@ -81,15 +81,20 @@ typedef struct fpreg32 elfcore_fpregset_t;
typedef struct reg32 elfcore_gregset_t;
typedef struct prpsinfo32 elfcore_prpsinfo_t;
typedef struct prstatus32 elfcore_prstatus_t;
typedef struct ptrace_lwpinfo32 elfcore_lwpinfo_t;
static void elf_convert_gregset(elfcore_gregset_t *rd, struct reg *rs);
static void elf_convert_fpregset(elfcore_fpregset_t *rd, struct fpreg *rs);
static void elf_convert_lwpinfo(struct ptrace_lwpinfo32 *pld,
struct ptrace_lwpinfo *pls);
#else
typedef fpregset_t elfcore_fpregset_t;
typedef gregset_t elfcore_gregset_t;
typedef prpsinfo_t elfcore_prpsinfo_t;
typedef prstatus_t elfcore_prstatus_t;
typedef struct ptrace_lwpinfo elfcore_lwpinfo_t;
#define elf_convert_gregset(d,s) *d = *s
#define elf_convert_fpregset(d,s) *d = *s
#define elf_convert_lwpinfo(d,s) *d = *s
#endif
typedef void* (*notefunc_t)(void *, size_t *);
@ -696,15 +701,18 @@ static void *
elf_note_ptlwpinfo(void *arg, size_t *sizep)
{
lwpid_t tid;
elfcore_lwpinfo_t *elf_info;
struct ptrace_lwpinfo lwpinfo;
void *p;
tid = *(lwpid_t *)arg;
p = calloc(1, sizeof(int) + sizeof(struct ptrace_lwpinfo));
p = calloc(1, sizeof(int) + sizeof(elfcore_lwpinfo_t));
if (p == NULL)
errx(1, "out of memory");
*(int *)p = sizeof(struct ptrace_lwpinfo);
ptrace(PT_LWPINFO, tid,
(char *)p + sizeof (int), sizeof(struct ptrace_lwpinfo));
*(int *)p = sizeof(elfcore_lwpinfo_t);
elf_info = (void *)((int *)p + 1);
ptrace(PT_LWPINFO, tid, (void *)&lwpinfo, sizeof(lwpinfo));
elf_convert_lwpinfo(elf_info, &lwpinfo);
*sizep = sizeof(int) + sizeof(struct ptrace_lwpinfo);
return (p);