Fix o32 core dumps on 64-bit kernel
Subsystems (2)
The core dump code in binfmt_elfo32.c has bitrotted. It no longer worked after elfcore.h started using inline functions - not sure when that was. With this, I have both single-threaded and multi-threaded core dumps working. I'm not sure about the FP bits, if a task is currently using hardware FP, but I just copied the existing brokenness from dump_fpu. Better than nothing.
arch/mips/kernel/binfmt_elfo32.c +63 -35
@@ -55,43 +55,10 @@#include <asm/processor.h> #include <linux/module.h> #include <linux/config.h> -#include <linux/elfcore.h> #include <linux/compat.h> -#define elf_prstatus elf_prstatus32 -struct elf_prstatus32 -{ -struct elf_siginfo pr_info;/* Info associated with signal */ -short pr_cursig;/* Current signal */ -unsigned int pr_sigpend;/* Set of pending signals */ -unsigned int pr_sighold;/* Set of held signals */ -pid_t pr_pid; -pid_t pr_ppid; -pid_t pr_pgrp; -pid_t pr_sid; -struct compat_timeval pr_utime;/* User time */ -struct compat_timeval pr_stime;/* System time */ -struct compat_timeval pr_cutime;/* Cumulative user time */ -struct compat_timeval pr_cstime;/* Cumulative system time */ -elf_gregset_t pr_reg;/* GP registers */ -int pr_fpvalid;/* True if math co-processor being used. */ -}; +#include <asm/ptrace.h> -#define elf_prpsinfo elf_prpsinfo32 -struct elf_prpsinfo32 -{ -char pr_state;/* numeric process state */ -char pr_sname;/* char for pr_state */ -char pr_zomb;/* zombie */ -char pr_nice;/* nice val */ -unsigned int pr_flag;/* flags */ -__kernel_uid_t pr_uid; -__kernel_gid_t pr_gid; -pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; -/* Lots missing */ -char pr_fname[16 ];/* filename of executable */ -char pr_psargs[ELF_PRARGSZ ];/* initial part of arg list */ -};#define elf_addr_t u32#define elf_caddr_t u32
@@ -110,10 +77,12 @@ value->tv_usec /=NSEC_PER_USEC ; } +/* These need to be here, before the incluson of elfcore.h. */ +#undef ELF_CORE_COPY_REGS#define ELF_CORE_COPY_REGS (_dest,_regs) elf32_core_copy_regs(_dest,_regs); -void elf32_core_copy_regs (elf_gregset_t _dest,struct pt_regs *_regs) +static void elf32_core_copy_regs (elf_gregset_t _dest,struct pt_regs *_regs) {int i;
@@ -130,6 +99,65 @@ _dest[i++] = (elf_greg_t ) _regs->cp0_cause; } +#undef ELF_CORE_COPY_TASK_REGS +#define ELF_CORE_COPY_TASK_REGS (_task,_dest) elf32_core_copy_task_regs(_task, *(_dest)) + +static int elf32_core_copy_task_regs (struct task_struct *_task,elf_gregset_t _dest) +{ +struct pt_regs *_regs; + _regs = (struct pt_regs *) ((unsigned long ) _task->thread_info + +THREAD_SIZE -32 -sizeof (struct pt_regs )); +elf32_core_copy_regs (_dest, _regs); +return 1 ; +} + +#undef ELF_CORE_COPY_FPREGS +#define ELF_CORE_COPY_FPREGS (tsk, elf_fpregs) elf32_dump_task_fpu(tsk, elf_fpregs) + +static int elf32_dump_task_fpu (struct task_struct *tsk,elf_fpregset_t *fpu) +{ +/* FIXME: Is this right? */ +memcpy (fpu, &tsk->thread.fpu,sizeof (tsk->thread.fpu)); +return 1 ; +} + +#include <linux/elfcore.h> + +#define elf_prstatus elf_prstatus32 +struct elf_prstatus32 +{ +struct elf_siginfo pr_info;/* Info associated with signal */ +short pr_cursig;/* Current signal */ +unsigned int pr_sigpend;/* Set of pending signals */ +unsigned int pr_sighold;/* Set of held signals */ +pid_t pr_pid; +pid_t pr_ppid; +pid_t pr_pgrp; +pid_t pr_sid; +struct compat_timeval pr_utime;/* User time */ +struct compat_timeval pr_stime;/* System time */ +struct compat_timeval pr_cutime;/* Cumulative user time */ +struct compat_timeval pr_cstime;/* Cumulative system time */ +elf_gregset_t pr_reg;/* GP registers */ +int pr_fpvalid;/* True if math co-processor being used. */ +}; + +#define elf_prpsinfo elf_prpsinfo32 +struct elf_prpsinfo32 +{ +char pr_state;/* numeric process state */ +char pr_sname;/* char for pr_state */ +char pr_zomb;/* zombie */ +char pr_nice;/* nice val */ +unsigned int pr_flag;/* flags */ +__kernel_uid_t pr_uid; +__kernel_gid_t pr_gid; +pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; +/* Lots missing */ +char pr_fname[16 ];/* filename of executable */ +char pr_psargs[ELF_PRARGSZ ];/* initial part of arg list */ +}; +MODULE_DESCRIPTION ("Binary format loader for compatibility with o32 Linux/MIPS binaries" );MODULE_AUTHOR ("Ralf Baechle ([email protected])" );
Signature · 1 line
Daniel Jacobowitz
The core dump code in binfmt_elfo32.c has bitrotted. It no longer worked after elfcore.h started using inline functions - not sure when that was. With this, I have both single-threaded and multi-threaded core dumps working. I'm not sure about the FP bits, if a task is currently using hardware FP, but I just copied the existing brokenness from dump_fpu. Better than nothing.
This patch also adds "$0" (saved syscall number), $k0, and $k1 back to the coredump. Don't worry, GDB knows that this isn't the real $0 value.
Updated for current 2.6 CVS.
arch/mips/kernel/binfmt_elfo32.c +65 -41
@@ -54,43 +54,9 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N#include <asm/processor.h> #include <linux/module.h> -#include <linux/elfcore.h> #include <linux/compat.h> - -#define elf_prstatus elf_prstatus32 -struct elf_prstatus32 -{ -struct elf_siginfo pr_info;/* Info associated with signal */ -short pr_cursig;/* Current signal */ -unsigned int pr_sigpend;/* Set of pending signals */ -unsigned int pr_sighold;/* Set of held signals */ -pid_t pr_pid; -pid_t pr_ppid; -pid_t pr_pgrp; -pid_t pr_sid; -struct compat_timeval pr_utime;/* User time */ -struct compat_timeval pr_stime;/* System time */ -struct compat_timeval pr_cutime;/* Cumulative user time */ -struct compat_timeval pr_cstime;/* Cumulative system time */ -elf_gregset_t pr_reg;/* GP registers */ -int pr_fpvalid;/* True if math co-processor being used. */ -}; - -#define elf_prpsinfo elf_prpsinfo32 -struct elf_prpsinfo32 -{ -char pr_state;/* numeric process state */ -char pr_sname;/* char for pr_state */ -char pr_zomb;/* zombie */ -char pr_nice;/* nice val */ -unsigned int pr_flag;/* flags */ -__kernel_uid_t pr_uid; -__kernel_gid_t pr_gid; -pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; -/* Lots missing */ -char pr_fname[16 ];/* filename of executable */ -char pr_psargs[ELF_PRARGSZ ];/* initial part of arg list */ -}; +#include <asm/ptrace.h> +#include <asm/reg.h> #define elf_addr_t u32#define elf_caddr_t u32
@@ -109,20 +75,19 @@ jiffies_to_compat_timeval(unsigned long value->tv_usec /=NSEC_PER_USEC ; } +/* These need to be here, before the incluson of elfcore.h. */ +#undef ELF_CORE_COPY_REGS#define ELF_CORE_COPY_REGS (_dest,_regs) elf32_core_copy_regs(_dest,_regs); -void elf32_core_copy_regs (elf_gregset_t grp,struct pt_regs *regs) +static void elf32_core_copy_regs (elf_gregset_t grp,struct pt_regs *regs) {int i;for (i =0 ; i <EF_R0 ; i++) grp[i] =0 ; - grp[EF_R0 ] =0 ; -for (i =1 ; i <=31 ; i++) +for (i =0 ; i <=31 ; i++) grp[EF_R0 + i] = (elf_greg_t ) regs->regs[i]; - grp[EF_R26 ] =0 ; - grp[EF_R27 ] =0 ; grp[EF_LO ] = (elf_greg_t ) regs->lo; grp[EF_HI ] = (elf_greg_t ) regs->hi; grp[EF_CP0_EPC ] = (elf_greg_t ) regs->cp0_epc;
@@ -134,6 +99,65 @@ void elf32_core_copy_regs(elf_gregset_t#endif } +#undef ELF_CORE_COPY_TASK_REGS +#define ELF_CORE_COPY_TASK_REGS (_task,_dest) elf32_core_copy_task_regs(_task, *(_dest)) + +static int elf32_core_copy_task_regs (struct task_struct *_task,elf_gregset_t _dest) +{ +struct pt_regs *_regs; + _regs = (struct pt_regs *) ((unsigned long ) _task->thread_info + +THREAD_SIZE -32 -sizeof (struct pt_regs )); +elf32_core_copy_regs (_dest, _regs); +return 1 ; +} + +#undef ELF_CORE_COPY_FPREGS +#define ELF_CORE_COPY_FPREGS (tsk, elf_fpregs) elf32_dump_task_fpu(tsk, elf_fpregs) + +static int elf32_dump_task_fpu (struct task_struct *tsk,elf_fpregset_t *fpu) +{ +/* FIXME: Is this right? */ +memcpy (fpu, &tsk->thread.fpu,sizeof (tsk->thread.fpu)); +return 1 ; +} + +#include <linux/elfcore.h> + +#define elf_prstatus elf_prstatus32 +struct elf_prstatus32 +{ +struct elf_siginfo pr_info;/* Info associated with signal */ +short pr_cursig;/* Current signal */ +unsigned int pr_sigpend;/* Set of pending signals */ +unsigned int pr_sighold;/* Set of held signals */ +pid_t pr_pid; +pid_t pr_ppid; +pid_t pr_pgrp; +pid_t pr_sid; +struct compat_timeval pr_utime;/* User time */ +struct compat_timeval pr_stime;/* System time */ +struct compat_timeval pr_cutime;/* Cumulative user time */ +struct compat_timeval pr_cstime;/* Cumulative system time */ +elf_gregset_t pr_reg;/* GP registers */ +int pr_fpvalid;/* True if math co-processor being used. */ +}; + +#define elf_prpsinfo elf_prpsinfo32 +struct elf_prpsinfo32 +{ +char pr_state;/* numeric process state */ +char pr_sname;/* char for pr_state */ +char pr_zomb;/* zombie */ +char pr_nice;/* nice val */ +unsigned int pr_flag;/* flags */ +__kernel_uid_t pr_uid; +__kernel_gid_t pr_gid; +pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; +/* Lots missing */ +char pr_fname[16 ];/* filename of executable */ +char pr_psargs[ELF_PRARGSZ ];/* initial part of arg list */ +}; +MODULE_DESCRIPTION ("Binary format loader for compatibility with o32 Linux/MIPS binaries" );MODULE_AUTHOR ("Ralf Baechle ([email protected])" );
arch/mips/kernel/process.c +1 -4
@@ -163,11 +163,8 @@ void dump_regs(elf_greg_t *gp, struct ptfor (i =0 ; i <EF_R0 ; i++) gp[i] =0 ; - gp[EF_R0 ] =0 ; -for (i =1 ; i <=31 ; i++) +for (i =0 ; i <=31 ; i++) gp[EF_R0 + i] = regs->regs[i]; - gp[EF_R26 ] =0 ; - gp[EF_R27 ] =0 ; gp[EF_LO ] = regs->lo; gp[EF_HI ] = regs->hi; gp[EF_CP0_EPC ] = regs->cp0_epc;
Signature · 2 lines
Daniel Jacobowitz CodeSourcery, LLC