Merge branch 'work.fdpic' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull fdpick coredump update from Al Viro: "Switches fdpic coredumps away from original aout dumping primitives to the same kind of regset use as regular elf coredumps do" * 'work.fdpic' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: [elf-fdpic] switch coredump to regsets [elf-fdpic] use elf_dump_thread_status() for the dumper thread as well [elf-fdpic] move allocation of elf_thread_status into elf_dump_thread_status() [elf-fdpic] coredump: don't bother with cyclic list for per-thread objects kill elf_fpxregs_t take fdpic-related parts of elf_prstatus out unexport linux/elfcore.h
This commit is contained in:
commit
0f43283be7
|
@ -179,8 +179,6 @@ extern void ia64_init_addr_space (void);
|
||||||
#define ELF_AR_SSD_OFFSET (56 * sizeof(elf_greg_t))
|
#define ELF_AR_SSD_OFFSET (56 * sizeof(elf_greg_t))
|
||||||
#define ELF_AR_END_OFFSET (57 * sizeof(elf_greg_t))
|
#define ELF_AR_END_OFFSET (57 * sizeof(elf_greg_t))
|
||||||
|
|
||||||
typedef unsigned long elf_fpxregset_t;
|
|
||||||
|
|
||||||
typedef unsigned long elf_greg_t;
|
typedef unsigned long elf_greg_t;
|
||||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,6 @@ static inline void ppc_elf_core_copy_regs(elf_gregset_t elf_regs,
|
||||||
}
|
}
|
||||||
#define ELF_CORE_COPY_REGS(gregs, regs) ppc_elf_core_copy_regs(gregs, regs);
|
#define ELF_CORE_COPY_REGS(gregs, regs) ppc_elf_core_copy_regs(gregs, regs);
|
||||||
|
|
||||||
typedef elf_vrregset_t elf_fpxregset_t;
|
|
||||||
|
|
||||||
/* ELF_HWCAP yields a mask that user programs can use to figure out what
|
/* ELF_HWCAP yields a mask that user programs can use to figure out what
|
||||||
instruction set this cpu supports. This could be done in userspace,
|
instruction set this cpu supports. This could be done in userspace,
|
||||||
but it's not easy, and we've already done it here. */
|
but it's not easy, and we've already done it here. */
|
||||||
|
|
|
@ -21,8 +21,6 @@ typedef struct user_i387_struct elf_fpregset_t;
|
||||||
|
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
|
|
||||||
typedef struct user_fxsr_struct elf_fpxregset_t;
|
|
||||||
|
|
||||||
#define R_386_NONE 0
|
#define R_386_NONE 0
|
||||||
#define R_386_32 1
|
#define R_386_32 1
|
||||||
#define R_386_PC32 2
|
#define R_386_PC32 2
|
||||||
|
|
|
@ -2038,9 +2038,6 @@ struct elf_thread_status
|
||||||
struct elf_prstatus prstatus; /* NT_PRSTATUS */
|
struct elf_prstatus prstatus; /* NT_PRSTATUS */
|
||||||
elf_fpregset_t fpu; /* NT_PRFPREG */
|
elf_fpregset_t fpu; /* NT_PRFPREG */
|
||||||
struct task_struct *thread;
|
struct task_struct *thread;
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */
|
|
||||||
#endif
|
|
||||||
struct memelfnote notes[3];
|
struct memelfnote notes[3];
|
||||||
int num_notes;
|
int num_notes;
|
||||||
};
|
};
|
||||||
|
@ -2071,15 +2068,6 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
|
||||||
t->num_notes++;
|
t->num_notes++;
|
||||||
sz += notesize(&t->notes[1]);
|
sz += notesize(&t->notes[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
if (elf_core_copy_task_xfpregs(p, &t->xfpu)) {
|
|
||||||
fill_note(&t->notes[2], "LINUX", ELF_CORE_XFPREG_TYPE,
|
|
||||||
sizeof(t->xfpu), &t->xfpu);
|
|
||||||
t->num_notes++;
|
|
||||||
sz += notesize(&t->notes[2]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2090,9 +2078,6 @@ struct elf_note_info {
|
||||||
struct elf_prpsinfo *psinfo; /* NT_PRPSINFO */
|
struct elf_prpsinfo *psinfo; /* NT_PRPSINFO */
|
||||||
struct list_head thread_list;
|
struct list_head thread_list;
|
||||||
elf_fpregset_t *fpu;
|
elf_fpregset_t *fpu;
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
elf_fpxregset_t *xfpu;
|
|
||||||
#endif
|
|
||||||
user_siginfo_t csigdata;
|
user_siginfo_t csigdata;
|
||||||
int thread_status_size;
|
int thread_status_size;
|
||||||
int numnote;
|
int numnote;
|
||||||
|
@ -2116,11 +2101,6 @@ static int elf_note_info_init(struct elf_note_info *info)
|
||||||
info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL);
|
info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL);
|
||||||
if (!info->fpu)
|
if (!info->fpu)
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
info->xfpu = kmalloc(sizeof(*info->xfpu), GFP_KERNEL);
|
|
||||||
if (!info->xfpu)
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2184,13 +2164,6 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
|
||||||
if (info->prstatus->pr_fpvalid)
|
if (info->prstatus->pr_fpvalid)
|
||||||
fill_note(info->notes + info->numnote++,
|
fill_note(info->notes + info->numnote++,
|
||||||
"CORE", NT_PRFPREG, sizeof(*info->fpu), info->fpu);
|
"CORE", NT_PRFPREG, sizeof(*info->fpu), info->fpu);
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
if (elf_core_copy_task_xfpregs(current, info->xfpu))
|
|
||||||
fill_note(info->notes + info->numnote++,
|
|
||||||
"LINUX", ELF_CORE_XFPREG_TYPE,
|
|
||||||
sizeof(*info->xfpu), info->xfpu);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2243,9 +2216,6 @@ static void free_note_info(struct elf_note_info *info)
|
||||||
kfree(info->psinfo);
|
kfree(info->psinfo);
|
||||||
kfree(info->notes);
|
kfree(info->notes);
|
||||||
kfree(info->fpu);
|
kfree(info->fpu);
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
kfree(info->xfpu);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <linux/elfcore.h>
|
#include <linux/elfcore.h>
|
||||||
#include <linux/coredump.h>
|
#include <linux/coredump.h>
|
||||||
#include <linux/dax.h>
|
#include <linux/dax.h>
|
||||||
|
#include <linux/regset.h>
|
||||||
|
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <asm/param.h>
|
#include <asm/param.h>
|
||||||
|
@ -1188,6 +1189,32 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_ELF_CORE
|
#ifdef CONFIG_ELF_CORE
|
||||||
|
|
||||||
|
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 */
|
||||||
|
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
|
||||||
|
* fields (below) used to communicate this information are placed
|
||||||
|
* immediately after ``pr_reg'', so that the loadmap addresses may
|
||||||
|
* be viewed as part of the register set if so desired.
|
||||||
|
*/
|
||||||
|
unsigned long pr_exec_fdpic_loadmap;
|
||||||
|
unsigned long pr_interp_fdpic_loadmap;
|
||||||
|
int pr_fpvalid; /* True if math co-processor being used. */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Decide whether a segment is worth dumping; default is yes to be
|
* Decide whether a segment is worth dumping; default is yes to be
|
||||||
* sure (missing info is worse than too much; etc).
|
* sure (missing info is worse than too much; etc).
|
||||||
|
@ -1344,7 +1371,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 *prstatus,
|
static void fill_prstatus(struct elf_prstatus_fdpic *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;
|
||||||
|
@ -1426,14 +1453,10 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
|
||||||
/* Here is the structure in which status of each thread is captured. */
|
/* Here is the structure in which status of each thread is captured. */
|
||||||
struct elf_thread_status
|
struct elf_thread_status
|
||||||
{
|
{
|
||||||
struct list_head list;
|
struct elf_thread_status *next;
|
||||||
struct elf_prstatus prstatus; /* NT_PRSTATUS */
|
struct elf_prstatus_fdpic prstatus; /* NT_PRSTATUS */
|
||||||
elf_fpregset_t fpu; /* NT_PRFPREG */
|
elf_fpregset_t fpu; /* NT_PRFPREG */
|
||||||
struct task_struct *thread;
|
struct memelfnote notes[2];
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */
|
|
||||||
#endif
|
|
||||||
struct memelfnote notes[3];
|
|
||||||
int num_notes;
|
int num_notes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1442,38 +1465,44 @@ struct elf_thread_status
|
||||||
* we need to keep a linked list of every thread's pr_status and then create
|
* we need to keep a linked list of every thread's pr_status and then create
|
||||||
* a single section for them in the final core file.
|
* a single section for them in the final core file.
|
||||||
*/
|
*/
|
||||||
static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
|
static struct elf_thread_status *elf_dump_thread_status(long signr, struct task_struct *p, int *sz)
|
||||||
{
|
{
|
||||||
struct task_struct *p = t->thread;
|
const struct user_regset_view *view = task_user_regset_view(p);
|
||||||
int sz = 0;
|
struct elf_thread_status *t;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
t->num_notes = 0;
|
t = kzalloc(sizeof(struct elf_thread_status), GFP_KERNEL);
|
||||||
|
if (!t)
|
||||||
|
return t;
|
||||||
|
|
||||||
fill_prstatus(&t->prstatus, p, signr);
|
fill_prstatus(&t->prstatus, p, signr);
|
||||||
elf_core_copy_task_regs(p, &t->prstatus.pr_reg);
|
regset_get(p, &view->regsets[0],
|
||||||
|
sizeof(t->prstatus.pr_reg), &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),
|
||||||
&t->prstatus);
|
&t->prstatus);
|
||||||
t->num_notes++;
|
t->num_notes++;
|
||||||
sz += notesize(&t->notes[0]);
|
*sz += notesize(&t->notes[0]);
|
||||||
|
|
||||||
|
for (i = 1; i < view->n; ++i) {
|
||||||
|
const struct user_regset *regset = &view->regsets[i];
|
||||||
|
if (regset->core_note_type != NT_PRFPREG)
|
||||||
|
continue;
|
||||||
|
if (regset->active && regset->active(p, regset) <= 0)
|
||||||
|
continue;
|
||||||
|
ret = regset_get(p, regset, sizeof(t->fpu), &t->fpu);
|
||||||
|
if (ret >= 0)
|
||||||
|
t->prstatus.pr_fpvalid = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL, &t->fpu);
|
|
||||||
if (t->prstatus.pr_fpvalid) {
|
if (t->prstatus.pr_fpvalid) {
|
||||||
fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu),
|
fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu),
|
||||||
&t->fpu);
|
&t->fpu);
|
||||||
t->num_notes++;
|
t->num_notes++;
|
||||||
sz += notesize(&t->notes[1]);
|
*sz += notesize(&t->notes[1]);
|
||||||
}
|
}
|
||||||
|
return t;
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
if (elf_core_copy_task_xfpregs(p, &t->xfpu)) {
|
|
||||||
fill_note(&t->notes[2], "LINUX", ELF_CORE_XFPREG_TYPE,
|
|
||||||
sizeof(t->xfpu), &t->xfpu);
|
|
||||||
t->num_notes++;
|
|
||||||
sz += notesize(&t->notes[2]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return sz;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
|
static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
|
||||||
|
@ -1552,23 +1581,15 @@ static size_t elf_core_vma_data_size(unsigned long mm_flags)
|
||||||
*/
|
*/
|
||||||
static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
||||||
{
|
{
|
||||||
#define NUM_NOTES 6
|
|
||||||
int has_dumped = 0;
|
int has_dumped = 0;
|
||||||
int segs;
|
int segs;
|
||||||
int i;
|
int i;
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
struct elfhdr *elf = NULL;
|
struct elfhdr *elf = NULL;
|
||||||
loff_t offset = 0, dataoff;
|
loff_t offset = 0, dataoff;
|
||||||
int numnote;
|
struct memelfnote psinfo_note, auxv_note;
|
||||||
struct memelfnote *notes = NULL;
|
|
||||||
struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
|
|
||||||
struct elf_prpsinfo *psinfo = NULL; /* NT_PRPSINFO */
|
struct elf_prpsinfo *psinfo = NULL; /* NT_PRPSINFO */
|
||||||
LIST_HEAD(thread_list);
|
struct elf_thread_status *thread_list = NULL;
|
||||||
struct list_head *t;
|
|
||||||
elf_fpregset_t *fpu = NULL;
|
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
elf_fpxregset_t *xfpu = NULL;
|
|
||||||
#endif
|
|
||||||
int thread_status_size = 0;
|
int thread_status_size = 0;
|
||||||
elf_addr_t *auxv;
|
elf_addr_t *auxv;
|
||||||
struct elf_phdr *phdr4note = NULL;
|
struct elf_phdr *phdr4note = NULL;
|
||||||
|
@ -1594,47 +1615,28 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
||||||
elf = kmalloc(sizeof(*elf), GFP_KERNEL);
|
elf = kmalloc(sizeof(*elf), GFP_KERNEL);
|
||||||
if (!elf)
|
if (!elf)
|
||||||
goto end_coredump;
|
goto end_coredump;
|
||||||
prstatus = kzalloc(sizeof(*prstatus), GFP_KERNEL);
|
|
||||||
if (!prstatus)
|
|
||||||
goto end_coredump;
|
|
||||||
psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
|
psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
|
||||||
if (!psinfo)
|
if (!psinfo)
|
||||||
goto end_coredump;
|
goto end_coredump;
|
||||||
notes = kmalloc_array(NUM_NOTES, sizeof(struct memelfnote),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!notes)
|
|
||||||
goto end_coredump;
|
|
||||||
fpu = kmalloc(sizeof(*fpu), GFP_KERNEL);
|
|
||||||
if (!fpu)
|
|
||||||
goto end_coredump;
|
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
xfpu = kmalloc(sizeof(*xfpu), GFP_KERNEL);
|
|
||||||
if (!xfpu)
|
|
||||||
goto end_coredump;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (ct = current->mm->core_state->dumper.next;
|
for (ct = current->mm->core_state->dumper.next;
|
||||||
ct; ct = ct->next) {
|
ct; ct = ct->next) {
|
||||||
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
|
tmp = elf_dump_thread_status(cprm->siginfo->si_signo,
|
||||||
|
ct->task, &thread_status_size);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
goto end_coredump;
|
goto end_coredump;
|
||||||
|
|
||||||
tmp->thread = ct->task;
|
tmp->next = thread_list;
|
||||||
list_add(&tmp->list, &thread_list);
|
thread_list = tmp;
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each(t, &thread_list) {
|
|
||||||
struct elf_thread_status *tmp;
|
|
||||||
int sz;
|
|
||||||
|
|
||||||
tmp = list_entry(t, struct elf_thread_status, list);
|
|
||||||
sz = elf_dump_thread_status(cprm->siginfo->si_signo, tmp);
|
|
||||||
thread_status_size += sz;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now collect the dump for the current */
|
/* now collect the dump for the current */
|
||||||
fill_prstatus(prstatus, current, cprm->siginfo->si_signo);
|
tmp = elf_dump_thread_status(cprm->siginfo->si_signo,
|
||||||
elf_core_copy_regs(&prstatus->pr_reg, cprm->regs);
|
current, &thread_status_size);
|
||||||
|
if (!tmp)
|
||||||
|
goto end_coredump;
|
||||||
|
tmp->next = thread_list;
|
||||||
|
thread_list = tmp;
|
||||||
|
|
||||||
segs = current->mm->map_count;
|
segs = current->mm->map_count;
|
||||||
segs += elf_core_extra_phdrs();
|
segs += elf_core_extra_phdrs();
|
||||||
|
@ -1656,51 +1658,28 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
||||||
* with info from their /proc.
|
* with info from their /proc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fill_note(notes + 0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus);
|
|
||||||
fill_psinfo(psinfo, current->group_leader, current->mm);
|
fill_psinfo(psinfo, current->group_leader, current->mm);
|
||||||
fill_note(notes + 1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
|
fill_note(&psinfo_note, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
|
||||||
|
thread_status_size += notesize(&psinfo_note);
|
||||||
numnote = 2;
|
|
||||||
|
|
||||||
auxv = (elf_addr_t *) current->mm->saved_auxv;
|
auxv = (elf_addr_t *) current->mm->saved_auxv;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
do
|
do
|
||||||
i += 2;
|
i += 2;
|
||||||
while (auxv[i - 2] != AT_NULL);
|
while (auxv[i - 2] != AT_NULL);
|
||||||
fill_note(¬es[numnote++], "CORE", NT_AUXV,
|
fill_note(&auxv_note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv);
|
||||||
i * sizeof(elf_addr_t), auxv);
|
thread_status_size += notesize(&auxv_note);
|
||||||
|
|
||||||
/* Try to dump the FPU. */
|
offset = sizeof(*elf); /* Elf header */
|
||||||
if ((prstatus->pr_fpvalid =
|
|
||||||
elf_core_copy_task_fpregs(current, cprm->regs, fpu)))
|
|
||||||
fill_note(notes + numnote++,
|
|
||||||
"CORE", NT_PRFPREG, sizeof(*fpu), fpu);
|
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
if (elf_core_copy_task_xfpregs(current, xfpu))
|
|
||||||
fill_note(notes + numnote++,
|
|
||||||
"LINUX", ELF_CORE_XFPREG_TYPE, sizeof(*xfpu), xfpu);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
offset += sizeof(*elf); /* Elf header */
|
|
||||||
offset += segs * sizeof(struct elf_phdr); /* Program headers */
|
offset += segs * sizeof(struct elf_phdr); /* Program headers */
|
||||||
|
|
||||||
/* Write notes phdr entry */
|
/* Write notes phdr entry */
|
||||||
{
|
phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
|
||||||
int sz = 0;
|
if (!phdr4note)
|
||||||
|
goto end_coredump;
|
||||||
|
|
||||||
for (i = 0; i < numnote; i++)
|
fill_elf_note_phdr(phdr4note, thread_status_size, offset);
|
||||||
sz += notesize(notes + i);
|
offset += thread_status_size;
|
||||||
|
|
||||||
sz += thread_status_size;
|
|
||||||
|
|
||||||
phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
|
|
||||||
if (!phdr4note)
|
|
||||||
goto end_coredump;
|
|
||||||
|
|
||||||
fill_elf_note_phdr(phdr4note, sz, offset);
|
|
||||||
offset += sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Page-align dumped data */
|
/* Page-align dumped data */
|
||||||
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
|
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
|
||||||
|
@ -1753,15 +1732,18 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
||||||
goto end_coredump;
|
goto end_coredump;
|
||||||
|
|
||||||
/* write out the notes section */
|
/* write out the notes section */
|
||||||
for (i = 0; i < numnote; i++)
|
if (!writenote(thread_list->notes, cprm))
|
||||||
if (!writenote(notes + i, cprm))
|
goto end_coredump;
|
||||||
|
if (!writenote(&psinfo_note, cprm))
|
||||||
|
goto end_coredump;
|
||||||
|
if (!writenote(&auxv_note, cprm))
|
||||||
|
goto end_coredump;
|
||||||
|
for (i = 1; i < thread_list->num_notes; i++)
|
||||||
|
if (!writenote(thread_list->notes + i, cprm))
|
||||||
goto end_coredump;
|
goto end_coredump;
|
||||||
|
|
||||||
/* write out the thread status notes section */
|
/* write out the thread status notes section */
|
||||||
list_for_each(t, &thread_list) {
|
for (tmp = thread_list->next; tmp; tmp = tmp->next) {
|
||||||
struct elf_thread_status *tmp =
|
|
||||||
list_entry(t, struct elf_thread_status, list);
|
|
||||||
|
|
||||||
for (i = 0; i < tmp->num_notes; i++)
|
for (i = 0; i < tmp->num_notes; i++)
|
||||||
if (!writenote(&tmp->notes[i], cprm))
|
if (!writenote(&tmp->notes[i], cprm))
|
||||||
goto end_coredump;
|
goto end_coredump;
|
||||||
|
@ -1789,23 +1771,16 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
||||||
}
|
}
|
||||||
|
|
||||||
end_coredump:
|
end_coredump:
|
||||||
while (!list_empty(&thread_list)) {
|
while (thread_list) {
|
||||||
struct list_head *tmp = thread_list.next;
|
tmp = thread_list;
|
||||||
list_del(tmp);
|
thread_list = thread_list->next;
|
||||||
kfree(list_entry(tmp, struct elf_thread_status, list));
|
kfree(tmp);
|
||||||
}
|
}
|
||||||
kfree(phdr4note);
|
kfree(phdr4note);
|
||||||
kfree(elf);
|
kfree(elf);
|
||||||
kfree(prstatus);
|
|
||||||
kfree(psinfo);
|
kfree(psinfo);
|
||||||
kfree(notes);
|
|
||||||
kfree(fpu);
|
|
||||||
kfree(shdr4extnum);
|
kfree(shdr4extnum);
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
kfree(xfpu);
|
|
||||||
#endif
|
|
||||||
return has_dumped;
|
return has_dumped;
|
||||||
#undef NUM_NOTES
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_ELF_CORE */
|
#endif /* CONFIG_ELF_CORE */
|
||||||
|
|
|
@ -32,10 +32,6 @@ struct compat_elf_prstatus
|
||||||
struct old_timeval32 pr_cutime;
|
struct old_timeval32 pr_cutime;
|
||||||
struct old_timeval32 pr_cstime;
|
struct old_timeval32 pr_cstime;
|
||||||
compat_elf_gregset_t pr_reg;
|
compat_elf_gregset_t pr_reg;
|
||||||
#ifdef CONFIG_BINFMT_ELF_FDPIC
|
|
||||||
compat_ulong_t pr_exec_fdpic_loadmap;
|
|
||||||
compat_ulong_t pr_interp_fdpic_loadmap;
|
|
||||||
#endif
|
|
||||||
compat_int_t pr_fpvalid;
|
compat_int_t pr_fpvalid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,65 @@
|
||||||
#include <linux/user.h>
|
#include <linux/user.h>
|
||||||
#include <linux/bug.h>
|
#include <linux/bug.h>
|
||||||
#include <linux/sched/task_stack.h>
|
#include <linux/sched/task_stack.h>
|
||||||
|
#include <linux/types.h>
|
||||||
#include <asm/elf.h>
|
#include <linux/signal.h>
|
||||||
#include <uapi/linux/elfcore.h>
|
#include <linux/time.h>
|
||||||
|
#include <linux/ptrace.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/elf.h>
|
||||||
|
|
||||||
struct coredump_params;
|
struct coredump_params;
|
||||||
|
|
||||||
|
struct elf_siginfo
|
||||||
|
{
|
||||||
|
int si_signo; /* signal number */
|
||||||
|
int si_code; /* extra code */
|
||||||
|
int si_errno; /* errno */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions to generate Intel SVR4-like core files.
|
||||||
|
* These mostly have the same names as the SVR4 types with "elf_"
|
||||||
|
* tacked on the front to prevent clashes with linux definitions,
|
||||||
|
* and the typedef forms have been avoided. This is mostly like
|
||||||
|
* 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_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 */
|
||||||
|
elf_gregset_t pr_reg; /* GP registers */
|
||||||
|
int pr_fpvalid; /* True if math co-processor being used. */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ELF_PRARGSZ (80) /* Number of chars for args */
|
||||||
|
|
||||||
|
struct elf_prpsinfo
|
||||||
|
{
|
||||||
|
char pr_state; /* numeric process state */
|
||||||
|
char pr_sname; /* char for pr_state */
|
||||||
|
char pr_zomb; /* zombie */
|
||||||
|
char pr_nice; /* nice val */
|
||||||
|
unsigned long 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 */
|
||||||
|
};
|
||||||
|
|
||||||
static inline void elf_core_copy_regs(elf_gregset_t *elfregs, struct pt_regs *regs)
|
static inline void elf_core_copy_regs(elf_gregset_t *elfregs, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
#ifdef ELF_CORE_COPY_REGS
|
#ifdef ELF_CORE_COPY_REGS
|
||||||
|
@ -51,13 +104,6 @@ static inline int elf_core_copy_task_fpregs(struct task_struct *t, struct pt_reg
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ELF_CORE_COPY_XFPREGS
|
|
||||||
static inline int elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu)
|
|
||||||
{
|
|
||||||
return ELF_CORE_COPY_XFPREGS(t, xfpu);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions parameterize elf_core_dump in fs/binfmt_elf.c to write out
|
* These functions parameterize elf_core_dump in fs/binfmt_elf.c to write out
|
||||||
* extra segments containing the gate DSO contents. Dumping its
|
* extra segments containing the gate DSO contents. Dumping its
|
||||||
|
|
|
@ -1,101 +0,0 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
|
||||||
#ifndef _UAPI_LINUX_ELFCORE_H
|
|
||||||
#define _UAPI_LINUX_ELFCORE_H
|
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <linux/signal.h>
|
|
||||||
#include <linux/time.h>
|
|
||||||
#include <linux/ptrace.h>
|
|
||||||
#include <linux/elf.h>
|
|
||||||
#include <linux/fs.h>
|
|
||||||
|
|
||||||
struct elf_siginfo
|
|
||||||
{
|
|
||||||
int si_signo; /* signal number */
|
|
||||||
int si_code; /* extra code */
|
|
||||||
int si_errno; /* errno */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __KERNEL__
|
|
||||||
typedef elf_greg_t greg_t;
|
|
||||||
typedef elf_gregset_t gregset_t;
|
|
||||||
typedef elf_fpregset_t fpregset_t;
|
|
||||||
typedef elf_fpxregset_t fpxregset_t;
|
|
||||||
#define NGREG ELF_NGREG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Definitions to generate Intel SVR4-like core files.
|
|
||||||
* These mostly have the same names as the SVR4 types with "elf_"
|
|
||||||
* tacked on the front to prevent clashes with linux definitions,
|
|
||||||
* and the typedef forms have been avoided. This is mostly like
|
|
||||||
* the SVR4 structure, but more Linuxy, with things that Linux does
|
|
||||||
* not support and which gdb doesn't really use excluded.
|
|
||||||
* Fields present but not used are marked with "XXX".
|
|
||||||
*/
|
|
||||||
struct elf_prstatus
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
long pr_flags; /* XXX Process flags */
|
|
||||||
short pr_why; /* XXX Reason for process halt */
|
|
||||||
short pr_what; /* XXX More detailed reason */
|
|
||||||
#endif
|
|
||||||
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 */
|
|
||||||
#if 0
|
|
||||||
struct sigaltstack pr_altstack; /* Alternate stack info */
|
|
||||||
struct sigaction pr_action; /* Signal action for current sig */
|
|
||||||
#endif
|
|
||||||
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 */
|
|
||||||
#if 0
|
|
||||||
long pr_instr; /* Current instruction */
|
|
||||||
#endif
|
|
||||||
elf_gregset_t pr_reg; /* GP registers */
|
|
||||||
#ifdef CONFIG_BINFMT_ELF_FDPIC
|
|
||||||
/* When using FDPIC, the loadmap addresses need to be communicated
|
|
||||||
* to GDB in order for GDB to do the necessary relocations. The
|
|
||||||
* fields (below) used to communicate this information are placed
|
|
||||||
* immediately after ``pr_reg'', so that the loadmap addresses may
|
|
||||||
* be viewed as part of the register set if so desired.
|
|
||||||
*/
|
|
||||||
unsigned long pr_exec_fdpic_loadmap;
|
|
||||||
unsigned long pr_interp_fdpic_loadmap;
|
|
||||||
#endif
|
|
||||||
int pr_fpvalid; /* True if math co-processor being used. */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ELF_PRARGSZ (80) /* Number of chars for args */
|
|
||||||
|
|
||||||
struct elf_prpsinfo
|
|
||||||
{
|
|
||||||
char pr_state; /* numeric process state */
|
|
||||||
char pr_sname; /* char for pr_state */
|
|
||||||
char pr_zomb; /* zombie */
|
|
||||||
char pr_nice; /* nice val */
|
|
||||||
unsigned long 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 */
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef __KERNEL__
|
|
||||||
typedef struct elf_prstatus prstatus_t;
|
|
||||||
typedef struct elf_prpsinfo prpsinfo_t;
|
|
||||||
#define PRARGSZ ELF_PRARGSZ
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _UAPI_LINUX_ELFCORE_H */
|
|
|
@ -86,7 +86,6 @@ arch/x86/include/uapi/asm/auxvec.h:CONFIG_X86_64
|
||||||
arch/x86/include/uapi/asm/mman.h:CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
|
arch/x86/include/uapi/asm/mman.h:CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
|
||||||
include/uapi/asm-generic/fcntl.h:CONFIG_64BIT
|
include/uapi/asm-generic/fcntl.h:CONFIG_64BIT
|
||||||
include/uapi/linux/atmdev.h:CONFIG_COMPAT
|
include/uapi/linux/atmdev.h:CONFIG_COMPAT
|
||||||
include/uapi/linux/elfcore.h:CONFIG_BINFMT_ELF_FDPIC
|
|
||||||
include/uapi/linux/eventpoll.h:CONFIG_PM_SLEEP
|
include/uapi/linux/eventpoll.h:CONFIG_PM_SLEEP
|
||||||
include/uapi/linux/hw_breakpoint.h:CONFIG_HAVE_MIXED_BREAKPOINTS_REGS
|
include/uapi/linux/hw_breakpoint.h:CONFIG_HAVE_MIXED_BREAKPOINTS_REGS
|
||||||
include/uapi/linux/pktcdvd.h:CONFIG_CDROM_PKTCDVD_WCACHE
|
include/uapi/linux/pktcdvd.h:CONFIG_CDROM_PKTCDVD_WCACHE
|
||||||
|
|
|
@ -28,7 +28,6 @@ no-header-test += linux/am437x-vpfe.h
|
||||||
no-header-test += linux/android/binder.h
|
no-header-test += linux/android/binder.h
|
||||||
no-header-test += linux/android/binderfs.h
|
no-header-test += linux/android/binderfs.h
|
||||||
no-header-test += linux/coda.h
|
no-header-test += linux/coda.h
|
||||||
no-header-test += linux/elfcore.h
|
|
||||||
no-header-test += linux/errqueue.h
|
no-header-test += linux/errqueue.h
|
||||||
no-header-test += linux/fsmap.h
|
no-header-test += linux/fsmap.h
|
||||||
no-header-test += linux/hdlc/ioctl.h
|
no-header-test += linux/hdlc/ioctl.h
|
||||||
|
|
Loading…
Reference in New Issue