diff -urN -X dontdiff linux/Documentation/Configure.help 2325-kcore/Documentation/Configure.help --- linux/Documentation/Configure.help Fri Oct 29 21:19:49 1999 +++ 2325-kcore/Documentation/Configure.help Tue Nov 2 10:53:10 1999 @@ -1912,6 +1912,23 @@ building a kernel for install/rescue disks or your system is very limited in memory. +Kernel core (/proc/kcore) format +CONFIG_KCORE_ELF + If you enabled support for /proc filesystem then the file /proc/kernel/kcore + will contain the kernel core image. This can be used in gdb: + + $ cd /usr/src/linux ; gdb vmlinux /proc/kernel/kcore + + Selecting ELF will make /proc/kerne/kcore appear in ELF core format as defined + by the Executable and Linking Format specification. Selecting A.OUT will + present the kcore file in the old "a.out" format which may be necessary + for some old versions of binutils or on some architectures. + + This is especially useful if you have compiled the kernel with "-g" option + to preserve debugging information. It is mainly used for examining kernel + data structures on the live kernel so if you don't understand what this + means or are not a kernel hacker, just leave it at its default value ELF. + Kernel support for ELF binaries CONFIG_BINFMT_ELF ELF (Executable and Linkable Format) is a format for libraries and diff -urN -X dontdiff linux/Documentation/filesystems/proc.txt 2325-kcore/Documentation/filesystems/proc.txt --- linux/Documentation/filesystems/proc.txt Thu Oct 14 22:22:08 1999 +++ 2325-kcore/Documentation/filesystems/proc.txt Tue Nov 2 11:10:54 1999 @@ -190,7 +190,6 @@ ide Directory containing info about the IDE subsystem interrupts Interrupt usage ioports I/O port usage - kcore Kernel core image kmsg Kernel messages ksyms Kernel symbol table loadavg Load average @@ -207,6 +206,7 @@ stat Overall statistics swaps Swap space utilization sys See chapter 2 + kernel Contains kernel core image called kcore, can be in ELF or A.OUT format. uptime System uptime version Kernel version .............................................................................. diff -urN -X dontdiff linux/arch/i386/config.in 2325-kcore/arch/i386/config.in --- linux/arch/i386/config.in Mon Oct 25 16:26:52 1999 +++ 2325-kcore/arch/i386/config.in Tue Nov 2 10:57:29 1999 @@ -104,6 +104,11 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL +if [ "$CONFIG_PROC_FS" = "y" ]; then + choice 'Kernel core (/proc/kcore) format' \ + "ELF CONFIG_KCORE_ELF \ + A.OUT CONFIG_KCORE_AOUT" ELF +fi tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC diff -urN -X dontdiff linux/arch/i386/defconfig 2325-kcore/arch/i386/defconfig --- linux/arch/i386/defconfig Thu Oct 28 00:16:32 1999 +++ 2325-kcore/arch/i386/defconfig Tue Nov 2 10:58:41 1999 @@ -63,6 +63,8 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_KCORE_AOUT is not set +CONFIG_KCORE_ELF=y CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=y diff -urN -X dontdiff linux/fs/proc/Makefile 2325-kcore/fs/proc/Makefile --- linux/fs/proc/Makefile Thu Oct 28 22:34:43 1999 +++ 2325-kcore/fs/proc/Makefile Tue Nov 2 10:58:13 1999 @@ -16,6 +16,12 @@ OX_OBJS := procfs_syms.o M_OBJS := +ifdef CONFIG_KCORE_ELF +O_OBJS += kcore.o +else +O_OBJS += kcore_aout.o +endif + ifeq ($(CONFIG_SUN_OPENPROMFS),y) O_OBJS += openpromfs.o else diff -urN -X dontdiff linux/fs/proc/array.c 2325-kcore/fs/proc/array.c --- linux/fs/proc/array.c Thu Oct 28 22:34:43 1999 +++ 2325-kcore/fs/proc/array.c Tue Nov 2 10:59:45 1999 @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include @@ -71,88 +70,6 @@ #include #include #include - - -static int open_kcore(struct inode * inode, struct file * filp) -{ - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; -} - -static ssize_t read_core(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - unsigned long p = *ppos, memsize; - ssize_t read; - ssize_t count1; - char * pnt; - struct user dump; -#if defined (__i386__) || defined (__mc68000__) -# define FIRST_MAPPED PAGE_SIZE /* we don't have page 0 mapped on x86.. */ -#else -# define FIRST_MAPPED 0 -#endif - - memset(&dump, 0, sizeof(struct user)); - dump.magic = CMAGIC; - dump.u_dsize = max_mapnr; -#if defined (__i386__) - dump.start_code = PAGE_OFFSET; -#endif -#ifdef __alpha__ - dump.start_data = PAGE_OFFSET; -#endif - - memsize = (max_mapnr + 1) << PAGE_SHIFT; - if (p >= memsize) - return 0; - if (count > memsize - p) - count = memsize - p; - read = 0; - - if (p < sizeof(struct user) && count > 0) { - count1 = count; - if (p + count1 > sizeof(struct user)) - count1 = sizeof(struct user)-p; - pnt = (char *) &dump + p; - copy_to_user(buf,(void *) pnt, count1); - buf += count1; - p += count1; - count -= count1; - read += count1; - } - - if (count > 0 && p < PAGE_SIZE + FIRST_MAPPED) { - count1 = PAGE_SIZE + FIRST_MAPPED - p; - if (count1 > count) - count1 = count; - clear_user(buf, count1); - buf += count1; - p += count1; - count -= count1; - read += count1; - } - if (count > 0) { - copy_to_user(buf, (void *) (PAGE_OFFSET+p-PAGE_SIZE), count); - read += count; - } - *ppos += read; - return read; -} - -static struct file_operations proc_kcore_operations = { - NULL, /* lseek */ - read_core, - NULL, /* write */ - NULL, /* readdir */ - NULL, /* poll */ - NULL, /* ioctl */ - NULL, /* mmap */ - open_kcore -}; - -struct inode_operations proc_kcore_inode_operations = { - &proc_kcore_operations, -}; /* * This function accesses profiling information. The returned data is diff -urN -X dontdiff linux/fs/proc/kcore.c 2325-kcore/fs/proc/kcore.c --- linux/fs/proc/kcore.c Thu Jan 1 01:00:00 1970 +++ 2325-kcore/fs/proc/kcore.c Tue Nov 2 11:00:01 1999 @@ -0,0 +1,297 @@ +/* + * fs/proc/kcore.c kernel ELF core dumper + * + * Modelled on fs/exec.c:aout_core_dump() + * Jeremy Fitzhardinge + * Implemented by David Howells + * Modified and incorporated into 2.3.x by Tigran Aivazian + */ + +#include +#include +#include +#include +#include + +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) + +/* An ELF note in memory */ +struct kcore_memelfnote +{ + const char *name; + int type; + unsigned int datasz; + void *data; +}; + +extern char saved_command_line[]; + +/*****************************************************************************/ +/* + * determine size of ELF note + */ +static int kcore_notesize(struct kcore_memelfnote *en) +{ + int sz; + + sz = sizeof(struct elf_note); + sz += roundup(strlen(en->name), 4); + sz += roundup(en->datasz, 4); + + return sz; +} /* end kcore_notesize() */ + +/*****************************************************************************/ +/* + * store a note in the header buffer + */ +static char *kcore_storenote(struct kcore_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 kcore_storenote() */ + +/*****************************************************************************/ +/* + * store an ELF coredump header in the supplied buffer + * - assume the memory image is the size specified + */ +static void kcore_store_hdr(char *bufp, size_t size, off_t dataoff) +{ + struct kcore_memelfnote notes[3]; + struct elf_prstatus prstatus; /* NT_PRSTATUS */ + struct elf_prpsinfo psinfo; /* NT_PRPSINFO */ + struct elf_phdr *nhdr, *dhdr; + struct elfhdr *elf; + 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 = kcore_notesize(¬es[0]); + bufp = kcore_storenote(¬es[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 = kcore_notesize(¬es[1]); + bufp = kcore_storenote(¬es[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 = kcore_notesize(¬es[2]); + bufp = kcore_storenote(¬es[2],bufp); + +} /* end kcore_store_hdr() */ + +/*****************************************************************************/ +/* + * read from the ELF header and then kernel memory + */ +static ssize_t read_kcore(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 + * Superceded by the ELF-style kcore + * Made conditional by Tigran Aivazian and + * David Howells + */ + +#include +#include +#include +#include + +/*****************************************************************************/ +/* + * read from the AOUT core header and then kernel memory + */ +static ssize_t read_kcore(struct file * file, char * buf, size_t count, loff_t *ppos) +{ + unsigned long p = *ppos, memsize; + ssize_t read; + ssize_t count1; + char * pnt; + struct user dump; +#if defined (__i386__) || defined (__mc68000__) +# define FIRST_MAPPED PAGE_SIZE /* we don't have page 0 mapped on x86.. */ +#else +# define FIRST_MAPPED 0 +#endif + + memset(&dump, 0, sizeof(struct user)); + dump.magic = CMAGIC; + dump.u_dsize = max_mapnr; +#if defined (__i386__) + dump.start_code = PAGE_OFFSET; +#endif +#ifdef __alpha__ + dump.start_data = PAGE_OFFSET; +#endif + + memsize = (max_mapnr + 1) << PAGE_SHIFT; + if (p >= memsize) + return 0; + if (count > memsize - p) + count = memsize - p; + read = 0; + + if (p < sizeof(struct user) && count > 0) { + count1 = count; + if (p + count1 > sizeof(struct user)) + count1 = sizeof(struct user)-p; + pnt = (char *) &dump + p; + copy_to_user(buf,(void *) pnt, count1); + buf += count1; + p += count1; + count -= count1; + read += count1; + } + + if (count > 0 && p < PAGE_SIZE + FIRST_MAPPED) { + count1 = PAGE_SIZE + FIRST_MAPPED - p; + if (count1 > count) + count1 = count; + clear_user(buf, count1); + buf += count1; + p += count1; + count -= count1; + read += count1; + } + if (count > 0) { + copy_to_user(buf, (void *) (PAGE_OFFSET+p-PAGE_SIZE), count); + read += count; + } + *ppos += read; + return read; +} /* end read_kcore() */ + +/*****************************************************************************/ +/* + * kcore open routine - check we have permission to do raw I/O + */ +static int open_kcore(struct inode *inode, struct file *filp) +{ + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; +} /* end open_kcore() */ + +/*****************************************************************************/ +/* + * describe the kcore file in terms of what operations can be performed on it + */ +static struct file_operations proc_kcore_operations = { + NULL, /* lseek */ + read_kcore, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + open_kcore /* open */ +}; + +struct inode_operations proc_kcore_inode_operations = { + &proc_kcore_operations, +}; diff -urN -X dontdiff linux/fs/proc/proc_misc.c 2325-kcore/fs/proc/proc_misc.c --- linux/fs/proc/proc_misc.c Mon Nov 1 19:37:00 1999 +++ 2325-kcore/fs/proc/proc_misc.c Tue Nov 2 11:37:54 1999 @@ -550,7 +550,7 @@ S_IFREG | S_IRUSR, 1, 0, 0, 0, &proc_kmsg_inode_operations }; -static struct proc_dir_entry proc_root_kcore = { +static struct proc_dir_entry proc_kernel_kcore = { 0, 5, "kcore", S_IFREG | S_IRUSR, 1, 0, 0, 0, &proc_kcore_inode_operations @@ -612,8 +612,8 @@ /* And now for trickier ones */ proc_register(&proc_root, &proc_root_kmsg); - proc_register(&proc_root, &proc_root_kcore); - proc_root_kcore.size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE; + proc_register(proc_root_kernel, &proc_kernel_kcore); + proc_kernel_kcore.size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE; if (prof_shift) { proc_register(&proc_root, &proc_root_profile); proc_root_profile.size = (1+prof_len) * sizeof(unsigned int); diff -urN -X dontdiff linux/fs/proc/procfs_syms.c 2325-kcore/fs/proc/procfs_syms.c --- linux/fs/proc/procfs_syms.c Thu Oct 28 22:34:43 1999 +++ 2325-kcore/fs/proc/procfs_syms.c Tue Nov 2 11:02:32 1999 @@ -22,6 +22,7 @@ EXPORT_SYMBOL(remove_proc_entry); EXPORT_SYMBOL(proc_root); EXPORT_SYMBOL(proc_root_fs); +EXPORT_SYMBOL(proc_root_kernel); EXPORT_SYMBOL(proc_get_inode); EXPORT_SYMBOL(proc_dir_inode_operations); EXPORT_SYMBOL(proc_net); diff -urN -X dontdiff linux/fs/proc/root.c 2325-kcore/fs/proc/root.c --- linux/fs/proc/root.c Thu Oct 28 22:34:43 1999 +++ 2325-kcore/fs/proc/root.c Tue Nov 2 11:21:11 1999 @@ -165,7 +165,7 @@ }; struct proc_dir_entry *proc_net, *proc_scsi, *proc_bus, *proc_sysvipc, - *proc_root_fs, *proc_root_driver; + *proc_root_fs, *proc_root_driver, *proc_root_kernel; #ifdef CONFIG_MCA struct proc_dir_entry *proc_mca; @@ -542,6 +542,7 @@ void __init proc_root_init(void) { proc_base_init(); + proc_root_kernel = create_proc_entry("kernel", S_IFDIR, 0); proc_misc_init(); proc_register(&proc_root, &proc_root_self); proc_net = create_proc_entry("net", S_IFDIR, 0); diff -urN -X dontdiff linux/include/linux/proc_fs.h 2325-kcore/include/linux/proc_fs.h --- linux/include/linux/proc_fs.h Mon Nov 1 21:38:26 1999 +++ 2325-kcore/include/linux/proc_fs.h Tue Nov 2 11:05:03 1999 @@ -193,6 +193,7 @@ extern struct proc_dir_entry *proc_bus; extern struct proc_dir_entry *proc_sysvipc; extern struct proc_dir_entry *proc_root_driver; +extern struct proc_dir_entry *proc_root_kernel; extern struct inode_operations proc_scsi_inode_operations; .