ia64/xen-unstable

view xen/common/symbols.c @ 9706:3c05406f5e0a

In some cases, say for instance for some bizzare reason
the tree was checked out of CVS, which doens't neccessarily
store file permissions, mkbuildtree may not be executable.
So run them explicitly via bash.

Signed-Off-By: Horms <horms@verge.net.au>
author kaf24@firebug.cl.cam.ac.uk
date Thu Apr 13 11:24:00 2006 +0100 (2006-04-13)
parents 06d84bf87159
children 34452b288046
line source
1 /*
2 * symbols.c: in-kernel printing of symbolic oopses and stack traces.
3 *
4 * Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
5 *
6 * ChangeLog:
7 *
8 * (25/Aug/2004) Paulo Marques <pmarques@grupopie.com>
9 * Changed the compression method from stem compression to "table lookup"
10 * compression (see tools/symbols.c for a more complete description)
11 */
13 #include <xen/config.h>
14 #include <xen/symbols.h>
15 #include <xen/init.h>
16 #include <xen/lib.h>
17 #include <xen/string.h>
19 /* These will be re-linked against their real values during the second link stage */
20 extern unsigned long symbols_addresses[] __attribute__((weak));
21 extern unsigned long symbols_num_syms __attribute__((weak,section("data")));
22 extern u8 symbols_names[] __attribute__((weak));
24 extern u8 symbols_token_table[] __attribute__((weak));
25 extern u16 symbols_token_index[] __attribute__((weak));
27 extern unsigned long symbols_markers[] __attribute__((weak));
29 /* expand a compressed symbol data into the resulting uncompressed string,
30 given the offset to where the symbol is in the compressed stream */
31 static unsigned int symbols_expand_symbol(unsigned int off, char *result)
32 {
33 int len, skipped_first = 0;
34 u8 *tptr, *data;
36 /* get the compressed symbol length from the first symbol byte */
37 data = &symbols_names[off];
38 len = *data;
39 data++;
41 /* update the offset to return the offset for the next symbol on
42 * the compressed stream */
43 off += len + 1;
45 /* for every byte on the compressed symbol data, copy the table
46 entry for that byte */
47 while(len) {
48 tptr = &symbols_token_table[ symbols_token_index[*data] ];
49 data++;
50 len--;
52 while (*tptr) {
53 if(skipped_first) {
54 *result = *tptr;
55 result++;
56 } else
57 skipped_first = 1;
58 tptr++;
59 }
60 }
62 *result = '\0';
64 /* return to offset to the next symbol */
65 return off;
66 }
68 /* find the offset on the compressed stream given and index in the
69 * symbols array */
70 static unsigned int get_symbol_offset(unsigned long pos)
71 {
72 u8 *name;
73 int i;
75 /* use the closest marker we have. We have markers every 256 positions,
76 * so that should be close enough */
77 name = &symbols_names[ symbols_markers[pos>>8] ];
79 /* sequentially scan all the symbols up to the point we're searching for.
80 * Every symbol is stored in a [<len>][<len> bytes of data] format, so we
81 * just need to add the len to the current pointer for every symbol we
82 * wish to skip */
83 for(i = 0; i < (pos&0xFF); i++)
84 name = name + (*name) + 1;
86 return name - symbols_names;
87 }
89 const char *symbols_lookup(unsigned long addr,
90 unsigned long *symbolsize,
91 unsigned long *offset,
92 char *namebuf)
93 {
94 unsigned long i, low, high, mid;
95 unsigned long symbol_end = 0;
97 /* This kernel should never had been booted. */
98 BUG_ON(!symbols_addresses);
100 namebuf[KSYM_NAME_LEN] = 0;
101 namebuf[0] = 0;
103 if (!is_kernel_text(addr))
104 return NULL;
106 /* do a binary search on the sorted symbols_addresses array */
107 low = 0;
108 high = symbols_num_syms;
110 while (high-low > 1) {
111 mid = (low + high) / 2;
112 if (symbols_addresses[mid] <= addr) low = mid;
113 else high = mid;
114 }
116 /* search for the first aliased symbol. Aliased symbols are
117 symbols with the same address */
118 while (low && symbols_addresses[low - 1] == symbols_addresses[low])
119 --low;
121 /* Grab name */
122 symbols_expand_symbol(get_symbol_offset(low), namebuf);
124 /* Search for next non-aliased symbol */
125 for (i = low + 1; i < symbols_num_syms; i++) {
126 if (symbols_addresses[i] > symbols_addresses[low]) {
127 symbol_end = symbols_addresses[i];
128 break;
129 }
130 }
132 /* if we found no next symbol, we use the end of the section */
133 if (!symbol_end)
134 symbol_end = kernel_text_end();
136 *symbolsize = symbol_end - symbols_addresses[low];
137 *offset = addr - symbols_addresses[low];
138 return namebuf;
139 }
141 /* Replace "%s" in format with address, or returns -errno. */
142 void __print_symbol(const char *fmt, unsigned long address)
143 {
144 const char *name;
145 unsigned long offset, size;
146 char namebuf[KSYM_NAME_LEN+1];
147 char buffer[sizeof("%s+%#lx/%#lx [%s]") + KSYM_NAME_LEN +
148 2*(BITS_PER_LONG*3/10) + 1];
150 name = symbols_lookup(address, &size, &offset, namebuf);
152 if (!name)
153 sprintf(buffer, "???");
154 else
155 sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
157 printk(fmt, buffer);
158 }