drm/radeon/kms: vram sizing on certain r100 chips needs workaround.
[linux-2.6.git] / kernel / kallsyms.c
1 /*
2  * kallsyms.c: in-kernel printing of symbolic oopses and stack traces.
3  *
4  * Rewritten and vastly simplified by Rusty Russell for in-kernel
5  * module loader:
6  *   Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
7  *
8  * ChangeLog:
9  *
10  * (25/Aug/2004) Paulo Marques <pmarques@grupopie.com>
11  *      Changed the compression method from stem compression to "table lookup"
12  *      compression (see scripts/kallsyms.c for a more complete description)
13  */
14 #include <linux/kallsyms.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/seq_file.h>
18 #include <linux/fs.h>
19 #include <linux/err.h>
20 #include <linux/proc_fs.h>
21 #include <linux/sched.h>        /* for cond_resched */
22 #include <linux/mm.h>
23 #include <linux/ctype.h>
24
25 #include <asm/sections.h>
26
27 #ifdef CONFIG_KALLSYMS_ALL
28 #define all_var 1
29 #else
30 #define all_var 0
31 #endif
32
33 /*
34  * These will be re-linked against their real values
35  * during the second link stage.
36  */
37 extern const unsigned long kallsyms_addresses[] __attribute__((weak));
38 extern const u8 kallsyms_names[] __attribute__((weak));
39
40 /*
41  * Tell the compiler that the count isn't in the small data section if the arch
42  * has one (eg: FRV).
43  */
44 extern const unsigned long kallsyms_num_syms
45 __attribute__((weak, section(".rodata")));
46
47 extern const u8 kallsyms_token_table[] __attribute__((weak));
48 extern const u16 kallsyms_token_index[] __attribute__((weak));
49
50 extern const unsigned long kallsyms_markers[] __attribute__((weak));
51
52 static inline int is_kernel_inittext(unsigned long addr)
53 {
54         if (addr >= (unsigned long)_sinittext
55             && addr <= (unsigned long)_einittext)
56                 return 1;
57         return 0;
58 }
59
60 static inline int is_kernel_text(unsigned long addr)
61 {
62         if (addr >= (unsigned long)_stext && addr <= (unsigned long)_etext)
63                 return 1;
64         return in_gate_area_no_task(addr);
65 }
66
67 static inline int is_kernel(unsigned long addr)
68 {
69         if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end)
70                 return 1;
71         return in_gate_area_no_task(addr);
72 }
73
74 static int is_ksym_addr(unsigned long addr)
75 {
76         if (all_var)
77                 return is_kernel(addr);
78
79         return is_kernel_text(addr) || is_kernel_inittext(addr);
80 }
81
82 /*
83  * Expand a compressed symbol data into the resulting uncompressed string,
84  * given the offset to where the symbol is in the compressed stream.
85  */
86 static unsigned int kallsyms_expand_symbol(unsigned int off, char *result)
87 {
88         int len, skipped_first = 0;
89         const u8 *tptr, *data;
90
91         /* Get the compressed symbol length from the first symbol byte. */
92         data = &kallsyms_names[off];
93         len = *data;
94         data++;
95
96         /*
97          * Update the offset to return the offset for the next symbol on
98          * the compressed stream.
99          */
100         off += len + 1;
101
102         /*
103          * For every byte on the compressed symbol data, copy the table
104          * entry for that byte.
105          */
106         while (len) {
107                 tptr = &kallsyms_token_table[kallsyms_token_index[*data]];
108                 data++;
109                 len--;
110
111                 while (*tptr) {
112                         if (skipped_first) {
113                                 *result = *tptr;
114                                 result++;
115                         } else
116                                 skipped_first = 1;
117                         tptr++;
118                 }
119         }
120
121         *result = '\0';
122
123         /* Return to offset to the next symbol. */
124         return off;
125 }
126
127 /*
128  * Get symbol type information. This is encoded as a single char at the
129  * beginning of the symbol name.
130  */
131 static char kallsyms_get_symbol_type(unsigned int off)
132 {
133         /*
134          * Get just the first code, look it up in the token table,
135          * and return the first char from this token.
136          */
137         return kallsyms_token_table[kallsyms_token_index[kallsyms_names[off + 1]]];
138 }
139
140
141 /*
142  * Find the offset on the compressed stream given and index in the
143  * kallsyms array.
144  */
145 static unsigned int get_symbol_offset(unsigned long pos)
146 {
147         const u8 *name;
148         int i;
149
150         /*
151          * Use the closest marker we have. We have markers every 256 positions,
152          * so that should be close enough.
153          */
154         name = &kallsyms_names[kallsyms_markers[pos >> 8]];
155
156         /*
157          * Sequentially scan all the symbols up to the point we're searching
158          * for. Every symbol is stored in a [<len>][<len> bytes of data] format,
159          * so we just need to add the len to the current pointer for every
160          * symbol we wish to skip.
161          */
162         for (i = 0; i < (pos & 0xFF); i++)
163                 name = name + (*name) + 1;
164
165         return name - kallsyms_names;
166 }
167
168 /* Lookup the address for this symbol. Returns 0 if not found. */
169 unsigned long kallsyms_lookup_name(const char *name)
170 {
171         char namebuf[KSYM_NAME_LEN];
172         unsigned long i;
173         unsigned int off;
174
175         for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
176                 off = kallsyms_expand_symbol(off, namebuf);
177
178                 if (strcmp(namebuf, name) == 0)
179                         return kallsyms_addresses[i];
180         }
181         return module_kallsyms_lookup_name(name);
182 }
183
184 int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
185                                       unsigned long),
186                             void *data)
187 {
188         char namebuf[KSYM_NAME_LEN];
189         unsigned long i;
190         unsigned int off;
191         int ret;
192
193         for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
194                 off = kallsyms_expand_symbol(off, namebuf);
195                 ret = fn(data, namebuf, NULL, kallsyms_addresses[i]);
196                 if (ret != 0)
197                         return ret;
198         }
199         return module_kallsyms_on_each_symbol(fn, data);
200 }
201 EXPORT_SYMBOL_GPL(kallsyms_on_each_symbol);
202
203 static unsigned long get_symbol_pos(unsigned long addr,
204                                     unsigned long *symbolsize,
205                                     unsigned long *offset)
206 {
207         unsigned long symbol_start = 0, symbol_end = 0;
208         unsigned long i, low, high, mid;
209
210         /* This kernel should never had been booted. */
211         BUG_ON(!kallsyms_addresses);
212
213         /* Do a binary search on the sorted kallsyms_addresses array. */
214         low = 0;
215         high = kallsyms_num_syms;
216
217         while (high - low > 1) {
218                 mid = low + (high - low) / 2;
219                 if (kallsyms_addresses[mid] <= addr)
220                         low = mid;
221                 else
222                         high = mid;
223         }
224
225         /*
226          * Search for the first aliased symbol. Aliased
227          * symbols are symbols with the same address.
228          */
229         while (low && kallsyms_addresses[low-1] == kallsyms_addresses[low])
230                 --low;
231
232         symbol_start = kallsyms_addresses[low];
233
234         /* Search for next non-aliased symbol. */
235         for (i = low + 1; i < kallsyms_num_syms; i++) {
236                 if (kallsyms_addresses[i] > symbol_start) {
237                         symbol_end = kallsyms_addresses[i];
238                         break;
239                 }
240         }
241
242         /* If we found no next symbol, we use the end of the section. */
243         if (!symbol_end) {
244                 if (is_kernel_inittext(addr))
245                         symbol_end = (unsigned long)_einittext;
246                 else if (all_var)
247                         symbol_end = (unsigned long)_end;
248                 else
249                         symbol_end = (unsigned long)_etext;
250         }
251
252         if (symbolsize)
253                 *symbolsize = symbol_end - symbol_start;
254         if (offset)
255                 *offset = addr - symbol_start;
256
257         return low;
258 }
259
260 /*
261  * Lookup an address but don't bother to find any names.
262  */
263 int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
264                                 unsigned long *offset)
265 {
266         char namebuf[KSYM_NAME_LEN];
267         if (is_ksym_addr(addr))
268                 return !!get_symbol_pos(addr, symbolsize, offset);
269
270         return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf);
271 }
272
273 /*
274  * Lookup an address
275  * - modname is set to NULL if it's in the kernel.
276  * - We guarantee that the returned name is valid until we reschedule even if.
277  *   It resides in a module.
278  * - We also guarantee that modname will be valid until rescheduled.
279  */
280 const char *kallsyms_lookup(unsigned long addr,
281                             unsigned long *symbolsize,
282                             unsigned long *offset,
283                             char **modname, char *namebuf)
284 {
285         namebuf[KSYM_NAME_LEN - 1] = 0;
286         namebuf[0] = 0;
287
288         if (is_ksym_addr(addr)) {
289                 unsigned long pos;
290
291                 pos = get_symbol_pos(addr, symbolsize, offset);
292                 /* Grab name */
293                 kallsyms_expand_symbol(get_symbol_offset(pos), namebuf);
294                 if (modname)
295                         *modname = NULL;
296                 return namebuf;
297         }
298
299         /* See if it's in a module. */
300         return module_address_lookup(addr, symbolsize, offset, modname,
301                                      namebuf);
302 }
303
304 int lookup_symbol_name(unsigned long addr, char *symname)
305 {
306         symname[0] = '\0';
307         symname[KSYM_NAME_LEN - 1] = '\0';
308
309         if (is_ksym_addr(addr)) {
310                 unsigned long pos;
311
312                 pos = get_symbol_pos(addr, NULL, NULL);
313                 /* Grab name */
314                 kallsyms_expand_symbol(get_symbol_offset(pos), symname);
315                 return 0;
316         }
317         /* See if it's in a module. */
318         return lookup_module_symbol_name(addr, symname);
319 }
320
321 int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
322                         unsigned long *offset, char *modname, char *name)
323 {
324         name[0] = '\0';
325         name[KSYM_NAME_LEN - 1] = '\0';
326
327         if (is_ksym_addr(addr)) {
328                 unsigned long pos;
329
330                 pos = get_symbol_pos(addr, size, offset);
331                 /* Grab name */
332                 kallsyms_expand_symbol(get_symbol_offset(pos), name);
333                 modname[0] = '\0';
334                 return 0;
335         }
336         /* See if it's in a module. */
337         return lookup_module_symbol_attrs(addr, size, offset, modname, name);
338 }
339
340 /* Look up a kernel symbol and return it in a text buffer. */
341 int sprint_symbol(char *buffer, unsigned long address)
342 {
343         char *modname;
344         const char *name;
345         unsigned long offset, size;
346         int len;
347
348         name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
349         if (!name)
350                 return sprintf(buffer, "0x%lx", address);
351
352         if (name != buffer)
353                 strcpy(buffer, name);
354         len = strlen(buffer);
355         buffer += len;
356
357         if (modname)
358                 len += sprintf(buffer, "+%#lx/%#lx [%s]",
359                                                 offset, size, modname);
360         else
361                 len += sprintf(buffer, "+%#lx/%#lx", offset, size);
362
363         return len;
364 }
365 EXPORT_SYMBOL_GPL(sprint_symbol);
366
367 /* Look up a kernel symbol and print it to the kernel messages. */
368 void __print_symbol(const char *fmt, unsigned long address)
369 {
370         char buffer[KSYM_SYMBOL_LEN];
371
372         sprint_symbol(buffer, address);
373
374         printk(fmt, buffer);
375 }
376 EXPORT_SYMBOL(__print_symbol);
377
378 /* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
379 struct kallsym_iter {
380         loff_t pos;
381         unsigned long value;
382         unsigned int nameoff; /* If iterating in core kernel symbols. */
383         char type;
384         char name[KSYM_NAME_LEN];
385         char module_name[MODULE_NAME_LEN];
386         int exported;
387 };
388
389 static int get_ksymbol_mod(struct kallsym_iter *iter)
390 {
391         if (module_get_kallsym(iter->pos - kallsyms_num_syms, &iter->value,
392                                 &iter->type, iter->name, iter->module_name,
393                                 &iter->exported) < 0)
394                 return 0;
395         return 1;
396 }
397
398 /* Returns space to next name. */
399 static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
400 {
401         unsigned off = iter->nameoff;
402
403         iter->module_name[0] = '\0';
404         iter->value = kallsyms_addresses[iter->pos];
405
406         iter->type = kallsyms_get_symbol_type(off);
407
408         off = kallsyms_expand_symbol(off, iter->name);
409
410         return off - iter->nameoff;
411 }
412
413 static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
414 {
415         iter->name[0] = '\0';
416         iter->nameoff = get_symbol_offset(new_pos);
417         iter->pos = new_pos;
418 }
419
420 /* Returns false if pos at or past end of file. */
421 static int update_iter(struct kallsym_iter *iter, loff_t pos)
422 {
423         /* Module symbols can be accessed randomly. */
424         if (pos >= kallsyms_num_syms) {
425                 iter->pos = pos;
426                 return get_ksymbol_mod(iter);
427         }
428
429         /* If we're not on the desired position, reset to new position. */
430         if (pos != iter->pos)
431                 reset_iter(iter, pos);
432
433         iter->nameoff += get_ksymbol_core(iter);
434         iter->pos++;
435
436         return 1;
437 }
438
439 static void *s_next(struct seq_file *m, void *p, loff_t *pos)
440 {
441         (*pos)++;
442
443         if (!update_iter(m->private, *pos))
444                 return NULL;
445         return p;
446 }
447
448 static void *s_start(struct seq_file *m, loff_t *pos)
449 {
450         if (!update_iter(m->private, *pos))
451                 return NULL;
452         return m->private;
453 }
454
455 static void s_stop(struct seq_file *m, void *p)
456 {
457 }
458
459 static int s_show(struct seq_file *m, void *p)
460 {
461         struct kallsym_iter *iter = m->private;
462
463         /* Some debugging symbols have no name.  Ignore them. */
464         if (!iter->name[0])
465                 return 0;
466
467         if (iter->module_name[0]) {
468                 char type;
469
470                 /*
471                  * Label it "global" if it is exported,
472                  * "local" if not exported.
473                  */
474                 type = iter->exported ? toupper(iter->type) :
475                                         tolower(iter->type);
476                 seq_printf(m, "%0*lx %c %s\t[%s]\n",
477                            (int)(2 * sizeof(void *)),
478                            iter->value, type, iter->name, iter->module_name);
479         } else
480                 seq_printf(m, "%0*lx %c %s\n",
481                            (int)(2 * sizeof(void *)),
482                            iter->value, iter->type, iter->name);
483         return 0;
484 }
485
486 static const struct seq_operations kallsyms_op = {
487         .start = s_start,
488         .next = s_next,
489         .stop = s_stop,
490         .show = s_show
491 };
492
493 static int kallsyms_open(struct inode *inode, struct file *file)
494 {
495         /*
496          * We keep iterator in m->private, since normal case is to
497          * s_start from where we left off, so we avoid doing
498          * using get_symbol_offset for every symbol.
499          */
500         struct kallsym_iter *iter;
501         int ret;
502
503         iter = kmalloc(sizeof(*iter), GFP_KERNEL);
504         if (!iter)
505                 return -ENOMEM;
506         reset_iter(iter, 0);
507
508         ret = seq_open(file, &kallsyms_op);
509         if (ret == 0)
510                 ((struct seq_file *)file->private_data)->private = iter;
511         else
512                 kfree(iter);
513         return ret;
514 }
515
516 static const struct file_operations kallsyms_operations = {
517         .open = kallsyms_open,
518         .read = seq_read,
519         .llseek = seq_lseek,
520         .release = seq_release_private,
521 };
522
523 static int __init kallsyms_init(void)
524 {
525         proc_create("kallsyms", 0444, NULL, &kallsyms_operations);
526         return 0;
527 }
528 device_initcall(kallsyms_init);