Index: 2.2.15pre19/Documentation/Configure.help --- 2.2.15pre19/Documentation/Configure.help Thu, 20 Apr 2000 22:09:39 +1000 kaos (linux-2.2/I/b/39_Configure. 1.2.1.3.1.7.6.1.2.1 644) +++ 2.2.15pre19/Documentation/Configure.help Fri, 21 Apr 2000 19:00:40 +1000 kaos (linux-2.2/I/b/39_Configure. 1.2.1.3.1.7.6.1.2.2.1.2 644) @@ -10220,6 +10220,16 @@ keys are documented in Documentation/sysrq.txt. Don't say Y unless you really know what this hack does. +Load all symbols for debugging +CONFIG_KALLSYMS + Normally only exported symbols are available to modules. For + debugging you may want all symbols, not just the exported ones. If + you say Y here then extra data is added to the kernel and modules, + this data lists all the non-stack symbols in the kernel or module + and can be used by any debugger. You need modutils >= 2.3.11 to use + this option. See "man kallsyms" for the data format, it adds 10-20% + to the size of the kernel and the loaded modules. If unsure, say N. + ISDN subsystem CONFIG_ISDN ISDN ("Integrated Services Digital Networks", called RNIS in France) Index: 2.2.15pre19/Makefile --- 2.2.15pre19/Makefile Thu, 20 Apr 2000 22:09:39 +1000 kaos (linux-2.2/G/b/14_Makefile 1.3.2.2.1.1.1.5.1.3.6.1.2.1 644) +++ 2.2.15pre19/Makefile Fri, 21 Apr 2000 18:19:45 +1000 kaos (linux-2.2/G/b/14_Makefile 1.3.2.2.1.1.1.5.1.3.6.1.2.2.1.1 644) @@ -31,6 +31,7 @@ OBJDUMP =$(CROSS_COMPILE)objdump MAKE =make GENKSYMS=/sbin/genksyms +KALLSYMS=/sbin/kallsyms all: do-it-all @@ -223,17 +224,36 @@ boot: vmlinux @$(MAKE) -C arch/$(ARCH)/boot +LD_VMLINUX := $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \ + --start-group \ + $(CORE_FILES) \ + $(FILESYSTEMS) \ + $(NETWORKS) \ + $(DRIVERS) \ + $(LIBS) \ + --end-group +ifeq ($(CONFIG_KALLSYMS),y) +LD_VMLINUX_KALLSYMS := _tmp_kallsyms3.o +else +LD_VMLINUX_KALLSYMS := +endif + vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs - $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \ - --start-group \ - $(CORE_FILES) \ - $(FILESYSTEMS) \ - $(NETWORKS) \ - $(DRIVERS) \ - $(LIBS) \ - --end-group \ - -o vmlinux + @if [ "$(CONFIG_KALLSYMS)" = "y" ]; then \ + echo kallsyms pass 1 && \ + echo $(LD_VMLINUX) -o _tmp_vmlinux1 && \ + $(LD_VMLINUX) -o _tmp_vmlinux1 && \ + $(KALLSYMS) _tmp_vmlinux1 > _tmp_kallsyms1.o && \ + echo kallsyms pass 2 && \ + $(LD_VMLINUX) _tmp_kallsyms1.o -o _tmp_vmlinux2 && \ + $(KALLSYMS) _tmp_vmlinux2 > _tmp_kallsyms2.o && \ + echo kallsyms pass 3 && \ + $(LD_VMLINUX) _tmp_kallsyms2.o -o _tmp_vmlinux3 && \ + $(KALLSYMS) _tmp_vmlinux3 > _tmp_kallsyms3.o; \ + fi + $(LD_VMLINUX) $(LD_VMLINUX_KALLSYMS) -o vmlinux $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map + @rm -f _tmp_vmlinux* _tmp_kallsyms* symlinks: rm -f include/asm Index: 2.2.15pre19/arch/alpha/vmlinux.lds --- 2.2.15pre19/arch/alpha/vmlinux.lds Fri, 05 Feb 1999 09:47:48 +1100 keith (linux-2.2/E/b/15_vmlinux.ld 1.1 644) +++ 2.2.15pre19/arch/alpha/vmlinux.lds Thu, 20 Apr 2000 22:49:11 +1000 kaos (linux-2.2/E/b/15_vmlinux.ld 1.2 644) @@ -21,6 +21,10 @@ __stop___ksymtab = .; .kstrtab : { *(.kstrtab) } + __start___kallsyms = .; /* All kernel symbols */ + __kallsyms : { *(__kallsyms) } + __stop___kallsyms = .; + /* Startup code */ . = ALIGN(8192); __init_begin = .; Index: 2.2.15pre19/arch/arm/vmlinux-armo.lds --- 2.2.15pre19/arch/arm/vmlinux-armo.lds Fri, 05 Feb 1999 09:47:48 +1100 keith (linux-2.2/p/b/6_vmlinux-ar 1.1 644) +++ 2.2.15pre19/arch/arm/vmlinux-armo.lds Thu, 20 Apr 2000 22:49:11 +1000 kaos (linux-2.2/p/b/6_vmlinux-ar 1.2 644) @@ -26,6 +26,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ + __kallsyms : { *(__kallsyms) } + __stop___kallsyms = .; + _etext = .; /* End of text section */ . = ALIGN(8192); Index: 2.2.15pre19/arch/arm/vmlinux-armv.lds --- 2.2.15pre19/arch/arm/vmlinux-armv.lds Fri, 05 Feb 1999 09:47:48 +1100 keith (linux-2.2/p/b/4_vmlinux-ar 1.1 644) +++ 2.2.15pre19/arch/arm/vmlinux-armv.lds Thu, 20 Apr 2000 22:49:11 +1000 kaos (linux-2.2/p/b/4_vmlinux-ar 1.1.1.1 644) @@ -26,6 +26,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ + __kallsyms : { *(__kallsyms) } + __stop___kallsyms = .; + _etext = .; /* End of text section */ . = ALIGN(8192); Index: 2.2.15pre19/arch/i386/config.in --- 2.2.15pre19/arch/i386/config.in Thu, 20 Apr 2000 22:09:39 +1000 kaos (linux-2.2/G/b/0_config.in 1.2.2.2.2.2 644) +++ 2.2.15pre19/arch/i386/config.in Fri, 21 Apr 2000 19:00:40 +1000 kaos (linux-2.2/G/b/0_config.in 1.2.2.2.2.3.1.1 644) @@ -207,5 +207,6 @@ #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ +bool 'Load all symbols for debugging' CONFIG_KALLSYMS endmenu Index: 2.2.15pre19/arch/i386/vmlinux.lds.S --- 2.2.15pre19/arch/i386/vmlinux.lds.S Tue, 10 Aug 1999 11:02:21 +1000 keith (linux-2.2/U/b/29_vmlinux.ld 1.1 644) +++ 2.2.15pre19/arch/i386/vmlinux.lds.S Thu, 20 Apr 2000 22:49:11 +1000 kaos (linux-2.2/U/b/29_vmlinux.ld 1.2 644) @@ -26,6 +26,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ + __kallsyms : { *(__kallsyms) } + __stop___kallsyms = .; + _etext = .; /* End of text section */ .data : { /* Data */ Index: 2.2.15pre19/arch/m68k/vmlinux.lds --- 2.2.15pre19/arch/m68k/vmlinux.lds Fri, 05 Feb 1999 09:47:48 +1100 keith (linux-2.2/s/b/37_vmlinux.ld 1.1 644) +++ 2.2.15pre19/arch/m68k/vmlinux.lds Thu, 20 Apr 2000 22:49:11 +1000 kaos (linux-2.2/s/b/37_vmlinux.ld 1.2 644) @@ -24,6 +24,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ + __kallsyms : { *(__kallsyms) } + __stop___kallsyms = .; + _etext = .; /* End of text section */ .data : { /* Data */ Index: 2.2.15pre19/arch/s390/vmlinux.lds --- 2.2.15pre19/arch/s390/vmlinux.lds Wed, 05 Jan 2000 09:26:04 +1100 keith (linux-2.2/l/c/32_vmlinux.ld 1.1 644) +++ 2.2.15pre19/arch/s390/vmlinux.lds Thu, 20 Apr 2000 22:49:11 +1000 kaos (linux-2.2/l/c/32_vmlinux.ld 1.2 644) @@ -26,6 +26,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ + __kallsyms : { *(__kallsyms) } + __stop___kallsyms = .; + _etext = .; /* End of text section */ .data : { /* Data */ Index: 2.2.15pre19/arch/sparc/vmlinux.lds --- 2.2.15pre19/arch/sparc/vmlinux.lds Wed, 24 Mar 1999 10:22:04 +1100 keith (linux-2.2/A/b/0_vmlinux.ld 1.2 644) +++ 2.2.15pre19/arch/sparc/vmlinux.lds Thu, 20 Apr 2000 22:49:11 +1000 kaos (linux-2.2/A/b/0_vmlinux.ld 1.3 644) @@ -32,6 +32,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ + __kallsyms : { *(__kallsyms) } + __stop___kallsyms = .; + . = ALIGN(32); .data.cacheline_aligned : { *(.data.cacheline_aligned) } Index: 2.2.15pre19/arch/sparc64/vmlinux.lds --- 2.2.15pre19/arch/sparc64/vmlinux.lds Fri, 05 Feb 1999 09:47:48 +1100 keith (linux-2.2/s/b/3_vmlinux.ld 1.1 644) +++ 2.2.15pre19/arch/sparc64/vmlinux.lds Thu, 20 Apr 2000 22:49:11 +1000 kaos (linux-2.2/s/b/3_vmlinux.ld 1.2 644) @@ -35,6 +35,9 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; __kstrtab : { *(.kstrtab) } + __start___kallsyms = .; /* All kernel symbols */ + __kallsyms : { *(__kallsyms) } + __stop___kallsyms = .; . = ALIGN(8192); __init_begin = .; .text.init : { *(.text.init) } Index: 2.2.15pre19/include/linux/kallsyms.h --- 2.2.15pre19/include/linux/kallsyms.h Fri, 21 Apr 2000 21:08:31 +1000 kaos () +++ 2.2.15pre19/include/linux/kallsyms.h Fri, 21 Apr 2000 20:52:46 +1000 kaos (linux-2.2/t/c/12_kallsyms.h 1.2 644) @@ -0,0 +1,131 @@ +/* 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: kallsyms.h 1.7 Fri, 21 Apr 2000 20:48:56 +1000 kaos $" + +#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)) + +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 */ + ); + +#endif /* kallsyms.h */ Index: 2.2.15pre19/include/linux/module.h --- 2.2.15pre19/include/linux/module.h Thu, 20 Apr 2000 22:09:39 +1000 kaos (linux-2.2/F/51_module.h 1.1.2.1 644) +++ 2.2.15pre19/include/linux/module.h Thu, 20 Apr 2000 22:49:11 +1000 kaos (linux-2.2/F/51_module.h 1.1.2.2 644) @@ -77,11 +77,14 @@ unsigned long gp; #endif /* Members past this point are extensions to the basic - module support and are optional. Use mod_opt_member() + module support and are optional. Use mod_member_present() to examine them. */ const struct module_persist *persist_start; const struct module_persist *persist_end; int (*can_unload)(void); + int runsize; /* In modutils, not currently used */ + const char *kallsyms_start; + const char *kallsyms_end; }; struct module_info Index: 2.2.15pre19/kernel/Makefile --- 2.2.15pre19/kernel/Makefile Fri, 05 Feb 1999 09:47:48 +1100 keith (linux-2.2/h/28_Makefile 1.1 644) +++ 2.2.15pre19/kernel/Makefile Fri, 21 Apr 2000 18:19:45 +1000 kaos (linux-2.2/h/28_Makefile 1.1.4.1 644) @@ -21,6 +21,10 @@ O_OBJS += kmod.o endif +ifeq ($(CONFIG_KALLSYMS),y) +O_OBJS += kallsyms.o +endif + ifeq ($(CONFIG_MODULES),y) OX_OBJS += ksyms.o endif Index: 2.2.15pre19/kernel/kallsyms.c --- 2.2.15pre19/kernel/kallsyms.c Fri, 21 Apr 2000 21:08:31 +1000 kaos () +++ 2.2.15pre19/kernel/kallsyms.c Fri, 21 Apr 2000 19:51:27 +1000 kaos (linux-2.2/t/c/11_kallsyms.c 1.1.1.1 644) @@ -0,0 +1,264 @@ +/* An example of using kallsyms data in a kernel debugger. + + Copyright 2000 Keith Owens April 2000 + + This file is part of the Linux modutils. + + 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: kallsyms.c 1.1 Fri, 21 Apr 2000 19:31:54 +1000 kaos $" + +/* + 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. + + You need modutils >= 2.3.11 and a kernel with the kallsyms patch + which was compiled with CONFIG_KALLSYMS. + */ + +#include +#include +#include +#include +#include + +/* These external symbols are only available on kernels compiled with + * CONFIG_KALLSYMS. + */ + +extern const char __start___kallsyms[]; +extern const char __stop___kallsyms[]; + +static struct module *local_module_list; + +static void get_module_list(void) +{ + const struct kallsyms_header *ka_hdr; + const struct kallsyms_section *ka_sec; + const struct kallsyms_symbol *ka_sym; + const char *ka_str; + int i; + const char *p; + + if (__start___kallsyms >= __stop___kallsyms) + return; + ka_hdr = (struct kallsyms_header *)__start___kallsyms; + ka_sec = (struct kallsyms_section *) + ((char *)(ka_hdr) + ka_hdr->section_off); + 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; kallsyms_next_sym(ka_hdr, ka_sym), ++i) { + p = ka_str + ka_sym->name_off; + if (strcmp(p, "module_list") == 0) { + if (ka_sym->symbol_addr) + local_module_list = *((struct module **)(ka_sym->symbol_addr)); + break; + } + } +} + +static void __inline__ do_first_time(void) +{ + static int first_time = 1; + if (first_time) + get_module_list(); + first_time = 0; +} + +/* 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; + + do_first_time(); + + /* Restart? */ + m = local_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) ? m->name : "kernel"; + *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; + + do_first_time(); + + for (m = local_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) ? m->name : "kernel"; + *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); +} Index: 2.2.15pre19/kernel/ksyms.c --- 2.2.15pre19/kernel/ksyms.c Thu, 20 Apr 2000 22:09:39 +1000 kaos (linux-2.2/h/19_ksyms.c 1.2.1.3.3.2 644) +++ 2.2.15pre19/kernel/ksyms.c Fri, 21 Apr 2000 18:19:45 +1000 kaos (linux-2.2/h/19_ksyms.c 1.2.1.3.3.3.1.1 644) @@ -46,6 +46,9 @@ #ifdef CONFIG_KMOD #include #endif +#ifdef CONFIG_KALLSYMS +#include +#endif extern char *get_options(char *str, int *ints); extern void set_device_ro(kdev_t dev,int flag); @@ -81,6 +84,15 @@ EXPORT_SYMBOL(get_module_symbol); #endif EXPORT_SYMBOL(get_options); + +#ifdef CONFIG_KALLSYMS +extern const char __start___kallsyms[]; +extern const char __stop___kallsyms[]; +EXPORT_SYMBOL(__start___kallsyms); +EXPORT_SYMBOL(__stop___kallsyms); +EXPORT_SYMBOL(kallsyms_symbol_to_address); +EXPORT_SYMBOL(kallsyms_address_to_symbol); +#endif /* process memory management */ EXPORT_SYMBOL(do_mmap); Index: 2.2.15pre19/kernel/module.c --- 2.2.15pre19/kernel/module.c Thu, 20 Apr 2000 22:09:39 +1000 kaos (linux-2.2/h/18_module.c 1.1.4.1 644) +++ 2.2.15pre19/kernel/module.c Fri, 21 Apr 2000 18:19:45 +1000 kaos (linux-2.2/h/18_module.c 1.1.4.2.1.1 644) @@ -14,11 +14,12 @@ * Heavily modified by Bjorn Ekwall May 1994 (C) * Rewritten by Richard Henderson Dec 1996 * Add MOD_INITIALIZING Keith Owens Nov 1999 + * Add kallsyms support, Keith Owens April 2000 * * This source is covered by the GNU GPL, the same as all kernel sources. */ -#ifdef CONFIG_MODULES /* a *big* #ifdef block... */ +#if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS) extern struct module_symbol __start___ksymtab[]; extern struct module_symbol __stop___ksymtab[]; @@ -26,6 +27,9 @@ extern const struct exception_table_entry __start___ex_table[]; extern const struct exception_table_entry __stop___ex_table[]; +extern const char __start___kallsyms[]; +extern const char __stop___kallsyms[]; + static struct module kernel_module = { sizeof(struct module), /* size_of_struct */ @@ -43,10 +47,16 @@ NULL, /* cleanup */ __start___ex_table, /* ex_table_start */ __stop___ex_table, /* ex_table_end */ + kallsyms_start: __start___kallsyms, + kallsyms_end: __stop___kallsyms, /* Rest are NULL */ }; struct module *module_list = &kernel_module; + +#endif /* defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS) */ + +#if defined(CONFIG_MODULES) /* The rest of the source */ static long get_mod_name(const char *user_name, char **buf); static void put_mod_name(char *buf);