lkml.org 
[lkml]   [2002]   [Sep]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [ANNOUNCE] [patch] kksymoops, in-kernel symbolic oopser, 2.5.38-B0

    okay, here is the new oops output:

    ------------[ cut here ]------------
    kernel BUG at time.c:99!
    invalid operand: 0000
    CPU: 1
    EIP: 0060:[<c011bd14>] Not tainted
    EFLAGS: 00010246
    EIP is at sys_gettimeofday+0x84/0x90
    eax: 0000004e ebx: cef9e000 ecx: 00000000 edx: 00000068
    esi: 00000000 edi: 00000000 ebp: bffffad8 esp: cef9ffa0
    ds: 0068 es: 0068 ss: 0068
    Process gettimeofday (pid: 549, threadinfo=cef9e000 task=cf84d860)
    Stack: 4001695c bffff414 40156154 00000004 c0112a40 cef9e000 400168e4 bffffb44
    c0107973 00000000 00000000 40156154 400168e4 bffffb44 bffffad8 0000004e
    0000002b 0000002b 0000004e 400cecc1 00000023 00000246 bffffacc 0000002b
    Call Trace: [<c0112a40>] do_page_fault+0x0/0x4a2
    [<c0107973>] syscall_call+0x7/0xb

    and the patch, against BK-curr:

    --- linux/arch/i386/kernel/head.S.orig Fri Sep 20 17:20:16 2002
    +++ linux/arch/i386/kernel/head.S Wed Sep 25 21:46:56 2002
    @@ -121,7 +121,7 @@
    */
    xorl %eax,%eax
    movl $__bss_start,%edi
    - movl $_end,%ecx
    + movl $__bss_stop,%ecx
    subl %edi,%ecx
    rep
    stosb
    --- linux/arch/i386/kernel/process.c.orig Fri Sep 20 17:20:12 2002
    +++ linux/arch/i386/kernel/process.c Wed Sep 25 21:46:56 2002
    @@ -33,6 +33,7 @@
    #include <linux/reboot.h>
    #include <linux/init.h>
    #include <linux/mc146818rtc.h>
    +#include <linux/module.h>

    #include <asm/uaccess.h>
    #include <asm/pgtable.h>
    @@ -155,8 +156,6 @@

    __setup("idle=", idle_setup);

    -extern void show_trace(unsigned long* esp);
    -
    void show_regs(struct pt_regs * regs)
    {
    unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
    @@ -164,6 +163,8 @@
    printk("\n");
    printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
    printk("EIP: %04x:[<%08lx>] CPU: %d",0xffff & regs->xcs,regs->eip, smp_processor_id());
    + print_symbol("EIP is at %s\n", regs->eip);
    +
    if (regs->xcs & 3)
    printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
    printk(" EFLAGS: %08lx %s\n",regs->eflags, print_tainted());
    --- linux/arch/i386/kernel/traps.c.orig Fri Sep 20 17:20:19 2002
    +++ linux/arch/i386/kernel/traps.c Wed Sep 25 21:46:56 2002
    @@ -94,7 +94,6 @@

    #ifdef CONFIG_MODULES

    -extern struct module *module_list;
    extern struct module kernel_module;

    static inline int kernel_text_address(unsigned long addr)
    @@ -142,10 +141,12 @@
    while (((long) stack & (THREAD_SIZE-1)) != 0) {
    addr = *stack++;
    if (kernel_text_address(addr)) {
    - if (i && ((i % 6) == 0))
    - printk("\n ");
    printk("[<%08lx>] ", addr);
    - i++;
    + if (print_symbol("%s\n", addr)) {
    + /* save screen space */
    + if ((i++ % 6) == 0)
    + printk("\n ");
    + }
    }
    }
    printk("\n");
    @@ -206,8 +207,11 @@
    esp = regs->esp;
    ss = regs->xss & 0xffff;
    }
    + print_modules();
    printk("CPU: %d\nEIP: %04x:[<%08lx>] %s\nEFLAGS: %08lx\n",
    smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags);
    +
    + print_symbol("EIP is at %s\n", regs->eip);
    printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
    regs->eax, regs->ebx, regs->ecx, regs->edx);
    printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
    @@ -268,6 +272,7 @@
    (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
    file = "<bad filename>";

    + printk("------------[ cut here ]------------\n");
    printk("kernel BUG at %s:%d!\n", file, line);

    no_bug:
    --- linux/arch/i386/Config.help.orig Fri Sep 20 17:20:16 2002
    +++ linux/arch/i386/Config.help Wed Sep 25 21:46:56 2002
    @@ -946,6 +946,11 @@
    of the BUG call as well as the EIP and oops trace. This aids
    debugging but costs about 70-100K of memory.

    +CONFIG_KALLSYMS
    + Say Y here to let the kernel print out symbolic crash information and
    + symbolic stack backtraces. This increases the size of the kernel
    + somewhat, as all symbols have to be loaded into the kernel image.
    +
    CONFIG_DEBUG_OBSOLETE
    Say Y here if you want to reduce the chances of the tree compiling,
    and are prepared to dig into driver internals to fix compile errors.
    --- linux/arch/i386/config.in.orig Wed Sep 25 21:43:13 2002
    +++ linux/arch/i386/config.in Wed Sep 25 21:46:56 2002
    @@ -435,6 +435,7 @@
    if [ "$CONFIG_HIGHMEM" = "y" ]; then
    bool ' Highmem debugging' CONFIG_DEBUG_HIGHMEM
    fi
    + bool ' Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS
    fi

    if [ "$CONFIG_X86_LOCAL_APIC" = "y" ]; then
    --- linux/arch/i386/vmlinux.lds.S.orig Fri Sep 20 17:20:19 2002
    +++ linux/arch/i386/vmlinux.lds.S Wed Sep 25 21:46:56 2002
    @@ -78,9 +78,13 @@
    .data.cacheline_aligned : { *(.data.cacheline_aligned) }

    __bss_start = .; /* BSS */
    - .bss : {
    - *(.bss)
    - }
    + .bss : { *(.bss) }
    + __bss_stop = .;
    +
    + __start___kallsyms = .; /* All kernel symbols */
    + __kallsyms : { *(__kallsyms) }
    + __stop___kallsyms = .;
    +
    _end = . ;

    /* Sections to be discarded */
    --- linux/include/linux/kallsyms.h.orig Wed Sep 25 21:46:56 2002
    +++ linux/include/linux/kallsyms.h Wed Sep 25 21:46:56 2002
    @@ -0,0 +1,163 @@
    +/* kallsyms headers
    + Copyright 2000 Keith Owens <kaos@ocs.com.au>
    +
    + This file is part of the Linux modutils. It is exported to kernel
    + space so debuggers can access the kallsyms data.
    +
    + The kallsyms data contains all the non-stack symbols from a kernel
    + or a module. The kernel symbols are held between __start___kallsyms
    + and __stop___kallsyms. The symbols for a module are accessed via
    + the struct module chain which is based at module_list.
    +
    + This program is free software; you can redistribute it and/or modify it
    + under the terms of the GNU General Public License as published by the
    + Free Software Foundation; either version 2 of the License, or (at your
    + option) any later version.
    +
    + This program is distributed in the hope that it will be useful, but
    + WITHOUT ANY WARRANTY; without even the implied warranty of
    + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + General Public License for more details.
    +
    + You should have received a copy of the GNU General Public License
    + along with this program; if not, write to the Free Software Foundation,
    + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    + */
    +
    +#ident "$Id: linux-2.4.9-kallsyms.patch,v 1.8 2002/02/11 18:34:53 arjanv Exp $"
    +
    +#ifndef MODUTILS_KALLSYMS_H
    +#define MODUTILS_KALLSYMS_H 1
    +
    +/* Have to (re)define these ElfW entries here because external kallsyms
    + * code does not have access to modutils/include/obj.h. This code is
    + * included from user spaces tools (modutils) and kernel, they need
    + * different includes.
    + */
    +
    +#ifndef ELFCLASS32
    +#ifdef __KERNEL__
    +#include <linux/elf.h>
    +#else /* __KERNEL__ */
    +#include <elf.h>
    +#endif /* __KERNEL__ */
    +#endif /* ELFCLASS32 */
    +
    +#ifndef ELFCLASSM
    +#define ELFCLASSM ELF_CLASS
    +#endif
    +
    +#ifndef ElfW
    +# if ELFCLASSM == ELFCLASS32
    +# define ElfW(x) Elf32_ ## x
    +# define ELFW(x) ELF32_ ## x
    +# else
    +# define ElfW(x) Elf64_ ## x
    +# define ELFW(x) ELF64_ ## x
    +# endif
    +#endif
    +
    +/* Format of data in the kallsyms section.
    + * Most of the fields are small numbers but the total size and all
    + * offsets can be large so use the 32/64 bit types for these fields.
    + *
    + * Do not use sizeof() on these structures, modutils may be using extra
    + * fields. Instead use the size fields in the header to access the
    + * other bits of data.
    + */
    +
    +struct kallsyms_header {
    + int size; /* Size of this header */
    + ElfW(Word) total_size; /* Total size of kallsyms data */
    + int sections; /* Number of section entries */
    + ElfW(Off) section_off; /* Offset to first section entry */
    + int section_size; /* Size of one section entry */
    + int symbols; /* Number of symbol entries */
    + ElfW(Off) symbol_off; /* Offset to first symbol entry */
    + int symbol_size; /* Size of one symbol entry */
    + ElfW(Off) string_off; /* Offset to first string */
    + ElfW(Addr) start; /* Start address of first section */
    + ElfW(Addr) end; /* End address of last section */
    +};
    +
    +struct kallsyms_section {
    + ElfW(Addr) start; /* Start address of section */
    + ElfW(Word) size; /* Size of this section */
    + ElfW(Off) name_off; /* Offset to section name */
    + ElfW(Word) flags; /* Flags from section */
    +};
    +
    +struct kallsyms_symbol {
    + ElfW(Off) section_off; /* Offset to section that owns this symbol */
    + ElfW(Addr) symbol_addr; /* Address of symbol */
    + ElfW(Off) name_off; /* Offset to symbol name */
    +};
    +
    +#define KALLSYMS_SEC_NAME "__kallsyms"
    +#define KALLSYMS_IDX 2 /* obj_kallsyms creates kallsyms as section 2 */
    +
    +#define kallsyms_next_sec(h,s) \
    + ((s) = (struct kallsyms_section *)((char *)(s) + (h)->section_size))
    +#define kallsyms_next_sym(h,s) \
    + ((s) = (struct kallsyms_symbol *)((char *)(s) + (h)->symbol_size))
    +
    +#ifdef CONFIG_KALLSYMS
    +
    +int kallsyms_symbol_to_address(
    + const char *name, /* Name to lookup */
    + unsigned long *token, /* Which module to start with */
    + const char **mod_name, /* Set to module name or "kernel" */
    + unsigned long *mod_start, /* Set to start address of module */
    + unsigned long *mod_end, /* Set to end address of module */
    + const char **sec_name, /* Set to section name */
    + unsigned long *sec_start, /* Set to start address of section */
    + unsigned long *sec_end, /* Set to end address of section */
    + const char **sym_name, /* Set to full symbol name */
    + unsigned long *sym_start, /* Set to start address of symbol */
    + unsigned long *sym_end /* Set to end address of symbol */
    + );
    +
    +int kallsyms_address_to_symbol(
    + unsigned long address, /* Address to lookup */
    + const char **mod_name, /* Set to module name */
    + unsigned long *mod_start, /* Set to start address of module */
    + unsigned long *mod_end, /* Set to end address of module */
    + const char **sec_name, /* Set to section name */
    + unsigned long *sec_start, /* Set to start address of section */
    + unsigned long *sec_end, /* Set to end address of section */
    + const char **sym_name, /* Set to full symbol name */
    + unsigned long *sym_start, /* Set to start address of symbol */
    + unsigned long *sym_end /* Set to end address of symbol */
    + );
    +
    +int kallsyms_sections(void *token,
    + int (*callback)(void *, /* token */
    + const char *, /* module name */
    + const char *, /* section name */
    + ElfW(Addr), /* Section start */
    + ElfW(Addr), /* Section end */
    + ElfW(Word) /* Section flags */
    + )
    + );
    +
    +#else
    +
    +static inline int kallsyms_address_to_symbol(
    + unsigned long address, /* Address to lookup */
    + const char **mod_name, /* Set to module name */
    + unsigned long *mod_start, /* Set to start address of module */
    + unsigned long *mod_end, /* Set to end address of module */
    + const char **sec_name, /* Set to section name */
    + unsigned long *sec_start, /* Set to start address of section */
    + unsigned long *sec_end, /* Set to end address of section */
    + const char **sym_name, /* Set to full symbol name */
    + unsigned long *sym_start, /* Set to start address of symbol */
    + unsigned long *sym_end /* Set to end address of symbol */
    + )
    +{
    + return -ESRCH;
    +}
    +
    +#endif
    +
    +#endif /* kallsyms.h */
    --- linux/include/linux/module.h.orig Fri Sep 20 17:20:32 2002
    +++ linux/include/linux/module.h Wed Sep 25 21:46:56 2002
    @@ -316,8 +316,6 @@
    #define MOD_DEC_USE_COUNT do { } while (0)
    #define MOD_IN_USE 1

    -extern struct module *module_list;
    -
    #endif /* !__GENKSYMS__ */

    #endif /* MODULE */
    @@ -504,6 +502,30 @@
    #define SET_MODULE_OWNER(some_struct) do { (some_struct)->owner = THIS_MODULE; } while (0)
    #else
    #define SET_MODULE_OWNER(some_struct) do { } while (0)
    +#endif
    +
    +extern void print_modules(void);
    +
    +#if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)
    +
    +extern struct module *module_list;
    +
    +/*
    + * print_symbols takes a format string containing one %s.
    + * If support for resolving symbols is compiled in, the %s will
    + * be replaced by the closest symbol to the address and the entire
    + * string is printk()ed. Otherwise, nothing is printed.
    + */
    +extern int print_symbol(const char *fmt, unsigned long address);
    +
    +#else
    +
    +static inline int
    +print_symbol(const char *fmt, unsigned long address)
    +{
    + return -ESRCH;
    +}
    +
    #endif

    #endif /* _LINUX_MODULE_H */
    --- linux/include/linux/sched.h.orig Wed Sep 25 21:43:13 2002
    +++ linux/include/linux/sched.h Wed Sep 25 21:46:56 2002
    @@ -151,7 +151,13 @@

    extern void sched_init(void);
    extern void init_idle(task_t *idle, int cpu);
    +
    extern void show_state(void);
    +extern void show_trace(unsigned long *stack);
    +extern void show_stack(unsigned long *stack);
    +extern void show_regs(struct pt_regs *);
    +
    +
    extern void cpu_init (void);
    extern void trap_init(void);
    extern void update_process_times(int user);
    --- linux/include/asm-i386/hardirq.h.orig Fri Sep 20 17:20:32 2002
    +++ linux/include/asm-i386/hardirq.h Wed Sep 25 21:46:56 2002
    @@ -97,6 +97,4 @@
    extern void synchronize_irq(unsigned int irq);
    #endif /* CONFIG_SMP */

    -extern void show_stack(unsigned long * esp);
    -
    #endif /* __ASM_HARDIRQ_H */
    --- linux/include/asm-i386/ptrace.h.orig Fri Sep 20 17:20:16 2002
    +++ linux/include/asm-i386/ptrace.h Wed Sep 25 21:46:56 2002
    @@ -57,7 +57,6 @@
    #ifdef __KERNEL__
    #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
    #define instruction_pointer(regs) ((regs)->eip)
    -extern void show_regs(struct pt_regs *);
    #endif

    #endif
    --- linux/kernel/Makefile.orig Fri Sep 20 17:20:19 2002
    +++ linux/kernel/Makefile Wed Sep 25 21:46:56 2002
    @@ -3,7 +3,7 @@
    #

    export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \
    - printk.o platform.o suspend.o dma.o
    + printk.o platform.o suspend.o dma.o module.o

    obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
    module.o exit.o itimer.o time.o softirq.o resource.o \
    @@ -14,6 +14,7 @@
    obj-$(CONFIG_SMP) += cpu.o
    obj-$(CONFIG_UID16) += uid16.o
    obj-$(CONFIG_MODULES) += ksyms.o
    +obj-$(CONFIG_KALLSYMS) += kallsyms.o
    obj-$(CONFIG_PM) += pm.o
    obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
    obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
    --- linux/kernel/kallsyms.c.orig Wed Sep 25 21:46:56 2002
    +++ linux/kernel/kallsyms.c Wed Sep 25 21:51:18 2002
    @@ -0,0 +1,227 @@
    +/*
    + * kksymoops.c: in-kernel printing of symbolic oopses and stack traces.
    + *
    + * Copyright 2000 Keith Owens <kaos@ocs.com.au> April 2000
    + * Copyright 2002 Arjan van de Ven <arjanv@redhat.com>
    + *
    + This code uses the list of all kernel and module symbols to :-
    +
    + * Find any non-stack symbol in a kernel or module. Symbols do
    + not have to be exported for debugging.
    +
    + * Convert an address to the module (or kernel) that owns it, the
    + section it is in and the nearest symbol. This finds all non-stack
    + symbols, not just exported ones.
    +
    + */
    +
    +#include <linux/mm.h>
    +#include <linux/module.h>
    +#include <linux/kallsyms.h>
    +
    +/* A symbol can appear in more than one module. A token is used to
    + * restart the scan at the next module, set the token to 0 for the
    + * first scan of each symbol.
    + */
    +
    +int kallsyms_symbol_to_address(
    + const char *name, /* Name to lookup */
    + unsigned long *token, /* Which module to start at */
    + const char **mod_name, /* Set to module name */
    + unsigned long *mod_start, /* Set to start address of module */
    + unsigned long *mod_end, /* Set to end address of module */
    + const char **sec_name, /* Set to section name */
    + unsigned long *sec_start, /* Set to start address of section */
    + unsigned long *sec_end, /* Set to end address of section */
    + const char **sym_name, /* Set to full symbol name */
    + unsigned long *sym_start, /* Set to start address of symbol */
    + unsigned long *sym_end /* Set to end address of symbol */
    + )
    +{
    + const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */
    + const struct kallsyms_section *ka_sec;
    + const struct kallsyms_symbol *ka_sym = NULL;
    + const char *ka_str = NULL;
    + const struct module *m;
    + int i = 0, l;
    + const char *p, *pt_R;
    + char *p2;
    +
    + /* Restart? */
    + m = module_list;
    + if (token && *token) {
    + for (; m; m = m->next)
    + if ((unsigned long)m == *token)
    + break;
    + if (m)
    + m = m->next;
    + }
    +
    + for (; m; m = m->next) {
    + if (!mod_member_present(m, kallsyms_start) ||
    + !mod_member_present(m, kallsyms_end) ||
    + m->kallsyms_start >= m->kallsyms_end)
    + continue;
    + ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
    + ka_sym = (struct kallsyms_symbol *)
    + ((char *)(ka_hdr) + ka_hdr->symbol_off);
    + ka_str =
    + ((char *)(ka_hdr) + ka_hdr->string_off);
    + for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
    + p = ka_str + ka_sym->name_off;
    + if (strcmp(p, name) == 0)
    + break;
    + /* Unversioned requests match versioned names */
    + if (!(pt_R = strstr(p, "_R")))
    + continue;
    + l = strlen(pt_R);
    + if (l < 10)
    + continue; /* Not _R.*xxxxxxxx */
    + (void)simple_strtoul(pt_R+l-8, &p2, 16);
    + if (*p2)
    + continue; /* Not _R.*xxxxxxxx */
    + if (strncmp(p, name, pt_R-p) == 0)
    + break; /* Match with version */
    + }
    + if (i < ka_hdr->symbols)
    + break;
    + }
    +
    + if (token)
    + *token = (unsigned long)m;
    + if (!m)
    + return(0); /* not found */
    +
    + ka_sec = (const struct kallsyms_section *)
    + ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off);
    + *mod_name = m->name;
    + *mod_start = ka_hdr->start;
    + *mod_end = ka_hdr->end;
    + *sec_name = ka_sec->name_off + ka_str;
    + *sec_start = ka_sec->start;
    + *sec_end = ka_sec->start + ka_sec->size;
    + *sym_name = ka_sym->name_off + ka_str;
    + *sym_start = ka_sym->symbol_addr;
    + if (i < ka_hdr->symbols-1) {
    + const struct kallsyms_symbol *ka_symn = ka_sym;
    + kallsyms_next_sym(ka_hdr, ka_symn);
    + *sym_end = ka_symn->symbol_addr;
    + }
    + else
    + *sym_end = *sec_end;
    + return(1);
    +}
    +
    +int kallsyms_address_to_symbol(
    + unsigned long address, /* Address to lookup */
    + const char **mod_name, /* Set to module name */
    + unsigned long *mod_start, /* Set to start address of module */
    + unsigned long *mod_end, /* Set to end address of module */
    + const char **sec_name, /* Set to section name */
    + unsigned long *sec_start, /* Set to start address of section */
    + unsigned long *sec_end, /* Set to end address of section */
    + const char **sym_name, /* Set to full symbol name */
    + unsigned long *sym_start, /* Set to start address of symbol */
    + unsigned long *sym_end /* Set to end address of symbol */
    + )
    +{
    + const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */
    + const struct kallsyms_section *ka_sec = NULL;
    + const struct kallsyms_symbol *ka_sym;
    + const char *ka_str;
    + const struct module *m;
    + int i;
    + unsigned long end;
    +
    + for (m = module_list; m; m = m->next) {
    +
    + if (!mod_member_present(m, kallsyms_start) ||
    + !mod_member_present(m, kallsyms_end) ||
    + m->kallsyms_start >= m->kallsyms_end)
    + continue;
    + ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
    + ka_sec = (const struct kallsyms_section *)
    + ((char *)ka_hdr + ka_hdr->section_off);
    + /* Is the address in any section in this module? */
    + for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
    + if (ka_sec->start <= address &&
    + (ka_sec->start + ka_sec->size) > address)
    + break;
    + }
    + if (i < ka_hdr->sections)
    + break; /* Found a matching section */
    + }
    +
    + if (!m)
    + return(0); /* not found */
    +
    + ka_sym = (struct kallsyms_symbol *)
    + ((char *)(ka_hdr) + ka_hdr->symbol_off);
    + ka_str =
    + ((char *)(ka_hdr) + ka_hdr->string_off);
    + *mod_name = m->name;
    + *mod_start = ka_hdr->start;
    + *mod_end = ka_hdr->end;
    + *sec_name = ka_sec->name_off + ka_str;
    + *sec_start = ka_sec->start;
    + *sec_end = ka_sec->start + ka_sec->size;
    + *sym_name = *sec_name; /* In case we find no matching symbol */
    + *sym_start = *sec_start;
    + *sym_end = *sec_end;
    +
    + for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
    + if (ka_sym->symbol_addr > address)
    + continue;
    + if (i < ka_hdr->symbols-1) {
    + const struct kallsyms_symbol *ka_symn = ka_sym;
    + kallsyms_next_sym(ka_hdr, ka_symn);
    + end = ka_symn->symbol_addr;
    + }
    + else
    + end = *sec_end;
    + if (end <= address)
    + continue;
    + if ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off
    + != (char *)ka_sec)
    + continue; /* wrong section */
    + *sym_name = ka_str + ka_sym->name_off;
    + *sym_start = ka_sym->symbol_addr;
    + *sym_end = end;
    + break;
    + }
    + return(1);
    +}
    +
    +/* List all sections in all modules. The callback routine is invoked with
    + * token, module name, section name, section start, section end, section flags.
    + */
    +int kallsyms_sections(void *token,
    + int (*callback)(void *, const char *, const char *, ElfW(Addr), ElfW(Addr), ElfW(Word)))
    +{
    + const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */
    + const struct kallsyms_section *ka_sec = NULL;
    + const char *ka_str;
    + const struct module *m;
    + int i;
    +
    + for (m = module_list; m; m = m->next) {
    + if (!mod_member_present(m, kallsyms_start) ||
    + !mod_member_present(m, kallsyms_end) ||
    + m->kallsyms_start >= m->kallsyms_end)
    + continue;
    + ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
    + ka_sec = (const struct kallsyms_section *) ((char *)ka_hdr + ka_hdr->section_off);
    + ka_str = ((char *)(ka_hdr) + ka_hdr->string_off);
    + for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
    + if (callback(
    + token,
    + *(m->name) ? m->name : "kernel",
    + ka_sec->name_off + ka_str,
    + ka_sec->start,
    + ka_sec->start + ka_sec->size,
    + ka_sec->flags))
    + return(0);
    + }
    + }
    + return(1);
    +}
    --- linux/kernel/module.c.orig Fri Sep 20 17:20:19 2002
    +++ linux/kernel/module.c Wed Sep 25 21:52:00 2002
    @@ -3,6 +3,7 @@
    #include <linux/module.h>
    #include <asm/module.h>
    #include <asm/uaccess.h>
    +#include <linux/kallsyms.h>
    #include <linux/vmalloc.h>
    #include <linux/smp_lock.h>
    #include <asm/pgalloc.h>
    @@ -39,13 +40,19 @@
    extern const struct exception_table_entry __start___ex_table[];
    extern const struct exception_table_entry __stop___ex_table[];

    -extern const char __start___kallsyms[] __attribute__ ((weak));
    -extern const char __stop___kallsyms[] __attribute__ ((weak));
    +extern const char __start___kallsyms[] __attribute__((weak));
    +extern const char __stop___kallsyms[] __attribute__((weak));
    +
    +/* modutils uses these exported symbols to figure out if
    + kallsyms support is present */
    +
    +EXPORT_SYMBOL(__start___kallsyms);
    +EXPORT_SYMBOL(__stop___kallsyms);

    struct module kernel_module =
    {
    .size_of_struct = sizeof(struct module),
    - .name = "",
    + .name = NULL,
    .uc = {ATOMIC_INIT(1)},
    .flags = MOD_RUNNING,
    .syms = __start___ksymtab,
    @@ -1220,6 +1227,30 @@
    .show = s_show
    };

    +#define MODLIST_SIZE 4096
    +
    +/*
    + * this function isn't smp safe but that's not really a problem; it's
    + * called from oops context only and any locking could actually prevent
    + * the oops from going out; the line that is generated is informational
    + * only and should NEVER prevent the real oops from going out.
    + */
    +void print_modules(void)
    +{
    + static char modlist[MODLIST_SIZE];
    + struct module *this_mod;
    + int pos = 0;
    +
    + this_mod = module_list;
    + while (this_mod) {
    + if (this_mod->name)
    + pos += snprintf(modlist+pos, MODLIST_SIZE-pos-1,
    + "%s ", this_mod->name);
    + this_mod = this_mod->next;
    + }
    + printk("%s\n",modlist);
    +}
    +
    #else /* CONFIG_MODULES */

    /* Dummy syscalls for people who don't want modules */
    @@ -1265,4 +1296,79 @@
    return 1;
    }

    +void print_modules(void)
    +{
    +}
    +
    #endif /* CONFIG_MODULES */
    +
    +
    +#if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)
    +
    +#define MAX_SYMBOL_SIZE 512
    +
    +static void
    +address_to_exported_symbol(unsigned long address, const char **mod_name,
    + const char **sym_name, unsigned long *sym_start,
    + unsigned long *sym_end)
    +{
    + struct module *this_mod;
    + int i;
    +
    + for (this_mod = module_list; this_mod; this_mod = this_mod->next) {
    + /* walk the symbol list of this module. Only symbols
    + who's address is smaller than the searched for address
    + are relevant; and only if it's better than the best so far */
    + for (i = 0; i < this_mod->nsyms; i++)
    + if ((this_mod->syms[i].value <= address) &&
    + (*sym_start < this_mod->syms[i].value)) {
    + *sym_start = this_mod->syms[i].value;
    + *sym_name = this_mod->syms[i].name;
    + *mod_name = this_mod->name;
    + if (i + 1 < this_mod->nsyms)
    + *sym_end = this_mod->syms[i+1].value;
    + else
    + *sym_end = (unsigned long) this_mod + this_mod->size;
    + }
    + }
    +}
    +
    +int
    +print_symbol(const char *fmt, unsigned long address)
    +{
    + /* static to not take up stackspace; if we race here too bad */
    + static char buffer[MAX_SYMBOL_SIZE];
    +
    + const char *mod_name = NULL, *sec_name = NULL, *sym_name = NULL;
    + unsigned long mod_start, mod_end, sec_start, sec_end,
    + sym_start, sym_end;
    + char *tag = "";
    +
    + memset(buffer, 0, MAX_SYMBOL_SIZE);
    +
    + sym_start = 0;
    + if (!kallsyms_address_to_symbol(address, &mod_name, &mod_start, &mod_end, &sec_name, &sec_start, &sec_end, &sym_name, &sym_start, &sym_end)) {
    + tag = "E ";
    + address_to_exported_symbol(address, &mod_name, &sym_name, &sym_start, &sym_end);
    + }
    +
    + if (sym_start) {
    + if (mod_name)
    + snprintf(buffer, MAX_SYMBOL_SIZE - 1, "%s%s+%#x/%#x [%s]",
    + tag, sym_name,
    + (unsigned int)(address - sym_start),
    + (unsigned int)(sym_end - sym_start),
    + mod_name);
    + else
    + snprintf(buffer, MAX_SYMBOL_SIZE - 1, "%s%s+%#x/%#x",
    + tag, sym_name,
    + (unsigned int)(address - sym_start),
    + (unsigned int)(sym_end - sym_start));
    + printk(fmt, buffer);
    + } else {
    + printk(fmt, "[unresolved]");
    + }
    + return 0;
    +}
    +
    +#endif
    --- linux/Makefile.orig Wed Sep 25 21:43:13 2002
    +++ linux/Makefile Wed Sep 25 21:46:56 2002
    @@ -138,6 +138,7 @@
    MAKEFILES = $(TOPDIR)/.config
    GENKSYMS = /sbin/genksyms
    DEPMOD = /sbin/depmod
    +KALLSYMS = /sbin/kallsyms
    PERL = perl
    MODFLAGS = -DMODULE
    CFLAGS_MODULE = $(MODFLAGS)
    @@ -291,32 +292,64 @@
    vmlinux-objs := $(HEAD) $(INIT) $(CORE_FILES) $(LIBS) $(DRIVERS) $(NETWORKS)

    quiet_cmd_link_vmlinux = LD $@
    -cmd_link_vmlinux = $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) $(HEAD) $(INIT) \
    - --start-group \
    - $(CORE_FILES) \
    - $(LIBS) \
    - $(DRIVERS) \
    - $(NETWORKS) \
    - --end-group \
    - -o vmlinux
    +define cmd_link_vmlinux
    + $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) $(HEAD) $(INIT) \
    + --start-group \
    + $(CORE_FILES) \
    + $(LIBS) \
    + $(DRIVERS) \
    + $(NETWORKS) \
    + --end-group \
    + $(filter $(kallsyms.o),$^) \
    + -o $@
    +endef

    # set -e makes the rule exit immediately on error

    -define rule_link_vmlinux
    +define rule_vmlinux
    set -e
    echo ' Generating build number'
    - . scripts/mkversion > .tmpversion
    - mv -f .tmpversion .version
    + . scripts/mkversion > .tmp_version
    + mv -f .tmp_version .version
    +$(MAKE) -C init
    $(call cmd,link_vmlinux)
    echo 'cmd_$@ := $(cmd_link_vmlinux)' > $(@D)/.$(@F).cmd
    - $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
    + $(NM) $@ | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
    endef

    LDFLAGS_vmlinux += -T arch/$(ARCH)/vmlinux.lds.s

    -vmlinux: $(vmlinux-objs) arch/$(ARCH)/vmlinux.lds.s FORCE
    - $(call if_changed_rule,link_vmlinux)
    +# Generate section listing all symbols and add it into vmlinux
    +
    +ifdef CONFIG_KALLSYMS
    +
    +kallsyms.o := .tmp_kallsyms.o
    +
    +quiet_cmd_kallsyms = KSYM $@
    +cmd_kallsyms = $(KALLSYMS) $< > $@
    +
    +.tmp_kallsyms.o: .tmp_vmlinux
    + $(call cmd,kallsyms)
    +
    +# After generating .tmp_vmlinux just like vmlinux, decrement the version
    +# number again, so the final vmlinux gets the same one.
    +# Ignore return value of 'expr'.
    +
    +define rule_.tmp_vmlinux
    + $(rule_vmlinux)
    + if expr 0`cat .version` - 1 > .tmp_version; then true; fi
    + mv -f .tmp_version .version
    +endef
    +
    +.tmp_vmlinux: $(vmlinux-objs) arch/$(ARCH)/vmlinux.lds.s FORCE
    + $(call if_changed_rule,.tmp_vmlinux)
    +
    +endif
    +
    +# Finally the vmlinux rule
    +
    +vmlinux: $(vmlinux-objs) $(kallsyms.o) arch/$(ARCH)/vmlinux.lds.s FORCE
    + $(call if_changed_rule,vmlinux)

    # The actual objects are generated when descending,
    # make sure no implicit rule kicks in
    @@ -820,7 +853,7 @@

    # FIXME Should go into a make.lib or something
    # ===========================================================================
    -echo_target = $(RELDIR)/$@
    +echo_target = $@

    a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(NOSTDINC_FLAGS) \
    $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o)
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 13:29    [W:0.079 / U:0.144 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site