Messages in this thread Patch in this message | | | Subject | Re: dilemma: /proc/kcore vs (x)kdebug. | Date | Thu, 01 Apr 1999 09:05:06 BST | From | David Howells <> |
| |
Tigran Aivazian wrote: > 3. Use what all good Linux books recommend: compile with -g and then do > gdb vmlinux /proc/kcore. > (does not work, try it and see).
I've got a patch which fixes this problem (which I've posted before)... It makes /proc/kcore an ELF core dump instead of an aout core dump.
All the best, David Howells
============= diff -uNr linux-2.2.1/fs/proc/Makefile linux/fs/proc/Makefile --- linux-2.2.1/fs/proc/Makefile Wed Jun 24 22:30:10 1998 +++ linux/fs/proc/Makefile Tue Mar 2 07:56:38 1999 @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile. O_TARGET := proc.o -O_OBJS := inode.o root.o base.o generic.o mem.o link.o fd.o array.o \ +O_OBJS := inode.o root.o base.o generic.o mem.o link.o fd.o array.o kcore.o \ kmsg.o scsi.o proc_tty.o ifdef CONFIG_OMIRR O_OBJS := $(O_OBJS) omirr.o diff -uNr linux-2.2.1/fs/proc/array.c linux/fs/proc/array.c --- linux-2.2.1/fs/proc/array.c Thu Jan 28 18:08:53 1999 +++ linux/fs/proc/array.c Tue Mar 2 07:57:31 1999 @@ -75,74 +75,6 @@ int get_malloc(char * buffer); #endif - -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; -#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, -}; - -struct inode_operations proc_kcore_inode_operations = { - &proc_kcore_operations, -}; - /* * This function accesses profiling information. The returned data is * binary: the sampling step and the actual contents of the profile diff -uNr linux-2.2.1/fs/proc/kcore.c linux/fs/proc/kcore.c --- linux-2.2.1/fs/proc/kcore.c Thu Jan 1 01:00:00 1970 +++ linux/fs/proc/kcore.c Tue Mar 2 08:03:17 1999 @@ -0,0 +1,313 @@ +/* + * kernel ELF core dumper + * + * Modelled on fs/exec.c:aout_core_dump() + * Jeremy Fitzhardinge <jeremy@sw.oz.au> + */ + +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/malloc.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; +}; + +static char saved_command_line[] = + "vmlinux BOOT_IMAGE=bus ro root=303 mem=127M"; + +/*****************************************************************************/ +/* + * 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(¬es[0]); + bufp = 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 = notesize(¬es[1]); + bufp = 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 = notesize(¬es[2]); + bufp = storenote(¬es[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() */ + +/*****************************************************************************/ +/* + * stop the module being unloaded when the file is open + */ +static int elf_kcore_open(struct inode *inode, struct file *file) +{ + MOD_INC_USE_COUNT; + + return 0; +} /* end elf_kcore_open() */ + +/*****************************************************************************/ +/* + * allow the module to be unloaded again + */ +static int elf_kcore_release(struct inode *inode, struct file *file) +{ + MOD_DEC_USE_COUNT; + + return 0; +} /* end elf_kcore_release() */ + +/*****************************************************************************/ +/* + * /proc interface + */ +static struct file_operations elf_kcore_operations = { + NULL, /* lseek */ + elf_kcore_read, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + elf_kcore_open, /* open */ + NULL, /* flush */ + elf_kcore_release /* release */ +}; + +struct inode_operations proc_kcore_inode_operations = { + &elf_kcore_operations, +}; - 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/
| |