Commit 9b565a8051b389e046209a5f68c93eade8de58bd
Exists in
master
and in
20 other branches
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar: "A couple of tooling fixlets and a PMU detection printout fix" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/x86: Fix PMU detection printout when no PMU is detected perf symbols: Demangle cloned functions perf machine: Fix path unpopulated in machine__create_modules() perf tools: Explicitly add libdl dependency perf probe: Fix probing symbols with optimization suffix perf trace: Add mmap2 handler perf kmem: Make it work again on non NUMA machines
Showing 8 changed files Side-by-side Diff
arch/x86/kernel/cpu/perf_event.c
tools/perf/builtin-kmem.c
tools/perf/builtin-trace.c
... | ... | @@ -1055,6 +1055,7 @@ |
1055 | 1055 | |
1056 | 1056 | trace->tool.sample = trace__process_sample; |
1057 | 1057 | trace->tool.mmap = perf_event__process_mmap; |
1058 | + trace->tool.mmap2 = perf_event__process_mmap2; | |
1058 | 1059 | trace->tool.comm = perf_event__process_comm; |
1059 | 1060 | trace->tool.exit = perf_event__process_exit; |
1060 | 1061 | trace->tool.fork = perf_event__process_fork; |
tools/perf/config/Makefile
... | ... | @@ -87,7 +87,7 @@ |
87 | 87 | CFLAGS += -Wextra |
88 | 88 | CFLAGS += -std=gnu99 |
89 | 89 | |
90 | -EXTLIBS = -lelf -lpthread -lrt -lm | |
90 | +EXTLIBS = -lelf -lpthread -lrt -lm -ldl | |
91 | 91 | |
92 | 92 | ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y) |
93 | 93 | CFLAGS += -fstack-protector-all |
tools/perf/util/machine.c
tools/perf/util/probe-finder.c
... | ... | @@ -118,7 +118,6 @@ |
118 | 118 | static int debuginfo__init_offline_dwarf(struct debuginfo *self, |
119 | 119 | const char *path) |
120 | 120 | { |
121 | - Dwfl_Module *mod; | |
122 | 121 | int fd; |
123 | 122 | |
124 | 123 | fd = open(path, O_RDONLY); |
125 | 124 | |
... | ... | @@ -129,11 +128,11 @@ |
129 | 128 | if (!self->dwfl) |
130 | 129 | goto error; |
131 | 130 | |
132 | - mod = dwfl_report_offline(self->dwfl, "", "", fd); | |
133 | - if (!mod) | |
131 | + self->mod = dwfl_report_offline(self->dwfl, "", "", fd); | |
132 | + if (!self->mod) | |
134 | 133 | goto error; |
135 | 134 | |
136 | - self->dbg = dwfl_module_getdwarf(mod, &self->bias); | |
135 | + self->dbg = dwfl_module_getdwarf(self->mod, &self->bias); | |
137 | 136 | if (!self->dbg) |
138 | 137 | goto error; |
139 | 138 | |
140 | 139 | |
141 | 140 | |
142 | 141 | |
... | ... | @@ -676,38 +675,43 @@ |
676 | 675 | } |
677 | 676 | |
678 | 677 | /* Convert subprogram DIE to trace point */ |
679 | -static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr, | |
680 | - bool retprobe, struct probe_trace_point *tp) | |
678 | +static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, | |
679 | + Dwarf_Addr paddr, bool retprobe, | |
680 | + struct probe_trace_point *tp) | |
681 | 681 | { |
682 | 682 | Dwarf_Addr eaddr, highaddr; |
683 | - const char *name; | |
683 | + GElf_Sym sym; | |
684 | + const char *symbol; | |
684 | 685 | |
685 | - /* Copy the name of probe point */ | |
686 | - name = dwarf_diename(sp_die); | |
687 | - if (name) { | |
688 | - if (dwarf_entrypc(sp_die, &eaddr) != 0) { | |
689 | - pr_warning("Failed to get entry address of %s\n", | |
690 | - dwarf_diename(sp_die)); | |
691 | - return -ENOENT; | |
692 | - } | |
693 | - if (dwarf_highpc(sp_die, &highaddr) != 0) { | |
694 | - pr_warning("Failed to get end address of %s\n", | |
695 | - dwarf_diename(sp_die)); | |
696 | - return -ENOENT; | |
697 | - } | |
698 | - if (paddr > highaddr) { | |
699 | - pr_warning("Offset specified is greater than size of %s\n", | |
700 | - dwarf_diename(sp_die)); | |
701 | - return -EINVAL; | |
702 | - } | |
703 | - tp->symbol = strdup(name); | |
704 | - if (tp->symbol == NULL) | |
705 | - return -ENOMEM; | |
706 | - tp->offset = (unsigned long)(paddr - eaddr); | |
707 | - } else | |
708 | - /* This function has no name. */ | |
709 | - tp->offset = (unsigned long)paddr; | |
686 | + /* Verify the address is correct */ | |
687 | + if (dwarf_entrypc(sp_die, &eaddr) != 0) { | |
688 | + pr_warning("Failed to get entry address of %s\n", | |
689 | + dwarf_diename(sp_die)); | |
690 | + return -ENOENT; | |
691 | + } | |
692 | + if (dwarf_highpc(sp_die, &highaddr) != 0) { | |
693 | + pr_warning("Failed to get end address of %s\n", | |
694 | + dwarf_diename(sp_die)); | |
695 | + return -ENOENT; | |
696 | + } | |
697 | + if (paddr > highaddr) { | |
698 | + pr_warning("Offset specified is greater than size of %s\n", | |
699 | + dwarf_diename(sp_die)); | |
700 | + return -EINVAL; | |
701 | + } | |
710 | 702 | |
703 | + /* Get an appropriate symbol from symtab */ | |
704 | + symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); | |
705 | + if (!symbol) { | |
706 | + pr_warning("Failed to find symbol at 0x%lx\n", | |
707 | + (unsigned long)paddr); | |
708 | + return -ENOENT; | |
709 | + } | |
710 | + tp->offset = (unsigned long)(paddr - sym.st_value); | |
711 | + tp->symbol = strdup(symbol); | |
712 | + if (!tp->symbol) | |
713 | + return -ENOMEM; | |
714 | + | |
711 | 715 | /* Return probe must be on the head of a subprogram */ |
712 | 716 | if (retprobe) { |
713 | 717 | if (eaddr != paddr) { |
... | ... | @@ -1149,7 +1153,7 @@ |
1149 | 1153 | tev = &tf->tevs[tf->ntevs++]; |
1150 | 1154 | |
1151 | 1155 | /* Trace point should be converted from subprogram DIE */ |
1152 | - ret = convert_to_trace_point(&pf->sp_die, pf->addr, | |
1156 | + ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr, | |
1153 | 1157 | pf->pev->point.retprobe, &tev->point); |
1154 | 1158 | if (ret < 0) |
1155 | 1159 | return ret; |
... | ... | @@ -1181,7 +1185,7 @@ |
1181 | 1185 | { |
1182 | 1186 | struct trace_event_finder tf = { |
1183 | 1187 | .pf = {.pev = pev, .callback = add_probe_trace_event}, |
1184 | - .max_tevs = max_tevs}; | |
1188 | + .mod = self->mod, .max_tevs = max_tevs}; | |
1185 | 1189 | int ret; |
1186 | 1190 | |
1187 | 1191 | /* Allocate result tevs array */ |
... | ... | @@ -1250,7 +1254,7 @@ |
1250 | 1254 | vl = &af->vls[af->nvls++]; |
1251 | 1255 | |
1252 | 1256 | /* Trace point should be converted from subprogram DIE */ |
1253 | - ret = convert_to_trace_point(&pf->sp_die, pf->addr, | |
1257 | + ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr, | |
1254 | 1258 | pf->pev->point.retprobe, &vl->point); |
1255 | 1259 | if (ret < 0) |
1256 | 1260 | return ret; |
... | ... | @@ -1289,6 +1293,7 @@ |
1289 | 1293 | { |
1290 | 1294 | struct available_var_finder af = { |
1291 | 1295 | .pf = {.pev = pev, .callback = add_available_vars}, |
1296 | + .mod = self->mod, | |
1292 | 1297 | .max_vls = max_vls, .externs = externs}; |
1293 | 1298 | int ret; |
1294 | 1299 |
tools/perf/util/probe-finder.h
... | ... | @@ -23,6 +23,7 @@ |
23 | 23 | /* debug information structure */ |
24 | 24 | struct debuginfo { |
25 | 25 | Dwarf *dbg; |
26 | + Dwfl_Module *mod; | |
26 | 27 | Dwfl *dwfl; |
27 | 28 | Dwarf_Addr bias; |
28 | 29 | }; |
... | ... | @@ -77,6 +78,7 @@ |
77 | 78 | |
78 | 79 | struct trace_event_finder { |
79 | 80 | struct probe_finder pf; |
81 | + Dwfl_Module *mod; /* For solving symbols */ | |
80 | 82 | struct probe_trace_event *tevs; /* Found trace events */ |
81 | 83 | int ntevs; /* Number of trace events */ |
82 | 84 | int max_tevs; /* Max number of trace events */ |
... | ... | @@ -84,6 +86,7 @@ |
84 | 86 | |
85 | 87 | struct available_var_finder { |
86 | 88 | struct probe_finder pf; |
89 | + Dwfl_Module *mod; /* For solving symbols */ | |
87 | 90 | struct variable_list *vls; /* Found variable lists */ |
88 | 91 | int nvls; /* Number of variable lists */ |
89 | 92 | int max_vls; /* Max no. of variable lists */ |
tools/perf/util/symbol-elf.c
... | ... | @@ -928,8 +928,33 @@ |
928 | 928 | * to it... |
929 | 929 | */ |
930 | 930 | if (symbol_conf.demangle) { |
931 | - demangled = bfd_demangle(NULL, elf_name, | |
931 | + /* | |
932 | + * The demangler doesn't deal with cloned functions. | |
933 | + * XXXX.clone.NUM or similar | |
934 | + * Strip the dot part and readd it later. | |
935 | + */ | |
936 | + char *p = (char *)elf_name, *dot; | |
937 | + dot = strchr(elf_name, '.'); | |
938 | + if (dot) { | |
939 | + p = strdup(elf_name); | |
940 | + if (!p) | |
941 | + goto new_symbol; | |
942 | + dot = strchr(p, '.'); | |
943 | + *dot = 0; | |
944 | + } | |
945 | + | |
946 | + demangled = bfd_demangle(NULL, p, | |
932 | 947 | DMGL_PARAMS | DMGL_ANSI); |
948 | + if (dot) | |
949 | + *dot = '.'; | |
950 | + if (demangled && dot) { | |
951 | + demangled = realloc(demangled, strlen(demangled) + strlen(dot) + 1); | |
952 | + if (!demangled) | |
953 | + goto new_symbol; | |
954 | + strcpy(demangled + (dot - p), dot); | |
955 | + } | |
956 | + if (p != elf_name) | |
957 | + free(p); | |
933 | 958 | if (demangled != NULL) |
934 | 959 | elf_name = demangled; |
935 | 960 | } |