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