Index: linux-2.4.24/arch/i386/kernel/process.c =================================================================== --- linux-2.4.24.orig/arch/i386/kernel/process.c 2004-06-24 09:06:29.000000000 +0400 +++ linux-2.4.24/arch/i386/kernel/process.c 2004-07-18 16:28:19.000000000 +0400 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -447,10 +448,14 @@ void show_regs(struct pt_regs * regs) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; + static char buffer[512]; + + lookup_symbol(regs->eip,buffer,512); 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()); + printk("\nEIP is at %s (" UTS_RELEASE ")\n",buffer); if (regs->xcs & 3) printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp); printk(" EFLAGS: %08lx %s\n",regs->eflags, print_tainted()); Index: linux-2.4.24/arch/i386/kernel/traps.c =================================================================== --- linux-2.4.24.orig/arch/i386/kernel/traps.c 2004-07-14 18:14:26.000000000 +0400 +++ linux-2.4.24/arch/i386/kernel/traps.c 2004-07-18 16:28:19.000000000 +0400 @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef CONFIG_MCA #include @@ -135,6 +136,8 @@ { int i; unsigned long addr; + /* static to not take up stackspace; if we race here too bad */ + static char buffer[512]; if (!stack) stack = (unsigned long*)&stack; @@ -144,9 +147,8 @@ while (((long) stack & (THREAD_SIZE-1)) != 0) { addr = *stack++; if (kernel_text_address(addr)) { - if (i && ((i % 6) == 0)) - printk("\n "); - printk(" [<%08lx>]", addr); + lookup_symbol(addr, buffer, 512); + printk("[<%08lx>] %s (0x%x))\n", addr,buffer,stack-1); i++; } } @@ -194,12 +196,17 @@ show_stack(0); } + +void print_modules(void); + + void show_registers(struct pt_regs *regs) { int i; int in_kernel = 1; unsigned long esp; unsigned short ss; + static char buffer[512]; esp = (unsigned long) (®s->esp); ss = __KERNEL_DS; @@ -208,8 +215,12 @@ esp = regs->esp; ss = regs->xss & 0xffff; } + + print_modules(); + lookup_symbol(regs->eip, buffer, 512); printk("CPU: %d\nEIP: %04x:[<%08lx>] %s\nEFLAGS: %08lx\n", smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags); + printk("\nEIP is at %s (" UTS_RELEASE ")\n",buffer); 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", @@ -269,7 +280,7 @@ if (__get_user(file, (char **)(eip + 4)) || (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) file = ""; - + printk("------------[ cut here ]------------\n"); printk("kernel BUG at %s:%d!\n", file, line); no_bug: Index: linux-2.4.24/arch/i386/config.in =================================================================== --- linux-2.4.24.orig/arch/i386/config.in 2004-07-14 18:14:27.000000000 +0400 +++ linux-2.4.24/arch/i386/config.in 2004-07-18 16:28:19.000000000 +0400 @@ -8,6 +8,7 @@ define_bool CONFIG_SBUS n define_bool CONFIG_UID16 y +define_bool CONFIG_KALLSYMS y mainmenu_option next_comment comment 'Code maturity level options' Index: linux-2.4.24/arch/i386/vmlinux.lds.S =================================================================== --- linux-2.4.24.orig/arch/i386/vmlinux.lds.S 2004-07-14 18:14:27.000000000 +0400 +++ linux-2.4.24/arch/i386/vmlinux.lds.S 2004-07-18 16:28:19.000000000 +0400 @@ -28,6 +28,11 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ + __kallsyms : { *(__kallsyms) } + __stop___kallsyms = .; + + .data : { /* Data */ *(.data) CONSTRUCTORS Index: linux-2.4.24/include/linux/kernel.h =================================================================== --- linux-2.4.24.orig/include/linux/kernel.h 2004-07-13 11:07:11.000000000 +0400 +++ linux-2.4.24/include/linux/kernel.h 2004-07-18 16:28:19.000000000 +0400 @@ -110,6 +110,8 @@ extern void dump_stack(void); +extern int lookup_symbol(unsigned long address, char *buffer, int buflen); + #if DEBUG #define pr_debug(fmt,arg...) \ printk(KERN_DEBUG fmt,##arg) Index: linux-2.4.24/include/linux/kallsyms.h =================================================================== --- linux-2.4.24.orig/include/linux/kallsyms.h 2003-01-30 13:24:37.000000000 +0300 +++ linux-2.4.24/include/linux/kallsyms.h 2004-07-18 16:28:19.000000000 +0400 @@ -0,0 +1,164 @@ +/* kallsyms headers + Copyright 2000 Keith Owens + + 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: kksymoops-2.4.24.vanilla.patch,v 1.6 2004/07/18 12:32:35 alex 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 +#else /* __KERNEL__ */ +#include +#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 */ + Index: linux-2.4.24/kernel/kksymoops.c =================================================================== --- linux-2.4.24.orig/kernel/kksymoops.c 2003-01-30 13:24:37.000000000 +0300 +++ linux-2.4.24/kernel/kksymoops.c 2004-07-18 16:28:19.000000000 +0400 @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#ifdef CONFIG_KALLSYMS +#include +#endif + + + +int lookup_symbol(unsigned long address, char *buffer, int buflen) +{ + struct module *this_mod; + unsigned long bestsofar; + + 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; + + if (!buffer) + return -EFAULT; + + if (buflen<256) + return -ENOMEM; + + memset(buffer,0,buflen); + +#ifdef CONFIG_KALLSYMS + if (!kallsyms_address_to_symbol(address,&mod_name,&mod_start,&mod_end,&sec_name, + &sec_start, &sec_end, &sym_name, &sym_start, &sym_end)) { + /* kallsyms doesn't have a clue; lets try harder */ + bestsofar = 0; + snprintf(buffer,buflen-1,"[unresolved]"); + + this_mod = module_list; + + while (this_mod != NULL) { + int i; + /* 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) && + (bestsofarsyms[i].value)) { + snprintf(buffer,buflen-1,"%s [%s] 0x%x", + this_mod->syms[i].name, + this_mod->name, + (unsigned int)(address - this_mod->syms[i].value)); + bestsofar = this_mod->syms[i].value; + } + this_mod = this_mod->next; + } + + } else { /* kallsyms success */ + snprintf(buffer,buflen-1,"%s [%s] 0x%x",sym_name,mod_name,(unsigned int)(address-sym_start)); + } +#endif + return strlen(buffer); +} + +static char modlist[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) +{ + struct module *this_mod; + int pos = 0; + memset(modlist,0,4096); + +#ifdef CONFIG_KALLSYMS + this_mod = module_list; + while (this_mod != NULL) { + if (this_mod->name != NULL) + pos +=snprintf(modlist+pos,160-pos-1,"%s ",this_mod->name); + this_mod = this_mod->next; + } + printk("%s\n",modlist); +#endif +} Index: linux-2.4.24/kernel/Makefile =================================================================== --- linux-2.4.24.orig/kernel/Makefile 2001-09-17 08:22:40.000000000 +0400 +++ linux-2.4.24/kernel/Makefile 2004-07-18 16:28:19.000000000 +0400 @@ -11,7 +11,7 @@ export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o -obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \ +obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o kksymoops.o kallsyms.o \ module.o exit.o itimer.o info.o time.o softirq.o resource.o \ sysctl.o acct.o capability.o ptrace.o timer.o user.o \ signal.o sys.o kmod.o context.o @@ -29,4 +29,7 @@ CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer endif +obj-$(CONFIG_KALLSYMS) += kksymoops.o +obj-$(CONFIG_KALLSYMS) += kallsyms.o + include $(TOPDIR)/Rules.make Index: linux-2.4.24/kernel/kallsyms.c =================================================================== --- linux-2.4.24.orig/kernel/kallsyms.c 2003-01-30 13:24:37.000000000 +0300 +++ linux-2.4.24/kernel/kallsyms.c 2004-07-18 16:28:19.000000000 +0400 @@ -0,0 +1,227 @@ +/* + * kksymoops.c: in-kernel printing of symbolic oopses and stack traces. + * + * Copyright 2000 Keith Owens April 2000 + * Copyright 2002 Arjan van de Ven + * + 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 +#include +#include + +/* 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); +} Index: linux-2.4.24/Makefile =================================================================== --- linux-2.4.24.orig/Makefile 2004-07-13 11:07:12.000000000 +0400 +++ linux-2.4.24/Makefile 2004-07-18 16:28:19.000000000 +0400 @@ -45,6 +45,7 @@ MAKEFILES = $(TOPDIR)/.config GENKSYMS = /sbin/genksyms DEPMOD = /sbin/depmod +KALLSYMS = /sbin/kallsyms MODFLAGS = -DMODULE CFLAGS_KERNEL = PERL = perl @@ -211,7 +212,7 @@ CLEAN_FILES = \ kernel/ksyms.lst include/linux/compile.h \ vmlinux System.map \ - .tmp* \ + $(TMPPREFIX).tmp* \ drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \ drivers/char/conmakehash \ drivers/char/drm/*-mod.c \ @@ -292,16 +293,42 @@ boot: vmlinux @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C arch/$(ARCH)/boot +LD_VMLINUX := $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \ + --start-group \ + $(CORE_FILES) \ + $(DRIVERS) \ + $(NETWORKS) \ + $(LIBS) \ + --end-group +ifeq ($(CONFIG_KALLSYMS),y) +LD_VMLINUX_KALLSYMS := $(TMPPREFIX).tmp_kallsyms3.o +else +LD_VMLINUX_KALLSYMS := +endif + vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o init/do_mounts.o linuxsubdirs - $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \ - --start-group \ - $(CORE_FILES) \ - $(DRIVERS) \ - $(NETWORKS) \ - $(LIBS) \ - --end-group \ - -o vmlinux + @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" kallsyms + +.PHONY: kallsyms + +kallsyms: +ifeq ($(CONFIG_KALLSYMS),y) + @echo kallsyms pass 1 + $(LD_VMLINUX) -o $(TMPPREFIX).tmp_vmlinux1 + @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux1 > $(TMPPREFIX).tmp_kallsyms1.o + @echo kallsyms pass 2 + @$(LD_VMLINUX) $(TMPPREFIX).tmp_kallsyms1.o -o $(TMPPREFIX).tmp_vmlinux2 + @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux2 > $(TMPPREFIX).tmp_kallsyms2.o + @echo kallsyms pass 3 + @$(LD_VMLINUX) $(TMPPREFIX).tmp_kallsyms2.o -o $(TMPPREFIX).tmp_vmlinux3 + @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux3 > $(TMPPREFIX).tmp_kallsyms3.o +endif + $(LD_VMLINUX) $(LD_VMLINUX_KALLSYMS) -o $(TMPPREFIX)vmlinux +ifneq ($(TMPPREFIX),) + mv $(TMPPREFIX)vmlinux vmlinux +endif $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map + @rm -f $(TMPPREFIX).tmp_vmlinux* $(TMPPREFIX).tmp_kallsyms* symlinks: rm -f include/asm