1#include <dirent.h>
2#include <errno.h>
3#include <stdlib.h>
4#include <stdio.h>
5#include <string.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <sys/param.h>
9#include <fcntl.h>
10#include <unistd.h>
11#include <inttypes.h>
12#include "build-id.h"
13#include "util.h"
14#include "debug.h"
15#include "machine.h"
16#include "symbol.h"
17#include "strlist.h"
18
19#include <elf.h>
20#include <limits.h>
21#include <sys/utsname.h>
22
23#ifndef KSYM_NAME_LEN
24#define KSYM_NAME_LEN 256
25#endif
26
27static int dso__load_kernel_sym(struct dso *dso, struct map *map,
28 symbol_filter_t filter);
29static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
30 symbol_filter_t filter);
31int vmlinux_path__nr_entries;
32char **vmlinux_path;
33
34struct symbol_conf symbol_conf = {
35 .use_modules = true,
36 .try_vmlinux_path = true,
37 .annotate_src = true,
38 .demangle = true,
39 .symfs = "",
40};
41
42static enum dso_binary_type binary_type_symtab[] = {
43 DSO_BINARY_TYPE__KALLSYMS,
44 DSO_BINARY_TYPE__GUEST_KALLSYMS,
45 DSO_BINARY_TYPE__JAVA_JIT,
46 DSO_BINARY_TYPE__DEBUGLINK,
47 DSO_BINARY_TYPE__BUILD_ID_CACHE,
48 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
49 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
50 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
51 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
52 DSO_BINARY_TYPE__GUEST_KMODULE,
53 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
54 DSO_BINARY_TYPE__NOT_FOUND,
55};
56
57#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab)
58
59bool symbol_type__is_a(char symbol_type, enum map_type map_type)
60{
61 symbol_type = toupper(symbol_type);
62
63 switch (map_type) {
64 case MAP__FUNCTION:
65 return symbol_type == 'T' || symbol_type == 'W';
66 case MAP__VARIABLE:
67 return symbol_type == 'D';
68 default:
69 return false;
70 }
71}
72
73static int prefix_underscores_count(const char *str)
74{
75 const char *tail = str;
76
77 while (*tail == '_')
78 tail++;
79
80 return tail - str;
81}
82
83#define SYMBOL_A 0
84#define SYMBOL_B 1
85
86static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
87{
88 s64 a;
89 s64 b;
90
91
92 a = syma->end - syma->start;
93 b = symb->end - symb->start;
94 if ((b == 0) && (a > 0))
95 return SYMBOL_A;
96 else if ((a == 0) && (b > 0))
97 return SYMBOL_B;
98
99
100 a = syma->binding == STB_WEAK;
101 b = symb->binding == STB_WEAK;
102 if (b && !a)
103 return SYMBOL_A;
104 if (a && !b)
105 return SYMBOL_B;
106
107
108 a = syma->binding == STB_GLOBAL;
109 b = symb->binding == STB_GLOBAL;
110 if (a && !b)
111 return SYMBOL_A;
112 if (b && !a)
113 return SYMBOL_B;
114
115
116 a = prefix_underscores_count(syma->name);
117 b = prefix_underscores_count(symb->name);
118 if (b > a)
119 return SYMBOL_A;
120 else if (a > b)
121 return SYMBOL_B;
122
123
124 if (strlen(syma->name) >= strlen(symb->name))
125 return SYMBOL_A;
126 else
127 return SYMBOL_B;
128}
129
130void symbols__fixup_duplicate(struct rb_root *symbols)
131{
132 struct rb_node *nd;
133 struct symbol *curr, *next;
134
135 nd = rb_first(symbols);
136
137 while (nd) {
138 curr = rb_entry(nd, struct symbol, rb_node);
139again:
140 nd = rb_next(&curr->rb_node);
141 next = rb_entry(nd, struct symbol, rb_node);
142
143 if (!nd)
144 break;
145
146 if (curr->start != next->start)
147 continue;
148
149 if (choose_best_symbol(curr, next) == SYMBOL_A) {
150 rb_erase(&next->rb_node, symbols);
151 goto again;
152 } else {
153 nd = rb_next(&curr->rb_node);
154 rb_erase(&curr->rb_node, symbols);
155 }
156 }
157}
158
159void symbols__fixup_end(struct rb_root *symbols)
160{
161 struct rb_node *nd, *prevnd = rb_first(symbols);
162 struct symbol *curr, *prev;
163
164 if (prevnd == NULL)
165 return;
166
167 curr = rb_entry(prevnd, struct symbol, rb_node);
168
169 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
170 prev = curr;
171 curr = rb_entry(nd, struct symbol, rb_node);
172
173 if (prev->end == prev->start && prev->end != curr->start)
174 prev->end = curr->start - 1;
175 }
176
177
178 if (curr->end == curr->start)
179 curr->end = roundup(curr->start, 4096);
180}
181
182void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
183{
184 struct map *prev, *curr;
185 struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]);
186
187 if (prevnd == NULL)
188 return;
189
190 curr = rb_entry(prevnd, struct map, rb_node);
191
192 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
193 prev = curr;
194 curr = rb_entry(nd, struct map, rb_node);
195 prev->end = curr->start - 1;
196 }
197
198
199
200
201
202 curr->end = ~0ULL;
203}
204
205struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
206{
207 size_t namelen = strlen(name) + 1;
208 struct symbol *sym = calloc(1, (symbol_conf.priv_size +
209 sizeof(*sym) + namelen));
210 if (sym == NULL)
211 return NULL;
212
213 if (symbol_conf.priv_size)
214 sym = ((void *)sym) + symbol_conf.priv_size;
215
216 sym->start = start;
217 sym->end = len ? start + len - 1 : start;
218 sym->binding = binding;
219 sym->namelen = namelen - 1;
220
221 pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n",
222 __func__, name, start, sym->end);
223 memcpy(sym->name, name, namelen);
224
225 return sym;
226}
227
228void symbol__delete(struct symbol *sym)
229{
230 free(((void *)sym) - symbol_conf.priv_size);
231}
232
233size_t symbol__fprintf(struct symbol *sym, FILE *fp)
234{
235 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n",
236 sym->start, sym->end,
237 sym->binding == STB_GLOBAL ? 'g' :
238 sym->binding == STB_LOCAL ? 'l' : 'w',
239 sym->name);
240}
241
242size_t symbol__fprintf_symname_offs(const struct symbol *sym,
243 const struct addr_location *al, FILE *fp)
244{
245 unsigned long offset;
246 size_t length;
247
248 if (sym && sym->name) {
249 length = fprintf(fp, "%s", sym->name);
250 if (al) {
251 offset = al->addr - sym->start;
252 length += fprintf(fp, "+0x%lx", offset);
253 }
254 return length;
255 } else
256 return fprintf(fp, "[unknown]");
257}
258
259size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp)
260{
261 return symbol__fprintf_symname_offs(sym, NULL, fp);
262}
263
264void symbols__delete(struct rb_root *symbols)
265{
266 struct symbol *pos;
267 struct rb_node *next = rb_first(symbols);
268
269 while (next) {
270 pos = rb_entry(next, struct symbol, rb_node);
271 next = rb_next(&pos->rb_node);
272 rb_erase(&pos->rb_node, symbols);
273 symbol__delete(pos);
274 }
275}
276
277void symbols__insert(struct rb_root *symbols, struct symbol *sym)
278{
279 struct rb_node **p = &symbols->rb_node;
280 struct rb_node *parent = NULL;
281 const u64 ip = sym->start;
282 struct symbol *s;
283
284 while (*p != NULL) {
285 parent = *p;
286 s = rb_entry(parent, struct symbol, rb_node);
287 if (ip < s->start)
288 p = &(*p)->rb_left;
289 else
290 p = &(*p)->rb_right;
291 }
292 rb_link_node(&sym->rb_node, parent, p);
293 rb_insert_color(&sym->rb_node, symbols);
294}
295
296static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
297{
298 struct rb_node *n;
299
300 if (symbols == NULL)
301 return NULL;
302
303 n = symbols->rb_node;
304
305 while (n) {
306 struct symbol *s = rb_entry(n, struct symbol, rb_node);
307
308 if (ip < s->start)
309 n = n->rb_left;
310 else if (ip > s->end)
311 n = n->rb_right;
312 else
313 return s;
314 }
315
316 return NULL;
317}
318
319struct symbol_name_rb_node {
320 struct rb_node rb_node;
321 struct symbol sym;
322};
323
324static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym)
325{
326 struct rb_node **p = &symbols->rb_node;
327 struct rb_node *parent = NULL;
328 struct symbol_name_rb_node *symn, *s;
329
330 symn = container_of(sym, struct symbol_name_rb_node, sym);
331
332 while (*p != NULL) {
333 parent = *p;
334 s = rb_entry(parent, struct symbol_name_rb_node, rb_node);
335 if (strcmp(sym->name, s->sym.name) < 0)
336 p = &(*p)->rb_left;
337 else
338 p = &(*p)->rb_right;
339 }
340 rb_link_node(&symn->rb_node, parent, p);
341 rb_insert_color(&symn->rb_node, symbols);
342}
343
344static void symbols__sort_by_name(struct rb_root *symbols,
345 struct rb_root *source)
346{
347 struct rb_node *nd;
348
349 for (nd = rb_first(source); nd; nd = rb_next(nd)) {
350 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
351 symbols__insert_by_name(symbols, pos);
352 }
353}
354
355static struct symbol *symbols__find_by_name(struct rb_root *symbols,
356 const char *name)
357{
358 struct rb_node *n;
359
360 if (symbols == NULL)
361 return NULL;
362
363 n = symbols->rb_node;
364
365 while (n) {
366 struct symbol_name_rb_node *s;
367 int cmp;
368
369 s = rb_entry(n, struct symbol_name_rb_node, rb_node);
370 cmp = strcmp(name, s->sym.name);
371
372 if (cmp < 0)
373 n = n->rb_left;
374 else if (cmp > 0)
375 n = n->rb_right;
376 else
377 return &s->sym;
378 }
379
380 return NULL;
381}
382
383struct symbol *dso__find_symbol(struct dso *dso,
384 enum map_type type, u64 addr)
385{
386 return symbols__find(&dso->symbols[type], addr);
387}
388
389struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
390 const char *name)
391{
392 return symbols__find_by_name(&dso->symbol_names[type], name);
393}
394
395void dso__sort_by_name(struct dso *dso, enum map_type type)
396{
397 dso__set_sorted_by_name(dso, type);
398 return symbols__sort_by_name(&dso->symbol_names[type],
399 &dso->symbols[type]);
400}
401
402size_t dso__fprintf_symbols_by_name(struct dso *dso,
403 enum map_type type, FILE *fp)
404{
405 size_t ret = 0;
406 struct rb_node *nd;
407 struct symbol_name_rb_node *pos;
408
409 for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) {
410 pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
411 fprintf(fp, "%s\n", pos->sym.name);
412 }
413
414 return ret;
415}
416
417int kallsyms__parse(const char *filename, void *arg,
418 int (*process_symbol)(void *arg, const char *name,
419 char type, u64 start))
420{
421 char *line = NULL;
422 size_t n;
423 int err = -1;
424 FILE *file = fopen(filename, "r");
425
426 if (file == NULL)
427 goto out_failure;
428
429 err = 0;
430
431 while (!feof(file)) {
432 u64 start;
433 int line_len, len;
434 char symbol_type;
435 char *symbol_name;
436
437 line_len = getline(&line, &n, file);
438 if (line_len < 0 || !line)
439 break;
440
441 line[--line_len] = '\0';
442
443 len = hex2u64(line, &start);
444
445 len++;
446 if (len + 2 >= line_len)
447 continue;
448
449 symbol_type = line[len];
450 len += 2;
451 symbol_name = line + len;
452 len = line_len - len;
453
454 if (len >= KSYM_NAME_LEN) {
455 err = -1;
456 break;
457 }
458
459 err = process_symbol(arg, symbol_name,
460 symbol_type, start);
461 if (err)
462 break;
463 }
464
465 free(line);
466 fclose(file);
467 return err;
468
469out_failure:
470 return -1;
471}
472
473struct process_kallsyms_args {
474 struct map *map;
475 struct dso *dso;
476};
477
478static u8 kallsyms2elf_type(char type)
479{
480 if (type == 'W')
481 return STB_WEAK;
482
483 return isupper(type) ? STB_GLOBAL : STB_LOCAL;
484}
485
486static int map__process_kallsym_symbol(void *arg, const char *name,
487 char type, u64 start)
488{
489 struct symbol *sym;
490 struct process_kallsyms_args *a = arg;
491 struct rb_root *root = &a->dso->symbols[a->map->type];
492
493 if (!symbol_type__is_a(type, a->map->type))
494 return 0;
495
496
497
498
499
500
501 sym = symbol__new(start, 0, kallsyms2elf_type(type), name);
502 if (sym == NULL)
503 return -ENOMEM;
504
505
506
507
508 symbols__insert(root, sym);
509
510 return 0;
511}
512
513
514
515
516
517
518static int dso__load_all_kallsyms(struct dso *dso, const char *filename,
519 struct map *map)
520{
521 struct process_kallsyms_args args = { .map = map, .dso = dso, };
522 return kallsyms__parse(filename, &args, map__process_kallsym_symbol);
523}
524
525
526
527
528
529
530static int dso__split_kallsyms(struct dso *dso, struct map *map,
531 symbol_filter_t filter)
532{
533 struct map_groups *kmaps = map__kmap(map)->kmaps;
534 struct machine *machine = kmaps->machine;
535 struct map *curr_map = map;
536 struct symbol *pos;
537 int count = 0, moved = 0;
538 struct rb_root *root = &dso->symbols[map->type];
539 struct rb_node *next = rb_first(root);
540 int kernel_range = 0;
541
542 while (next) {
543 char *module;
544
545 pos = rb_entry(next, struct symbol, rb_node);
546 next = rb_next(&pos->rb_node);
547
548 module = strchr(pos->name, '\t');
549 if (module) {
550 if (!symbol_conf.use_modules)
551 goto discard_symbol;
552
553 *module++ = '\0';
554
555 if (strcmp(curr_map->dso->short_name, module)) {
556 if (curr_map != map &&
557 dso->kernel == DSO_TYPE_GUEST_KERNEL &&
558 machine__is_default_guest(machine)) {
559
560
561
562
563
564
565
566 dso__set_loaded(curr_map->dso,
567 curr_map->type);
568 }
569
570 curr_map = map_groups__find_by_name(kmaps,
571 map->type, module);
572 if (curr_map == NULL) {
573 pr_debug("%s/proc/{kallsyms,modules} "
574 "inconsistency while looking "
575 "for \"%s\" module!\n",
576 machine->root_dir, module);
577 curr_map = map;
578 goto discard_symbol;
579 }
580
581 if (curr_map->dso->loaded &&
582 !machine__is_default_guest(machine))
583 goto discard_symbol;
584 }
585
586
587
588
589 pos->start = curr_map->map_ip(curr_map, pos->start);
590 pos->end = curr_map->map_ip(curr_map, pos->end);
591 } else if (curr_map != map) {
592 char dso_name[PATH_MAX];
593 struct dso *ndso;
594
595 if (count == 0) {
596 curr_map = map;
597 goto filter_symbol;
598 }
599
600 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
601 snprintf(dso_name, sizeof(dso_name),
602 "[guest.kernel].%d",
603 kernel_range++);
604 else
605 snprintf(dso_name, sizeof(dso_name),
606 "[kernel].%d",
607 kernel_range++);
608
609 ndso = dso__new(dso_name);
610 if (ndso == NULL)
611 return -1;
612
613 ndso->kernel = dso->kernel;
614
615 curr_map = map__new2(pos->start, ndso, map->type);
616 if (curr_map == NULL) {
617 dso__delete(ndso);
618 return -1;
619 }
620
621 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
622 map_groups__insert(kmaps, curr_map);
623 ++kernel_range;
624 }
625filter_symbol:
626 if (filter && filter(curr_map, pos)) {
627discard_symbol: rb_erase(&pos->rb_node, root);
628 symbol__delete(pos);
629 } else {
630 if (curr_map != map) {
631 rb_erase(&pos->rb_node, root);
632 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
633 ++moved;
634 } else
635 ++count;
636 }
637 }
638
639 if (curr_map != map &&
640 dso->kernel == DSO_TYPE_GUEST_KERNEL &&
641 machine__is_default_guest(kmaps->machine)) {
642 dso__set_loaded(curr_map->dso, curr_map->type);
643 }
644
645 return count + moved;
646}
647
648bool symbol__restricted_filename(const char *filename,
649 const char *restricted_filename)
650{
651 bool restricted = false;
652
653 if (symbol_conf.kptr_restrict) {
654 char *r = realpath(filename, NULL);
655
656 if (r != NULL) {
657 restricted = strcmp(r, restricted_filename) == 0;
658 free(r);
659 return restricted;
660 }
661 }
662
663 return restricted;
664}
665
666int dso__load_kallsyms(struct dso *dso, const char *filename,
667 struct map *map, symbol_filter_t filter)
668{
669 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
670 return -1;
671
672 if (dso__load_all_kallsyms(dso, filename, map) < 0)
673 return -1;
674
675 symbols__fixup_duplicate(&dso->symbols[map->type]);
676 symbols__fixup_end(&dso->symbols[map->type]);
677
678 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
679 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS;
680 else
681 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS;
682
683 return dso__split_kallsyms(dso, map, filter);
684}
685
686static int dso__load_perf_map(struct dso *dso, struct map *map,
687 symbol_filter_t filter)
688{
689 char *line = NULL;
690 size_t n;
691 FILE *file;
692 int nr_syms = 0;
693
694 file = fopen(dso->long_name, "r");
695 if (file == NULL)
696 goto out_failure;
697
698 while (!feof(file)) {
699 u64 start, size;
700 struct symbol *sym;
701 int line_len, len;
702
703 line_len = getline(&line, &n, file);
704 if (line_len < 0)
705 break;
706
707 if (!line)
708 goto out_failure;
709
710 line[--line_len] = '\0';
711
712 len = hex2u64(line, &start);
713
714 len++;
715 if (len + 2 >= line_len)
716 continue;
717
718 len += hex2u64(line + len, &size);
719
720 len++;
721 if (len + 2 >= line_len)
722 continue;
723
724 sym = symbol__new(start, size, STB_GLOBAL, line + len);
725
726 if (sym == NULL)
727 goto out_delete_line;
728
729 if (filter && filter(map, sym))
730 symbol__delete(sym);
731 else {
732 symbols__insert(&dso->symbols[map->type], sym);
733 nr_syms++;
734 }
735 }
736
737 free(line);
738 fclose(file);
739
740 return nr_syms;
741
742out_delete_line:
743 free(line);
744out_failure:
745 return -1;
746}
747
748int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
749{
750 char *name;
751 int ret = -1;
752 u_int i;
753 struct machine *machine;
754 char *root_dir = (char *) "";
755 int ss_pos = 0;
756 struct symsrc ss_[2];
757 struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
758
759 dso__set_loaded(dso, map->type);
760
761 if (dso->kernel == DSO_TYPE_KERNEL)
762 return dso__load_kernel_sym(dso, map, filter);
763 else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
764 return dso__load_guest_kernel_sym(dso, map, filter);
765
766 if (map->groups && map->groups->machine)
767 machine = map->groups->machine;
768 else
769 machine = NULL;
770
771 dso->adjust_symbols = 0;
772
773 if (strncmp(dso->name, "/tmp/perf-", 10) == 0) {
774 struct stat st;
775
776 if (lstat(dso->name, &st) < 0)
777 return -1;
778
779 if (st.st_uid && (st.st_uid != geteuid())) {
780 pr_warning("File %s not owned by current user or root, "
781 "ignoring it.\n", dso->name);
782 return -1;
783 }
784
785 ret = dso__load_perf_map(dso, map, filter);
786 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
787 DSO_BINARY_TYPE__NOT_FOUND;
788 return ret;
789 }
790
791 if (machine)
792 root_dir = machine->root_dir;
793
794 name = malloc(PATH_MAX);
795 if (!name)
796 return -1;
797
798
799
800
801
802 for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) {
803 struct symsrc *ss = &ss_[ss_pos];
804 bool next_slot = false;
805
806 enum dso_binary_type symtab_type = binary_type_symtab[i];
807
808 if (dso__binary_type_file(dso, symtab_type,
809 root_dir, name, PATH_MAX))
810 continue;
811
812
813 if (symsrc__init(ss, dso, name, symtab_type) < 0)
814 continue;
815
816 if (!syms_ss && symsrc__has_symtab(ss)) {
817 syms_ss = ss;
818 next_slot = true;
819 }
820
821 if (!runtime_ss && symsrc__possibly_runtime(ss)) {
822 runtime_ss = ss;
823 next_slot = true;
824 }
825
826 if (next_slot) {
827 ss_pos++;
828
829 if (syms_ss && runtime_ss)
830 break;
831 }
832
833 }
834
835 if (!runtime_ss && !syms_ss)
836 goto out_free;
837
838 if (runtime_ss && !syms_ss) {
839 syms_ss = runtime_ss;
840 }
841
842
843 if (!runtime_ss && syms_ss)
844 runtime_ss = syms_ss;
845
846 if (syms_ss)
847 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, 0);
848 else
849 ret = -1;
850
851 if (ret > 0) {
852 int nr_plt;
853
854 nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss, map, filter);
855 if (nr_plt > 0)
856 ret += nr_plt;
857 }
858
859 for (; ss_pos > 0; ss_pos--)
860 symsrc__destroy(&ss_[ss_pos - 1]);
861out_free:
862 free(name);
863 if (ret < 0 && strstr(dso->name, " (deleted)") != NULL)
864 return 0;
865 return ret;
866}
867
868struct map *map_groups__find_by_name(struct map_groups *mg,
869 enum map_type type, const char *name)
870{
871 struct rb_node *nd;
872
873 for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) {
874 struct map *map = rb_entry(nd, struct map, rb_node);
875
876 if (map->dso && strcmp(map->dso->short_name, name) == 0)
877 return map;
878 }
879
880 return NULL;
881}
882
883int dso__load_vmlinux(struct dso *dso, struct map *map,
884 const char *vmlinux, symbol_filter_t filter)
885{
886 int err = -1;
887 struct symsrc ss;
888 char symfs_vmlinux[PATH_MAX];
889 enum dso_binary_type symtab_type;
890
891 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s",
892 symbol_conf.symfs, vmlinux);
893
894 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
895 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
896 else
897 symtab_type = DSO_BINARY_TYPE__VMLINUX;
898
899 if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type))
900 return -1;
901
902 err = dso__load_sym(dso, map, &ss, &ss, filter, 0);
903 symsrc__destroy(&ss);
904
905 if (err > 0) {
906 dso__set_long_name(dso, (char *)vmlinux);
907 dso__set_loaded(dso, map->type);
908 pr_debug("Using %s for symbols\n", symfs_vmlinux);
909 }
910
911 return err;
912}
913
914int dso__load_vmlinux_path(struct dso *dso, struct map *map,
915 symbol_filter_t filter)
916{
917 int i, err = 0;
918 char *filename;
919
920 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
921 vmlinux_path__nr_entries + 1);
922
923 filename = dso__build_id_filename(dso, NULL, 0);
924 if (filename != NULL) {
925 err = dso__load_vmlinux(dso, map, filename, filter);
926 if (err > 0) {
927 dso->lname_alloc = 1;
928 goto out;
929 }
930 free(filename);
931 }
932
933 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
934 err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter);
935 if (err > 0) {
936 dso__set_long_name(dso, strdup(vmlinux_path[i]));
937 dso->lname_alloc = 1;
938 break;
939 }
940 }
941out:
942 return err;
943}
944
945static int dso__load_kernel_sym(struct dso *dso, struct map *map,
946 symbol_filter_t filter)
947{
948 int err;
949 const char *kallsyms_filename = NULL;
950 char *kallsyms_allocated_filename = NULL;
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966 if (symbol_conf.kallsyms_name != NULL) {
967 kallsyms_filename = symbol_conf.kallsyms_name;
968 goto do_kallsyms;
969 }
970
971 if (symbol_conf.vmlinux_name != NULL) {
972 err = dso__load_vmlinux(dso, map,
973 symbol_conf.vmlinux_name, filter);
974 if (err > 0) {
975 dso__set_long_name(dso,
976 strdup(symbol_conf.vmlinux_name));
977 dso->lname_alloc = 1;
978 goto out_fixup;
979 }
980 return err;
981 }
982
983 if (vmlinux_path != NULL) {
984 err = dso__load_vmlinux_path(dso, map, filter);
985 if (err > 0)
986 goto out_fixup;
987 }
988
989
990 if (symbol_conf.symfs[0] != 0)
991 return -1;
992
993
994
995
996
997
998 if (dso->has_build_id) {
999 u8 kallsyms_build_id[BUILD_ID_SIZE];
1000 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1001
1002 if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id,
1003 sizeof(kallsyms_build_id)) == 0) {
1004 if (dso__build_id_equal(dso, kallsyms_build_id)) {
1005 kallsyms_filename = "/proc/kallsyms";
1006 goto do_kallsyms;
1007 }
1008 }
1009
1010
1011
1012
1013 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1014 sbuild_id);
1015
1016 if (asprintf(&kallsyms_allocated_filename,
1017 "%s/.debug/[kernel.kallsyms]/%s",
1018 getenv("HOME"), sbuild_id) == -1) {
1019 pr_err("Not enough memory for kallsyms file lookup\n");
1020 return -1;
1021 }
1022
1023 kallsyms_filename = kallsyms_allocated_filename;
1024
1025 if (access(kallsyms_filename, F_OK)) {
1026 pr_err("No kallsyms or vmlinux with build-id %s "
1027 "was found\n", sbuild_id);
1028 free(kallsyms_allocated_filename);
1029 return -1;
1030 }
1031 } else {
1032
1033
1034
1035
1036 kallsyms_filename = "/proc/kallsyms";
1037 }
1038
1039do_kallsyms:
1040 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);
1041 if (err > 0)
1042 pr_debug("Using %s for symbols\n", kallsyms_filename);
1043 free(kallsyms_allocated_filename);
1044
1045 if (err > 0) {
1046 dso__set_long_name(dso, strdup("[kernel.kallsyms]"));
1047out_fixup:
1048 map__fixup_start(map);
1049 map__fixup_end(map);
1050 }
1051
1052 return err;
1053}
1054
1055static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1056 symbol_filter_t filter)
1057{
1058 int err;
1059 const char *kallsyms_filename = NULL;
1060 struct machine *machine;
1061 char path[PATH_MAX];
1062
1063 if (!map->groups) {
1064 pr_debug("Guest kernel map hasn't the point to groups\n");
1065 return -1;
1066 }
1067 machine = map->groups->machine;
1068
1069 if (machine__is_default_guest(machine)) {
1070
1071
1072
1073
1074
1075 if (symbol_conf.default_guest_vmlinux_name != NULL) {
1076 err = dso__load_vmlinux(dso, map,
1077 symbol_conf.default_guest_vmlinux_name, filter);
1078 goto out_try_fixup;
1079 }
1080
1081 kallsyms_filename = symbol_conf.default_guest_kallsyms;
1082 if (!kallsyms_filename)
1083 return -1;
1084 } else {
1085 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
1086 kallsyms_filename = path;
1087 }
1088
1089 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);
1090 if (err > 0)
1091 pr_debug("Using %s for symbols\n", kallsyms_filename);
1092
1093out_try_fixup:
1094 if (err > 0) {
1095 if (kallsyms_filename != NULL) {
1096 machine__mmap_name(machine, path, sizeof(path));
1097 dso__set_long_name(dso, strdup(path));
1098 }
1099 map__fixup_start(map);
1100 map__fixup_end(map);
1101 }
1102
1103 return err;
1104}
1105
1106static void vmlinux_path__exit(void)
1107{
1108 while (--vmlinux_path__nr_entries >= 0) {
1109 free(vmlinux_path[vmlinux_path__nr_entries]);
1110 vmlinux_path[vmlinux_path__nr_entries] = NULL;
1111 }
1112
1113 free(vmlinux_path);
1114 vmlinux_path = NULL;
1115}
1116
1117static int vmlinux_path__init(void)
1118{
1119 struct utsname uts;
1120 char bf[PATH_MAX];
1121
1122 vmlinux_path = malloc(sizeof(char *) * 5);
1123 if (vmlinux_path == NULL)
1124 return -1;
1125
1126 vmlinux_path[vmlinux_path__nr_entries] = strdup("vmlinux");
1127 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1128 goto out_fail;
1129 ++vmlinux_path__nr_entries;
1130 vmlinux_path[vmlinux_path__nr_entries] = strdup("/boot/vmlinux");
1131 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1132 goto out_fail;
1133 ++vmlinux_path__nr_entries;
1134
1135
1136 if (symbol_conf.symfs[0] != 0)
1137 return 0;
1138
1139 if (uname(&uts) < 0)
1140 return -1;
1141
1142 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
1143 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1144 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1145 goto out_fail;
1146 ++vmlinux_path__nr_entries;
1147 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release);
1148 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1149 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1150 goto out_fail;
1151 ++vmlinux_path__nr_entries;
1152 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux",
1153 uts.release);
1154 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1155 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1156 goto out_fail;
1157 ++vmlinux_path__nr_entries;
1158
1159 return 0;
1160
1161out_fail:
1162 vmlinux_path__exit();
1163 return -1;
1164}
1165
1166static int setup_list(struct strlist **list, const char *list_str,
1167 const char *list_name)
1168{
1169 if (list_str == NULL)
1170 return 0;
1171
1172 *list = strlist__new(true, list_str);
1173 if (!*list) {
1174 pr_err("problems parsing %s list\n", list_name);
1175 return -1;
1176 }
1177 return 0;
1178}
1179
1180static bool symbol__read_kptr_restrict(void)
1181{
1182 bool value = false;
1183
1184 if (geteuid() != 0) {
1185 FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r");
1186 if (fp != NULL) {
1187 char line[8];
1188
1189 if (fgets(line, sizeof(line), fp) != NULL)
1190 value = atoi(line) != 0;
1191
1192 fclose(fp);
1193 }
1194 }
1195
1196 return value;
1197}
1198
1199int symbol__init(void)
1200{
1201 const char *symfs;
1202
1203 if (symbol_conf.initialized)
1204 return 0;
1205
1206 symbol_conf.priv_size = PERF_ALIGN(symbol_conf.priv_size, sizeof(u64));
1207
1208 symbol__elf_init();
1209
1210 if (symbol_conf.sort_by_name)
1211 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
1212 sizeof(struct symbol));
1213
1214 if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0)
1215 return -1;
1216
1217 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') {
1218 pr_err("'.' is the only non valid --field-separator argument\n");
1219 return -1;
1220 }
1221
1222 if (setup_list(&symbol_conf.dso_list,
1223 symbol_conf.dso_list_str, "dso") < 0)
1224 return -1;
1225
1226 if (setup_list(&symbol_conf.comm_list,
1227 symbol_conf.comm_list_str, "comm") < 0)
1228 goto out_free_dso_list;
1229
1230 if (setup_list(&symbol_conf.sym_list,
1231 symbol_conf.sym_list_str, "symbol") < 0)
1232 goto out_free_comm_list;
1233
1234
1235
1236
1237
1238 symfs = realpath(symbol_conf.symfs, NULL);
1239 if (symfs == NULL)
1240 symfs = symbol_conf.symfs;
1241 if (strcmp(symfs, "/") == 0)
1242 symbol_conf.symfs = "";
1243 if (symfs != symbol_conf.symfs)
1244 free((void *)symfs);
1245
1246 symbol_conf.kptr_restrict = symbol__read_kptr_restrict();
1247
1248 symbol_conf.initialized = true;
1249 return 0;
1250
1251out_free_comm_list:
1252 strlist__delete(symbol_conf.comm_list);
1253out_free_dso_list:
1254 strlist__delete(symbol_conf.dso_list);
1255 return -1;
1256}
1257
1258void symbol__exit(void)
1259{
1260 if (!symbol_conf.initialized)
1261 return;
1262 strlist__delete(symbol_conf.sym_list);
1263 strlist__delete(symbol_conf.dso_list);
1264 strlist__delete(symbol_conf.comm_list);
1265 vmlinux_path__exit();
1266 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
1267 symbol_conf.initialized = false;
1268}
1269