coredump unification for regset and non-regset architectures
Subsystems (10)
Al Viro
maintainerRFC PATCH 1/1 coredump unification for regset and non-regset architectures
Resurrecting an old work - elf coredumps mess reduction.
Back in 2008 some of the architectures have switched to use of regsets for elf coredumps. Unfortunately, back then the helpers used by other architectures used to be shared with a.out coredump support, which made their calling conventions, etc. hard to modify. As the result, Roland went for duplicating quite a bit of coredump-generating logics, with ifdef selecting the right variant.
Since then the copies had drifted apart - changes made
to one of them and applicable to both had not been propagated, etc. Many (but not all) architectures have switched to regset variant. And a.out coredump support had been removed, which made it easier to modify the primitives on non-regset architectures.
Series below attempts to make use of that; it had been
started about 4 years ago, but got stalled several times.
Review and testing would be very appreciated. Individual
patches - in followups. Alternatively, it can be found ingit://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.gitd #work.elfcore.
Al Viro (10):
kill signal_pt_regs()
kill coredump_params->regs
kill extern of vsyscall32_sysctl
[elf][regset] clean fill_note_info() a bit
[elf][regset] simplify thread list handling in fill_note_info() elf_core_copy_task_regs(): task_pt_regs is defined everywhere [elf][non-regset] uninline elf_core_copy_task_fpregs() (and lose pt_regs argument) [elf][non-regset] use elf_core_copy_task_regs() for dumper as well [elf] unify regset and non-regset cases
[elf] get rid of get_note_info_size()
arch/alpha/include/asm/elf.h | 6 - arch/alpha/include/asm/ptrace.h | 1 - arch/alpha/kernel/process.c | 8 +- arch/csky/kernel/process.c | 3 +- arch/m68k/kernel/process.c | 3 +- arch/microblaze/kernel/process.c | 2 +- arch/um/kernel/process.c | 2 +- arch/x86/include/asm/elf.h | 1 - arch/x86/um/asm/elf.h | 4 - fs/binfmt_elf.c | 271 ++++++++------------------------------- fs/coredump.c | 1 - include/linux/coredump.h | 1 - include/linux/elfcore.h | 13 +- include/linux/ptrace.h | 9 -- kernel/signal.c | 2 +- 15 files changed, 61 insertions(+), 266 deletions(-)
Al Viro
maintainerPATCH 1/10 kill signal_pt_regs()
Once upon at it was used on hot paths, but that had not been true since 2013. IOW, there's no point for arch-optimized equivalent of task_pt_regs(current) - remaining two users are not worth bothering with.
--- arch/alpha/include/asm/ptrace.h | 1 - fs/coredump.c | 2 +- include/linux/ptrace.h | 9 --------- kernel/signal.c | 2 +- 4 files changed, 2 insertions(+), 12 deletions(-)
arch/alpha/include/asm/ptrace.h +0 -1
@@ -16,7 +16,6 @@#define current_pt_regs () \ ((struct pt_regs *) ((char *)current_thread_info() + 2*PAGE_SIZE) - 1) -#define signal_pt_regs current_pt_regs#define force_successful_syscall_return () (current_pt_regs()->r0 = 0)
fs/coredump.c +1 -1
@@ -525,7 +525,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)static atomic_t core_dump_count =ATOMIC_INIT (0 );struct coredump_params cprm = { .siginfo = siginfo, - .regs =signal_pt_regs (), + .regs =task_pt_regs (current), .limit =rlimit (RLIMIT_CORE ),/* * We must use the same mm->flags while dumping core to avoid
include/linux/ptrace.h +0 -9
@@ -389,15 +389,6 @@ static inline void user_single_step_report(struct pt_regs *regs)#define current_pt_regs () task_pt_regs(current)#endif -/* -* unlike current_pt_regs(), this one is equal to task_pt_regs(current) -* on *all* architectures; the only reason to have a per-arch definition -* is optimisation. -*/ -#ifndef signal_pt_regs -#define signal_pt_regs () task_pt_regs(current) -#endif -#ifndef current_user_stack_pointer#define current_user_stack_pointer () user_stack_pointer(current_pt_regs())#endif
kernel/signal.c +1 -1
@@ -1255,7 +1255,7 @@ int send_signal_locked(int sig, struct kernel_siginfo *info,static void print_fatal_signal (int signr) { -struct pt_regs *regs =signal_pt_regs (); +struct pt_regs *regs =task_pt_regs (current);pr_info ("potentially unexpected fatal signal %d.\n" , signr);#if defined(__i386__) && !defined(__arch_um__)
Signature · 1 line
2.30.2
Al Viro
maintainerPATCH 3/10 kill extern of vsyscall32_sysctl
it's been dead for years.
--- arch/x86/include/asm/elf.h | 1 - 1 file changed, 1 deletion(-)
arch/x86/include/asm/elf.h +0 -1
@@ -226,7 +226,6 @@ do { \/* I'm not sure if we can use '-' here */ #define ELF_PLATFORM ("x86_64")extern void set_personality_64bit (void ); -extern unsigned int sysctl_vsyscall32;extern int force_personality32;#endif /* !CONFIG_X86_32 */
Signature · 1 line
2.30.2
Al Viro
maintainerPATCH 2/10 kill coredump_params->regs
In reply to Al Viroit's always task_pt_regs(current)
--- fs/binfmt_elf.c | 4 ++-- fs/coredump.c | 1 - include/linux/coredump.h | 1 - 3 files changed, 2 insertions(+), 4 deletions(-)
fs/binfmt_elf.c +2 -2
@@ -2082,7 +2082,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->common, current, cprm->siginfo->si_signo); -elf_core_copy_regs (&info->prstatus->pr_reg, cprm->regs); +elf_core_copy_regs (&info->prstatus->pr_reg,task_pt_regs (current));/* Set up header */ fill_elf_header (elf, phdrs,ELF_ARCH ,ELF_CORE_EFLAGS );
@@ -2109,7 +2109,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,/* Try to dump the FPU. */ info->prstatus->pr_fpvalid = -elf_core_copy_task_fpregs (current, cprm->regs, info->fpu); +elf_core_copy_task_fpregs (current,task_pt_regs (current), info->fpu);if (info->prstatus->pr_fpvalid)fill_note (info->notes + info->numnote++,"CORE" ,NT_PRFPREG ,sizeof (*info->fpu), info->fpu);
fs/coredump.c +0 -1
@@ -525,7 +525,6 @@ void do_coredump(const kernel_siginfo_t *siginfo)static atomic_t core_dump_count =ATOMIC_INIT (0 );struct coredump_params cprm = { .siginfo = siginfo, - .regs =task_pt_regs (current), .limit =rlimit (RLIMIT_CORE ),/* * We must use the same mm->flags while dumping core to avoid
include/linux/coredump.h +0 -1
@@ -18,7 +18,6 @@ struct core_vma_metadata {struct coredump_params {const kernel_siginfo_t *siginfo; -struct pt_regs *regs;struct file *file;unsigned long limit;unsigned long mm_flags;
Signature · 1 line
2.30.2
Al Viro
maintainerPATCH 6/10 elf_core_copy_task_regs(): task_pt_regs is defined everywhere
In reply to Al ViroHad been since 2011 for all live architectures, ever since 2013 for all architectures, period.
--- include/linux/elfcore.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/elfcore.h +1 -1
@@ -88,7 +88,7 @@ static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* {#if defined (ELF_CORE_COPY_TASK_REGS )return ELF_CORE_COPY_TASK_REGS (t, elfregs); -#elif defined (task_pt_regs) +#else elf_core_copy_regs (elfregs,task_pt_regs (t));#endif return 0 ;
Signature · 1 line
2.30.2
Al Viro
maintainerPATCH 5/10 simplify thread list handling in fill_note_info()
In reply to Al Virofill_note_info() iterates through the list of threads collected in mm->core_state->dumper, allocating a struct elf_thread_core_info instance for each and linking those into a list.
We need the entry corresponding to current to be first in the resulting list, so the logics for list insertion is
if it's for current or list is empty
insert in the head
else
insert after the first element
However, in mm->core_state->dumper the entry for current is guaranteed to be the first one. Which means that both parts of condition will be true on the first iteration and neither will be true on all subsequent ones.
Taking the first iteration out of the loop simplifies things nicely...
--- fs/binfmt_elf.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-)
fs/binfmt_elf.c +10 -12
@@ -1866,7 +1866,14 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,/* * Allocate a structure for each thread. */ -for (ct = &dump_task->signal->core_state->dumper; ct; ct = ct->next) { + info->thread =kzalloc (offsetof(struct elf_thread_core_info , + notes[info->thread_notes]), + GFP_KERNEL); +if (unlikely (!info->thread)) +return 0 ; + + info->thread->task = dump_task; +for (ct = dump_task->signal->core_state->dumper.next; ct; ct = ct->next) { t =kzalloc (offsetof(struct elf_thread_core_info , notes[info->thread_notes]), GFP_KERNEL);
@@ -1874,17 +1881,8 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,return 0 ; t->task = ct->task; -if (ct->task == dump_task || !info->thread) { - t->next = info->thread; - info->thread = t; - }else { -/* -* Make sure to keep the original task at -* the head of the list. -*/ - t->next = info->thread->next; - info->thread->next = t; - } + t->next = info->thread->next; + info->thread->next = t; }/*
Signature · 1 line
2.30.2
Al Viro
maintainerPATCH 4/10 clean fill_note_info() a bit
In reply to Al Viro*info is already initialized...
--- fs/binfmt_elf.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-)
fs/binfmt_elf.c +2 -9
@@ -1833,24 +1833,17 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,struct elf_thread_core_info *t;struct elf_prpsinfo *psinfo;struct core_thread *ct; -unsigned int i; - - info->size =0 ; - info->thread =NULL ; psinfo =kmalloc (sizeof (*psinfo),GFP_KERNEL ); -if (psinfo ==NULL ) { - info->psinfo.data =NULL ;/* So we don't free this wrongly */ +if (!psinfo)return 0 ; - } -fill_note (&info->psinfo,"CORE" ,NT_PRPSINFO ,sizeof (*psinfo), psinfo);/* * Figure out how many notes we're going to need for each thread. */ info->thread_notes =0 ; -for (i =0 ; i < view->n; ++i) +for (int i =0 ; i < view->n; ++i)if (view->regsets[i].core_note_type !=0 ) ++info->thread_notes;
Signature · 1 line
2.30.2
Al Viro
maintainerPATCH 8/10 use elf_core_copy_task_regs() for dumper as well
In reply to Al Viroelf_core_copy_regs() is equivalent to elf_core_copy_task_regs() of current on all architectures.
--- fs/binfmt_elf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/binfmt_elf.c +1 -1
@@ -2072,7 +2072,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->common, current, cprm->siginfo->si_signo); -elf_core_copy_regs (&info->prstatus->pr_reg,task_pt_regs (current)); +elf_core_copy_task_regs (current, &info->prstatus->pr_reg);/* Set up header */ fill_elf_header (elf, phdrs,ELF_ARCH ,ELF_CORE_EFLAGS );
Signature · 1 line
2.30.2
Al Viro
maintainerPATCH 7/10 uninline elf_core_copy_task_fpregs() (and lose pt_regs argument)
In reply to Al ViroDon't bother with pointless macros - we are not sharing it with aout coredumps anymore. Just convert the underlying functions to the same arguments (nobody uses regs, actually) and call them elf_core_copy_task_fpregs(). And unexport the entire bunch, while we are at it.
--- arch/alpha/include/asm/elf.h | 6 ------ arch/alpha/kernel/process.c | 8 +++----- arch/csky/kernel/process.c | 3 +-- arch/m68k/kernel/process.c | 3 +-- arch/microblaze/kernel/process.c | 2 +- arch/um/kernel/process.c | 2 +- arch/x86/um/asm/elf.h | 4 ---- fs/binfmt_elf.c | 5 ++--- include/linux/elfcore.h | 11 +---------- 9 files changed, 10 insertions(+), 34 deletions(-)
arch/alpha/include/asm/elf.h +0 -6
@@ -120,12 +120,6 @@ extern int dump_elf_task(elf_greg_t *dest, struct task_struct *task);#define ELF_CORE_COPY_TASK_REGS (TASK ,DEST ) \ dump_elf_task(*(DEST), TASK) -/* Similar, but for the FP registers. */ - -extern int dump_elf_task_fp (elf_fpreg_t *dest,struct task_struct *task); -#define ELF_CORE_COPY_FPREGS (TASK ,DEST ) \ - dump_elf_task_fp(*(DEST), TASK) -/* This yields a mask that user programs can use to figure out what instruction set this CPU supports. This is trivial on Alpha, but not so on other machines. */
arch/alpha/kernel/process.c +3 -5
@@ -333,14 +333,12 @@ dump_elf_task(elf_greg_t *dest, struct task_struct *task) }EXPORT_SYMBOL (dump_elf_task); -int -dump_elf_task_fp (elf_fpreg_t *dest,struct task_struct *task) +int elf_core_copy_task_fpregs (struct task_struct *t,elf_fpregset_t *fpu) { -struct switch_stack *sw = (struct switch_stack *)task_pt_regs (task) -1 ; -memcpy (dest, sw->fp,32 *8 ); +struct switch_stack *sw = (struct switch_stack *)task_pt_regs (t) -1 ; +memcpy (fpu, sw->fp,32 *8 );return 1 ; } -EXPORT_SYMBOL (dump_elf_task_fp);/* * Return saved PC of a blocked thread. This assumes the frame
arch/csky/kernel/process.c +1 -2
@@ -69,12 +69,11 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) }/* Fill in the fpu structure for a core dump. */ -int dump_fpu (struct pt_regs *regs,struct user_fp *fpu) +int elf_core_copy_task_fpregs (struct task_struct *t,elf_fpregset_t *fpu) {memcpy (fpu, ¤t->thread.user_fp,sizeof (*fpu));return 1 ; } -EXPORT_SYMBOL (dump_fpu);int dump_task_regs (struct task_struct *tsk,elf_gregset_t *pr_regs) {
arch/m68k/kernel/process.c +1 -2
@@ -213,7 +213,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) }/* Fill in the fpu structure for a core dump. */ -int dump_fpu (struct pt_regs *regs,struct user_m68kfp_struct *fpu) +int elf_core_copy_task_fpregs (struct task_struct *t,elf_fpregset_t *fpu) {if (FPU_IS_EMU ) {int i;
@@ -262,7 +262,6 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)return 1 ; } -EXPORT_SYMBOL (dump_fpu);unsigned long __get_wchan (struct task_struct *p) {
arch/microblaze/kernel/process.c +1 -1
@@ -133,7 +133,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp)/* * Set up a thread for executing a new program */ -int dump_fpu (struct pt_regs *regs,elf_fpregset_t *fpregs) +int elf_core_copy_task_fpregs (struct task_struct *t,elf_fpregset_t *fpu) {return 0 ;/* MicroBlaze has no separate FPU registers */ }
arch/um/kernel/process.c +1 -1
@@ -393,7 +393,7 @@ unsigned long __get_wchan(struct task_struct *p)return 0 ; } -int elf_core_copy_fpregs (struct task_struct *t,elf_fpregset_t *fpu) +int elf_core_copy_task_fpregs (struct task_struct *t,elf_fpregset_t *fpu) {int cpu =current_thread_info ()->cpu;
arch/x86/um/asm/elf.h +0 -4
@@ -201,10 +201,6 @@ typedef struct user_i387_struct elf_fpregset_t;struct task_struct ; -extern int elf_core_copy_fpregs (struct task_struct *t,elf_fpregset_t *fpu); - -#define ELF_CORE_COPY_FPREGS (t, fpu) elf_core_copy_fpregs(t, fpu) -#define ELF_EXEC_PAGESIZE 4096#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
fs/binfmt_elf.c +2 -3
@@ -2001,8 +2001,7 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t) t->num_notes++; sz +=notesize (&t->notes[0 ]); -if ((t->prstatus.pr_fpvalid =elf_core_copy_task_fpregs (p,NULL , - &t->fpu))) { +if ((t->prstatus.pr_fpvalid =elf_core_copy_task_fpregs (p, &t->fpu))) {fill_note (&t->notes[1 ],"CORE" ,NT_PRFPREG ,sizeof (t->fpu), &(t->fpu)); t->num_notes++;
@@ -2100,7 +2099,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,/* Try to dump the FPU. */ info->prstatus->pr_fpvalid = -elf_core_copy_task_fpregs (current,task_pt_regs (current), info->fpu); +elf_core_copy_task_fpregs (current, info->fpu);if (info->prstatus->pr_fpvalid)fill_note (info->notes + info->numnote++,"CORE" ,NT_PRFPREG ,sizeof (*info->fpu), info->fpu);
include/linux/elfcore.h +1 -10
@@ -94,16 +94,7 @@ static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t*return 0 ; } -extern int dump_fpu (struct pt_regs *,elf_fpregset_t *); - -static inline int elf_core_copy_task_fpregs (struct task_struct *t,struct pt_regs *regs,elf_fpregset_t *fpu) -{ -#ifdef ELF_CORE_COPY_FPREGS -return ELF_CORE_COPY_FPREGS (t, fpu); -#else -return dump_fpu (regs, fpu); -#endif -} +int elf_core_copy_task_fpregs (struct task_struct *t,elf_fpregset_t *fpu);#ifdef CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS /*
Signature · 1 line
2.30.2
Al Viro
maintainerPATCH 10/10 get rid of get_note_info_size()
In reply to Al Viroit's trivial now...
--- fs/binfmt_elf.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
fs/binfmt_elf.c +1 -6
@@ -1946,11 +1946,6 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,return 1 ; } -static size_t get_note_info_size (struct elf_note_info *info) -{ -return info->size; -} -/* * Write all the notes for each thread. When writing the first thread, the * process-wide notes are interleaved after the first thread-specific note.
@@ -2068,7 +2063,7 @@ static int elf_core_dump(struct coredump_params *cprm)/* Write notes phdr entry */ { -size_t sz =get_note_info_size (&info); +size_t sz = info.size;/* For cell spufs */ sz +=elf_coredump_extra_notes_size ();
Signature · 1 line
2.30.2
Al Viro
maintainerPATCH 9/10 unify regset and non-regset cases
In reply to Al ViroThe only real difference is in filling per-thread notes - getting
the values of registers. And this is the only part that is worth
an ifdef - we don't need to duplicate the logics regarding gathering threads, filling other notes, etc.
It would've been hard to do back when regset-based variant had been introduced, mostly due to sharing bits and pieces of helpers with aout coredumps. As the result, too much had been duplicated and the copies had drifted away since then. Now it can be done cleanly...
--- fs/binfmt_elf.c | 230 ++++++++---------------------------------------- 1 file changed, 38 insertions(+), 192 deletions(-)
fs/binfmt_elf.c +38 -192
@@ -1723,7 +1723,6 @@ static int fill_files_note(struct memelfnote *note, struct coredump_params *cprmreturn 0 ; } -#ifdef CORE_DUMP_USE_REGSET #include <linux/regset.h> struct elf_thread_core_info {
@@ -1744,6 +1743,7 @@ struct elf_note_info {int thread_notes; }; +#ifdef CORE_DUMP_USE_REGSET /* * When a regset has a writeback hook, we call it on each thread before * dumping user memory. On register window machines, this makes sure the
@@ -1823,13 +1823,41 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,return 1 ; } +#else +static int fill_thread_core_info (struct elf_thread_core_info *t, +const struct user_regset_view *view, +long signr,struct elf_note_info *info) +{ +struct task_struct *p = t->task; +elf_fpregset_t *fpu; + +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), + &(t->prstatus)); + info->size +=notesize (&t->notes[0 ]); + + fpu =kzalloc (sizeof (elf_fpregset_t),GFP_KERNEL ); +if (!fpu || !elf_core_copy_task_fpregs (p, fpu)) { +kfree (fpu); +return 1 ; + } + + t->prstatus.pr_fpvalid =1 ; +fill_note (&t->notes[1 ],"CORE" ,NT_PRFPREG ,sizeof (*fpu), fpu); + info->size +=notesize (&t->notes[1 ]); + +return 1 ; +} +#endif static int fill_note_info (struct elfhdr *elf,int phdrs,struct elf_note_info *info,struct coredump_params *cprm) {struct task_struct *dump_task = current; -const struct user_regset_view *view =task_user_regset_view (dump_task); +const struct user_regset_view *view;struct elf_thread_core_info *t;struct elf_prpsinfo *psinfo;struct core_thread *ct;
@@ -1839,6 +1867,9 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,return 0 ;fill_note (&info->psinfo,"CORE" ,NT_PRPSINFO ,sizeof (*psinfo), psinfo); +#ifdef CORE_DUMP_USE_REGSET + view =task_user_regset_view (dump_task); +/* * Figure out how many notes we're going to need for each thread. */
@@ -1862,6 +1893,11 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,*/ fill_elf_header (elf, phdrs, view->e_machine, view->e_flags); +#else + view =NULL ; + info->thread_notes =2 ; +fill_elf_header (elf, phdrs,ELF_ARCH ,ELF_CORE_EFLAGS ); +#endif /* * Allocate a structure for each thread.
@@ -1969,196 +2005,6 @@ static void free_note_info(struct elf_note_info *info)kvfree (info->files.data); } -#else - -/* Here is the structure in which status of each thread is captured. */ -struct elf_thread_status -{ -struct list_head list; -struct elf_prstatus prstatus;/* NT_PRSTATUS */ -elf_fpregset_t fpu;/* NT_PRFPREG */ -struct task_struct *thread; -struct memelfnote notes[3 ]; -int num_notes; -}; - -/* -* In order to add the specific thread information for the elf file format, -* we need to keep a linked list of every threads pr_status and then create -* a single section for them in the final core file. -*/ -static int elf_dump_thread_status (long signr,struct elf_thread_status *t) -{ -int sz =0 ; -struct task_struct *p = t->thread; - t->num_notes =0 ; - -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), - &(t->prstatus)); - t->num_notes++; - sz +=notesize (&t->notes[0 ]); - -if ((t->prstatus.pr_fpvalid =elf_core_copy_task_fpregs (p, &t->fpu))) { -fill_note (&t->notes[1 ],"CORE" ,NT_PRFPREG ,sizeof (t->fpu), - &(t->fpu)); - t->num_notes++; - sz +=notesize (&t->notes[1 ]); - } -return sz; -} - -struct elf_note_info { -struct memelfnote *notes; -struct memelfnote *notes_files; -struct elf_prstatus *prstatus;/* NT_PRSTATUS */ -struct elf_prpsinfo *psinfo;/* NT_PRPSINFO */ -struct list_head thread_list; -elf_fpregset_t *fpu; -user_siginfo_t csigdata; -int thread_status_size; -int numnote; -}; - -static int elf_note_info_init (struct elf_note_info *info) -{ -memset (info,0 ,sizeof (*info)); -INIT_LIST_HEAD (&info->thread_list); - -/* Allocate space for ELF notes */ - info->notes =kmalloc_array (8 ,sizeof (struct memelfnote ),GFP_KERNEL ); -if (!info->notes) -return 0 ; - info->psinfo =kmalloc (sizeof (*info->psinfo),GFP_KERNEL ); -if (!info->psinfo) -return 0 ; - info->prstatus =kmalloc (sizeof (*info->prstatus),GFP_KERNEL ); -if (!info->prstatus) -return 0 ; - info->fpu =kmalloc (sizeof (*info->fpu),GFP_KERNEL ); -if (!info->fpu) -return 0 ; -return 1 ; -} - -static int fill_note_info (struct elfhdr *elf,int phdrs, -struct elf_note_info *info, -struct coredump_params *cprm) -{ -struct core_thread *ct; -struct elf_thread_status *ets; - -if (!elf_note_info_init (info)) -return 0 ; - -for (ct = current->signal->core_state->dumper.next; - ct; ct = ct->next) { - ets =kzalloc (sizeof (*ets),GFP_KERNEL ); -if (!ets) -return 0 ; - - ets->thread = ct->task; -list_add (&ets->list, &info->thread_list); - } - -list_for_each_entry (ets, &info->thread_list, list) { -int sz; - - sz =elf_dump_thread_status (cprm->siginfo->si_signo, ets); - info->thread_status_size += sz; - } -/* now collect the dump for the current */ -memset (info->prstatus,0 ,sizeof (*info->prstatus)); -fill_prstatus (&info->prstatus->common, current, cprm->siginfo->si_signo); -elf_core_copy_task_regs (current, &info->prstatus->pr_reg); - -/* Set up header */ -fill_elf_header (elf, phdrs,ELF_ARCH ,ELF_CORE_EFLAGS ); - -/* -* Set up the notes in similar form to SVR4 core dumps made -* with info from their /proc. -*/ - -fill_note (info->notes +0 ,"CORE" ,NT_PRSTATUS , -sizeof (*info->prstatus), info->prstatus); -fill_psinfo (info->psinfo, current->group_leader, current->mm); -fill_note (info->notes +1 ,"CORE" ,NT_PRPSINFO , -sizeof (*info->psinfo), info->psinfo); - -fill_siginfo_note (info->notes +2 , &info->csigdata, cprm->siginfo); -fill_auxv_note (info->notes +3 , current->mm); - info->numnote =4 ; - -if (fill_files_note (info->notes + info->numnote, cprm) ==0 ) { - info->notes_files = info->notes + info->numnote; - info->numnote++; - } - -/* Try to dump the FPU. */ - info->prstatus->pr_fpvalid = -elf_core_copy_task_fpregs (current, info->fpu); -if (info->prstatus->pr_fpvalid) -fill_note (info->notes + info->numnote++, -"CORE" ,NT_PRFPREG ,sizeof (*info->fpu), info->fpu); -return 1 ; -} - -static size_t get_note_info_size (struct elf_note_info *info) -{ -int sz =0 ; -int i; - -for (i =0 ; i < info->numnote; i++) - sz +=notesize (info->notes + i); - - sz += info->thread_status_size; - -return sz; -} - -static int write_note_info (struct elf_note_info *info, -struct coredump_params *cprm) -{ -struct elf_thread_status *ets; -int i; - -for (i =0 ; i < info->numnote; i++) -if (!writenote (info->notes + i, cprm)) -return 0 ; - -/* write out the thread status notes section */ -list_for_each_entry (ets, &info->thread_list, list) { -for (i =0 ; i < ets->num_notes; i++) -if (!writenote (&ets->notes[i], cprm)) -return 0 ; - } - -return 1 ; -} - -static void free_note_info (struct elf_note_info *info) -{ -while (!list_empty (&info->thread_list)) { -struct list_head *tmp = info->thread_list.next; -list_del (tmp); -kfree (list_entry(tmp ,struct elf_thread_status ,list )); - } - -/* Free data possibly allocated by fill_files_note(): */ -if (info->notes_files) -kvfree (info->notes_files->data); - -kfree (info->prstatus); -kfree (info->psinfo); -kfree (info->notes); -kfree (info->fpu); -} - -#endif -static void fill_extnum_info (struct elfhdr *elf,struct elf_shdr *shdr4extnum,elf_addr_t e_shoff,int segs) {
Signature · 1 line
2.30.2
Re: [PATCH 07/10] [elf][non-regset] uninline elf_core_copy_task_fpregs() (and lose pt_regs argument)
In reply to Al ViroQuoted 8 lines · Al Viro
Don't bother with pointless macros - we are not sharing it with aout coredumps anymore. Just convert the underlying functions to the same arguments (nobody uses regs, actually) and call them
elf_core_copy_task_fpregs(). And unexport the entire bunch, while we are at it.Signed-off-by Al Viro <[email protected]>arch/m68k/kernel/process.c | 3 +--
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds