elf_prstatus: collect the common part (everything before pr_reg) into a struct
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 13 Jun 2020 04:08:44 +0000 (00:08 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 6 Jan 2021 13:38:29 +0000 (08:38 -0500)
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>
arch/ia64/kernel/crash.c
arch/mips/kernel/binfmt_elfn32.c
arch/mips/kernel/binfmt_elfo32.c
arch/powerpc/platforms/powernv/opal-core.c
arch/s390/kernel/crash_dump.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/compat_binfmt_elf.c
include/linux/elfcore-compat.h
include/linux/elfcore.h
kernel/kexec_core.c

index fec70d662d0c2da737308bfbdd74e45d6088a5d4..4f47741005d26e160671556529f3985ee8509307 100644 (file)
@@ -43,7 +43,7 @@ crash_save_this_cpu(void)
 
        elf_greg_t *dst = (elf_greg_t *)&(prstatus->pr_reg);
        memset(prstatus, 0, sizeof(*prstatus));
-       prstatus->pr_pid = current->pid;
+       prstatus->common.pr_pid = current->pid;
 
        ia64_dump_cpu_regs(dst);
        cfm = dst[43];
index 6ee3f7218c675b6c605d06776ef1164ef6d13441..136dc0c9300d9380a48e0d67a78cc23669e53267 100644 (file)
@@ -44,7 +44,8 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 #include <linux/math64.h>
 
 #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 */
        short   pr_cursig;              /* Current signal */
@@ -58,6 +59,10 @@ struct elf_prstatus32
        struct old_timeval32 pr_stime; /* System time */
        struct old_timeval32 pr_cutime;/* Cumulative user time */
        struct old_timeval32 pr_cstime;/* Cumulative system time */
+};
+struct elf_prstatus32
+{
+       struct elf_prstatus32_common common:
        elf_gregset_t pr_reg;   /* GP registers */
        int pr_fpvalid;         /* True if math co-processor being used.  */
 };
index 6dd103d3cebba2f299fa60489b65c9377f975ee4..b1f4b8f1dee7f74fcc6f13acd278299c86f4a3cc 100644 (file)
@@ -49,7 +49,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 #include <linux/math64.h>
 
 #define elf_prstatus elf_prstatus32
-struct elf_prstatus32
+struct elf_prstatus32_common
 {
        struct elf_siginfo pr_info;     /* Info associated with signal */
        short   pr_cursig;              /* Current signal */
@@ -63,6 +63,10 @@ struct elf_prstatus32
        struct old_timeval32 pr_stime; /* System time */
        struct old_timeval32 pr_cutime;/* Cumulative user time */
        struct old_timeval32 pr_cstime;/* Cumulative system time */
+};
+struct elf_prstatus32
+{
+       struct elf_prstatus32_common common:
        elf_gregset_t pr_reg;   /* GP registers */
        int pr_fpvalid;         /* True if math co-processor being used.  */
 };
index 23571f0b555a6829de04cbe80ef5f7efe0cb4d6c..0d9ba70f72517e4f46cd71173299fdce53bdb7fb 100644 (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'
         * to every PIR to avoid misinterpretations in GDB.
         */
-       prstatus->pr_pid  = cpu_to_be32(100 + pir);
-       prstatus->pr_ppid = cpu_to_be32(1);
+       prstatus->common.pr_pid  = cpu_to_be32(100 + pir);
+       prstatus->common.pr_ppid = cpu_to_be32(1);
 
        /*
         * Indicate SIGUSR1 for crash initiated from kernel.
@@ -130,7 +130,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, int pir,
                short sig;
 
                sig = kernel_initiated ? SIGUSR1 : SIGTERM;
-               prstatus->pr_cursig = cpu_to_be16(sig);
+               prstatus->common.pr_cursig = cpu_to_be16(sig);
        }
 }
 
index 205b2e2648aae3dd502ea37a0418040e0b0dc8b9..0e36dfc9ccd6e3435c68f8e8a5fb2a6f0b9c6689 100644 (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.psw, sa->psw, sizeof(sa->psw));
        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 */
        memset(&nt_fpregset, 0, sizeof(nt_fpregset));
        memcpy(&nt_fpregset.fpc, &sa->fpc, sizeof(sa->fpc));
index 8380478d3d9279e0594717694dba2ae002ad200c..4c1550b13899efd7200081e2faeb072d69d5ab5d 100644 (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
  * 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)
 {
        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.
         * 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],
                   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;
        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);        
        
        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 */
        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);
 
        /* Set up header */
index be4062b8ba75eef23d71b19de1c52a9e65efd064..03d81a14bcbf601f7150b2d152a05ca6b8706b40 100644 (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_siginfo pr_info;     /* Info associated with signal */
-       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 */
+       struct elf_prstatus_common      common;
        elf_gregset_t pr_reg;   /* GP registers */
        /* When using FDPIC, the loadmap addresses need to be communicated
         * 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
  * 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)
 {
        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_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,
@@ -1405,7 +1391,9 @@ static struct elf_thread_status *elf_dump_thread_status(long signr, struct task_
        if (!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],
                   sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg);
 
index 962df845ed511e99c847094b112a2d97be94c0da..feb48a5c2d441c394baa07bd26301abc99330f7f 100644 (file)
@@ -50,6 +50,7 @@
  * which requires asm/elf.h to define compat_elf_gregset_t et al.
  */
 #define elf_prstatus   compat_elf_prstatus
+#define elf_prstatus_common    compat_elf_prstatus_common
 #define elf_prpsinfo   compat_elf_prpsinfo
 
 #undef ns_to_kernel_old_timeval
index 10485f0c9740c96b84d4653c1a176120ecd7044e..4aeda5f1f038580a6e803176b90aff65ac55520d 100644 (file)
@@ -17,7 +17,7 @@ struct compat_elf_siginfo
        compat_int_t                    si_errno;
 };
 
-struct compat_elf_prstatus
+struct compat_elf_prstatus_common
 {
        struct compat_elf_siginfo       pr_info;
        short                           pr_cursig;
@@ -31,6 +31,11 @@ struct compat_elf_prstatus
        struct old_timeval32            pr_stime;
        struct old_timeval32            pr_cutime;
        struct old_timeval32            pr_cstime;
+};
+
+struct compat_elf_prstatus
+{
+       struct compat_elf_prstatus_common       common;
        compat_elf_gregset_t            pr_reg;
        compat_int_t                    pr_fpvalid;
 };
index de51c1bef27daa80df2c730e0d5ea0df27ebe048..2aaa15779d50bb723b6c5a10922798c0a3bf3395 100644 (file)
@@ -29,7 +29,7 @@ struct elf_siginfo
  * the SVR4 structure, but more Linuxy, with things that Linux does
  * 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 */
        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_cutime;  /* Cumulative user 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 */
        int pr_fpvalid;         /* True if math co-processor being used.  */
 };
index 4f8efc278aa75bc22fc4387e11fe6b8d48548135..80905e5aa8aedccd016fbe7de2f549e4838a5382 100644 (file)
@@ -1076,7 +1076,7 @@ void crash_save_cpu(struct pt_regs *regs, int cpu)
        if (!buf)
                return;
        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);
        buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS,
                              &prstatus, sizeof(prstatus));