ia64/xen-unstable

view xen/common/symbols.c @ 17062:0769835cf50f

x86 shadow: Reduce scope of shadow lock.

emulate_map_dest doesn't require holding lock, since
only shadow related operation possibly involved is to
remove shadow which is less frequent and can acquire
lock inside. Rest are either guest table walk or
per-vcpu monitor table manipulation

Signed-off-by Kevin Tian <kevin.tian@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Feb 14 10:33:12 2008 +0000 (2008-02-14)
parents 3a0b808d917a
children
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/kernel.h>
16 #include <xen/init.h>
17 #include <xen/lib.h>
18 #include <xen/string.h>
19 #include <xen/spinlock.h>
21 extern unsigned long symbols_addresses[];
22 extern unsigned long symbols_num_syms;
23 extern u8 symbols_names[];
25 extern u8 symbols_token_table[];
26 extern u16 symbols_token_index[];
28 extern unsigned long symbols_markers[];
30 /* expand a compressed symbol data into the resulting uncompressed string,
31 given the offset to where the symbol is in the compressed stream */
32 static unsigned int symbols_expand_symbol(unsigned int off, char *result)
33 {
34 int len, skipped_first = 0;
35 u8 *tptr, *data;
37 /* get the compressed symbol length from the first symbol byte */
38 data = &symbols_names[off];
39 len = *data;
40 data++;
42 /* update the offset to return the offset for the next symbol on
43 * the compressed stream */
44 off += len + 1;
46 /* for every byte on the compressed symbol data, copy the table
47 entry for that byte */
48 while(len) {
49 tptr = &symbols_token_table[ symbols_token_index[*data] ];
50 data++;
51 len--;
53 while (*tptr) {
54 if(skipped_first) {
55 *result = *tptr;
56 result++;
57 } else
58 skipped_first = 1;
59 tptr++;
60 }
61 }
63 *result = '\0';
65 /* return to offset to the next symbol */
66 return off;
67 }
69 /* find the offset on the compressed stream given and index in the
70 * symbols array */
71 static unsigned int get_symbol_offset(unsigned long pos)
72 {
73 u8 *name;
74 int i;
76 /* use the closest marker we have. We have markers every 256 positions,
77 * so that should be close enough */
78 name = &symbols_names[ symbols_markers[pos>>8] ];
80 /* sequentially scan all the symbols up to the point we're searching for.
81 * Every symbol is stored in a [<len>][<len> bytes of data] format, so we
82 * just need to add the len to the current pointer for every symbol we
83 * wish to skip */
84 for(i = 0; i < (pos&0xFF); i++)
85 name = name + (*name) + 1;
87 return name - symbols_names;
88 }
90 const char *symbols_lookup(unsigned long addr,
91 unsigned long *symbolsize,
92 unsigned long *offset,
93 char *namebuf)
94 {
95 unsigned long i, low, high, mid;
96 unsigned long symbol_end = 0;
98 namebuf[KSYM_NAME_LEN] = 0;
99 namebuf[0] = 0;
101 if (!is_kernel_text(addr) && !is_kernel_inittext(addr))
102 return NULL;
104 /* do a binary search on the sorted symbols_addresses array */
105 low = 0;
106 high = symbols_num_syms;
108 while (high-low > 1) {
109 mid = (low + high) / 2;
110 if (symbols_addresses[mid] <= addr) low = mid;
111 else high = mid;
112 }
114 /* search for the first aliased symbol. Aliased symbols are
115 symbols with the same address */
116 while (low && symbols_addresses[low - 1] == symbols_addresses[low])
117 --low;
119 /* Grab name */
120 symbols_expand_symbol(get_symbol_offset(low), namebuf);
122 /* Search for next non-aliased symbol */
123 for (i = low + 1; i < symbols_num_syms; i++) {
124 if (symbols_addresses[i] > symbols_addresses[low]) {
125 symbol_end = symbols_addresses[i];
126 break;
127 }
128 }
130 /* if we found no next symbol, we use the end of the section */
131 if (!symbol_end)
132 symbol_end = is_kernel_inittext(addr) ?
133 (unsigned long)_einittext : (unsigned long)_etext;
135 *symbolsize = symbol_end - symbols_addresses[low];
136 *offset = addr - symbols_addresses[low];
137 return namebuf;
138 }
140 /* Replace "%s" in format with address, or returns -errno. */
141 void __print_symbol(const char *fmt, unsigned long address)
142 {
143 const char *name;
144 unsigned long offset, size, flags;
146 static DEFINE_SPINLOCK(lock);
147 static char namebuf[KSYM_NAME_LEN+1];
148 #define BUFFER_SIZE sizeof("%s+%#lx/%#lx [%s]") + KSYM_NAME_LEN + \
149 2*(BITS_PER_LONG*3/10) + 1
150 static char buffer[BUFFER_SIZE];
152 spin_lock_irqsave(&lock, flags);
154 name = symbols_lookup(address, &size, &offset, namebuf);
156 if (!name)
157 snprintf(buffer, BUFFER_SIZE, "???");
158 else
159 snprintf(buffer, BUFFER_SIZE, "%s+%#lx/%#lx", name, offset, size);
161 printk(fmt, buffer);
163 spin_unlock_irqrestore(&lock, flags);
164 }