lkml.org 
[lkml]   [1999]   [May]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[PATCH] /proc/kcore_elf against 2.3.3
Date
From

Please find attached a patch to provide a 'kernel core' file in /proc that is
based on the ELF format rather than the a.out format. I've found that gdb has
a lot of problems accessing data with the a.out format, and none with this
(depending on the version of gcc used).

Tigran Aivazian has tried it, modified it, and has just prepared a version
that applies cleanly to 2.3.3 (attached below). There shouldn't be much problem
applying it as there is little impact on extant code.

The version attached here creates an extra proc file "/proc/kcore_elf" rather
than changing "/proc/kcore" itself, but that can be easily changed.

There's also a copy on:

http://www.aivazian.demon.co.uk/patches/elf-kcore-2.3.3.patch

All the best,
David Howells
===============================================================================

diff -urN linux/fs/proc/Makefile linux-2.3.3-kcore/fs/proc/Makefile
- --- linux/fs/proc/Makefile Wed Jun 24 22:30:10 1998
+++ linux-2.3.3-kcore/fs/proc/Makefile Tue May 25 10:02:56 1999
@@ -9,7 +9,7 @@

O_TARGET := proc.o
O_OBJS := inode.o root.o base.o generic.o mem.o link.o fd.o array.o \
- - kmsg.o scsi.o proc_tty.o
+ kmsg.o scsi.o proc_tty.o kcore.o
ifdef CONFIG_OMIRR
O_OBJS := $(O_OBJS) omirr.o
endif
diff -urN linux/fs/proc/kcore.c linux-2.3.3-kcore/fs/proc/kcore.c
- --- linux/fs/proc/kcore.c Thu Jan 1 01:00:00 1970
+++ linux-2.3.3-kcore/fs/proc/kcore.c Tue May 25 10:03:21 1999
@@ -0,0 +1,281 @@
+/*
+ * kernel ELF core dumper
+ *
+ * Modelled on fs/exec.c:aout_core_dump()
+ * Jeremy Fitzhardinge <jeremy@sw.oz.au>
+ * Implemented by David Howells <David.Howells@nexor.co.uk>
+ * Minor modifications by Tigran Aivazian <tigran@sco.com>
+ */
+
+#include <linux/mm.h>
+#include <linux/proc_fs.h>
+#include <linux/elf.h>
+#include <linux/elfcore.h>
+#include <asm/uaccess.h>
+
+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
+
+/* An ELF note in memory */
+struct memelfnote
+{
+ const char *name;
+ int type;
+ unsigned int datasz;
+ void *data;
+};
+
+extern char saved_command_line[];
+
+/*****************************************************************************/
+/*
+ * determine size of ELF note
+ */
+static int notesize(struct memelfnote *en)
+{
+ int sz;
+
+ sz = sizeof(struct elf_note);
+ sz += roundup(strlen(en->name), 4);
+ sz += roundup(en->datasz, 4);
+
+ return sz;
+} /* end notesize() */
+
+/*****************************************************************************/
+/*
+ * store a note in the header buffer
+ */
+static char *storenote(struct memelfnote *men, char *bufp)
+{
+ struct elf_note en;
+
+#define DUMP_WRITE(addr,nr) do { memcpy(bufp,addr,nr); bufp += nr; } while(0)
+
+ en.n_namesz = strlen(men->name);
+ en.n_descsz = men->datasz;
+ en.n_type = men->type;
+
+ DUMP_WRITE(&en, sizeof(en));
+ DUMP_WRITE(men->name, en.n_namesz);
+
+ /* XXX - cast from long long to long to avoid need for libgcc.a */
+ bufp = (char*) roundup((unsigned long)bufp,4);
+ DUMP_WRITE(men->data, men->datasz);
+ bufp = (char*) roundup((unsigned long)bufp,4);
+
+#undef DUMP_WRITE
+
+ return bufp;
+} /* end storenote() */
+
+/*****************************************************************************/
+/*
+ * store an ELF coredump header in the supplied buffer
+ * - assume the memory image is the size specified
+ */
+static void elf_kcore_store_hdr(char *bufp, size_t size, off_t dataoff)
+{
+ struct elf_prstatus prstatus; /* NT_PRSTATUS */
+ struct elf_prpsinfo psinfo; /* NT_PRPSINFO */
+ struct elf_phdr *nhdr, *dhdr;
+ struct elfhdr *elf;
+ struct memelfnote notes[3];
+ off_t offset = 0;
+
+ /* acquire an ELF header block from the buffer */
+ elf = (struct elfhdr *) bufp;
+ bufp += sizeof(*elf);
+ offset += sizeof(*elf);
+
+ /* set up header */
+ memcpy(elf->e_ident,ELFMAG,SELFMAG);
+ elf->e_ident[EI_CLASS] = ELF_CLASS;
+ elf->e_ident[EI_DATA] = ELF_DATA;
+ elf->e_ident[EI_VERSION]= EV_CURRENT;
+ memset(elf->e_ident+EI_PAD,0,EI_NIDENT-EI_PAD);
+
+ elf->e_type = ET_CORE;
+ elf->e_machine = ELF_ARCH;
+ elf->e_version = EV_CURRENT;
+ elf->e_entry = 0;
+ elf->e_phoff = sizeof(*elf);
+ elf->e_shoff = 0;
+ elf->e_flags = 0;
+ elf->e_ehsize = sizeof(*elf);
+ elf->e_phentsize= sizeof(struct elf_phdr);
+ elf->e_phnum = 2; /* no. of segments */
+ elf->e_shentsize= 0;
+ elf->e_shnum = 0;
+ elf->e_shstrndx = 0;
+
+ /* acquire an ELF program header blocks from the buffer for notes */
+ nhdr = (struct elf_phdr *) bufp;
+ bufp += sizeof(*nhdr);
+ offset += sizeof(*nhdr);
+
+ /* store program headers for notes dump */
+ nhdr->p_type = PT_NOTE;
+ nhdr->p_offset = 0;
+ nhdr->p_vaddr = 0;
+ nhdr->p_paddr = 0;
+ nhdr->p_memsz = 0;
+ nhdr->p_flags = 0;
+ nhdr->p_align = 0;
+
+ /* acquire an ELF program header blocks from the buffer for data */
+ dhdr = (struct elf_phdr *) bufp;
+ bufp += sizeof(*dhdr);
+ offset += sizeof(*dhdr);
+
+ /* store program headers for data dump */
+ dhdr->p_type = PT_LOAD;
+ dhdr->p_flags = PF_R|PF_W|PF_X;
+ dhdr->p_offset = dataoff;
+ dhdr->p_vaddr = PAGE_OFFSET;
+ dhdr->p_paddr = __pa(PAGE_OFFSET);
+ dhdr->p_filesz = size;
+ dhdr->p_memsz = size;
+ dhdr->p_align = PAGE_SIZE;
+
+ /*
+ * Set up the notes in similar form to SVR4 core dumps made
+ * with info from their /proc.
+ */
+ nhdr->p_offset = offset;
+ nhdr->p_filesz = 0;
+
+ /* set up the process status */
+ notes[0].name = "CORE";
+ notes[0].type = NT_PRSTATUS;
+ notes[0].datasz = sizeof(prstatus);
+ notes[0].data = &prstatus;
+
+ memset(&prstatus,0,sizeof(prstatus));
+
+ nhdr->p_filesz = notesize(&notes[0]);
+ bufp = storenote(&notes[0],bufp);
+
+ /* set up the process info */
+ notes[1].name = "CORE";
+ notes[1].type = NT_PRPSINFO;
+ notes[1].datasz = sizeof(psinfo);
+ notes[1].data = &psinfo;
+
+ memset(&psinfo,0,sizeof(psinfo));
+ psinfo.pr_state = 0;
+ psinfo.pr_sname = 'R';
+ psinfo.pr_zomb = 0;
+
+ strcpy(psinfo.pr_fname,"vmlinux");
+ strncpy(psinfo.pr_psargs,saved_command_line,ELF_PRARGSZ);
+
+ nhdr->p_filesz = notesize(&notes[1]);
+ bufp = storenote(&notes[1],bufp);
+
+ /* set up the task structure */
+ notes[2].name = "CORE";
+ notes[2].type = NT_TASKSTRUCT;
+ notes[2].datasz = sizeof(*current);
+ notes[2].data = current;
+
+ nhdr->p_filesz = notesize(&notes[2]);
+ bufp = storenote(&notes[2],bufp);
+
+} /* end elf_kcore_store_hdr() */
+
+/*****************************************************************************/
+/*
+ * read from the ELF header and then kernel memory
+ */
+static ssize_t elf_kcore_read(struct file *file, char *buffer, size_t buflen,
+ loff_t *fpos)
+{
+ ssize_t acc;
+ size_t size, tsz;
+ char *page;
+
+ /* work out how much file we allow to be read */
+ size = ((size_t)high_memory - PAGE_OFFSET) + PAGE_SIZE;
+ acc = 0;
+
+ /* see if file pointer already beyond EOF */
+ if (buflen==0 || *fpos>=size)
+ return 0;
+
+ /* trim buflen to not go beyond EOF */
+ if (buflen > size-*fpos)
+ buflen = size - *fpos;
+
+ /* construct an ELF core header if we'll need some of it */
+ if (*fpos<PAGE_SIZE) {
+ /* get a buffer */
+ page = (char*) __get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ tsz = PAGE_SIZE-*fpos;
+ if (buflen < tsz)
+ tsz = buflen;
+
+ /* create a header */
+ memset(page,0,PAGE_SIZE);
+ elf_kcore_store_hdr(page,size-PAGE_SIZE,PAGE_SIZE);
+
+ /* copy data to the users buffer */
+ copy_to_user(buffer,page,tsz);
+ buflen -= tsz;
+ *fpos += tsz;
+ buffer += tsz;
+ acc += tsz;
+
+ free_page((unsigned long) page);
+
+ /* leave now if filled buffer already */
+ if (buflen==0)
+ return tsz;
+ }
+
+ /* where page 0 not mapped, write zeros into buffer */
+#if defined (__i386__) || defined (__mc68000__)
+ if (*fpos < PAGE_SIZE*2) {
+ /* work out how much to clear */
+ tsz = PAGE_SIZE*2 - *fpos;
+ if (buflen < tsz)
+ tsz = buflen;
+
+ /* write zeros to buffer */
+ clear_user(buffer,tsz);
+ buflen -= tsz;
+ *fpos += tsz;
+ buffer += tsz;
+ acc += tsz;
+
+ /* leave now if filled buffer already */
+ if (buflen==0)
+ return tsz;
+ }
+#endif
+
+ /* fill the remainder of the buffer from kernel VM space */
+#if defined (__i386__) || defined (__mc68000__)
+ copy_to_user(buffer,__va(*fpos-PAGE_SIZE),buflen);
+#else
+ copy_to_user(buffer,__va(*fpos),buflen);
+#endif
+ acc += buflen;
+
+ return acc;
+
+} /* end elf_kcore_read() */
+
+/*****************************************************************************/
+/* data structures for registering /proc/kcore_elf */
+
+static struct file_operations elf_kcore_operations = {
+ read: elf_kcore_read
+};
+
+/* root.c places this into struct proc_dir_entry proc_root_kcore_elf */
+struct inode_operations proc_kcore_elf_inode_operations = {
+ &elf_kcore_operations
+};
diff -urN linux/fs/proc/root.c linux-2.3.3-kcore/fs/proc/root.c
- --- linux/fs/proc/root.c Wed Apr 28 16:47:39 1999
+++ linux-2.3.3-kcore/fs/proc/root.c Tue May 25 10:04:36 1999
@@ -566,6 +566,11 @@
S_IFREG | S_IRUSR, 1, 0, 0,
0, &proc_kcore_inode_operations
};
+static struct proc_dir_entry proc_root_kcore_elf = {
+ PROC_KCORE_ELF, 9, "kcore_elf",
+ S_IFREG | S_IRUSR, 1, 0, 0,
+ 0, &proc_kcore_elf_inode_operations
+};
#ifdef CONFIG_MODULES
static struct proc_dir_entry proc_root_modules = {
PROC_MODULES, 7, "modules",
@@ -693,6 +698,8 @@
#endif
proc_register(&proc_root, &proc_root_kcore);
proc_root_kcore.size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE;
+ proc_register(&proc_root, &proc_root_kcore_elf);
+ proc_root_kcore_elf.size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE;

#ifdef CONFIG_MODULES
proc_register(&proc_root, &proc_root_modules);
diff -urN linux/include/linux/proc_fs.h linux-2.3.3-kcore/include/linux/proc_fs.h
- --- linux/include/linux/proc_fs.h Sun May 16 21:18:51 1999
+++ linux-2.3.3-kcore/include/linux/proc_fs.h Tue May 25 10:05:21 1999
@@ -52,7 +52,8 @@
PROC_STRAM,
PROC_SOUND,
PROC_MTRR, /* whether enabled or not */
- - PROC_FS
+ PROC_FS,
+ PROC_KCORE_ELF
};

enum pid_directory_inos {
@@ -413,6 +414,7 @@
extern struct inode_operations proc_array_inode_operations;
extern struct inode_operations proc_arraylong_inode_operations;
extern struct inode_operations proc_kcore_inode_operations;
+extern struct inode_operations proc_kcore_elf_inode_operations;
extern struct inode_operations proc_profile_inode_operations;
extern struct inode_operations proc_kmsg_inode_operations;
extern struct inode_operations proc_link_inode_operations;



------- End of Forwarded Message

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:51    [W:0.028 / U:0.148 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site