Whamcloud - gitweb
- landing of b_hd_cleanup_merge to HEAD.
[fs/lustre-release.git] / lustre / kernel_patches / patches / kksymoops-2.4.24.vanilla.patch
1 Index: linux-2.4.24-b1_4/arch/i386/kernel/process.c
2 ===================================================================
3 --- linux-2.4.24-b1_4.orig/arch/i386/kernel/process.c   2003-11-29 02:26:19.000000000 +0800
4 +++ linux-2.4.24-b1_4/arch/i386/kernel/process.c        2004-09-06 17:53:50.000000000 +0800
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-b1_4/arch/i386/kernel/traps.c
29 ===================================================================
30 --- linux-2.4.24-b1_4.orig/arch/i386/kernel/traps.c     2004-09-06 17:53:35.000000000 +0800
31 +++ linux-2.4.24-b1_4/arch/i386/kernel/traps.c  2004-09-06 17:53:50.000000000 +0800
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-b1_4/arch/i386/config.in
102 ===================================================================
103 --- linux-2.4.24-b1_4.orig/arch/i386/config.in  2004-09-06 17:53:39.000000000 +0800
104 +++ linux-2.4.24-b1_4/arch/i386/config.in       2004-09-06 17:53:50.000000000 +0800
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-b1_4/arch/i386/vmlinux.lds.S
114 ===================================================================
115 --- linux-2.4.24-b1_4.orig/arch/i386/vmlinux.lds.S      2004-09-06 17:53:39.000000000 +0800
116 +++ linux-2.4.24-b1_4/arch/i386/vmlinux.lds.S   2004-09-06 17:53:50.000000000 +0800
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-b1_4/include/linux/kernel.h
130 ===================================================================
131 --- linux-2.4.24-b1_4.orig/include/linux/kernel.h       2004-09-06 17:44:47.000000000 +0800
132 +++ linux-2.4.24-b1_4/include/linux/kernel.h    2004-09-06 17:55:19.000000000 +0800
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-b1_4/include/linux/kallsyms.h
143 ===================================================================
144 --- linux-2.4.24-b1_4.orig/include/linux/kallsyms.h     2003-01-30 18:24:37.000000000 +0800
145 +++ linux-2.4.24-b1_4/include/linux/kallsyms.h  2004-09-06 17:53:50.000000000 +0800
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.7 2004/10/23 13:47:08 yury 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-b1_4/kernel/kksymoops.c
312 ===================================================================
313 --- linux-2.4.24-b1_4.orig/kernel/kksymoops.c   2003-01-30 18:24:37.000000000 +0800
314 +++ linux-2.4.24-b1_4/kernel/kksymoops.c        2004-09-06 17:53:50.000000000 +0800
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-b1_4/kernel/Makefile
399 ===================================================================
400 --- linux-2.4.24-b1_4.orig/kernel/Makefile      2001-09-17 12:22:40.000000000 +0800
401 +++ linux-2.4.24-b1_4/kernel/Makefile   2004-09-06 17:56:17.000000000 +0800
402 @@ -29,4 +29,7 @@
403  CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer
404  endif
405  
406 +obj-$(CONFIG_KALLSYMS) += kksymoops.o
407 +obj-$(CONFIG_KALLSYMS) += kallsyms.o
408 +
409  include $(TOPDIR)/Rules.make
410 Index: linux-2.4.24-b1_4/kernel/kallsyms.c
411 ===================================================================
412 --- linux-2.4.24-b1_4.orig/kernel/kallsyms.c    2003-01-30 18:24:37.000000000 +0800
413 +++ linux-2.4.24-b1_4/kernel/kallsyms.c 2004-09-06 17:53:50.000000000 +0800
414 @@ -0,0 +1,227 @@
415 +/*
416 + * kksymoops.c: in-kernel printing of symbolic oopses and stack traces.
417 + *
418 + *  Copyright 2000 Keith Owens <kaos@ocs.com.au> April 2000
419 + *  Copyright 2002 Arjan van de Ven <arjanv@redhat.com>
420 + *
421 +   This code uses the list of all kernel and module symbols to :-
422 +
423 +   * Find any non-stack symbol in a kernel or module.  Symbols do
424 +     not have to be exported for debugging.
425 +
426 +   * Convert an address to the module (or kernel) that owns it, the
427 +     section it is in and the nearest symbol.  This finds all non-stack
428 +     symbols, not just exported ones.
429 +
430 + */
431 +
432 +#include <linux/mm.h>
433 +#include <linux/module.h>
434 +#include <linux/kallsyms.h>
435 +
436 +/* A symbol can appear in more than one module.  A token is used to
437 + * restart the scan at the next module, set the token to 0 for the
438 + * first scan of each symbol.
439 + */
440 +
441 +int kallsyms_symbol_to_address(
442 +       const char       *name,         /* Name to lookup */
443 +       unsigned long    *token,        /* Which module to start at */
444 +       const char      **mod_name,     /* Set to module name */
445 +       unsigned long    *mod_start,    /* Set to start address of module */
446 +       unsigned long    *mod_end,      /* Set to end address of module */
447 +       const char      **sec_name,     /* Set to section name */
448 +       unsigned long    *sec_start,    /* Set to start address of section */
449 +       unsigned long    *sec_end,      /* Set to end address of section */
450 +       const char      **sym_name,     /* Set to full symbol name */
451 +       unsigned long    *sym_start,    /* Set to start address of symbol */
452 +       unsigned long    *sym_end       /* Set to end address of symbol */
453 +       )
454 +{
455 +       const struct kallsyms_header    *ka_hdr = NULL; /* stupid gcc */
456 +       const struct kallsyms_section   *ka_sec;
457 +       const struct kallsyms_symbol    *ka_sym = NULL;
458 +       const char                      *ka_str = NULL;
459 +       const struct module *m;
460 +       int i = 0, l;
461 +       const char *p, *pt_R;
462 +       char *p2;
463 +
464 +       /* Restart? */
465 +       m = module_list;
466 +       if (token && *token) {
467 +               for (; m; m = m->next)
468 +                       if ((unsigned long)m == *token)
469 +                               break;
470 +               if (m)
471 +                       m = m->next;
472 +       }
473 +
474 +       for (; m; m = m->next) {
475 +               if (!mod_member_present(m, kallsyms_start) || 
476 +                   !mod_member_present(m, kallsyms_end) ||
477 +                   m->kallsyms_start >= m->kallsyms_end)
478 +                       continue;
479 +               ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
480 +               ka_sym = (struct kallsyms_symbol *)
481 +                       ((char *)(ka_hdr) + ka_hdr->symbol_off);
482 +               ka_str = 
483 +                       ((char *)(ka_hdr) + ka_hdr->string_off);
484 +               for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
485 +                       p = ka_str + ka_sym->name_off;
486 +                       if (strcmp(p, name) == 0)
487 +                               break;
488 +                       /* Unversioned requests match versioned names */
489 +                       if (!(pt_R = strstr(p, "_R")))
490 +                               continue;
491 +                       l = strlen(pt_R);
492 +                       if (l < 10)
493 +                               continue;       /* Not _R.*xxxxxxxx */
494 +                       (void)simple_strtoul(pt_R+l-8, &p2, 16);
495 +                       if (*p2)
496 +                               continue;       /* Not _R.*xxxxxxxx */
497 +                       if (strncmp(p, name, pt_R-p) == 0)
498 +                               break;  /* Match with version */
499 +               }
500 +               if (i < ka_hdr->symbols)
501 +                       break;
502 +       }
503 +
504 +       if (token)
505 +               *token = (unsigned long)m;
506 +       if (!m)
507 +               return(0);      /* not found */
508 +
509 +       ka_sec = (const struct kallsyms_section *)
510 +               ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off);
511 +       *mod_name = m->name;
512 +       *mod_start = ka_hdr->start;
513 +       *mod_end = ka_hdr->end;
514 +       *sec_name = ka_sec->name_off + ka_str;
515 +       *sec_start = ka_sec->start;
516 +       *sec_end = ka_sec->start + ka_sec->size;
517 +       *sym_name = ka_sym->name_off + ka_str;
518 +       *sym_start = ka_sym->symbol_addr;
519 +       if (i < ka_hdr->symbols-1) {
520 +               const struct kallsyms_symbol *ka_symn = ka_sym;
521 +               kallsyms_next_sym(ka_hdr, ka_symn);
522 +               *sym_end = ka_symn->symbol_addr;
523 +       }
524 +       else
525 +               *sym_end = *sec_end;
526 +       return(1);
527 +}
528 +
529 +int kallsyms_address_to_symbol(
530 +       unsigned long     address,      /* Address to lookup */
531 +       const char      **mod_name,     /* Set to module name */
532 +       unsigned long    *mod_start,    /* Set to start address of module */
533 +       unsigned long    *mod_end,      /* Set to end address of module */
534 +       const char      **sec_name,     /* Set to section name */
535 +       unsigned long    *sec_start,    /* Set to start address of section */
536 +       unsigned long    *sec_end,      /* Set to end address of section */
537 +       const char      **sym_name,     /* Set to full symbol name */
538 +       unsigned long    *sym_start,    /* Set to start address of symbol */
539 +       unsigned long    *sym_end       /* Set to end address of symbol */
540 +       )
541 +{
542 +       const struct kallsyms_header    *ka_hdr = NULL; /* stupid gcc */
543 +       const struct kallsyms_section   *ka_sec = NULL;
544 +       const struct kallsyms_symbol    *ka_sym;
545 +       const char                      *ka_str;
546 +       const struct module *m;
547 +       int i;
548 +       unsigned long end;
549 +
550 +       for (m = module_list; m; m = m->next) {
551 +         
552 +               if (!mod_member_present(m, kallsyms_start) || 
553 +                   !mod_member_present(m, kallsyms_end) ||
554 +                   m->kallsyms_start >= m->kallsyms_end)
555 +                       continue;
556 +               ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
557 +               ka_sec = (const struct kallsyms_section *)
558 +                       ((char *)ka_hdr + ka_hdr->section_off);
559 +               /* Is the address in any section in this module? */
560 +               for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
561 +                       if (ka_sec->start <= address &&
562 +                           (ka_sec->start + ka_sec->size) > address)
563 +                               break;
564 +               }
565 +               if (i < ka_hdr->sections)
566 +                       break;  /* Found a matching section */
567 +       }
568 +
569 +       if (!m)
570 +               return(0);      /* not found */
571 +
572 +       ka_sym = (struct kallsyms_symbol *)
573 +               ((char *)(ka_hdr) + ka_hdr->symbol_off);
574 +       ka_str = 
575 +               ((char *)(ka_hdr) + ka_hdr->string_off);
576 +       *mod_name = m->name;
577 +       *mod_start = ka_hdr->start;
578 +       *mod_end = ka_hdr->end;
579 +       *sec_name = ka_sec->name_off + ka_str;
580 +       *sec_start = ka_sec->start;
581 +       *sec_end = ka_sec->start + ka_sec->size;
582 +       *sym_name = *sec_name;          /* In case we find no matching symbol */
583 +       *sym_start = *sec_start;
584 +       *sym_end = *sec_end;
585 +
586 +       for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
587 +               if (ka_sym->symbol_addr > address)
588 +                       continue;
589 +               if (i < ka_hdr->symbols-1) {
590 +                       const struct kallsyms_symbol *ka_symn = ka_sym;
591 +                       kallsyms_next_sym(ka_hdr, ka_symn);
592 +                       end = ka_symn->symbol_addr;
593 +               }
594 +               else
595 +                       end = *sec_end;
596 +               if (end <= address)
597 +                       continue;
598 +               if ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off
599 +                   != (char *)ka_sec)
600 +                       continue;       /* wrong section */
601 +               *sym_name = ka_str + ka_sym->name_off;
602 +               *sym_start = ka_sym->symbol_addr;
603 +               *sym_end = end;
604 +               break;
605 +       }
606 +       return(1);
607 +}
608 +
609 +/* List all sections in all modules.  The callback routine is invoked with
610 + * token, module name, section name, section start, section end, section flags.
611 + */
612 +int kallsyms_sections(void *token,
613 +                     int (*callback)(void *, const char *, const char *, ElfW(Addr), ElfW(Addr), ElfW(Word)))
614 +{
615 +       const struct kallsyms_header    *ka_hdr = NULL; /* stupid gcc */
616 +       const struct kallsyms_section   *ka_sec = NULL;
617 +       const char                      *ka_str;
618 +       const struct module *m;
619 +       int i;
620 +
621 +       for (m = module_list; m; m = m->next) {
622 +               if (!mod_member_present(m, kallsyms_start) || 
623 +                   !mod_member_present(m, kallsyms_end) ||
624 +                   m->kallsyms_start >= m->kallsyms_end)
625 +                       continue;
626 +               ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
627 +               ka_sec = (const struct kallsyms_section *) ((char *)ka_hdr + ka_hdr->section_off);
628 +               ka_str = ((char *)(ka_hdr) + ka_hdr->string_off);
629 +               for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
630 +                       if (callback(
631 +                               token,
632 +                               *(m->name) ? m->name : "kernel",
633 +                               ka_sec->name_off + ka_str,
634 +                               ka_sec->start,
635 +                               ka_sec->start + ka_sec->size,
636 +                               ka_sec->flags))
637 +                               return(0);
638 +               }
639 +       }
640 +       return(1);
641 +}
642 Index: linux-2.4.24-b1_4/Makefile
643 ===================================================================
644 --- linux-2.4.24-b1_4.orig/Makefile     2004-09-06 17:44:47.000000000 +0800
645 +++ linux-2.4.24-b1_4/Makefile  2004-09-06 17:53:50.000000000 +0800
646 @@ -45,6 +45,7 @@
647  MAKEFILES      = $(TOPDIR)/.config
648  GENKSYMS       = /sbin/genksyms
649  DEPMOD         = /sbin/depmod
650 +KALLSYMS       = /sbin/kallsyms
651  MODFLAGS       = -DMODULE
652  CFLAGS_KERNEL  =
653  PERL           = perl
654 @@ -211,7 +212,7 @@
655  CLEAN_FILES = \
656         kernel/ksyms.lst include/linux/compile.h \
657         vmlinux System.map \
658 -       .tmp* \
659 +       $(TMPPREFIX).tmp* \
660         drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \
661         drivers/char/conmakehash \
662         drivers/char/drm/*-mod.c \
663 @@ -292,16 +293,42 @@
664  boot: vmlinux
665         @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C arch/$(ARCH)/boot
666  
667 +LD_VMLINUX     := $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \
668 +                       --start-group \
669 +                       $(CORE_FILES) \
670 +                       $(DRIVERS) \
671 +                      $(NETWORKS) \
672 +                       $(LIBS) \
673 +                       --end-group
674 +ifeq ($(CONFIG_KALLSYMS),y)
675 +LD_VMLINUX_KALLSYMS    := $(TMPPREFIX).tmp_kallsyms3.o
676 +else
677 +LD_VMLINUX_KALLSYMS    :=
678 +endif
679 +
680  vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o init/do_mounts.o linuxsubdirs
681 -       $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \
682 -               --start-group \
683 -               $(CORE_FILES) \
684 -               $(DRIVERS) \
685 -               $(NETWORKS) \
686 -               $(LIBS) \
687 -               --end-group \
688 -               -o vmlinux
689 +       @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" kallsyms
690 +
691 +.PHONY:        kallsyms
692 +
693 +kallsyms:
694 +ifeq ($(CONFIG_KALLSYMS),y)
695 +       @echo kallsyms pass 1
696 +       $(LD_VMLINUX) -o $(TMPPREFIX).tmp_vmlinux1
697 +       @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux1 > $(TMPPREFIX).tmp_kallsyms1.o
698 +       @echo kallsyms pass 2
699 +       @$(LD_VMLINUX) $(TMPPREFIX).tmp_kallsyms1.o -o $(TMPPREFIX).tmp_vmlinux2
700 +       @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux2 > $(TMPPREFIX).tmp_kallsyms2.o
701 +       @echo kallsyms pass 3
702 +       @$(LD_VMLINUX) $(TMPPREFIX).tmp_kallsyms2.o -o $(TMPPREFIX).tmp_vmlinux3
703 +       @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux3 > $(TMPPREFIX).tmp_kallsyms3.o
704 +endif
705 +       $(LD_VMLINUX) $(LD_VMLINUX_KALLSYMS) -o $(TMPPREFIX)vmlinux
706 +ifneq ($(TMPPREFIX),)
707 +       mv $(TMPPREFIX)vmlinux vmlinux
708 +endif
709         $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
710 +       @rm -f $(TMPPREFIX).tmp_vmlinux* $(TMPPREFIX).tmp_kallsyms*
711  
712  symlinks:
713         rm -f include/asm