From 9753d385a4f2a1d0782914e7f13a6e937f2333ee Mon Sep 17 00:00:00 2001 From: houfeng Date: Thu, 24 Jun 2004 03:58:32 +0000 Subject: [PATCH] add linux/kallsyms.h kernel/kallsyms.c modify Makefile arch/i386/vmlinux.lds.S for loopup symbol --- .../patches/kksymoops-2.4.24.vanilla.patch | 516 ++++++++++++++++++++- 1 file changed, 501 insertions(+), 15 deletions(-) diff --git a/lustre/kernel_patches/patches/kksymoops-2.4.24.vanilla.patch b/lustre/kernel_patches/patches/kksymoops-2.4.24.vanilla.patch index dd76be4..7fe1b4e 100644 --- a/lustre/kernel_patches/patches/kksymoops-2.4.24.vanilla.patch +++ b/lustre/kernel_patches/patches/kksymoops-2.4.24.vanilla.patch @@ -1,15 +1,3 @@ -diff -urNp linux-700/arch/i386/config.in linux-720/arch/i386/config.in ---- linux-700/arch/i386/config.in -+++ linux-720/arch/i386/config.in -@@ -9,8 +9,6 @@ define_bool CONFIG_SBUS n - - define_bool CONFIG_UID16 y - -+define_bool CONFIG_KALLSYMS y -+ - mainmenu_option next_comment - comment 'Code maturity level options' - bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL diff -urNp linux-700/arch/i386/kernel/process.c linux-720/arch/i386/kernel/process.c --- linux-700/arch/i386/kernel/process.c +++ linux-720/arch/i386/kernel/process.c @@ -207,14 +195,512 @@ diff -urNp linux-700/kernel/kksymoops.c linux-720/kernel/kksymoops.c +#endif +} diff -urNp linux-700/kernel/Makefile linux-720/kernel/Makefile ---- linux-700/kernel/Makefile 2001-09-17 06:22:40.000000000 +0200 +--- linux-700/kernel/Makefile 2001-09-17 06:22:40.000000000 +0800 +++ linux-720/kernel/Makefile -@@ -14,7 +14,7 @@ export-objs = signal.o sys.o kmod.o cont +@@ -14,11 +14,13 @@ export-objs = signal.o sys.o kmod.o cont obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.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 -+ signal.o sys.o kmod.o context.o kksymoops.o ++ signal.o sys.o kmod.o context.o kksymoops.o kallsyms.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += ksyms.o + obj-$(CONFIG_PM) += pm.o ++obj-$(CONFIG_KALLSYMS) += kksymoops.o ++obj-$(CONFIG_KALLSYMS) += kallsyms.o + + ifneq ($(CONFIG_IA64),y) + # According to Alan Modra , the -fno-omit-frame-pointer is +diff -urNp arch/i386/config.in linux-720/arch/i386/config.in +--- /arch/i386/config.in 2004-06-15 16:58:41.000000000 +0800 ++++ /linux-720/arch/i386/config.in +@@ -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' +diff -urNp include/linux/kallsyms.h linux-700/include/linux/kallsyms.h.orig +--- /include/linux/kallsyms.h Thu Sep 26 15:27:16 2002 ++++ /linux-700/include/linux/kallsyms.h.orig Thu Sep 26 15:27:16 2002 +@@ -0,0 +1,163 @@ ++/* 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.3 2004/06/24 03:58:32 houfeng 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 */ +--- linux/kernel/kallsyms.c.orig Thu Sep 26 15:27:16 2002 ++++ linux/kernel/kallsyms.c Thu Sep 26 15:27:16 2002 +@@ -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); ++} +--- linux/Makefile 2004-06-16 19:25:21.000000000 +0800 ++++ linux/Makefile.bak 2004-06-22 11:25:02.000000000 +0800 +@@ -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 +--- linux/arch/i386/vmlinux.lds.S 2004-06-16 19:25:26.000000000 +0800 ++++ linux/arch/i386/vmlinux.lds.S.bak 2004-06-22 11:23:53.000000000 +0800 +@@ -28,6 +28,11 @@ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + ++ __start___kallsyms = .; /* All kernel symbols */ ++ __kallsyms : { *(__kallsyms) } ++ __stop___kallsyms = .; ++ ++ + .data : { /* Data */ + *(.data) + CONSTRUCTORS -- 1.8.3.1