]> sourceware.org Git - systemtap.git/blob - runtime/transport/symbols.c
8c453a553bba5be2a1682c953ed989e02a21cc1b
[systemtap.git] / runtime / transport / symbols.c
1 /* -*- linux-c -*-
2 * symbols.c - stp symbol and module functions
3 *
4 * Copyright (C) Red Hat Inc, 2006-2008
5 *
6 * This file is part of systemtap, and is free software. You can
7 * redistribute it and/or modify it under the terms of the GNU General
8 * Public License (GPL); either version 2, or (at your option) any
9 * later version.
10 *
11 * The u32_swap(), generic_swap(), and sort() functions were adapted from
12 * lib/sort.c of kernel 2.6.22-rc5. It was written by Matt Mackall.
13 */
14
15 #ifndef _SYMBOLS_C_
16 #define _SYMBOLS_C_
17 #include "../sym.h"
18
19 static char *_stp_symbol_data = NULL;
20 static int _stp_symbol_state = 0;
21 static char *_stp_module_data = NULL;
22 static int _stp_module_state = 0;
23
24
25 /* these are all the symbol types we are interested in */
26 static int _stp_sym_type_ok(int type)
27 {
28 switch (type) {
29 case 'T':
30 case 't':
31 return 1;
32 default:
33 return 0;
34 }
35 return 0;
36 }
37
38 /* From a module struct, scan the symtab and figure out how much space */
39 /* we need to store all the parts we are interested in */
40 static unsigned _stp_get_sym_sizes(struct module *m, unsigned *dsize)
41 {
42 unsigned int i;
43 unsigned num = 0, datasize = 0;
44 for (i=0; i < m->num_symtab; i++) {
45 char *str = (char *)(m->strtab + m->symtab[i].st_name);
46 if (*str != '\0' && _stp_sym_type_ok(m->symtab[i].st_info)) {
47 datasize += strlen(str)+1;
48 num++;
49 }
50 }
51 *dsize = datasize;
52 return num;
53 }
54
55 /* allocate space for a module and symbols */
56 static struct _stp_module * _stp_alloc_module(unsigned num, unsigned datasize, unsigned unwindsize)
57 {
58 struct _stp_module *mod = (struct _stp_module *)_stp_kzalloc(sizeof(struct _stp_module));
59 if (mod == NULL)
60 goto bad;
61
62 mod->symbols = (struct _stp_symbol *)_stp_kmalloc(num * sizeof(struct _stp_symbol));
63 if (mod->symbols == NULL) {
64 mod->symbols = (struct _stp_symbol *)_stp_vmalloc(num * sizeof(struct _stp_symbol));
65 if (mod->symbols == NULL)
66 goto bad;
67 mod->allocated = 1;
68 }
69
70 mod->symbol_data = _stp_kmalloc(datasize);
71 if (mod->symbol_data == NULL) {
72 mod->symbol_data = _stp_vmalloc(datasize);
73 if (mod->symbol_data == NULL)
74 goto bad;
75 mod->allocated |= 2;
76 }
77
78 mod->unwind_data = _stp_kmalloc(unwindsize);
79 if (mod->unwind_data == NULL) {
80 mod->unwind_data = _stp_vmalloc(unwindsize);
81 if (mod->unwind_data == NULL)
82 goto bad;
83 mod->allocated |= 4;
84 }
85
86 mod->num_symbols = num;
87 return mod;
88
89 bad:
90 if (mod) {
91 if (mod->symbols) {
92 if (mod->allocated & 1)
93 _stp_vfree(mod->symbols);
94 else
95 _stp_kfree(mod->symbols);
96 mod->symbols = NULL;
97 }
98 if (mod->symbol_data) {
99 if (mod->allocated & 2)
100 _stp_vfree(mod->symbol_data);
101 else
102 _stp_kfree(mod->symbol_data);
103 mod->symbol_data = NULL;
104 }
105 _stp_kfree(mod);
106 if (mod->symbols) {
107 if (mod->allocated & 1)
108 _stp_vfree(mod->symbols);
109 else
110 _stp_kfree(mod->symbols);
111 mod->symbols = NULL;
112 }
113 _stp_kfree(mod);
114 }
115 return NULL;
116 }
117
118 static struct _stp_module * _stp_alloc_module_from_module (struct module *m, uint32_t unwind_len)
119 {
120 unsigned datasize, num = _stp_get_sym_sizes(m, &datasize);
121 return _stp_alloc_module(num, datasize, unwind_len);
122 }
123
124 static void _stp_free_module(struct _stp_module *mod)
125 {
126 /* The module write lock is held. Any prior readers of this */
127 /* module's data will have read locks and need to finish before */
128 /* the memory is freed. */
129 write_lock(&mod->lock);
130 write_unlock(&mod->lock); /* there will be no more readers */
131
132 /* free symbol memory */
133 if (mod->symbols) {
134 if (mod->allocated & 1)
135 _stp_vfree(mod->symbols);
136 else
137 _stp_kfree(mod->symbols);
138 mod->symbols = NULL;
139 }
140 if (mod->symbol_data) {
141 if (mod->allocated & 2)
142 _stp_vfree(mod->symbol_data);
143 else
144 _stp_kfree(mod->symbol_data);
145 mod->symbol_data = NULL;
146
147 }
148 if (mod->unwind_data) {
149 if (mod->allocated & 4)
150 _stp_vfree(mod->unwind_data);
151 else
152 _stp_kfree(mod->unwind_data);
153 mod->unwind_data = NULL;
154
155 }
156 if (mod->sections) {
157 _stp_kfree(mod->sections);
158 mod->sections = NULL;
159 }
160
161 /* free module memory */
162 _stp_kfree(mod);
163 }
164
165 /* Delete a module and free its memory. */
166 /* The module lock should already be held before calling this. */
167 static void _stp_del_module(struct _stp_module *mod)
168 {
169 int i, num;
170
171 // kbug(DEBUG_SYMBOLS, "deleting %s\n", mod->name);
172
173 /* signal relocation code to clear its cache */
174 _stp_module_relocate((char *)-1, NULL, 0);
175
176 /* remove module from the arrays */
177 for (num = 0; num < _stp_num_modules; num++) {
178 if (_stp_modules[num] == mod)
179 break;
180 }
181 if (num >= _stp_num_modules)
182 return;
183
184 for (i = num; i < _stp_num_modules-1; i++)
185 _stp_modules[i] = _stp_modules[i+1];
186
187 for (num = 0; num < _stp_num_modules; num++) {
188 if (_stp_modules_by_addr[num] == mod)
189 break;
190 }
191 for (i = num; i < _stp_num_modules-1; i++)
192 _stp_modules_by_addr[i] = _stp_modules_by_addr[i+1];
193
194 _stp_num_modules--;
195
196 _stp_free_module(mod);
197 }
198
199 static void _stp_free_modules(void)
200 {
201 int i;
202 unsigned long flags;
203
204 /* This only happens when the systemtap module unloads */
205 /* so there is no need for locks. */
206 for (i = _stp_num_modules - 1; i >= 0; i--)
207 _stp_del_module(_stp_modules[i]);
208 }
209
210 static unsigned long _stp_kallsyms_lookup_name(const char *name);
211
212 /* process the KERNEL symbols */
213 static int _stp_do_symbols(const char __user *buf, int count)
214 {
215 struct _stp_symbol *s;
216 unsigned datasize, num, unwindsize;
217 int i;
218
219 switch (_stp_symbol_state) {
220 case 0:
221 if (count != sizeof(struct _stp_msg_symbol_hdr)) {
222 errk("count=%d\n", count);
223 return -EFAULT;
224 }
225 if (get_user(num, (unsigned __user *)buf))
226 return -EFAULT;
227 if (get_user(datasize, (unsigned __user *)(buf+4)))
228 return -EFAULT;
229 if (get_user(unwindsize, (unsigned __user *)(buf+8)))
230 return -EFAULT;
231 dbug(DEBUG_UNWIND, "num=%d datasize=%d unwindsize=%d\n", num, datasize, unwindsize);
232
233 _stp_modules[0] = _stp_alloc_module(num, datasize, unwindsize);
234 if (_stp_modules[0] == NULL) {
235 errk("cannot allocate memory\n");
236 return -EFAULT;
237 }
238 rwlock_init(&_stp_modules[0]->lock);
239 _stp_symbol_state = 1;
240 break;
241 case 1:
242 dbug(DEBUG_SYMBOLS, "got stap_symbols, count=%d\n", count);
243 if (copy_from_user ((char *)_stp_modules[0]->symbols, buf, count))
244 return -EFAULT;
245 _stp_symbol_state = 2;
246 break;
247 case 2:
248 dbug(DEBUG_SYMBOLS, "got symbol data, count=%d buf=%p\n", count, buf);
249 if (copy_from_user (_stp_modules[0]->symbol_data, buf, count))
250 return -EFAULT;
251 _stp_num_modules = 1;
252
253 s = _stp_modules[0]->symbols;
254 for (i = 0; i < _stp_modules[0]->num_symbols; i++)
255 s[i].symbol += (long)_stp_modules[0]->symbol_data;
256
257 _stp_symbol_state = 3;
258 /* NB: this mapping is used by kernel/_stext pseudo-relocations. */
259 _stp_modules[0]->text = _stp_kallsyms_lookup_name("_stext");
260 _stp_modules[0]->data = _stp_kallsyms_lookup_name("_etext");
261 _stp_modules[0]->text_size = _stp_modules[0]->data - _stp_modules[0]->text;
262 _stp_modules_by_addr[0] = _stp_modules[0];
263 dbug(DEBUG_SYMBOLS, "Got kernel symbols. text=%p len=%u\n",
264 (int64_t)_stp_modules[0]->text, _stp_modules[0]->text_size);
265 break;
266 case 3:
267 dbug(DEBUG_UNWIND, "got unwind data, count=%d\n", count);
268 _stp_symbol_state = 4;
269 if (copy_from_user (_stp_modules[0]->unwind_data, buf, count)) {
270 _dbug("cfu failed\n");
271 return -EFAULT;
272 }
273 _stp_modules[0]->unwind_data_len = count;
274 break;
275 default:
276 errk("unexpected symbol data of size %d.\n", count);
277 }
278 return count;
279 }
280
281 static int _stp_compare_addr(const void *p1, const void *p2)
282 {
283 struct _stp_symbol *s1 = (struct _stp_symbol *)p1;
284 struct _stp_symbol *s2 = (struct _stp_symbol *)p2;
285 if (s1->addr == s2->addr) return 0;
286 if (s1->addr < s2->addr) return -1;
287 return 1;
288 }
289
290 static void _stp_swap_symbol(void *x, void *y, int size)
291 {
292 struct _stp_symbol *a = (struct _stp_symbol *)x;
293 struct _stp_symbol *b = (struct _stp_symbol *)y;
294 unsigned long addr = a->addr;
295 const char *symbol = a->symbol;
296 a->addr = b->addr;
297 a->symbol = b->symbol;
298 b->addr = addr;
299 b->symbol = symbol;
300 }
301
302 static void u32_swap(void *a, void *b, int size)
303 {
304 u32 t = *(u32 *)a;
305 *(u32 *)a = *(u32 *)b;
306 *(u32 *)b = t;
307 }
308
309 static void generic_swap(void *a, void *b, int size)
310 {
311 do {
312 char t = *(char *)a;
313 *(char *)a++ = *(char *)b;
314 *(char *)b++ = t;
315 } while (--size > 0);
316 }
317
318 /**
319 * sort - sort an array of elements
320 * @base: pointer to data to sort
321 * @num: number of elements
322 * @size: size of each element
323 * @cmp: pointer to comparison function
324 * @swap: pointer to swap function or NULL
325 *
326 * This function does a heapsort on the given array. You may provide a
327 * swap function optimized to your element type.
328 *
329 * Sorting time is O(n log n) both on average and worst-case. While
330 * qsort is about 20% faster on average, it suffers from exploitable
331 * O(n*n) worst-case behavior and extra memory requirements that make
332 * it less suitable for kernel use.
333 */
334 void _stp_sort(void *base, size_t num, size_t size,
335 int (*cmp)(const void *, const void *),
336 void (*swap)(void *, void *, int size))
337 {
338 /* pre-scale counters for performance */
339 int i = (num/2 - 1) * size, n = num * size, c, r;
340
341 if (!swap)
342 swap = (size == 4 ? u32_swap : generic_swap);
343
344 /* heapify */
345 for ( ; i >= 0; i -= size) {
346 for (r = i; r * 2 + size < n; r = c) {
347 c = r * 2 + size;
348 if (c < n - size && cmp(base + c, base + c + size) < 0)
349 c += size;
350 if (cmp(base + r, base + c) >= 0)
351 break;
352 swap(base + r, base + c, size);
353 }
354 }
355
356 /* sort */
357 for (i = n - size; i >= 0; i -= size) {
358 swap(base, base + i, size);
359 for (r = 0; r * 2 + size < i; r = c) {
360 c = r * 2 + size;
361 if (c < i - size && cmp(base + c, base + c + size) < 0)
362 c += size;
363 if (cmp(base + r, base + c) >= 0)
364 break;
365 swap(base + r, base + c, size);
366 }
367 }
368 }
369
370 /* Create a new _stp_module and load the symbols */
371 static struct _stp_module *_stp_load_module_symbols (struct _stp_module *imod, uint32_t unwind_len)
372 {
373 unsigned i, num=0;
374 struct module *m = (struct module *)imod->module;
375 struct _stp_module *mod = NULL;
376 char *dataptr;
377
378 if (m == NULL) {
379 kbug(DEBUG_SYMBOLS, "imod->module is NULL\n");
380 return NULL;
381 }
382 if (try_module_get(m)) {
383
384 mod = _stp_alloc_module_from_module(m, unwind_len);
385 if (mod == NULL) {
386 module_put(m);
387 errk("failed to allocate memory for module.\n");
388 return NULL;
389 }
390
391 strlcpy(mod->name, imod->name, STP_MODULE_NAME_LEN);
392 mod->module = imod->module;
393 mod->text = imod->text;
394 mod->data = imod->data;
395 mod->num_sections = imod->num_sections;
396 mod->sections = imod->sections;
397 mod->text_size = m->core_text_size;
398 rwlock_init(&mod->lock);
399
400 /* now copy all the symbols we are interested in */
401 dataptr = mod->symbol_data;
402 for (i=0; i < m->num_symtab; i++) {
403 char *str = (char *)(m->strtab + m->symtab[i].st_name);
404 if (*str != '\0' && _stp_sym_type_ok(m->symtab[i].st_info)) {
405 mod->symbols[num].symbol = dataptr;
406 mod->symbols[num].addr = m->symtab[i].st_value;
407 while (*str) *dataptr++ = *str++;
408 *dataptr++ = 0;
409 num++;
410 }
411 }
412 module_put(m);
413
414 /* sort symbols by address */
415 _stp_sort (mod->symbols, num, sizeof(struct _stp_symbol), _stp_compare_addr, _stp_swap_symbol);
416 }
417 return mod;
418 }
419
420 /* Remove any old module info from our database */
421 static void _stp_module_exists_delete (struct _stp_module *mod)
422 {
423 int i, num;
424
425 /* remove any old modules with the same name */
426 for (num = 1; num < _stp_num_modules; num++) {
427 if (strcmp(_stp_modules[num]->name, mod->name) == 0) {
428 dbug(DEBUG_SYMBOLS, "found existing module with name %s. Deleting.\n", mod->name);
429 _stp_del_module(_stp_modules[num]);
430 break;
431 }
432 }
433
434 /* remove modules with overlapping addresses */
435 for (num = 1; num < _stp_num_modules; num++) {
436 if (mod->text + mod->text_size < _stp_modules_by_addr[num]->text)
437 continue;
438 if (mod->text < _stp_modules_by_addr[num]->text
439 + _stp_modules_by_addr[num]->text_size) {
440 dbug(DEBUG_SYMBOLS, "New module %s overlaps with old module %s. Deleting old.\n",
441 mod->name, _stp_modules_by_addr[num]->name);
442 _stp_del_module(_stp_modules_by_addr[num]);
443 }
444 }
445
446 }
447
448 static int _stp_ins_module(struct _stp_module *mod)
449 {
450 int i, num, res, ret = 0;
451 unsigned long flags;
452
453 // kbug(DEBUG_SYMBOLS, "insert %s\n", mod->name);
454
455 STP_WLOCK_MODULES;
456
457 _stp_module_exists_delete(mod);
458
459 /* check for overflow */
460 if (_stp_num_modules == STP_MAX_MODULES) {
461 errk("Exceeded the limit of %d modules\n", STP_MAX_MODULES);
462 ret = -ENOMEM;
463 goto done;
464 }
465
466 /* insert alphabetically in _stp_modules[] */
467 for (num = 1; num < _stp_num_modules; num++)
468 if (strcmp(_stp_modules[num]->name, mod->name) > 0)
469 break;
470 for (i = _stp_num_modules; i > num; i--)
471 _stp_modules[i] = _stp_modules[i-1];
472 _stp_modules[num] = mod;
473
474 /* insert by text address in _stp_modules_by_addr[] */
475 for (num = 1; num < _stp_num_modules; num++)
476 if (mod->text < _stp_modules_by_addr[num]->text)
477 break;
478 for (i = _stp_num_modules; i > num; i--)
479 _stp_modules_by_addr[i] = _stp_modules_by_addr[i-1];
480 _stp_modules_by_addr[num] = mod;
481
482 _stp_num_modules++;
483
484 done:
485 STP_WUNLOCK_MODULES;
486 return ret;
487 }
488
489
490 /* Called from procfs.c when a STP_MODULE msg is received */
491 static int _stp_do_module(const char __user *buf, int count)
492 {
493 struct _stp_msg_module tmpmod;
494 struct _stp_module mod, *m;
495 unsigned i, section_len;
496
497 if (count < (int)sizeof(tmpmod)) {
498 errk("expected %d and got %d\n", (int)sizeof(tmpmod), count);
499 return -EFAULT;
500 }
501 if (copy_from_user ((char *)&tmpmod, buf, sizeof(tmpmod)))
502 return -EFAULT;
503
504 section_len = count - sizeof(tmpmod) - tmpmod.unwind_len;
505 if (section_len <= 0) {
506 errk("section_len = %d\n", section_len);
507 return -EFAULT;
508 }
509 dbug(DEBUG_SYMBOLS, "Got module %s, count=%d section_len=%d unwind_len=%d\n",
510 tmpmod.name, count, section_len, tmpmod.unwind_len);
511
512 strcpy(mod.name, tmpmod.name);
513 mod.module = tmpmod.module;
514 mod.text = tmpmod.text;
515 mod.data = tmpmod.data;
516 mod.num_sections = tmpmod.num_sections;
517
518 /* copy in section data */
519 mod.sections = _stp_kmalloc(section_len);
520 if (mod.sections == NULL) {
521 errk("unable to allocate memory.\n");
522 return -EFAULT;
523 }
524 if (copy_from_user ((char *)mod.sections, buf+sizeof(tmpmod), section_len)) {
525 _stp_kfree(mod.sections);
526 return -EFAULT;
527 }
528 for (i = 0; i < mod.num_sections; i++) {
529 mod.sections[i].symbol =
530 (char *)((long)mod.sections[i].symbol
531 + (long)((long)mod.sections + mod.num_sections * sizeof(struct _stp_symbol)));
532 }
533
534 #if 0
535 for (i = 0; i < mod.num_sections; i++)
536 _dbug("section %d (stored at %p): %s %lx\n", i, &mod.sections[i], mod.sections[i].symbol, mod.sections[i].addr);
537 #endif
538
539 /* load symbols from tmpmod.module to mod */
540 m = _stp_load_module_symbols(&mod, tmpmod.unwind_len);
541 if (m == NULL) {
542 _stp_kfree(mod.sections);
543 return 0;
544 }
545
546 dbug(DEBUG_SYMBOLS, "module %s loaded. Text=%p text_size=%u\n", m->name, (int64_t)m->text, m->text_size);
547 /* finally copy unwind info */
548 if (copy_from_user (m->unwind_data, buf+sizeof(tmpmod)+section_len, tmpmod.unwind_len)) {
549 _stp_free_module(m);
550 _stp_kfree(mod.sections);
551 return -EFAULT;
552 }
553 m->unwind_data_len = tmpmod.unwind_len;
554
555 if (_stp_ins_module(m) < 0) {
556 _stp_free_module(m);
557 return -ENOMEM;
558 }
559
560 return count;
561 }
562
563 static int _stp_ctl_send (int type, void *data, int len);
564
565 static int _stp_module_load_notify(struct notifier_block * self, unsigned long val, void * data)
566 {
567 struct module *mod = (struct module *)data;
568 struct _stp_module rmod;
569
570 switch (val) {
571 case MODULE_STATE_COMING:
572 dbug(DEBUG_SYMBOLS, "module %s load notify\n", mod->name);
573 strlcpy(rmod.name, mod->name, STP_MODULE_NAME_LEN);
574 _stp_ctl_send(STP_MODULE, &rmod, sizeof(struct _stp_module));
575 break;
576 default:
577 errk("module loaded? val=%ld\n", val);
578 }
579 return 0;
580 }
581
582 static struct notifier_block _stp_module_load_nb = {
583 .notifier_call = _stp_module_load_notify,
584 };
585
586 #endif /* _SYMBOLS_C_ */
This page took 0.0631 seconds and 4 git commands to generate.