Whamcloud - gitweb
b=4336
[fs/lustre-release.git] / lustre / kernel_patches / patches / kksymoops-2.4.24.vanilla.patch
1 Index: linux-2.4.24/arch/i386/kernel/process.c
2 ===================================================================
3 --- linux-2.4.24.orig/arch/i386/kernel/process.c        2004-06-24 09:06:29.000000000 +0400
4 +++ linux-2.4.24/arch/i386/kernel/process.c     2004-07-18 16:28:19.000000000 +0400
5 @@ -33,6 +33,7 @@
6  #include <linux/reboot.h>
7  #include <linux/init.h>
8  #include <linux/mc146818rtc.h>
9 +#include <linux/version.h>
10  
11  #include <asm/uaccess.h>
12  #include <asm/pgtable.h>
13 @@ -447,10 +448,14 @@
14  void show_regs(struct pt_regs * regs)
15  {
16         unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
17 +       static char buffer[512];
18 +
19 +       lookup_symbol(regs->eip,buffer,512);
20  
21         printk("\n");
22         printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
23         printk("EIP: %04x:[<%08lx>] CPU: %d",0xffff & regs->xcs,regs->eip, smp_processor_id());
24 +       printk("\nEIP is at %s (" UTS_RELEASE ")\n",buffer);
25         if (regs->xcs & 3)
26                 printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
27         printk(" EFLAGS: %08lx    %s\n",regs->eflags, print_tainted());
28 Index: linux-2.4.24/arch/i386/kernel/traps.c
29 ===================================================================
30 --- linux-2.4.24.orig/arch/i386/kernel/traps.c  2004-07-14 18:14:26.000000000 +0400
31 +++ linux-2.4.24/arch/i386/kernel/traps.c       2004-07-18 16:28:19.000000000 +0400
32 @@ -24,6 +24,7 @@
33  #include <linux/spinlock.h>
34  #include <linux/interrupt.h>
35  #include <linux/highmem.h>
36 +#include <linux/version.h>
37  
38  #ifdef CONFIG_MCA
39  #include <linux/mca.h>
40 @@ -135,6 +136,8 @@
41  {
42         int i;
43         unsigned long addr;
44 +       /* static to not take up stackspace; if we race here too bad */
45 +       static char buffer[512];
46  
47         if (!stack)
48                 stack = (unsigned long*)&stack;
49 @@ -144,9 +147,8 @@
50         while (((long) stack & (THREAD_SIZE-1)) != 0) {
51                 addr = *stack++;
52                 if (kernel_text_address(addr)) {
53 -                       if (i && ((i % 6) == 0))
54 -                               printk("\n ");
55 -                       printk(" [<%08lx>]", addr);
56 +                       lookup_symbol(addr, buffer, 512);
57 +                       printk("[<%08lx>] %s (0x%x))\n", addr,buffer,stack-1);
58                         i++;
59                 }
60         }
61 @@ -194,12 +196,17 @@
62         show_stack(0);
63  }
64  
65 +
66 +void print_modules(void);
67 +
68 +
69  void show_registers(struct pt_regs *regs)
70  {
71         int i;
72         int in_kernel = 1;
73         unsigned long esp;
74         unsigned short ss;
75 +       static char buffer[512];
76  
77         esp = (unsigned long) (&regs->esp);
78         ss = __KERNEL_DS;
79 @@ -208,8 +215,12 @@
80                 esp = regs->esp;
81                 ss = regs->xss & 0xffff;
82         }
83 +
84 +       print_modules();
85 +       lookup_symbol(regs->eip, buffer, 512);
86         printk("CPU:    %d\nEIP:    %04x:[<%08lx>]    %s\nEFLAGS: %08lx\n",
87                 smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags);
88 +       printk("\nEIP is at %s (" UTS_RELEASE ")\n",buffer);
89         printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
90                 regs->eax, regs->ebx, regs->ecx, regs->edx);
91         printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
92 @@ -269,7 +280,7 @@
93         if (__get_user(file, (char **)(eip + 4)) ||
94                 (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
95                 file = "<bad filename>";
96 -
97 +       printk("------------[ cut here ]------------\n");
98         printk("kernel BUG at %s:%d!\n", file, line);
99  
100  no_bug:
101 Index: linux-2.4.24/arch/i386/config.in
102 ===================================================================
103 --- linux-2.4.24.orig/arch/i386/config.in       2004-07-14 18:14:27.000000000 +0400
104 +++ linux-2.4.24/arch/i386/config.in    2004-07-18 16:28:19.000000000 +0400
105 @@ -8,6 +8,7 @@
106  define_bool CONFIG_SBUS n
107  
108  define_bool CONFIG_UID16 y
109 +define_bool CONFIG_KALLSYMS y
110  
111  mainmenu_option next_comment
112  comment 'Code maturity level options'
113 Index: linux-2.4.24/arch/i386/vmlinux.lds.S
114 ===================================================================
115 --- linux-2.4.24.orig/arch/i386/vmlinux.lds.S   2004-07-14 18:14:27.000000000 +0400
116 +++ linux-2.4.24/arch/i386/vmlinux.lds.S        2004-07-18 16:28:19.000000000 +0400
117 @@ -28,6 +28,11 @@
118    __ksymtab : { *(__ksymtab) }
119    __stop___ksymtab = .;
120  
121 +  __start___kallsyms = .;      /* All kernel symbols */
122 +  __kallsyms : { *(__kallsyms) }
123 +  __stop___kallsyms = .;
124 +
125 +
126    .data : {                    /* Data */
127         *(.data)
128         CONSTRUCTORS
129 Index: linux-2.4.24/include/linux/kernel.h
130 ===================================================================
131 --- linux-2.4.24.orig/include/linux/kernel.h    2004-07-13 11:07:11.000000000 +0400
132 +++ linux-2.4.24/include/linux/kernel.h 2004-07-18 16:28:19.000000000 +0400
133 @@ -110,6 +110,8 @@
134  
135  extern void dump_stack(void);
136  
137 +extern int lookup_symbol(unsigned long address, char *buffer, int buflen);
138 +
139  #if DEBUG
140  #define pr_debug(fmt,arg...) \
141         printk(KERN_DEBUG fmt,##arg)
142 Index: linux-2.4.24/include/linux/kallsyms.h
143 ===================================================================
144 --- linux-2.4.24.orig/include/linux/kallsyms.h  2003-01-30 13:24:37.000000000 +0300
145 +++ linux-2.4.24/include/linux/kallsyms.h       2004-07-18 16:28:19.000000000 +0400
146 @@ -0,0 +1,164 @@
147 +/* kallsyms headers
148 +   Copyright 2000 Keith Owens <kaos@ocs.com.au>
149 +
150 +   This file is part of the Linux modutils.  It is exported to kernel
151 +   space so debuggers can access the kallsyms data.
152 +
153 +   The kallsyms data contains all the non-stack symbols from a kernel
154 +   or a module.  The kernel symbols are held between __start___kallsyms
155 +   and __stop___kallsyms.  The symbols for a module are accessed via
156 +   the struct module chain which is based at module_list.
157 +
158 +   This program is free software; you can redistribute it and/or modify it
159 +   under the terms of the GNU General Public License as published by the
160 +   Free Software Foundation; either version 2 of the License, or (at your
161 +   option) any later version.
162 +
163 +   This program is distributed in the hope that it will be useful, but
164 +   WITHOUT ANY WARRANTY; without even the implied warranty of
165 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
166 +   General Public License for more details.
167 +
168 +   You should have received a copy of the GNU General Public License
169 +   along with this program; if not, write to the Free Software Foundation,
170 +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
171 + */
172 +
173 +#ident "$Id: kksymoops-2.4.24.vanilla.patch,v 1.6 2004/07/18 12:32:35 alex Exp $"
174 +
175 +#ifndef MODUTILS_KALLSYMS_H
176 +#define MODUTILS_KALLSYMS_H 1
177 +
178 +/* Have to (re)define these ElfW entries here because external kallsyms
179 + * code does not have access to modutils/include/obj.h.  This code is
180 + * included from user spaces tools (modutils) and kernel, they need
181 + * different includes.
182 + */
183 +
184 +#ifndef ELFCLASS32
185 +#ifdef __KERNEL__
186 +#include <linux/elf.h>
187 +#else  /* __KERNEL__ */
188 +#include <elf.h>
189 +#endif /* __KERNEL__ */
190 +#endif /* ELFCLASS32 */
191 +
192 +#ifndef ELFCLASSM
193 +#define ELFCLASSM ELF_CLASS
194 +#endif
195 +
196 +#ifndef ElfW
197 +# if ELFCLASSM == ELFCLASS32
198 +#  define ElfW(x)  Elf32_ ## x
199 +#  define ELFW(x)  ELF32_ ## x
200 +# else
201 +#  define ElfW(x)  Elf64_ ## x
202 +#  define ELFW(x)  ELF64_ ## x
203 +# endif
204 +#endif
205 +
206 +/* Format of data in the kallsyms section.
207 + * Most of the fields are small numbers but the total size and all
208 + * offsets can be large so use the 32/64 bit types for these fields.
209 + *
210 + * Do not use sizeof() on these structures, modutils may be using extra
211 + * fields.  Instead use the size fields in the header to access the
212 + * other bits of data.
213 + */  
214 +
215 +struct kallsyms_header {
216 +       int             size;           /* Size of this header */
217 +       ElfW(Word)      total_size;     /* Total size of kallsyms data */
218 +       int             sections;       /* Number of section entries */
219 +       ElfW(Off)       section_off;    /* Offset to first section entry */
220 +       int             section_size;   /* Size of one section entry */
221 +       int             symbols;        /* Number of symbol entries */
222 +       ElfW(Off)       symbol_off;     /* Offset to first symbol entry */
223 +       int             symbol_size;    /* Size of one symbol entry */
224 +       ElfW(Off)       string_off;     /* Offset to first string */
225 +       ElfW(Addr)      start;          /* Start address of first section */
226 +       ElfW(Addr)      end;            /* End address of last section */
227 +};
228 +
229 +struct kallsyms_section {
230 +       ElfW(Addr)      start;          /* Start address of section */
231 +       ElfW(Word)      size;           /* Size of this section */
232 +       ElfW(Off)       name_off;       /* Offset to section name */
233 +       ElfW(Word)      flags;          /* Flags from section */
234 +};
235 +
236 +struct kallsyms_symbol {
237 +       ElfW(Off)       section_off;    /* Offset to section that owns this symbol */
238 +       ElfW(Addr)      symbol_addr;    /* Address of symbol */
239 +       ElfW(Off)       name_off;       /* Offset to symbol name */
240 +};
241 +
242 +#define KALLSYMS_SEC_NAME "__kallsyms"
243 +#define KALLSYMS_IDX 2                 /* obj_kallsyms creates kallsyms as section 2 */
244 +
245 +#define kallsyms_next_sec(h,s) \
246 +       ((s) = (struct kallsyms_section *)((char *)(s) + (h)->section_size))
247 +#define kallsyms_next_sym(h,s) \
248 +       ((s) = (struct kallsyms_symbol *)((char *)(s) + (h)->symbol_size))
249 +
250 +#ifdef CONFIG_KALLSYMS
251 +
252 +int kallsyms_symbol_to_address(
253 +       const char       *name,                 /* Name to lookup */
254 +       unsigned long    *token,                /* Which module to start with */
255 +       const char      **mod_name,             /* Set to module name or "kernel" */
256 +       unsigned long    *mod_start,            /* Set to start address of module */
257 +       unsigned long    *mod_end,              /* Set to end address of module */
258 +       const char      **sec_name,             /* Set to section name */
259 +       unsigned long    *sec_start,            /* Set to start address of section */
260 +       unsigned long    *sec_end,              /* Set to end address of section */
261 +       const char      **sym_name,             /* Set to full symbol name */
262 +       unsigned long    *sym_start,            /* Set to start address of symbol */
263 +       unsigned long    *sym_end               /* Set to end address of symbol */
264 +       );
265 +
266 +int kallsyms_address_to_symbol(
267 +       unsigned long     address,              /* Address to lookup */
268 +       const char      **mod_name,             /* Set to module name */
269 +       unsigned long    *mod_start,            /* Set to start address of module */
270 +       unsigned long    *mod_end,              /* Set to end address of module */
271 +       const char      **sec_name,             /* Set to section name */
272 +       unsigned long    *sec_start,            /* Set to start address of section */
273 +       unsigned long    *sec_end,              /* Set to end address of section */
274 +       const char      **sym_name,             /* Set to full symbol name */
275 +       unsigned long    *sym_start,            /* Set to start address of symbol */
276 +       unsigned long    *sym_end               /* Set to end address of symbol */
277 +       );
278 +
279 +int kallsyms_sections(void *token,
280 +                     int (*callback)(void *,   /* token */
281 +                       const char *,           /* module name */
282 +                       const char *,           /* section name */
283 +                       ElfW(Addr),             /* Section start */
284 +                       ElfW(Addr),             /* Section end */
285 +                       ElfW(Word)              /* Section flags */
286 +                     )
287 +               );
288 +
289 +#else
290 +
291 +static inline int kallsyms_address_to_symbol(
292 +       unsigned long     address,              /* Address to lookup */
293 +       const char      **mod_name,             /* Set to module name */
294 +       unsigned long    *mod_start,            /* Set to start address of module */
295 +       unsigned long    *mod_end,              /* Set to end address of module */
296 +       const char      **sec_name,             /* Set to section name */
297 +       unsigned long    *sec_start,            /* Set to start address of section */
298 +       unsigned long    *sec_end,              /* Set to end address of section */
299 +       const char      **sym_name,             /* Set to full symbol name */
300 +       unsigned long    *sym_start,            /* Set to start address of symbol */
301 +       unsigned long    *sym_end               /* Set to end address of symbol */
302 +       )
303 +{
304 +       return -ESRCH;
305 +}
306 +
307 +#endif
308 +
309 +#endif /* kallsyms.h */
310 +
311 Index: linux-2.4.24/kernel/kksymoops.c
312 ===================================================================
313 --- linux-2.4.24.orig/kernel/kksymoops.c        2003-01-30 13:24:37.000000000 +0300
314 +++ linux-2.4.24/kernel/kksymoops.c     2004-07-18 16:28:19.000000000 +0400
315 @@ -0,0 +1,82 @@
316 +#include <linux/module.h>
317 +#include <linux/string.h>
318 +#include <linux/errno.h>
319 +#include <linux/kernel.h>
320 +#include <linux/config.h>
321 +#ifdef CONFIG_KALLSYMS
322 +#include <linux/kallsyms.h>
323 +#endif
324 +
325 +
326 +
327 +int lookup_symbol(unsigned long address, char *buffer, int buflen)
328 +{
329 +       struct module *this_mod;
330 +       unsigned long bestsofar;
331 +
332 +       const char *mod_name = NULL, *sec_name = NULL, *sym_name = NULL;
333 +       unsigned long mod_start,mod_end,sec_start,sec_end,sym_start,sym_end;
334 +       
335 +       if (!buffer)
336 +               return -EFAULT;
337 +       
338 +       if (buflen<256)
339 +               return -ENOMEM;
340 +       
341 +       memset(buffer,0,buflen);
342 +
343 +#ifdef CONFIG_KALLSYMS
344 +       if (!kallsyms_address_to_symbol(address,&mod_name,&mod_start,&mod_end,&sec_name,
345 +               &sec_start, &sec_end, &sym_name, &sym_start, &sym_end)) {
346 +               /* kallsyms doesn't have a clue; lets try harder */
347 +               bestsofar = 0;
348 +               snprintf(buffer,buflen-1,"[unresolved]");
349 +               
350 +               this_mod = module_list;
351 +
352 +               while (this_mod != NULL) {
353 +                       int i;
354 +                       /* walk the symbol list of this module. Only symbols
355 +                          who's address is smaller than the searched for address
356 +                          are relevant; and only if it's better than the best so far */
357 +                       for (i=0; i< this_mod->nsyms; i++)
358 +                               if ((this_mod->syms[i].value<=address) &&
359 +                                       (bestsofar<this_mod->syms[i].value)) {
360 +                                       snprintf(buffer,buflen-1,"%s [%s] 0x%x",
361 +                                               this_mod->syms[i].name,
362 +                                               this_mod->name,
363 +                                               (unsigned int)(address - this_mod->syms[i].value));
364 +                                       bestsofar = this_mod->syms[i].value;
365 +                               }
366 +                       this_mod = this_mod->next;
367 +               }
368 +
369 +       } else { /* kallsyms success */
370 +               snprintf(buffer,buflen-1,"%s [%s] 0x%x",sym_name,mod_name,(unsigned int)(address-sym_start));
371 +       }
372 +#endif
373 +       return strlen(buffer);
374 +}
375 +
376 +static char modlist[4096];
377 +/* this function isn't smp safe but that's not really a problem; it's called from
378 + * oops context only and any locking could actually prevent the oops from going out;
379 + * the line that is generated is informational only and should NEVER prevent the real oops
380 + * from going out. 
381 + */
382 +void print_modules(void)
383 +{
384 +       struct module *this_mod;
385 +       int pos = 0;
386 +       memset(modlist,0,4096);
387 +
388 +#ifdef CONFIG_KALLSYMS
389 +       this_mod = module_list;
390 +       while (this_mod != NULL) {
391 +               if (this_mod->name != NULL)
392 +                       pos +=snprintf(modlist+pos,160-pos-1,"%s ",this_mod->name);
393 +               this_mod = this_mod->next;
394 +       }
395 +       printk("%s\n",modlist);
396 +#endif
397 +}
398 Index: linux-2.4.24/kernel/Makefile
399 ===================================================================
400 --- linux-2.4.24.orig/kernel/Makefile   2001-09-17 08:22:40.000000000 +0400
401 +++ linux-2.4.24/kernel/Makefile        2004-07-18 16:28:19.000000000 +0400
402 @@ -11,7 +11,7 @@
403  
404  export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o
405  
406 -obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
407 +obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o kksymoops.o kallsyms.o \
408             module.o exit.o itimer.o info.o time.o softirq.o resource.o \
409             sysctl.o acct.o capability.o ptrace.o timer.o user.o \
410             signal.o sys.o kmod.o context.o
411 @@ -29,4 +29,7 @@
412  CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer
413  endif
414  
415 +obj-$(CONFIG_KALLSYMS) += kksymoops.o
416 +obj-$(CONFIG_KALLSYMS) += kallsyms.o
417 +
418  include $(TOPDIR)/Rules.make
419 Index: linux-2.4.24/kernel/kallsyms.c
420 ===================================================================
421 --- linux-2.4.24.orig/kernel/kallsyms.c 2003-01-30 13:24:37.000000000 +0300
422 +++ linux-2.4.24/kernel/kallsyms.c      2004-07-18 16:28:19.000000000 +0400
423 @@ -0,0 +1,227 @@
424 +/*
425 + * kksymoops.c: in-kernel printing of symbolic oopses and stack traces.
426 + *
427 + *  Copyright 2000 Keith Owens <kaos@ocs.com.au> April 2000
428 + *  Copyright 2002 Arjan van de Ven <arjanv@redhat.com>
429 + *
430 +   This code uses the list of all kernel and module symbols to :-
431 +
432 +   * Find any non-stack symbol in a kernel or module.  Symbols do
433 +     not have to be exported for debugging.
434 +
435 +   * Convert an address to the module (or kernel) that owns it, the
436 +     section it is in and the nearest symbol.  This finds all non-stack
437 +     symbols, not just exported ones.
438 +
439 + */
440 +
441 +#include <linux/mm.h>
442 +#include <linux/module.h>
443 +#include <linux/kallsyms.h>
444 +
445 +/* A symbol can appear in more than one module.  A token is used to
446 + * restart the scan at the next module, set the token to 0 for the
447 + * first scan of each symbol.
448 + */
449 +
450 +int kallsyms_symbol_to_address(
451 +       const char       *name,         /* Name to lookup */
452 +       unsigned long    *token,        /* Which module to start at */
453 +       const char      **mod_name,     /* Set to module name */
454 +       unsigned long    *mod_start,    /* Set to start address of module */
455 +       unsigned long    *mod_end,      /* Set to end address of module */
456 +       const char      **sec_name,     /* Set to section name */
457 +       unsigned long    *sec_start,    /* Set to start address of section */
458 +       unsigned long    *sec_end,      /* Set to end address of section */
459 +       const char      **sym_name,     /* Set to full symbol name */
460 +       unsigned long    *sym_start,    /* Set to start address of symbol */
461 +       unsigned long    *sym_end       /* Set to end address of symbol */
462 +       )
463 +{
464 +       const struct kallsyms_header    *ka_hdr = NULL; /* stupid gcc */
465 +       const struct kallsyms_section   *ka_sec;
466 +       const struct kallsyms_symbol    *ka_sym = NULL;
467 +       const char                      *ka_str = NULL;
468 +       const struct module *m;
469 +       int i = 0, l;
470 +       const char *p, *pt_R;
471 +       char *p2;
472 +
473 +       /* Restart? */
474 +       m = module_list;
475 +       if (token && *token) {
476 +               for (; m; m = m->next)
477 +                       if ((unsigned long)m == *token)
478 +                               break;
479 +               if (m)
480 +                       m = m->next;
481 +       }
482 +
483 +       for (; m; m = m->next) {
484 +               if (!mod_member_present(m, kallsyms_start) || 
485 +                   !mod_member_present(m, kallsyms_end) ||
486 +                   m->kallsyms_start >= m->kallsyms_end)
487 +                       continue;
488 +               ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
489 +               ka_sym = (struct kallsyms_symbol *)
490 +                       ((char *)(ka_hdr) + ka_hdr->symbol_off);
491 +               ka_str = 
492 +                       ((char *)(ka_hdr) + ka_hdr->string_off);
493 +               for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
494 +                       p = ka_str + ka_sym->name_off;
495 +                       if (strcmp(p, name) == 0)
496 +                               break;
497 +                       /* Unversioned requests match versioned names */
498 +                       if (!(pt_R = strstr(p, "_R")))
499 +                               continue;
500 +                       l = strlen(pt_R);
501 +                       if (l < 10)
502 +                               continue;       /* Not _R.*xxxxxxxx */
503 +                       (void)simple_strtoul(pt_R+l-8, &p2, 16);
504 +                       if (*p2)
505 +                               continue;       /* Not _R.*xxxxxxxx */
506 +                       if (strncmp(p, name, pt_R-p) == 0)
507 +                               break;  /* Match with version */
508 +               }
509 +               if (i < ka_hdr->symbols)
510 +                       break;
511 +       }
512 +
513 +       if (token)
514 +               *token = (unsigned long)m;
515 +       if (!m)
516 +               return(0);      /* not found */
517 +
518 +       ka_sec = (const struct kallsyms_section *)
519 +               ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off);
520 +       *mod_name = m->name;
521 +       *mod_start = ka_hdr->start;
522 +       *mod_end = ka_hdr->end;
523 +       *sec_name = ka_sec->name_off + ka_str;
524 +       *sec_start = ka_sec->start;
525 +       *sec_end = ka_sec->start + ka_sec->size;
526 +       *sym_name = ka_sym->name_off + ka_str;
527 +       *sym_start = ka_sym->symbol_addr;
528 +       if (i < ka_hdr->symbols-1) {
529 +               const struct kallsyms_symbol *ka_symn = ka_sym;
530 +               kallsyms_next_sym(ka_hdr, ka_symn);
531 +               *sym_end = ka_symn->symbol_addr;
532 +       }
533 +       else
534 +               *sym_end = *sec_end;
535 +       return(1);
536 +}
537 +
538 +int kallsyms_address_to_symbol(
539 +       unsigned long     address,      /* Address to lookup */
540 +       const char      **mod_name,     /* Set to module name */
541 +       unsigned long    *mod_start,    /* Set to start address of module */
542 +       unsigned long    *mod_end,      /* Set to end address of module */
543 +       const char      **sec_name,     /* Set to section name */
544 +       unsigned long    *sec_start,    /* Set to start address of section */
545 +       unsigned long    *sec_end,      /* Set to end address of section */
546 +       const char      **sym_name,     /* Set to full symbol name */
547 +       unsigned long    *sym_start,    /* Set to start address of symbol */
548 +       unsigned long    *sym_end       /* Set to end address of symbol */
549 +       )
550 +{
551 +       const struct kallsyms_header    *ka_hdr = NULL; /* stupid gcc */
552 +       const struct kallsyms_section   *ka_sec = NULL;
553 +       const struct kallsyms_symbol    *ka_sym;
554 +       const char                      *ka_str;
555 +       const struct module *m;
556 +       int i;
557 +       unsigned long end;
558 +
559 +       for (m = module_list; m; m = m->next) {
560 +         
561 +               if (!mod_member_present(m, kallsyms_start) || 
562 +                   !mod_member_present(m, kallsyms_end) ||
563 +                   m->kallsyms_start >= m->kallsyms_end)
564 +                       continue;
565 +               ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
566 +               ka_sec = (const struct kallsyms_section *)
567 +                       ((char *)ka_hdr + ka_hdr->section_off);
568 +               /* Is the address in any section in this module? */
569 +               for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
570 +                       if (ka_sec->start <= address &&
571 +                           (ka_sec->start + ka_sec->size) > address)
572 +                               break;
573 +               }
574 +               if (i < ka_hdr->sections)
575 +                       break;  /* Found a matching section */
576 +       }
577 +
578 +       if (!m)
579 +               return(0);      /* not found */
580 +
581 +       ka_sym = (struct kallsyms_symbol *)
582 +               ((char *)(ka_hdr) + ka_hdr->symbol_off);
583 +       ka_str = 
584 +               ((char *)(ka_hdr) + ka_hdr->string_off);
585 +       *mod_name = m->name;
586 +       *mod_start = ka_hdr->start;
587 +       *mod_end = ka_hdr->end;
588 +       *sec_name = ka_sec->name_off + ka_str;
589 +       *sec_start = ka_sec->start;
590 +       *sec_end = ka_sec->start + ka_sec->size;
591 +       *sym_name = *sec_name;          /* In case we find no matching symbol */
592 +       *sym_start = *sec_start;
593 +       *sym_end = *sec_end;
594 +
595 +       for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
596 +               if (ka_sym->symbol_addr > address)
597 +                       continue;
598 +               if (i < ka_hdr->symbols-1) {
599 +                       const struct kallsyms_symbol *ka_symn = ka_sym;
600 +                       kallsyms_next_sym(ka_hdr, ka_symn);
601 +                       end = ka_symn->symbol_addr;
602 +               }
603 +               else
604 +                       end = *sec_end;
605 +               if (end <= address)
606 +                       continue;
607 +               if ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off
608 +                   != (char *)ka_sec)
609 +                       continue;       /* wrong section */
610 +               *sym_name = ka_str + ka_sym->name_off;
611 +               *sym_start = ka_sym->symbol_addr;
612 +               *sym_end = end;
613 +               break;
614 +       }
615 +       return(1);
616 +}
617 +
618 +/* List all sections in all modules.  The callback routine is invoked with
619 + * token, module name, section name, section start, section end, section flags.
620 + */
621 +int kallsyms_sections(void *token,
622 +                     int (*callback)(void *, const char *, const char *, ElfW(Addr), ElfW(Addr), ElfW(Word)))
623 +{
624 +       const struct kallsyms_header    *ka_hdr = NULL; /* stupid gcc */
625 +       const struct kallsyms_section   *ka_sec = NULL;
626 +       const char                      *ka_str;
627 +       const struct module *m;
628 +       int i;
629 +
630 +       for (m = module_list; m; m = m->next) {
631 +               if (!mod_member_present(m, kallsyms_start) || 
632 +                   !mod_member_present(m, kallsyms_end) ||
633 +                   m->kallsyms_start >= m->kallsyms_end)
634 +                       continue;
635 +               ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
636 +               ka_sec = (const struct kallsyms_section *) ((char *)ka_hdr + ka_hdr->section_off);
637 +               ka_str = ((char *)(ka_hdr) + ka_hdr->string_off);
638 +               for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
639 +                       if (callback(
640 +                               token,
641 +                               *(m->name) ? m->name : "kernel",
642 +                               ka_sec->name_off + ka_str,
643 +                               ka_sec->start,
644 +                               ka_sec->start + ka_sec->size,
645 +                               ka_sec->flags))
646 +                               return(0);
647 +               }
648 +       }
649 +       return(1);
650 +}
651 Index: linux-2.4.24/Makefile
652 ===================================================================
653 --- linux-2.4.24.orig/Makefile  2004-07-13 11:07:12.000000000 +0400
654 +++ linux-2.4.24/Makefile       2004-07-18 16:28:19.000000000 +0400
655 @@ -45,6 +45,7 @@
656  MAKEFILES      = $(TOPDIR)/.config
657  GENKSYMS       = /sbin/genksyms
658  DEPMOD         = /sbin/depmod
659 +KALLSYMS       = /sbin/kallsyms
660  MODFLAGS       = -DMODULE
661  CFLAGS_KERNEL  =
662  PERL           = perl
663 @@ -211,7 +212,7 @@
664  CLEAN_FILES = \
665         kernel/ksyms.lst include/linux/compile.h \
666         vmlinux System.map \
667 -       .tmp* \
668 +       $(TMPPREFIX).tmp* \
669         drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \
670         drivers/char/conmakehash \
671         drivers/char/drm/*-mod.c \
672 @@ -292,16 +293,42 @@
673  boot: vmlinux
674         @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C arch/$(ARCH)/boot
675  
676 +LD_VMLINUX     := $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \
677 +                       --start-group \
678 +                       $(CORE_FILES) \
679 +                       $(DRIVERS) \
680 +                      $(NETWORKS) \
681 +                       $(LIBS) \
682 +                       --end-group
683 +ifeq ($(CONFIG_KALLSYMS),y)
684 +LD_VMLINUX_KALLSYMS    := $(TMPPREFIX).tmp_kallsyms3.o
685 +else
686 +LD_VMLINUX_KALLSYMS    :=
687 +endif
688 +
689  vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o init/do_mounts.o linuxsubdirs
690 -       $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \
691 -               --start-group \
692 -               $(CORE_FILES) \
693 -               $(DRIVERS) \
694 -               $(NETWORKS) \
695 -               $(LIBS) \
696 -               --end-group \
697 -               -o vmlinux
698 +       @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" kallsyms
699 +
700 +.PHONY:        kallsyms
701 +
702 +kallsyms:
703 +ifeq ($(CONFIG_KALLSYMS),y)
704 +       @echo kallsyms pass 1
705 +       $(LD_VMLINUX) -o $(TMPPREFIX).tmp_vmlinux1
706 +       @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux1 > $(TMPPREFIX).tmp_kallsyms1.o
707 +       @echo kallsyms pass 2
708 +       @$(LD_VMLINUX) $(TMPPREFIX).tmp_kallsyms1.o -o $(TMPPREFIX).tmp_vmlinux2
709 +       @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux2 > $(TMPPREFIX).tmp_kallsyms2.o
710 +       @echo kallsyms pass 3
711 +       @$(LD_VMLINUX) $(TMPPREFIX).tmp_kallsyms2.o -o $(TMPPREFIX).tmp_vmlinux3
712 +       @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux3 > $(TMPPREFIX).tmp_kallsyms3.o
713 +endif
714 +       $(LD_VMLINUX) $(LD_VMLINUX_KALLSYMS) -o $(TMPPREFIX)vmlinux
715 +ifneq ($(TMPPREFIX),)
716 +       mv $(TMPPREFIX)vmlinux vmlinux
717 +endif
718         $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
719 +       @rm -f $(TMPPREFIX).tmp_vmlinux* $(TMPPREFIX).tmp_kallsyms*
720  
721  symlinks:
722         rm -f include/asm