elf_prstatus: collect the common part (everything before pr_reg) into a struct

Preparations to doing i386 compat elf_prstatus sanely - rather than duplicating
the beginning of compat_elf_prstatus, take these fields into a separate
structure (compat_elf_prstatus_common), so that it could be reused.  Due to
the incestous relationship between binfmt_elf.c and compat_binfmt_elf.c we
need the same shape change done to native struct elf_prstatus, gathering the
fields prior to pr_reg into a new structure (struct elf_prstatus_common).

Fortunately, offset of pr_reg is always a multiple of 16 with no padding
right before it, so it's possible to turn all the stuff prior to it into
a single member without disturbing the layout.

[build fix from Geert Uytterhoeven folded in]

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2020-06-13 00:08:44 -04:00
parent 8a00dd0012
commit f2485a2dc9
11 changed files with 39 additions and 31 deletions

View File

@ -43,7 +43,7 @@ crash_save_this_cpu(void)
elf_greg_t *dst = (elf_greg_t *)&(prstatus->pr_reg); elf_greg_t *dst = (elf_greg_t *)&(prstatus->pr_reg);
memset(prstatus, 0, sizeof(*prstatus)); memset(prstatus, 0, sizeof(*prstatus));
prstatus->pr_pid = current->pid; prstatus->common.pr_pid = current->pid;
ia64_dump_cpu_regs(dst); ia64_dump_cpu_regs(dst);
cfm = dst[43]; cfm = dst[43];

View File

@ -44,7 +44,8 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
#include <linux/math64.h> #include <linux/math64.h>
#define elf_prstatus elf_prstatus32 #define elf_prstatus elf_prstatus32
struct elf_prstatus32 #define elf_prstatus_common elf_prstatus32_common
struct elf_prstatus32_common
{ {
struct elf_siginfo pr_info; /* Info associated with signal */ struct elf_siginfo pr_info; /* Info associated with signal */
short pr_cursig; /* Current signal */ short pr_cursig; /* Current signal */
@ -58,6 +59,10 @@ struct elf_prstatus32
struct old_timeval32 pr_stime; /* System time */ struct old_timeval32 pr_stime; /* System time */
struct old_timeval32 pr_cutime;/* Cumulative user time */ struct old_timeval32 pr_cutime;/* Cumulative user time */
struct old_timeval32 pr_cstime;/* Cumulative system time */ struct old_timeval32 pr_cstime;/* Cumulative system time */
};
struct elf_prstatus32
{
struct elf_prstatus32_common common:
elf_gregset_t pr_reg; /* GP registers */ elf_gregset_t pr_reg; /* GP registers */
int pr_fpvalid; /* True if math co-processor being used. */ int pr_fpvalid; /* True if math co-processor being used. */
}; };

View File

@ -49,7 +49,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
#include <linux/math64.h> #include <linux/math64.h>
#define elf_prstatus elf_prstatus32 #define elf_prstatus elf_prstatus32
struct elf_prstatus32 struct elf_prstatus32_common
{ {
struct elf_siginfo pr_info; /* Info associated with signal */ struct elf_siginfo pr_info; /* Info associated with signal */
short pr_cursig; /* Current signal */ short pr_cursig; /* Current signal */
@ -63,6 +63,10 @@ struct elf_prstatus32
struct old_timeval32 pr_stime; /* System time */ struct old_timeval32 pr_stime; /* System time */
struct old_timeval32 pr_cutime;/* Cumulative user time */ struct old_timeval32 pr_cutime;/* Cumulative user time */
struct old_timeval32 pr_cstime;/* Cumulative system time */ struct old_timeval32 pr_cstime;/* Cumulative system time */
};
struct elf_prstatus32
{
struct elf_prstatus32_common common:
elf_gregset_t pr_reg; /* GP registers */ elf_gregset_t pr_reg; /* GP registers */
int pr_fpvalid; /* True if math co-processor being used. */ int pr_fpvalid; /* True if math co-processor being used. */
}; };

View File

@ -119,8 +119,8 @@ static void fill_prstatus(struct elf_prstatus *prstatus, int pir,
* As a PIR value could also be '0', add an offset of '100' * As a PIR value could also be '0', add an offset of '100'
* to every PIR to avoid misinterpretations in GDB. * to every PIR to avoid misinterpretations in GDB.
*/ */
prstatus->pr_pid = cpu_to_be32(100 + pir); prstatus->common.pr_pid = cpu_to_be32(100 + pir);
prstatus->pr_ppid = cpu_to_be32(1); prstatus->common.pr_ppid = cpu_to_be32(1);
/* /*
* Indicate SIGUSR1 for crash initiated from kernel. * Indicate SIGUSR1 for crash initiated from kernel.
@ -130,7 +130,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, int pir,
short sig; short sig;
sig = kernel_initiated ? SIGUSR1 : SIGTERM; sig = kernel_initiated ? SIGUSR1 : SIGTERM;
prstatus->pr_cursig = cpu_to_be16(sig); prstatus->common.pr_cursig = cpu_to_be16(sig);
} }
} }

View File

@ -365,7 +365,7 @@ static void *fill_cpu_elf_notes(void *ptr, int cpu, struct save_area *sa)
memcpy(&nt_prstatus.pr_reg.gprs, sa->gprs, sizeof(sa->gprs)); memcpy(&nt_prstatus.pr_reg.gprs, sa->gprs, sizeof(sa->gprs));
memcpy(&nt_prstatus.pr_reg.psw, sa->psw, sizeof(sa->psw)); memcpy(&nt_prstatus.pr_reg.psw, sa->psw, sizeof(sa->psw));
memcpy(&nt_prstatus.pr_reg.acrs, sa->acrs, sizeof(sa->acrs)); memcpy(&nt_prstatus.pr_reg.acrs, sa->acrs, sizeof(sa->acrs));
nt_prstatus.pr_pid = cpu; nt_prstatus.common.pr_pid = cpu;
/* Prepare fpregset (floating point) note */ /* Prepare fpregset (floating point) note */
memset(&nt_fpregset, 0, sizeof(nt_fpregset)); memset(&nt_fpregset, 0, sizeof(nt_fpregset));
memcpy(&nt_fpregset.fpc, &sa->fpc, sizeof(sa->fpc)); memcpy(&nt_fpregset.fpc, &sa->fpc, sizeof(sa->fpc));

View File

@ -1495,7 +1495,7 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
* fill up all the fields in prstatus from the given task struct, except * fill up all the fields in prstatus from the given task struct, except
* registers which need to be filled up separately. * registers which need to be filled up separately.
*/ */
static void fill_prstatus(struct elf_prstatus *prstatus, static void fill_prstatus(struct elf_prstatus_common *prstatus,
struct task_struct *p, long signr) struct task_struct *p, long signr)
{ {
prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
@ -1736,7 +1736,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
* than being the whole note contents. We fill the reset in here. * than being the whole note contents. We fill the reset in here.
* We assume that regset 0 is NT_PRSTATUS. * We assume that regset 0 is NT_PRSTATUS.
*/ */
fill_prstatus(&t->prstatus, t->task, signr); fill_prstatus(&t->prstatus.common, t->task, signr);
regset_get(t->task, &view->regsets[0], regset_get(t->task, &view->regsets[0],
sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg); sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg);
@ -1958,7 +1958,7 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
struct task_struct *p = t->thread; struct task_struct *p = t->thread;
t->num_notes = 0; t->num_notes = 0;
fill_prstatus(&t->prstatus, p, signr); fill_prstatus(&t->prstatus.common, p, signr);
elf_core_copy_task_regs(p, &t->prstatus.pr_reg); elf_core_copy_task_regs(p, &t->prstatus.pr_reg);
fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus),
@ -2037,7 +2037,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
} }
/* now collect the dump for the current */ /* now collect the dump for the current */
memset(info->prstatus, 0, sizeof(*info->prstatus)); memset(info->prstatus, 0, sizeof(*info->prstatus));
fill_prstatus(info->prstatus, current, siginfo->si_signo); fill_prstatus(&info->prstatus->common, current, siginfo->si_signo);
elf_core_copy_regs(&info->prstatus->pr_reg, regs); elf_core_copy_regs(&info->prstatus->pr_reg, regs);
/* Set up header */ /* Set up header */

View File

@ -1191,18 +1191,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
struct elf_prstatus_fdpic struct elf_prstatus_fdpic
{ {
struct elf_siginfo pr_info; /* Info associated with signal */ struct elf_prstatus_common common;
short pr_cursig; /* Current signal */
unsigned long pr_sigpend; /* Set of pending signals */
unsigned long pr_sighold; /* Set of held signals */
pid_t pr_pid;
pid_t pr_ppid;
pid_t pr_pgrp;
pid_t pr_sid;
struct __kernel_old_timeval pr_utime; /* User time */
struct __kernel_old_timeval pr_stime; /* System time */
struct __kernel_old_timeval pr_cutime; /* Cumulative user time */
struct __kernel_old_timeval pr_cstime; /* Cumulative system time */
elf_gregset_t pr_reg; /* GP registers */ elf_gregset_t pr_reg; /* GP registers */
/* When using FDPIC, the loadmap addresses need to be communicated /* When using FDPIC, the loadmap addresses need to be communicated
* to GDB in order for GDB to do the necessary relocations. The * to GDB in order for GDB to do the necessary relocations. The
@ -1301,7 +1290,7 @@ static inline void fill_note(struct memelfnote *note, const char *name, int type
* fill up all the fields in prstatus from the given task struct, except * fill up all the fields in prstatus from the given task struct, except
* registers which need to be filled up separately. * registers which need to be filled up separately.
*/ */
static void fill_prstatus(struct elf_prstatus_fdpic *prstatus, static void fill_prstatus(struct elf_prstatus_common *prstatus,
struct task_struct *p, long signr) struct task_struct *p, long signr)
{ {
prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
@ -1332,9 +1321,6 @@ static void fill_prstatus(struct elf_prstatus_fdpic *prstatus,
} }
prstatus->pr_cutime = ns_to_kernel_old_timeval(p->signal->cutime); prstatus->pr_cutime = ns_to_kernel_old_timeval(p->signal->cutime);
prstatus->pr_cstime = ns_to_kernel_old_timeval(p->signal->cstime); prstatus->pr_cstime = ns_to_kernel_old_timeval(p->signal->cstime);
prstatus->pr_exec_fdpic_loadmap = p->mm->context.exec_fdpic_loadmap;
prstatus->pr_interp_fdpic_loadmap = p->mm->context.interp_fdpic_loadmap;
} }
static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
@ -1405,7 +1391,9 @@ static struct elf_thread_status *elf_dump_thread_status(long signr, struct task_
if (!t) if (!t)
return t; return t;
fill_prstatus(&t->prstatus, p, signr); fill_prstatus(&t->prstatus.common, p, signr);
t->prstatus.pr_exec_fdpic_loadmap = p->mm->context.exec_fdpic_loadmap;
t->prstatus.pr_interp_fdpic_loadmap = p->mm->context.interp_fdpic_loadmap;
regset_get(p, &view->regsets[0], regset_get(p, &view->regsets[0],
sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg); sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg);

View File

@ -50,6 +50,7 @@
* which requires asm/elf.h to define compat_elf_gregset_t et al. * which requires asm/elf.h to define compat_elf_gregset_t et al.
*/ */
#define elf_prstatus compat_elf_prstatus #define elf_prstatus compat_elf_prstatus
#define elf_prstatus_common compat_elf_prstatus_common
#define elf_prpsinfo compat_elf_prpsinfo #define elf_prpsinfo compat_elf_prpsinfo
#undef ns_to_kernel_old_timeval #undef ns_to_kernel_old_timeval

View File

@ -17,7 +17,7 @@ struct compat_elf_siginfo
compat_int_t si_errno; compat_int_t si_errno;
}; };
struct compat_elf_prstatus struct compat_elf_prstatus_common
{ {
struct compat_elf_siginfo pr_info; struct compat_elf_siginfo pr_info;
short pr_cursig; short pr_cursig;
@ -31,6 +31,11 @@ struct compat_elf_prstatus
struct old_timeval32 pr_stime; struct old_timeval32 pr_stime;
struct old_timeval32 pr_cutime; struct old_timeval32 pr_cutime;
struct old_timeval32 pr_cstime; struct old_timeval32 pr_cstime;
};
struct compat_elf_prstatus
{
struct compat_elf_prstatus_common common;
compat_elf_gregset_t pr_reg; compat_elf_gregset_t pr_reg;
compat_int_t pr_fpvalid; compat_int_t pr_fpvalid;
}; };

View File

@ -29,7 +29,7 @@ struct elf_siginfo
* the SVR4 structure, but more Linuxy, with things that Linux does * the SVR4 structure, but more Linuxy, with things that Linux does
* not support and which gdb doesn't really use excluded. * not support and which gdb doesn't really use excluded.
*/ */
struct elf_prstatus struct elf_prstatus_common
{ {
struct elf_siginfo pr_info; /* Info associated with signal */ struct elf_siginfo pr_info; /* Info associated with signal */
short pr_cursig; /* Current signal */ short pr_cursig; /* Current signal */
@ -43,6 +43,11 @@ struct elf_prstatus
struct __kernel_old_timeval pr_stime; /* System time */ struct __kernel_old_timeval pr_stime; /* System time */
struct __kernel_old_timeval pr_cutime; /* Cumulative user time */ struct __kernel_old_timeval pr_cutime; /* Cumulative user time */
struct __kernel_old_timeval pr_cstime; /* Cumulative system time */ struct __kernel_old_timeval pr_cstime; /* Cumulative system time */
};
struct elf_prstatus
{
struct elf_prstatus_common common;
elf_gregset_t pr_reg; /* GP registers */ elf_gregset_t pr_reg; /* GP registers */
int pr_fpvalid; /* True if math co-processor being used. */ int pr_fpvalid; /* True if math co-processor being used. */
}; };

View File

@ -1076,7 +1076,7 @@ void crash_save_cpu(struct pt_regs *regs, int cpu)
if (!buf) if (!buf)
return; return;
memset(&prstatus, 0, sizeof(prstatus)); memset(&prstatus, 0, sizeof(prstatus));
prstatus.pr_pid = current->pid; prstatus.common.pr_pid = current->pid;
elf_core_copy_kernel_regs(&prstatus.pr_reg, regs); elf_core_copy_kernel_regs(&prstatus.pr_reg, regs);
buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS, buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS,
&prstatus, sizeof(prstatus)); &prstatus, sizeof(prstatus));