.. | .. |
---|
4 | 4 | #include <stdlib.h> |
---|
5 | 5 | #include <stdio.h> |
---|
6 | 6 | #include <string.h> |
---|
| 7 | +#include <linux/capability.h> |
---|
7 | 8 | #include <linux/kernel.h> |
---|
8 | 9 | #include <linux/mman.h> |
---|
| 10 | +#include <linux/string.h> |
---|
| 11 | +#include <linux/time64.h> |
---|
9 | 12 | #include <sys/types.h> |
---|
10 | 13 | #include <sys/stat.h> |
---|
11 | 14 | #include <sys/param.h> |
---|
.. | .. |
---|
14 | 17 | #include <inttypes.h> |
---|
15 | 18 | #include "annotate.h" |
---|
16 | 19 | #include "build-id.h" |
---|
17 | | -#include "util.h" |
---|
| 20 | +#include "cap.h" |
---|
| 21 | +#include "dso.h" |
---|
| 22 | +#include "util.h" // lsdir() |
---|
18 | 23 | #include "debug.h" |
---|
| 24 | +#include "event.h" |
---|
19 | 25 | #include "machine.h" |
---|
| 26 | +#include "map.h" |
---|
20 | 27 | #include "symbol.h" |
---|
| 28 | +#include "map_symbol.h" |
---|
| 29 | +#include "mem-events.h" |
---|
| 30 | +#include "symsrc.h" |
---|
21 | 31 | #include "strlist.h" |
---|
22 | 32 | #include "intlist.h" |
---|
23 | 33 | #include "namespaces.h" |
---|
24 | 34 | #include "header.h" |
---|
25 | 35 | #include "path.h" |
---|
26 | | -#include "sane_ctype.h" |
---|
| 36 | +#include <linux/ctype.h> |
---|
| 37 | +#include <linux/zalloc.h> |
---|
27 | 38 | |
---|
28 | 39 | #include <elf.h> |
---|
29 | 40 | #include <limits.h> |
---|
.. | .. |
---|
38 | 49 | char **vmlinux_path; |
---|
39 | 50 | |
---|
40 | 51 | struct symbol_conf symbol_conf = { |
---|
| 52 | + .nanosecs = false, |
---|
41 | 53 | .use_modules = true, |
---|
42 | 54 | .try_vmlinux_path = true, |
---|
43 | 55 | .demangle = true, |
---|
44 | 56 | .demangle_kernel = false, |
---|
45 | 57 | .cumulate_callchain = true, |
---|
| 58 | + .time_quantum = 100 * NSEC_PER_MSEC, /* 100ms */ |
---|
46 | 59 | .show_hist_headers = true, |
---|
47 | 60 | .symfs = "", |
---|
48 | 61 | .event_group = true, |
---|
49 | 62 | .inline_name = true, |
---|
| 63 | + .res_sample = 0, |
---|
50 | 64 | }; |
---|
51 | 65 | |
---|
52 | 66 | static enum dso_binary_type binary_type_symtab[] = { |
---|
.. | .. |
---|
85 | 99 | tail++; |
---|
86 | 100 | |
---|
87 | 101 | return tail - str; |
---|
88 | | -} |
---|
89 | | - |
---|
90 | | -void __weak arch__symbols__fixup_end(struct symbol *p, struct symbol *c) |
---|
91 | | -{ |
---|
92 | | - p->end = c->start; |
---|
93 | 102 | } |
---|
94 | 103 | |
---|
95 | 104 | const char * __weak arch__normalize_symbol_name(const char *name) |
---|
.. | .. |
---|
169 | 178 | return arch__choose_best_symbol(syma, symb); |
---|
170 | 179 | } |
---|
171 | 180 | |
---|
172 | | -void symbols__fixup_duplicate(struct rb_root *symbols) |
---|
| 181 | +void symbols__fixup_duplicate(struct rb_root_cached *symbols) |
---|
173 | 182 | { |
---|
174 | 183 | struct rb_node *nd; |
---|
175 | 184 | struct symbol *curr, *next; |
---|
.. | .. |
---|
177 | 186 | if (symbol_conf.allow_aliases) |
---|
178 | 187 | return; |
---|
179 | 188 | |
---|
180 | | - nd = rb_first(symbols); |
---|
| 189 | + nd = rb_first_cached(symbols); |
---|
181 | 190 | |
---|
182 | 191 | while (nd) { |
---|
183 | 192 | curr = rb_entry(nd, struct symbol, rb_node); |
---|
.. | .. |
---|
192 | 201 | continue; |
---|
193 | 202 | |
---|
194 | 203 | if (choose_best_symbol(curr, next) == SYMBOL_A) { |
---|
195 | | - rb_erase(&next->rb_node, symbols); |
---|
| 204 | + rb_erase_cached(&next->rb_node, symbols); |
---|
196 | 205 | symbol__delete(next); |
---|
197 | 206 | goto again; |
---|
198 | 207 | } else { |
---|
199 | 208 | nd = rb_next(&curr->rb_node); |
---|
200 | | - rb_erase(&curr->rb_node, symbols); |
---|
| 209 | + rb_erase_cached(&curr->rb_node, symbols); |
---|
201 | 210 | symbol__delete(curr); |
---|
202 | 211 | } |
---|
203 | 212 | } |
---|
204 | 213 | } |
---|
205 | 214 | |
---|
206 | | -void symbols__fixup_end(struct rb_root *symbols) |
---|
| 215 | +/* Update zero-sized symbols using the address of the next symbol */ |
---|
| 216 | +void symbols__fixup_end(struct rb_root_cached *symbols, bool is_kallsyms) |
---|
207 | 217 | { |
---|
208 | | - struct rb_node *nd, *prevnd = rb_first(symbols); |
---|
| 218 | + struct rb_node *nd, *prevnd = rb_first_cached(symbols); |
---|
209 | 219 | struct symbol *curr, *prev; |
---|
210 | 220 | |
---|
211 | 221 | if (prevnd == NULL) |
---|
.. | .. |
---|
217 | 227 | prev = curr; |
---|
218 | 228 | curr = rb_entry(nd, struct symbol, rb_node); |
---|
219 | 229 | |
---|
220 | | - if (prev->end == prev->start && prev->end != curr->start) |
---|
221 | | - arch__symbols__fixup_end(prev, curr); |
---|
| 230 | + /* |
---|
| 231 | + * On some architecture kernel text segment start is located at |
---|
| 232 | + * some low memory address, while modules are located at high |
---|
| 233 | + * memory addresses (or vice versa). The gap between end of |
---|
| 234 | + * kernel text segment and beginning of first module's text |
---|
| 235 | + * segment is very big. Therefore do not fill this gap and do |
---|
| 236 | + * not assign it to the kernel dso map (kallsyms). |
---|
| 237 | + * |
---|
| 238 | + * In kallsyms, it determines module symbols using '[' character |
---|
| 239 | + * like in: |
---|
| 240 | + * ffffffffc1937000 T hdmi_driver_init [snd_hda_codec_hdmi] |
---|
| 241 | + */ |
---|
| 242 | + if (prev->end == prev->start) { |
---|
| 243 | + /* Last kernel/module symbol mapped to end of page */ |
---|
| 244 | + if (is_kallsyms && (!strchr(prev->name, '[') != |
---|
| 245 | + !strchr(curr->name, '['))) |
---|
| 246 | + prev->end = roundup(prev->end + 4096, 4096); |
---|
| 247 | + else |
---|
| 248 | + prev->end = curr->start; |
---|
| 249 | + |
---|
| 250 | + pr_debug4("%s sym:%s end:%#" PRIx64 "\n", |
---|
| 251 | + __func__, prev->name, prev->end); |
---|
| 252 | + } |
---|
222 | 253 | } |
---|
223 | 254 | |
---|
224 | 255 | /* Last entry */ |
---|
.. | .. |
---|
226 | 257 | curr->end = roundup(curr->start, 4096) + 4096; |
---|
227 | 258 | } |
---|
228 | 259 | |
---|
229 | | -void map_groups__fixup_end(struct map_groups *mg) |
---|
| 260 | +void maps__fixup_end(struct maps *maps) |
---|
230 | 261 | { |
---|
231 | | - struct maps *maps = &mg->maps; |
---|
232 | | - struct map *next, *curr; |
---|
| 262 | + struct map *prev = NULL, *curr; |
---|
233 | 263 | |
---|
234 | 264 | down_write(&maps->lock); |
---|
235 | 265 | |
---|
236 | | - curr = maps__first(maps); |
---|
237 | | - if (curr == NULL) |
---|
238 | | - goto out_unlock; |
---|
| 266 | + maps__for_each_entry(maps, curr) { |
---|
| 267 | + if (prev != NULL && !prev->end) |
---|
| 268 | + prev->end = curr->start; |
---|
239 | 269 | |
---|
240 | | - for (next = map__next(curr); next; next = map__next(curr)) { |
---|
241 | | - if (!curr->end) |
---|
242 | | - curr->end = next->start; |
---|
243 | | - curr = next; |
---|
| 270 | + prev = curr; |
---|
244 | 271 | } |
---|
245 | 272 | |
---|
246 | 273 | /* |
---|
247 | 274 | * We still haven't the actual symbols, so guess the |
---|
248 | 275 | * last map final address. |
---|
249 | 276 | */ |
---|
250 | | - if (!curr->end) |
---|
| 277 | + if (curr && !curr->end) |
---|
251 | 278 | curr->end = ~0ULL; |
---|
252 | 279 | |
---|
253 | | -out_unlock: |
---|
254 | 280 | up_write(&maps->lock); |
---|
255 | 281 | } |
---|
256 | 282 | |
---|
.. | .. |
---|
288 | 314 | free(((void *)sym) - symbol_conf.priv_size); |
---|
289 | 315 | } |
---|
290 | 316 | |
---|
291 | | -void symbols__delete(struct rb_root *symbols) |
---|
| 317 | +void symbols__delete(struct rb_root_cached *symbols) |
---|
292 | 318 | { |
---|
293 | 319 | struct symbol *pos; |
---|
294 | | - struct rb_node *next = rb_first(symbols); |
---|
| 320 | + struct rb_node *next = rb_first_cached(symbols); |
---|
295 | 321 | |
---|
296 | 322 | while (next) { |
---|
297 | 323 | pos = rb_entry(next, struct symbol, rb_node); |
---|
298 | 324 | next = rb_next(&pos->rb_node); |
---|
299 | | - rb_erase(&pos->rb_node, symbols); |
---|
| 325 | + rb_erase_cached(&pos->rb_node, symbols); |
---|
300 | 326 | symbol__delete(pos); |
---|
301 | 327 | } |
---|
302 | 328 | } |
---|
303 | 329 | |
---|
304 | | -void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel) |
---|
| 330 | +void __symbols__insert(struct rb_root_cached *symbols, |
---|
| 331 | + struct symbol *sym, bool kernel) |
---|
305 | 332 | { |
---|
306 | | - struct rb_node **p = &symbols->rb_node; |
---|
| 333 | + struct rb_node **p = &symbols->rb_root.rb_node; |
---|
307 | 334 | struct rb_node *parent = NULL; |
---|
308 | 335 | const u64 ip = sym->start; |
---|
309 | 336 | struct symbol *s; |
---|
| 337 | + bool leftmost = true; |
---|
310 | 338 | |
---|
311 | 339 | if (kernel) { |
---|
312 | 340 | const char *name = sym->name; |
---|
.. | .. |
---|
324 | 352 | s = rb_entry(parent, struct symbol, rb_node); |
---|
325 | 353 | if (ip < s->start) |
---|
326 | 354 | p = &(*p)->rb_left; |
---|
327 | | - else |
---|
| 355 | + else { |
---|
328 | 356 | p = &(*p)->rb_right; |
---|
| 357 | + leftmost = false; |
---|
| 358 | + } |
---|
329 | 359 | } |
---|
330 | 360 | rb_link_node(&sym->rb_node, parent, p); |
---|
331 | | - rb_insert_color(&sym->rb_node, symbols); |
---|
| 361 | + rb_insert_color_cached(&sym->rb_node, symbols, leftmost); |
---|
332 | 362 | } |
---|
333 | 363 | |
---|
334 | | -void symbols__insert(struct rb_root *symbols, struct symbol *sym) |
---|
| 364 | +void symbols__insert(struct rb_root_cached *symbols, struct symbol *sym) |
---|
335 | 365 | { |
---|
336 | 366 | __symbols__insert(symbols, sym, false); |
---|
337 | 367 | } |
---|
338 | 368 | |
---|
339 | | -static struct symbol *symbols__find(struct rb_root *symbols, u64 ip) |
---|
| 369 | +static struct symbol *symbols__find(struct rb_root_cached *symbols, u64 ip) |
---|
340 | 370 | { |
---|
341 | 371 | struct rb_node *n; |
---|
342 | 372 | |
---|
343 | 373 | if (symbols == NULL) |
---|
344 | 374 | return NULL; |
---|
345 | 375 | |
---|
346 | | - n = symbols->rb_node; |
---|
| 376 | + n = symbols->rb_root.rb_node; |
---|
347 | 377 | |
---|
348 | 378 | while (n) { |
---|
349 | 379 | struct symbol *s = rb_entry(n, struct symbol, rb_node); |
---|
.. | .. |
---|
359 | 389 | return NULL; |
---|
360 | 390 | } |
---|
361 | 391 | |
---|
362 | | -static struct symbol *symbols__first(struct rb_root *symbols) |
---|
| 392 | +static struct symbol *symbols__first(struct rb_root_cached *symbols) |
---|
363 | 393 | { |
---|
364 | | - struct rb_node *n = rb_first(symbols); |
---|
| 394 | + struct rb_node *n = rb_first_cached(symbols); |
---|
365 | 395 | |
---|
366 | 396 | if (n) |
---|
367 | 397 | return rb_entry(n, struct symbol, rb_node); |
---|
.. | .. |
---|
369 | 399 | return NULL; |
---|
370 | 400 | } |
---|
371 | 401 | |
---|
372 | | -static struct symbol *symbols__last(struct rb_root *symbols) |
---|
| 402 | +static struct symbol *symbols__last(struct rb_root_cached *symbols) |
---|
373 | 403 | { |
---|
374 | | - struct rb_node *n = rb_last(symbols); |
---|
| 404 | + struct rb_node *n = rb_last(&symbols->rb_root); |
---|
375 | 405 | |
---|
376 | 406 | if (n) |
---|
377 | 407 | return rb_entry(n, struct symbol, rb_node); |
---|
.. | .. |
---|
389 | 419 | return NULL; |
---|
390 | 420 | } |
---|
391 | 421 | |
---|
392 | | -static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym) |
---|
| 422 | +static void symbols__insert_by_name(struct rb_root_cached *symbols, struct symbol *sym) |
---|
393 | 423 | { |
---|
394 | | - struct rb_node **p = &symbols->rb_node; |
---|
| 424 | + struct rb_node **p = &symbols->rb_root.rb_node; |
---|
395 | 425 | struct rb_node *parent = NULL; |
---|
396 | 426 | struct symbol_name_rb_node *symn, *s; |
---|
| 427 | + bool leftmost = true; |
---|
397 | 428 | |
---|
398 | 429 | symn = container_of(sym, struct symbol_name_rb_node, sym); |
---|
399 | 430 | |
---|
.. | .. |
---|
402 | 433 | s = rb_entry(parent, struct symbol_name_rb_node, rb_node); |
---|
403 | 434 | if (strcmp(sym->name, s->sym.name) < 0) |
---|
404 | 435 | p = &(*p)->rb_left; |
---|
405 | | - else |
---|
| 436 | + else { |
---|
406 | 437 | p = &(*p)->rb_right; |
---|
| 438 | + leftmost = false; |
---|
| 439 | + } |
---|
407 | 440 | } |
---|
408 | 441 | rb_link_node(&symn->rb_node, parent, p); |
---|
409 | | - rb_insert_color(&symn->rb_node, symbols); |
---|
| 442 | + rb_insert_color_cached(&symn->rb_node, symbols, leftmost); |
---|
410 | 443 | } |
---|
411 | 444 | |
---|
412 | | -static void symbols__sort_by_name(struct rb_root *symbols, |
---|
413 | | - struct rb_root *source) |
---|
| 445 | +static void symbols__sort_by_name(struct rb_root_cached *symbols, |
---|
| 446 | + struct rb_root_cached *source) |
---|
414 | 447 | { |
---|
415 | 448 | struct rb_node *nd; |
---|
416 | 449 | |
---|
417 | | - for (nd = rb_first(source); nd; nd = rb_next(nd)) { |
---|
| 450 | + for (nd = rb_first_cached(source); nd; nd = rb_next(nd)) { |
---|
418 | 451 | struct symbol *pos = rb_entry(nd, struct symbol, rb_node); |
---|
419 | 452 | symbols__insert_by_name(symbols, pos); |
---|
420 | 453 | } |
---|
.. | .. |
---|
437 | 470 | return arch__compare_symbol_names(name, str); |
---|
438 | 471 | } |
---|
439 | 472 | |
---|
440 | | -static struct symbol *symbols__find_by_name(struct rb_root *symbols, |
---|
| 473 | +static struct symbol *symbols__find_by_name(struct rb_root_cached *symbols, |
---|
441 | 474 | const char *name, |
---|
442 | 475 | enum symbol_tag_include includes) |
---|
443 | 476 | { |
---|
.. | .. |
---|
447 | 480 | if (symbols == NULL) |
---|
448 | 481 | return NULL; |
---|
449 | 482 | |
---|
450 | | - n = symbols->rb_node; |
---|
| 483 | + n = symbols->rb_root.rb_node; |
---|
451 | 484 | |
---|
452 | 485 | while (n) { |
---|
453 | 486 | int cmp; |
---|
.. | .. |
---|
497 | 530 | sym->start == sym->end)) { |
---|
498 | 531 | dso->last_find_result.symbol = sym; |
---|
499 | 532 | } |
---|
| 533 | +} |
---|
| 534 | + |
---|
| 535 | +void dso__delete_symbol(struct dso *dso, struct symbol *sym) |
---|
| 536 | +{ |
---|
| 537 | + rb_erase_cached(&sym->rb_node, &dso->symbols); |
---|
| 538 | + symbol__delete(sym); |
---|
| 539 | + dso__reset_find_symbol_cache(dso); |
---|
500 | 540 | } |
---|
501 | 541 | |
---|
502 | 542 | struct symbol *dso__find_symbol(struct dso *dso, u64 addr) |
---|
.. | .. |
---|
550 | 590 | dso__set_sorted_by_name(dso); |
---|
551 | 591 | return symbols__sort_by_name(&dso->symbol_names, &dso->symbols); |
---|
552 | 592 | } |
---|
| 593 | + |
---|
| 594 | +/* |
---|
| 595 | + * While we find nice hex chars, build a long_val. |
---|
| 596 | + * Return number of chars processed. |
---|
| 597 | + */ |
---|
| 598 | +static int hex2u64(const char *ptr, u64 *long_val) |
---|
| 599 | +{ |
---|
| 600 | + char *p; |
---|
| 601 | + |
---|
| 602 | + *long_val = strtoull(ptr, &p, 16); |
---|
| 603 | + |
---|
| 604 | + return p - ptr; |
---|
| 605 | +} |
---|
| 606 | + |
---|
553 | 607 | |
---|
554 | 608 | int modules__parse(const char *filename, void *arg, |
---|
555 | 609 | int (*process_module)(void *arg, const char *name, |
---|
.. | .. |
---|
620 | 674 | static bool symbol__is_idle(const char *name) |
---|
621 | 675 | { |
---|
622 | 676 | const char * const idle_symbols[] = { |
---|
| 677 | + "acpi_idle_do_entry", |
---|
| 678 | + "acpi_processor_ffh_cstate_enter", |
---|
| 679 | + "arch_cpu_idle", |
---|
623 | 680 | "cpu_idle", |
---|
624 | 681 | "cpu_startup_entry", |
---|
| 682 | + "idle_cpu", |
---|
625 | 683 | "intel_idle", |
---|
626 | 684 | "default_idle", |
---|
627 | 685 | "native_safe_halt", |
---|
.. | .. |
---|
629 | 687 | "exit_idle", |
---|
630 | 688 | "mwait_idle", |
---|
631 | 689 | "mwait_idle_with_hints", |
---|
| 690 | + "mwait_idle_with_hints.constprop.0", |
---|
632 | 691 | "poll_idle", |
---|
633 | 692 | "ppc64_runlatch_off", |
---|
634 | 693 | "pseries_dedicated_idle_sleep", |
---|
| 694 | + "psw_idle", |
---|
| 695 | + "psw_idle_exit", |
---|
635 | 696 | NULL |
---|
636 | 697 | }; |
---|
637 | 698 | int i; |
---|
| 699 | + static struct strlist *idle_symbols_list; |
---|
638 | 700 | |
---|
639 | | - for (i = 0; idle_symbols[i]; i++) { |
---|
640 | | - if (!strcmp(idle_symbols[i], name)) |
---|
641 | | - return true; |
---|
642 | | - } |
---|
| 701 | + if (idle_symbols_list) |
---|
| 702 | + return strlist__has_entry(idle_symbols_list, name); |
---|
643 | 703 | |
---|
644 | | - return false; |
---|
| 704 | + idle_symbols_list = strlist__new(NULL, NULL); |
---|
| 705 | + |
---|
| 706 | + for (i = 0; idle_symbols[i]; i++) |
---|
| 707 | + strlist__add(idle_symbols_list, idle_symbols[i]); |
---|
| 708 | + |
---|
| 709 | + return strlist__has_entry(idle_symbols_list, name); |
---|
645 | 710 | } |
---|
646 | 711 | |
---|
647 | 712 | static int map__process_kallsym_symbol(void *arg, const char *name, |
---|
.. | .. |
---|
649 | 714 | { |
---|
650 | 715 | struct symbol *sym; |
---|
651 | 716 | struct dso *dso = arg; |
---|
652 | | - struct rb_root *root = &dso->symbols; |
---|
| 717 | + struct rb_root_cached *root = &dso->symbols; |
---|
653 | 718 | |
---|
654 | 719 | if (!symbol_type__filter(type)) |
---|
655 | 720 | return 0; |
---|
.. | .. |
---|
681 | 746 | return kallsyms__parse(filename, dso, map__process_kallsym_symbol); |
---|
682 | 747 | } |
---|
683 | 748 | |
---|
684 | | -static int map_groups__split_kallsyms_for_kcore(struct map_groups *kmaps, struct dso *dso) |
---|
| 749 | +static int maps__split_kallsyms_for_kcore(struct maps *kmaps, struct dso *dso) |
---|
685 | 750 | { |
---|
686 | 751 | struct map *curr_map; |
---|
687 | 752 | struct symbol *pos; |
---|
688 | 753 | int count = 0; |
---|
689 | | - struct rb_root old_root = dso->symbols; |
---|
690 | | - struct rb_root *root = &dso->symbols; |
---|
691 | | - struct rb_node *next = rb_first(root); |
---|
| 754 | + struct rb_root_cached old_root = dso->symbols; |
---|
| 755 | + struct rb_root_cached *root = &dso->symbols; |
---|
| 756 | + struct rb_node *next = rb_first_cached(root); |
---|
692 | 757 | |
---|
693 | 758 | if (!kmaps) |
---|
694 | 759 | return -1; |
---|
695 | 760 | |
---|
696 | | - *root = RB_ROOT; |
---|
| 761 | + *root = RB_ROOT_CACHED; |
---|
697 | 762 | |
---|
698 | 763 | while (next) { |
---|
699 | 764 | char *module; |
---|
.. | .. |
---|
701 | 766 | pos = rb_entry(next, struct symbol, rb_node); |
---|
702 | 767 | next = rb_next(&pos->rb_node); |
---|
703 | 768 | |
---|
704 | | - rb_erase_init(&pos->rb_node, &old_root); |
---|
705 | | - |
---|
| 769 | + rb_erase_cached(&pos->rb_node, &old_root); |
---|
| 770 | + RB_CLEAR_NODE(&pos->rb_node); |
---|
706 | 771 | module = strchr(pos->name, '\t'); |
---|
707 | 772 | if (module) |
---|
708 | 773 | *module = '\0'; |
---|
709 | 774 | |
---|
710 | | - curr_map = map_groups__find(kmaps, pos->start); |
---|
| 775 | + curr_map = maps__find(kmaps, pos->start); |
---|
711 | 776 | |
---|
712 | 777 | if (!curr_map) { |
---|
713 | 778 | symbol__delete(pos); |
---|
.. | .. |
---|
734 | 799 | * kernel range is broken in several maps, named [kernel].N, as we don't have |
---|
735 | 800 | * the original ELF section names vmlinux have. |
---|
736 | 801 | */ |
---|
737 | | -static int map_groups__split_kallsyms(struct map_groups *kmaps, struct dso *dso, u64 delta, |
---|
738 | | - struct map *initial_map) |
---|
| 802 | +static int maps__split_kallsyms(struct maps *kmaps, struct dso *dso, u64 delta, |
---|
| 803 | + struct map *initial_map) |
---|
739 | 804 | { |
---|
740 | 805 | struct machine *machine; |
---|
741 | 806 | struct map *curr_map = initial_map; |
---|
742 | 807 | struct symbol *pos; |
---|
743 | 808 | int count = 0, moved = 0; |
---|
744 | | - struct rb_root *root = &dso->symbols; |
---|
745 | | - struct rb_node *next = rb_first(root); |
---|
| 809 | + struct rb_root_cached *root = &dso->symbols; |
---|
| 810 | + struct rb_node *next = rb_first_cached(root); |
---|
746 | 811 | int kernel_range = 0; |
---|
747 | 812 | bool x86_64; |
---|
748 | 813 | |
---|
.. | .. |
---|
768 | 833 | |
---|
769 | 834 | if (strcmp(curr_map->dso->short_name, module)) { |
---|
770 | 835 | if (curr_map != initial_map && |
---|
771 | | - dso->kernel == DSO_TYPE_GUEST_KERNEL && |
---|
| 836 | + dso->kernel == DSO_SPACE__KERNEL_GUEST && |
---|
772 | 837 | machine__is_default_guest(machine)) { |
---|
773 | 838 | /* |
---|
774 | 839 | * We assume all symbols of a module are |
---|
.. | .. |
---|
780 | 845 | dso__set_loaded(curr_map->dso); |
---|
781 | 846 | } |
---|
782 | 847 | |
---|
783 | | - curr_map = map_groups__find_by_name(kmaps, module); |
---|
| 848 | + curr_map = maps__find_by_name(kmaps, module); |
---|
784 | 849 | if (curr_map == NULL) { |
---|
785 | 850 | pr_debug("%s/proc/{kallsyms,modules} " |
---|
786 | 851 | "inconsistency while looking " |
---|
.. | .. |
---|
825 | 890 | goto add_symbol; |
---|
826 | 891 | } |
---|
827 | 892 | |
---|
828 | | - if (dso->kernel == DSO_TYPE_GUEST_KERNEL) |
---|
| 893 | + if (dso->kernel == DSO_SPACE__KERNEL_GUEST) |
---|
829 | 894 | snprintf(dso_name, sizeof(dso_name), |
---|
830 | 895 | "[guest.kernel].%d", |
---|
831 | 896 | kernel_range++); |
---|
.. | .. |
---|
847 | 912 | } |
---|
848 | 913 | |
---|
849 | 914 | curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; |
---|
850 | | - map_groups__insert(kmaps, curr_map); |
---|
| 915 | + maps__insert(kmaps, curr_map); |
---|
851 | 916 | ++kernel_range; |
---|
852 | 917 | } else if (delta) { |
---|
853 | 918 | /* Kernel was relocated at boot time */ |
---|
.. | .. |
---|
856 | 921 | } |
---|
857 | 922 | add_symbol: |
---|
858 | 923 | if (curr_map != initial_map) { |
---|
859 | | - rb_erase(&pos->rb_node, root); |
---|
| 924 | + rb_erase_cached(&pos->rb_node, root); |
---|
860 | 925 | symbols__insert(&curr_map->dso->symbols, pos); |
---|
861 | 926 | ++moved; |
---|
862 | 927 | } else |
---|
.. | .. |
---|
864 | 929 | |
---|
865 | 930 | continue; |
---|
866 | 931 | discard_symbol: |
---|
867 | | - rb_erase(&pos->rb_node, root); |
---|
| 932 | + rb_erase_cached(&pos->rb_node, root); |
---|
868 | 933 | symbol__delete(pos); |
---|
869 | 934 | } |
---|
870 | 935 | |
---|
871 | 936 | if (curr_map != initial_map && |
---|
872 | | - dso->kernel == DSO_TYPE_GUEST_KERNEL && |
---|
| 937 | + dso->kernel == DSO_SPACE__KERNEL_GUEST && |
---|
873 | 938 | machine__is_default_guest(kmaps->machine)) { |
---|
874 | 939 | dso__set_loaded(curr_map->dso); |
---|
875 | 940 | } |
---|
.. | .. |
---|
1032 | 1097 | return ret; |
---|
1033 | 1098 | } |
---|
1034 | 1099 | |
---|
1035 | | -struct map *map_groups__first(struct map_groups *mg) |
---|
1036 | | -{ |
---|
1037 | | - return maps__first(&mg->maps); |
---|
1038 | | -} |
---|
1039 | | - |
---|
1040 | | -static int do_validate_kcore_modules(const char *filename, |
---|
1041 | | - struct map_groups *kmaps) |
---|
| 1100 | +static int do_validate_kcore_modules(const char *filename, struct maps *kmaps) |
---|
1042 | 1101 | { |
---|
1043 | 1102 | struct rb_root modules = RB_ROOT; |
---|
1044 | 1103 | struct map *old_map; |
---|
.. | .. |
---|
1048 | 1107 | if (err) |
---|
1049 | 1108 | return err; |
---|
1050 | 1109 | |
---|
1051 | | - old_map = map_groups__first(kmaps); |
---|
1052 | | - while (old_map) { |
---|
1053 | | - struct map *next = map_groups__next(old_map); |
---|
| 1110 | + maps__for_each_entry(kmaps, old_map) { |
---|
1054 | 1111 | struct module_info *mi; |
---|
1055 | 1112 | |
---|
1056 | 1113 | if (!__map__is_kmodule(old_map)) { |
---|
1057 | | - old_map = next; |
---|
1058 | 1114 | continue; |
---|
1059 | 1115 | } |
---|
1060 | 1116 | |
---|
.. | .. |
---|
1064 | 1120 | err = -EINVAL; |
---|
1065 | 1121 | goto out; |
---|
1066 | 1122 | } |
---|
1067 | | - |
---|
1068 | | - old_map = next; |
---|
1069 | 1123 | } |
---|
1070 | 1124 | out: |
---|
1071 | 1125 | delete_modules(&modules); |
---|
.. | .. |
---|
1100 | 1154 | static int validate_kcore_modules(const char *kallsyms_filename, |
---|
1101 | 1155 | struct map *map) |
---|
1102 | 1156 | { |
---|
1103 | | - struct map_groups *kmaps = map__kmaps(map); |
---|
| 1157 | + struct maps *kmaps = map__kmaps(map); |
---|
1104 | 1158 | char modules_filename[PATH_MAX]; |
---|
1105 | 1159 | |
---|
1106 | 1160 | if (!kmaps) |
---|
.. | .. |
---|
1159 | 1213 | return 0; |
---|
1160 | 1214 | } |
---|
1161 | 1215 | |
---|
| 1216 | +/* |
---|
| 1217 | + * Merges map into maps by splitting the new map within the existing map |
---|
| 1218 | + * regions. |
---|
| 1219 | + */ |
---|
| 1220 | +int maps__merge_in(struct maps *kmaps, struct map *new_map) |
---|
| 1221 | +{ |
---|
| 1222 | + struct map *old_map; |
---|
| 1223 | + LIST_HEAD(merged); |
---|
| 1224 | + |
---|
| 1225 | + maps__for_each_entry(kmaps, old_map) { |
---|
| 1226 | + /* no overload with this one */ |
---|
| 1227 | + if (new_map->end < old_map->start || |
---|
| 1228 | + new_map->start >= old_map->end) |
---|
| 1229 | + continue; |
---|
| 1230 | + |
---|
| 1231 | + if (new_map->start < old_map->start) { |
---|
| 1232 | + /* |
---|
| 1233 | + * |new...... |
---|
| 1234 | + * |old.... |
---|
| 1235 | + */ |
---|
| 1236 | + if (new_map->end < old_map->end) { |
---|
| 1237 | + /* |
---|
| 1238 | + * |new......| -> |new..| |
---|
| 1239 | + * |old....| -> |old....| |
---|
| 1240 | + */ |
---|
| 1241 | + new_map->end = old_map->start; |
---|
| 1242 | + } else { |
---|
| 1243 | + /* |
---|
| 1244 | + * |new.............| -> |new..| |new..| |
---|
| 1245 | + * |old....| -> |old....| |
---|
| 1246 | + */ |
---|
| 1247 | + struct map *m = map__clone(new_map); |
---|
| 1248 | + |
---|
| 1249 | + if (!m) |
---|
| 1250 | + return -ENOMEM; |
---|
| 1251 | + |
---|
| 1252 | + m->end = old_map->start; |
---|
| 1253 | + list_add_tail(&m->node, &merged); |
---|
| 1254 | + new_map->pgoff += old_map->end - new_map->start; |
---|
| 1255 | + new_map->start = old_map->end; |
---|
| 1256 | + } |
---|
| 1257 | + } else { |
---|
| 1258 | + /* |
---|
| 1259 | + * |new...... |
---|
| 1260 | + * |old.... |
---|
| 1261 | + */ |
---|
| 1262 | + if (new_map->end < old_map->end) { |
---|
| 1263 | + /* |
---|
| 1264 | + * |new..| -> x |
---|
| 1265 | + * |old.........| -> |old.........| |
---|
| 1266 | + */ |
---|
| 1267 | + map__put(new_map); |
---|
| 1268 | + new_map = NULL; |
---|
| 1269 | + break; |
---|
| 1270 | + } else { |
---|
| 1271 | + /* |
---|
| 1272 | + * |new......| -> |new...| |
---|
| 1273 | + * |old....| -> |old....| |
---|
| 1274 | + */ |
---|
| 1275 | + new_map->pgoff += old_map->end - new_map->start; |
---|
| 1276 | + new_map->start = old_map->end; |
---|
| 1277 | + } |
---|
| 1278 | + } |
---|
| 1279 | + } |
---|
| 1280 | + |
---|
| 1281 | + while (!list_empty(&merged)) { |
---|
| 1282 | + old_map = list_entry(merged.next, struct map, node); |
---|
| 1283 | + list_del_init(&old_map->node); |
---|
| 1284 | + maps__insert(kmaps, old_map); |
---|
| 1285 | + map__put(old_map); |
---|
| 1286 | + } |
---|
| 1287 | + |
---|
| 1288 | + if (new_map) { |
---|
| 1289 | + maps__insert(kmaps, new_map); |
---|
| 1290 | + map__put(new_map); |
---|
| 1291 | + } |
---|
| 1292 | + return 0; |
---|
| 1293 | +} |
---|
| 1294 | + |
---|
1162 | 1295 | static int dso__load_kcore(struct dso *dso, struct map *map, |
---|
1163 | 1296 | const char *kallsyms_filename) |
---|
1164 | 1297 | { |
---|
1165 | | - struct map_groups *kmaps = map__kmaps(map); |
---|
| 1298 | + struct maps *kmaps = map__kmaps(map); |
---|
1166 | 1299 | struct kcore_mapfn_data md; |
---|
1167 | | - struct map *old_map, *new_map, *replacement_map = NULL; |
---|
| 1300 | + struct map *old_map, *new_map, *replacement_map = NULL, *next; |
---|
1168 | 1301 | struct machine *machine; |
---|
1169 | 1302 | bool is_64_bit; |
---|
1170 | 1303 | int err, fd; |
---|
.. | .. |
---|
1211 | 1344 | } |
---|
1212 | 1345 | |
---|
1213 | 1346 | /* Remove old maps */ |
---|
1214 | | - old_map = map_groups__first(kmaps); |
---|
1215 | | - while (old_map) { |
---|
1216 | | - struct map *next = map_groups__next(old_map); |
---|
1217 | | - |
---|
1218 | | - if (old_map != map) |
---|
1219 | | - map_groups__remove(kmaps, old_map); |
---|
1220 | | - old_map = next; |
---|
| 1347 | + maps__for_each_entry_safe(kmaps, old_map, next) { |
---|
| 1348 | + /* |
---|
| 1349 | + * We need to preserve eBPF maps even if they are |
---|
| 1350 | + * covered by kcore, because we need to access |
---|
| 1351 | + * eBPF dso for source data. |
---|
| 1352 | + */ |
---|
| 1353 | + if (old_map != map && !__map__is_bpf_prog(old_map)) |
---|
| 1354 | + maps__remove(kmaps, old_map); |
---|
1221 | 1355 | } |
---|
1222 | 1356 | machine->trampolines_mapped = false; |
---|
1223 | 1357 | |
---|
.. | .. |
---|
1246 | 1380 | map->unmap_ip = new_map->unmap_ip; |
---|
1247 | 1381 | /* Ensure maps are correctly ordered */ |
---|
1248 | 1382 | map__get(map); |
---|
1249 | | - map_groups__remove(kmaps, map); |
---|
1250 | | - map_groups__insert(kmaps, map); |
---|
| 1383 | + maps__remove(kmaps, map); |
---|
| 1384 | + maps__insert(kmaps, map); |
---|
1251 | 1385 | map__put(map); |
---|
| 1386 | + map__put(new_map); |
---|
1252 | 1387 | } else { |
---|
1253 | | - map_groups__insert(kmaps, new_map); |
---|
| 1388 | + /* |
---|
| 1389 | + * Merge kcore map into existing maps, |
---|
| 1390 | + * and ensure that current maps (eBPF) |
---|
| 1391 | + * stay intact. |
---|
| 1392 | + */ |
---|
| 1393 | + if (maps__merge_in(kmaps, new_map)) |
---|
| 1394 | + goto out_err; |
---|
1254 | 1395 | } |
---|
1255 | | - |
---|
1256 | | - map__put(new_map); |
---|
1257 | 1396 | } |
---|
1258 | 1397 | |
---|
1259 | 1398 | if (machine__is(machine, "x86_64")) { |
---|
.. | .. |
---|
1273 | 1412 | * Set the data type and long name so that kcore can be read via |
---|
1274 | 1413 | * dso__data_read_addr(). |
---|
1275 | 1414 | */ |
---|
1276 | | - if (dso->kernel == DSO_TYPE_GUEST_KERNEL) |
---|
| 1415 | + if (dso->kernel == DSO_SPACE__KERNEL_GUEST) |
---|
1277 | 1416 | dso->binary_type = DSO_BINARY_TYPE__GUEST_KCORE; |
---|
1278 | 1417 | else |
---|
1279 | 1418 | dso->binary_type = DSO_BINARY_TYPE__KCORE; |
---|
.. | .. |
---|
1334 | 1473 | if (kallsyms__delta(kmap, filename, &delta)) |
---|
1335 | 1474 | return -1; |
---|
1336 | 1475 | |
---|
1337 | | - symbols__fixup_end(&dso->symbols); |
---|
| 1476 | + symbols__fixup_end(&dso->symbols, true); |
---|
1338 | 1477 | symbols__fixup_duplicate(&dso->symbols); |
---|
1339 | 1478 | |
---|
1340 | | - if (dso->kernel == DSO_TYPE_GUEST_KERNEL) |
---|
| 1479 | + if (dso->kernel == DSO_SPACE__KERNEL_GUEST) |
---|
1341 | 1480 | dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS; |
---|
1342 | 1481 | else |
---|
1343 | 1482 | dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; |
---|
1344 | 1483 | |
---|
1345 | 1484 | if (!no_kcore && !dso__load_kcore(dso, map, filename)) |
---|
1346 | | - return map_groups__split_kallsyms_for_kcore(kmap->kmaps, dso); |
---|
| 1485 | + return maps__split_kallsyms_for_kcore(kmap->kmaps, dso); |
---|
1347 | 1486 | else |
---|
1348 | | - return map_groups__split_kallsyms(kmap->kmaps, dso, delta, map); |
---|
| 1487 | + return maps__split_kallsyms(kmap->kmaps, dso, delta, map); |
---|
1349 | 1488 | } |
---|
1350 | 1489 | |
---|
1351 | 1490 | int dso__load_kallsyms(struct dso *dso, const char *filename, |
---|
.. | .. |
---|
1411 | 1550 | return -1; |
---|
1412 | 1551 | } |
---|
1413 | 1552 | |
---|
| 1553 | +#ifdef HAVE_LIBBFD_SUPPORT |
---|
| 1554 | +#define PACKAGE 'perf' |
---|
| 1555 | +#include <bfd.h> |
---|
| 1556 | + |
---|
| 1557 | +static int bfd_symbols__cmpvalue(const void *a, const void *b) |
---|
| 1558 | +{ |
---|
| 1559 | + const asymbol *as = *(const asymbol **)a, *bs = *(const asymbol **)b; |
---|
| 1560 | + |
---|
| 1561 | + if (bfd_asymbol_value(as) != bfd_asymbol_value(bs)) |
---|
| 1562 | + return bfd_asymbol_value(as) - bfd_asymbol_value(bs); |
---|
| 1563 | + |
---|
| 1564 | + return bfd_asymbol_name(as)[0] - bfd_asymbol_name(bs)[0]; |
---|
| 1565 | +} |
---|
| 1566 | + |
---|
| 1567 | +static int bfd2elf_binding(asymbol *symbol) |
---|
| 1568 | +{ |
---|
| 1569 | + if (symbol->flags & BSF_WEAK) |
---|
| 1570 | + return STB_WEAK; |
---|
| 1571 | + if (symbol->flags & BSF_GLOBAL) |
---|
| 1572 | + return STB_GLOBAL; |
---|
| 1573 | + if (symbol->flags & BSF_LOCAL) |
---|
| 1574 | + return STB_LOCAL; |
---|
| 1575 | + return -1; |
---|
| 1576 | +} |
---|
| 1577 | + |
---|
| 1578 | +int dso__load_bfd_symbols(struct dso *dso, const char *debugfile) |
---|
| 1579 | +{ |
---|
| 1580 | + int err = -1; |
---|
| 1581 | + long symbols_size, symbols_count, i; |
---|
| 1582 | + asection *section; |
---|
| 1583 | + asymbol **symbols, *sym; |
---|
| 1584 | + struct symbol *symbol; |
---|
| 1585 | + bfd *abfd; |
---|
| 1586 | + u64 start, len; |
---|
| 1587 | + |
---|
| 1588 | + abfd = bfd_openr(dso->long_name, NULL); |
---|
| 1589 | + if (!abfd) |
---|
| 1590 | + return -1; |
---|
| 1591 | + |
---|
| 1592 | + if (!bfd_check_format(abfd, bfd_object)) { |
---|
| 1593 | + pr_debug2("%s: cannot read %s bfd file.\n", __func__, |
---|
| 1594 | + dso->long_name); |
---|
| 1595 | + goto out_close; |
---|
| 1596 | + } |
---|
| 1597 | + |
---|
| 1598 | + if (bfd_get_flavour(abfd) == bfd_target_elf_flavour) |
---|
| 1599 | + goto out_close; |
---|
| 1600 | + |
---|
| 1601 | + section = bfd_get_section_by_name(abfd, ".text"); |
---|
| 1602 | + if (section) |
---|
| 1603 | + dso->text_offset = section->vma - section->filepos; |
---|
| 1604 | + |
---|
| 1605 | + bfd_close(abfd); |
---|
| 1606 | + |
---|
| 1607 | + abfd = bfd_openr(debugfile, NULL); |
---|
| 1608 | + if (!abfd) |
---|
| 1609 | + return -1; |
---|
| 1610 | + |
---|
| 1611 | + if (!bfd_check_format(abfd, bfd_object)) { |
---|
| 1612 | + pr_debug2("%s: cannot read %s bfd file.\n", __func__, |
---|
| 1613 | + debugfile); |
---|
| 1614 | + goto out_close; |
---|
| 1615 | + } |
---|
| 1616 | + |
---|
| 1617 | + if (bfd_get_flavour(abfd) == bfd_target_elf_flavour) |
---|
| 1618 | + goto out_close; |
---|
| 1619 | + |
---|
| 1620 | + symbols_size = bfd_get_symtab_upper_bound(abfd); |
---|
| 1621 | + if (symbols_size == 0) { |
---|
| 1622 | + bfd_close(abfd); |
---|
| 1623 | + return 0; |
---|
| 1624 | + } |
---|
| 1625 | + |
---|
| 1626 | + if (symbols_size < 0) |
---|
| 1627 | + goto out_close; |
---|
| 1628 | + |
---|
| 1629 | + symbols = malloc(symbols_size); |
---|
| 1630 | + if (!symbols) |
---|
| 1631 | + goto out_close; |
---|
| 1632 | + |
---|
| 1633 | + symbols_count = bfd_canonicalize_symtab(abfd, symbols); |
---|
| 1634 | + if (symbols_count < 0) |
---|
| 1635 | + goto out_free; |
---|
| 1636 | + |
---|
| 1637 | + qsort(symbols, symbols_count, sizeof(asymbol *), bfd_symbols__cmpvalue); |
---|
| 1638 | + |
---|
| 1639 | +#ifdef bfd_get_section |
---|
| 1640 | +#define bfd_asymbol_section bfd_get_section |
---|
| 1641 | +#endif |
---|
| 1642 | + for (i = 0; i < symbols_count; ++i) { |
---|
| 1643 | + sym = symbols[i]; |
---|
| 1644 | + section = bfd_asymbol_section(sym); |
---|
| 1645 | + if (bfd2elf_binding(sym) < 0) |
---|
| 1646 | + continue; |
---|
| 1647 | + |
---|
| 1648 | + while (i + 1 < symbols_count && |
---|
| 1649 | + bfd_asymbol_section(symbols[i + 1]) == section && |
---|
| 1650 | + bfd2elf_binding(symbols[i + 1]) < 0) |
---|
| 1651 | + i++; |
---|
| 1652 | + |
---|
| 1653 | + if (i + 1 < symbols_count && |
---|
| 1654 | + bfd_asymbol_section(symbols[i + 1]) == section) |
---|
| 1655 | + len = symbols[i + 1]->value - sym->value; |
---|
| 1656 | + else |
---|
| 1657 | + len = section->size - sym->value; |
---|
| 1658 | + |
---|
| 1659 | + start = bfd_asymbol_value(sym) - dso->text_offset; |
---|
| 1660 | + symbol = symbol__new(start, len, bfd2elf_binding(sym), STT_FUNC, |
---|
| 1661 | + bfd_asymbol_name(sym)); |
---|
| 1662 | + if (!symbol) |
---|
| 1663 | + goto out_free; |
---|
| 1664 | + |
---|
| 1665 | + symbols__insert(&dso->symbols, symbol); |
---|
| 1666 | + } |
---|
| 1667 | +#ifdef bfd_get_section |
---|
| 1668 | +#undef bfd_asymbol_section |
---|
| 1669 | +#endif |
---|
| 1670 | + |
---|
| 1671 | + symbols__fixup_end(&dso->symbols, false); |
---|
| 1672 | + symbols__fixup_duplicate(&dso->symbols); |
---|
| 1673 | + dso->adjust_symbols = 1; |
---|
| 1674 | + |
---|
| 1675 | + err = 0; |
---|
| 1676 | +out_free: |
---|
| 1677 | + free(symbols); |
---|
| 1678 | +out_close: |
---|
| 1679 | + bfd_close(abfd); |
---|
| 1680 | + return err; |
---|
| 1681 | +} |
---|
| 1682 | +#endif |
---|
| 1683 | + |
---|
1414 | 1684 | static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod, |
---|
1415 | 1685 | enum dso_binary_type type) |
---|
1416 | 1686 | { |
---|
.. | .. |
---|
1423 | 1693 | case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO: |
---|
1424 | 1694 | case DSO_BINARY_TYPE__BUILDID_DEBUGINFO: |
---|
1425 | 1695 | case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: |
---|
1426 | | - return !kmod && dso->kernel == DSO_TYPE_USER; |
---|
| 1696 | + return !kmod && dso->kernel == DSO_SPACE__USER; |
---|
1427 | 1697 | |
---|
1428 | 1698 | case DSO_BINARY_TYPE__KALLSYMS: |
---|
1429 | 1699 | case DSO_BINARY_TYPE__VMLINUX: |
---|
1430 | 1700 | case DSO_BINARY_TYPE__KCORE: |
---|
1431 | | - return dso->kernel == DSO_TYPE_KERNEL; |
---|
| 1701 | + return dso->kernel == DSO_SPACE__KERNEL; |
---|
1432 | 1702 | |
---|
1433 | 1703 | case DSO_BINARY_TYPE__GUEST_KALLSYMS: |
---|
1434 | 1704 | case DSO_BINARY_TYPE__GUEST_VMLINUX: |
---|
1435 | 1705 | case DSO_BINARY_TYPE__GUEST_KCORE: |
---|
1436 | | - return dso->kernel == DSO_TYPE_GUEST_KERNEL; |
---|
| 1706 | + return dso->kernel == DSO_SPACE__KERNEL_GUEST; |
---|
1437 | 1707 | |
---|
1438 | 1708 | case DSO_BINARY_TYPE__GUEST_KMODULE: |
---|
1439 | 1709 | case DSO_BINARY_TYPE__GUEST_KMODULE_COMP: |
---|
.. | .. |
---|
1441 | 1711 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: |
---|
1442 | 1712 | /* |
---|
1443 | 1713 | * kernel modules know their symtab type - it's set when |
---|
1444 | | - * creating a module dso in machine__findnew_module_map(). |
---|
| 1714 | + * creating a module dso in machine__addnew_module_map(). |
---|
1445 | 1715 | */ |
---|
1446 | 1716 | return kmod && dso->symtab_type == type; |
---|
1447 | 1717 | |
---|
.. | .. |
---|
1449 | 1719 | case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: |
---|
1450 | 1720 | return true; |
---|
1451 | 1721 | |
---|
| 1722 | + case DSO_BINARY_TYPE__BPF_PROG_INFO: |
---|
| 1723 | + case DSO_BINARY_TYPE__BPF_IMAGE: |
---|
| 1724 | + case DSO_BINARY_TYPE__OOL: |
---|
1452 | 1725 | case DSO_BINARY_TYPE__NOT_FOUND: |
---|
1453 | 1726 | default: |
---|
1454 | 1727 | return false; |
---|
.. | .. |
---|
1498 | 1771 | char *name; |
---|
1499 | 1772 | int ret = -1; |
---|
1500 | 1773 | u_int i; |
---|
1501 | | - struct machine *machine; |
---|
| 1774 | + struct machine *machine = NULL; |
---|
1502 | 1775 | char *root_dir = (char *) ""; |
---|
1503 | 1776 | int ss_pos = 0; |
---|
1504 | 1777 | struct symsrc ss_[2]; |
---|
1505 | 1778 | struct symsrc *syms_ss = NULL, *runtime_ss = NULL; |
---|
1506 | 1779 | bool kmod; |
---|
1507 | 1780 | bool perfmap; |
---|
1508 | | - unsigned char build_id[BUILD_ID_SIZE]; |
---|
| 1781 | + struct build_id bid; |
---|
1509 | 1782 | struct nscookie nsc; |
---|
1510 | 1783 | char newmapname[PATH_MAX]; |
---|
1511 | 1784 | const char *map_path = dso->long_name; |
---|
.. | .. |
---|
1527 | 1800 | goto out; |
---|
1528 | 1801 | } |
---|
1529 | 1802 | |
---|
1530 | | - if (map->groups && map->groups->machine) |
---|
1531 | | - machine = map->groups->machine; |
---|
1532 | | - else |
---|
1533 | | - machine = NULL; |
---|
| 1803 | + kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || |
---|
| 1804 | + dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || |
---|
| 1805 | + dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE || |
---|
| 1806 | + dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; |
---|
1534 | 1807 | |
---|
1535 | | - if (dso->kernel) { |
---|
1536 | | - if (dso->kernel == DSO_TYPE_KERNEL) |
---|
| 1808 | + if (dso->kernel && !kmod) { |
---|
| 1809 | + if (dso->kernel == DSO_SPACE__KERNEL) |
---|
1537 | 1810 | ret = dso__load_kernel_sym(dso, map); |
---|
1538 | | - else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) |
---|
| 1811 | + else if (dso->kernel == DSO_SPACE__KERNEL_GUEST) |
---|
1539 | 1812 | ret = dso__load_guest_kernel_sym(dso, map); |
---|
1540 | 1813 | |
---|
| 1814 | + machine = map__kmaps(map)->machine; |
---|
1541 | 1815 | if (machine__is(machine, "x86_64")) |
---|
1542 | 1816 | machine__map_x86_64_entry_trampolines(machine, dso); |
---|
1543 | 1817 | goto out; |
---|
.. | .. |
---|
1546 | 1820 | dso->adjust_symbols = 0; |
---|
1547 | 1821 | |
---|
1548 | 1822 | if (perfmap) { |
---|
1549 | | - struct stat st; |
---|
1550 | | - |
---|
1551 | | - if (lstat(map_path, &st) < 0) |
---|
1552 | | - goto out; |
---|
1553 | | - |
---|
1554 | | - if (!symbol_conf.force && st.st_uid && (st.st_uid != geteuid())) { |
---|
1555 | | - pr_warning("File %s not owned by current user or root, " |
---|
1556 | | - "ignoring it (use -f to override).\n", map_path); |
---|
1557 | | - goto out; |
---|
1558 | | - } |
---|
1559 | | - |
---|
1560 | 1823 | ret = dso__load_perf_map(map_path, dso); |
---|
1561 | 1824 | dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : |
---|
1562 | 1825 | DSO_BINARY_TYPE__NOT_FOUND; |
---|
.. | .. |
---|
1570 | 1833 | if (!name) |
---|
1571 | 1834 | goto out; |
---|
1572 | 1835 | |
---|
1573 | | - kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || |
---|
1574 | | - dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || |
---|
1575 | | - dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE || |
---|
1576 | | - dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; |
---|
1577 | | - |
---|
1578 | | - |
---|
1579 | 1836 | /* |
---|
1580 | 1837 | * Read the build id if possible. This is required for |
---|
1581 | 1838 | * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work |
---|
.. | .. |
---|
1583 | 1840 | if (!dso->has_build_id && |
---|
1584 | 1841 | is_regular_file(dso->long_name)) { |
---|
1585 | 1842 | __symbol__join_symfs(name, PATH_MAX, dso->long_name); |
---|
1586 | | - if (filename__read_build_id(name, build_id, BUILD_ID_SIZE) > 0) |
---|
1587 | | - dso__set_build_id(dso, build_id); |
---|
| 1843 | + if (filename__read_build_id(name, &bid) > 0) |
---|
| 1844 | + dso__set_build_id(dso, &bid); |
---|
1588 | 1845 | } |
---|
1589 | 1846 | |
---|
1590 | 1847 | /* |
---|
.. | .. |
---|
1597 | 1854 | bool next_slot = false; |
---|
1598 | 1855 | bool is_reg; |
---|
1599 | 1856 | bool nsexit; |
---|
| 1857 | + int bfdrc = -1; |
---|
1600 | 1858 | int sirc = -1; |
---|
1601 | 1859 | |
---|
1602 | 1860 | enum dso_binary_type symtab_type = binary_type_symtab[i]; |
---|
.. | .. |
---|
1615 | 1873 | nsinfo__mountns_exit(&nsc); |
---|
1616 | 1874 | |
---|
1617 | 1875 | is_reg = is_regular_file(name); |
---|
| 1876 | +#ifdef HAVE_LIBBFD_SUPPORT |
---|
1618 | 1877 | if (is_reg) |
---|
| 1878 | + bfdrc = dso__load_bfd_symbols(dso, name); |
---|
| 1879 | +#endif |
---|
| 1880 | + if (is_reg && bfdrc < 0) |
---|
1619 | 1881 | sirc = symsrc__init(ss, dso, name, symtab_type); |
---|
1620 | 1882 | |
---|
1621 | 1883 | if (nsexit) |
---|
1622 | 1884 | nsinfo__mountns_enter(dso->nsinfo, &nsc); |
---|
| 1885 | + |
---|
| 1886 | + if (bfdrc == 0) { |
---|
| 1887 | + ret = 0; |
---|
| 1888 | + break; |
---|
| 1889 | + } |
---|
1623 | 1890 | |
---|
1624 | 1891 | if (!is_reg || sirc < 0) |
---|
1625 | 1892 | continue; |
---|
.. | .. |
---|
1685 | 1952 | return ret; |
---|
1686 | 1953 | } |
---|
1687 | 1954 | |
---|
1688 | | -struct map *map_groups__find_by_name(struct map_groups *mg, const char *name) |
---|
| 1955 | +static int map__strcmp(const void *a, const void *b) |
---|
1689 | 1956 | { |
---|
1690 | | - struct maps *maps = &mg->maps; |
---|
| 1957 | + const struct map *ma = *(const struct map **)a, *mb = *(const struct map **)b; |
---|
| 1958 | + return strcmp(ma->dso->short_name, mb->dso->short_name); |
---|
| 1959 | +} |
---|
| 1960 | + |
---|
| 1961 | +static int map__strcmp_name(const void *name, const void *b) |
---|
| 1962 | +{ |
---|
| 1963 | + const struct map *map = *(const struct map **)b; |
---|
| 1964 | + return strcmp(name, map->dso->short_name); |
---|
| 1965 | +} |
---|
| 1966 | + |
---|
| 1967 | +void __maps__sort_by_name(struct maps *maps) |
---|
| 1968 | +{ |
---|
| 1969 | + qsort(maps->maps_by_name, maps->nr_maps, sizeof(struct map *), map__strcmp); |
---|
| 1970 | +} |
---|
| 1971 | + |
---|
| 1972 | +static int map__groups__sort_by_name_from_rbtree(struct maps *maps) |
---|
| 1973 | +{ |
---|
| 1974 | + struct map *map; |
---|
| 1975 | + struct map **maps_by_name = realloc(maps->maps_by_name, maps->nr_maps * sizeof(map)); |
---|
| 1976 | + int i = 0; |
---|
| 1977 | + |
---|
| 1978 | + if (maps_by_name == NULL) |
---|
| 1979 | + return -1; |
---|
| 1980 | + |
---|
| 1981 | + maps->maps_by_name = maps_by_name; |
---|
| 1982 | + maps->nr_maps_allocated = maps->nr_maps; |
---|
| 1983 | + |
---|
| 1984 | + maps__for_each_entry(maps, map) |
---|
| 1985 | + maps_by_name[i++] = map; |
---|
| 1986 | + |
---|
| 1987 | + __maps__sort_by_name(maps); |
---|
| 1988 | + return 0; |
---|
| 1989 | +} |
---|
| 1990 | + |
---|
| 1991 | +static struct map *__maps__find_by_name(struct maps *maps, const char *name) |
---|
| 1992 | +{ |
---|
| 1993 | + struct map **mapp; |
---|
| 1994 | + |
---|
| 1995 | + if (maps->maps_by_name == NULL && |
---|
| 1996 | + map__groups__sort_by_name_from_rbtree(maps)) |
---|
| 1997 | + return NULL; |
---|
| 1998 | + |
---|
| 1999 | + mapp = bsearch(name, maps->maps_by_name, maps->nr_maps, sizeof(*mapp), map__strcmp_name); |
---|
| 2000 | + if (mapp) |
---|
| 2001 | + return *mapp; |
---|
| 2002 | + return NULL; |
---|
| 2003 | +} |
---|
| 2004 | + |
---|
| 2005 | +struct map *maps__find_by_name(struct maps *maps, const char *name) |
---|
| 2006 | +{ |
---|
1691 | 2007 | struct map *map; |
---|
1692 | 2008 | |
---|
1693 | 2009 | down_read(&maps->lock); |
---|
1694 | 2010 | |
---|
1695 | | - for (map = maps__first(maps); map; map = map__next(map)) { |
---|
1696 | | - if (map->dso && strcmp(map->dso->short_name, name) == 0) |
---|
1697 | | - goto out_unlock; |
---|
| 2011 | + if (maps->last_search_by_name && strcmp(maps->last_search_by_name->dso->short_name, name) == 0) { |
---|
| 2012 | + map = maps->last_search_by_name; |
---|
| 2013 | + goto out_unlock; |
---|
1698 | 2014 | } |
---|
| 2015 | + /* |
---|
| 2016 | + * If we have maps->maps_by_name, then the name isn't in the rbtree, |
---|
| 2017 | + * as maps->maps_by_name mirrors the rbtree when lookups by name are |
---|
| 2018 | + * made. |
---|
| 2019 | + */ |
---|
| 2020 | + map = __maps__find_by_name(maps, name); |
---|
| 2021 | + if (map || maps->maps_by_name != NULL) |
---|
| 2022 | + goto out_unlock; |
---|
| 2023 | + |
---|
| 2024 | + /* Fallback to traversing the rbtree... */ |
---|
| 2025 | + maps__for_each_entry(maps, map) |
---|
| 2026 | + if (strcmp(map->dso->short_name, name) == 0) { |
---|
| 2027 | + maps->last_search_by_name = map; |
---|
| 2028 | + goto out_unlock; |
---|
| 2029 | + } |
---|
1699 | 2030 | |
---|
1700 | 2031 | map = NULL; |
---|
1701 | 2032 | |
---|
.. | .. |
---|
1717 | 2048 | else |
---|
1718 | 2049 | symbol__join_symfs(symfs_vmlinux, vmlinux); |
---|
1719 | 2050 | |
---|
1720 | | - if (dso->kernel == DSO_TYPE_GUEST_KERNEL) |
---|
| 2051 | + if (dso->kernel == DSO_SPACE__KERNEL_GUEST) |
---|
1721 | 2052 | symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX; |
---|
1722 | 2053 | else |
---|
1723 | 2054 | symtab_type = DSO_BINARY_TYPE__VMLINUX; |
---|
.. | .. |
---|
1729 | 2060 | symsrc__destroy(&ss); |
---|
1730 | 2061 | |
---|
1731 | 2062 | if (err > 0) { |
---|
1732 | | - if (dso->kernel == DSO_TYPE_GUEST_KERNEL) |
---|
| 2063 | + if (dso->kernel == DSO_SPACE__KERNEL_GUEST) |
---|
1733 | 2064 | dso->binary_type = DSO_BINARY_TYPE__GUEST_VMLINUX; |
---|
1734 | 2065 | else |
---|
1735 | 2066 | dso->binary_type = DSO_BINARY_TYPE__VMLINUX; |
---|
.. | .. |
---|
1816 | 2147 | |
---|
1817 | 2148 | static char *dso__find_kallsyms(struct dso *dso, struct map *map) |
---|
1818 | 2149 | { |
---|
1819 | | - u8 host_build_id[BUILD_ID_SIZE]; |
---|
| 2150 | + struct build_id bid; |
---|
1820 | 2151 | char sbuild_id[SBUILD_ID_SIZE]; |
---|
1821 | 2152 | bool is_host = false; |
---|
1822 | 2153 | char path[PATH_MAX]; |
---|
.. | .. |
---|
1829 | 2160 | goto proc_kallsyms; |
---|
1830 | 2161 | } |
---|
1831 | 2162 | |
---|
1832 | | - if (sysfs__read_build_id("/sys/kernel/notes", host_build_id, |
---|
1833 | | - sizeof(host_build_id)) == 0) |
---|
1834 | | - is_host = dso__build_id_equal(dso, host_build_id); |
---|
| 2163 | + if (sysfs__read_build_id("/sys/kernel/notes", &bid) == 0) |
---|
| 2164 | + is_host = dso__build_id_equal(dso, &bid); |
---|
1835 | 2165 | |
---|
1836 | 2166 | /* Try a fast path for /proc/kallsyms if possible */ |
---|
1837 | 2167 | if (is_host) { |
---|
.. | .. |
---|
1847 | 2177 | goto proc_kallsyms; |
---|
1848 | 2178 | } |
---|
1849 | 2179 | |
---|
1850 | | - build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); |
---|
| 2180 | + build_id__sprintf(&dso->bid, sbuild_id); |
---|
1851 | 2181 | |
---|
1852 | 2182 | /* Find kallsyms in build-id cache with kcore */ |
---|
1853 | 2183 | scnprintf(path, sizeof(path), "%s/%s/%s", |
---|
.. | .. |
---|
1937 | 2267 | { |
---|
1938 | 2268 | int err; |
---|
1939 | 2269 | const char *kallsyms_filename = NULL; |
---|
1940 | | - struct machine *machine; |
---|
| 2270 | + struct machine *machine = map__kmaps(map)->machine; |
---|
1941 | 2271 | char path[PATH_MAX]; |
---|
1942 | | - |
---|
1943 | | - if (!map->groups) { |
---|
1944 | | - pr_debug("Guest kernel map hasn't the point to groups\n"); |
---|
1945 | | - return -1; |
---|
1946 | | - } |
---|
1947 | | - machine = map->groups->machine; |
---|
1948 | 2272 | |
---|
1949 | 2273 | if (machine__is_default_guest(machine)) { |
---|
1950 | 2274 | /* |
---|
.. | .. |
---|
2093 | 2417 | char line[8]; |
---|
2094 | 2418 | |
---|
2095 | 2419 | if (fgets(line, sizeof(line), fp) != NULL) |
---|
2096 | | - value = ((geteuid() != 0) || (getuid() != 0)) ? |
---|
2097 | | - (atoi(line) != 0) : |
---|
2098 | | - (atoi(line) == 2); |
---|
| 2420 | + value = perf_cap__capable(CAP_SYSLOG) ? |
---|
| 2421 | + (atoi(line) >= 2) : |
---|
| 2422 | + (atoi(line) != 0); |
---|
2099 | 2423 | |
---|
2100 | 2424 | fclose(fp); |
---|
2101 | 2425 | } |
---|
2102 | 2426 | |
---|
| 2427 | + /* Per kernel/kallsyms.c: |
---|
| 2428 | + * we also restrict when perf_event_paranoid > 1 w/o CAP_SYSLOG |
---|
| 2429 | + */ |
---|
| 2430 | + if (perf_event_paranoid() > 1 && !perf_cap__capable(CAP_SYSLOG)) |
---|
| 2431 | + value = true; |
---|
| 2432 | + |
---|
2103 | 2433 | return value; |
---|
2104 | 2434 | } |
---|
2105 | 2435 | |
---|