Commit 2e54af56 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] /proc/PID/auxv file and NT_AUXV core note

From: Roland McGrath <roland@redhat.com>

gdb really needs some way to know the AT_SYSINFO_EHDR value for a process
being debugged or for the dead process described by a core file.  Without
this value, it can't find the information necessary to show backtraces of
threads waiting in system calls.  There are any number of ways this
information could be made available.  Here is one solution that provides
more debugging information in a clean and general fashion.

I've added access to the AT_* values passed to a process for third parties
to examine for debugging purposes.  The same data passed on the stack at
startup is made available in /proc/PID/auxv and is written in an NT_AUXV
note in core dumps.  (Both of these are consistent with what Solaris does
using the same names.)

Here are two different patches that implement the same thing differently.
The first patch uses a ref-counted data structure to copy the aux vector
and shares among forked mm's until they exec and get a new one.  The second
patch avoids the complexity of that data structure by simply expanding the
mm_struct with space to hold a copy of the data.  Both patches work
correctly; I have examined the new /proc/PID/auxv file and core dumps.

I hope you will consider including one of these patches, or at least some
way of getting at this information from the debugger.  I am certainly open
to other suggestions on implementing this feature, and to suggestions on
alternative interfaces for getting the AT_SYSINFO_EHDR value cleanly.
parent e13a7aa5
...@@ -134,7 +134,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, ...@@ -134,7 +134,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
elf_addr_t *sp, *u_platform; elf_addr_t *sp, *u_platform;
const char *k_platform = ELF_PLATFORM; const char *k_platform = ELF_PLATFORM;
int items; int items;
elf_addr_t elf_info[40]; elf_addr_t *elf_info;
int ei_index = 0; int ei_index = 0;
struct task_struct *tsk = current; struct task_struct *tsk = current;
...@@ -169,6 +169,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, ...@@ -169,6 +169,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
} }
/* Create the ELF interpreter info */ /* Create the ELF interpreter info */
elf_info = current->mm->saved_auxv;
#define NEW_AUX_ENT(id, val) \ #define NEW_AUX_ENT(id, val) \
do { elf_info[ei_index++] = id; elf_info[ei_index++] = val; } while (0) do { elf_info[ei_index++] = id; elf_info[ei_index++] = val; } while (0)
...@@ -1186,7 +1187,7 @@ static int elf_dump_thread_status(long signr, struct task_struct * p, struct lis ...@@ -1186,7 +1187,7 @@ static int elf_dump_thread_status(long signr, struct task_struct * p, struct lis
*/ */
static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
{ {
#define NUM_NOTES 5 #define NUM_NOTES 6
int has_dumped = 0; int has_dumped = 0;
mm_segment_t fs; mm_segment_t fs;
int segs; int segs;
...@@ -1196,7 +1197,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) ...@@ -1196,7 +1197,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
struct elfhdr *elf = NULL; struct elfhdr *elf = NULL;
off_t offset = 0, dataoff; off_t offset = 0, dataoff;
unsigned long limit = current->rlim[RLIMIT_CORE].rlim_cur; unsigned long limit = current->rlim[RLIMIT_CORE].rlim_cur;
int numnote = NUM_NOTES; int numnote;
struct memelfnote *notes = NULL; struct memelfnote *notes = NULL;
struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
struct elf_prpsinfo *psinfo = NULL; /* NT_PRPSINFO */ struct elf_prpsinfo *psinfo = NULL; /* NT_PRPSINFO */
...@@ -1287,18 +1288,24 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) ...@@ -1287,18 +1288,24 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
fill_note(notes +2, "CORE", NT_TASKSTRUCT, sizeof(*current), current); fill_note(notes +2, "CORE", NT_TASKSTRUCT, sizeof(*current), current);
numnote = 3;
i = 0;
do
i += 2;
while (current->mm->saved_auxv[i - 2] != AT_NULL);
fill_note(&notes[numnote++], "CORE", NT_AUXV,
i * sizeof current->mm->saved_auxv[0],
current->mm->saved_auxv);
/* Try to dump the FPU. */ /* Try to dump the FPU. */
if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, fpu))) if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, fpu)))
fill_note(notes +3, "CORE", NT_PRFPREG, sizeof(*fpu), fpu); fill_note(notes + numnote++,
else "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
--numnote;
#ifdef ELF_CORE_COPY_XFPREGS #ifdef ELF_CORE_COPY_XFPREGS
if (elf_core_copy_task_xfpregs(current, xfpu)) if (elf_core_copy_task_xfpregs(current, xfpu))
fill_note(notes +4, "LINUX", NT_PRXFPREG, sizeof(*xfpu), xfpu); fill_note(notes + numnote++,
else "LINUX", NT_PRXFPREG, sizeof(*xfpu), xfpu);
--numnote;
#else
numnote--;
#endif #endif
fs = get_fs(); fs = get_fs();
......
...@@ -395,6 +395,7 @@ typedef struct elf64_shdr { ...@@ -395,6 +395,7 @@ typedef struct elf64_shdr {
#define NT_PRFPREG 2 #define NT_PRFPREG 2
#define NT_PRPSINFO 3 #define NT_PRPSINFO 3
#define NT_TASKSTRUCT 4 #define NT_TASKSTRUCT 4
#define NT_AUXV 6
#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */
......
...@@ -207,6 +207,8 @@ struct mm_struct { ...@@ -207,6 +207,8 @@ struct mm_struct {
cpumask_t cpu_vm_mask; cpumask_t cpu_vm_mask;
unsigned long swap_address; unsigned long swap_address;
unsigned long saved_auxv[40]; /* for /proc/PID/auxv */
unsigned dumpable:1; unsigned dumpable:1;
#ifdef CONFIG_HUGETLB_PAGE #ifdef CONFIG_HUGETLB_PAGE
int used_hugetlb; int used_hugetlb;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment