diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-28 17:21:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-28 17:21:13 -0400 |
commit | 9b565a8051b389e046209a5f68c93eade8de58bd (patch) | |
tree | 421884209c61b00e08fe7d47c957dc210df9a2b5 | |
parent | ddd23eb1829988cc1ebc58a2f622c56c508e219e (diff) | |
parent | 8a3da6c7d0031fcb6a0d17f9c7a68b0e01f52855 (diff) |
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
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-kmem.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 1 | ||||
-rw-r--r-- | tools/perf/config/Makefile | 2 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 2 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 77 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.h | 3 | ||||
-rw-r--r-- | tools/perf/util/symbol-elf.c | 27 |
8 files changed, 75 insertions, 41 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index a9c606bb4945..897783b3302a 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -1506,7 +1506,7 @@ static int __init init_hw_perf_events(void) | |||
1506 | err = amd_pmu_init(); | 1506 | err = amd_pmu_init(); |
1507 | break; | 1507 | break; |
1508 | default: | 1508 | default: |
1509 | return 0; | 1509 | err = -ENOTSUPP; |
1510 | } | 1510 | } |
1511 | if (err != 0) { | 1511 | if (err != 0) { |
1512 | pr_cont("no PMU driver, software events only.\n"); | 1512 | pr_cont("no PMU driver, software events only.\n"); |
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index c2dff9cb1f2c..9b5f077fee5b 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -101,7 +101,7 @@ static int setup_cpunode_map(void) | |||
101 | 101 | ||
102 | dir1 = opendir(PATH_SYS_NODE); | 102 | dir1 = opendir(PATH_SYS_NODE); |
103 | if (!dir1) | 103 | if (!dir1) |
104 | return -1; | 104 | return 0; |
105 | 105 | ||
106 | while ((dent1 = readdir(dir1)) != NULL) { | 106 | while ((dent1 = readdir(dir1)) != NULL) { |
107 | if (dent1->d_type != DT_DIR || | 107 | if (dent1->d_type != DT_DIR || |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index fd4853404727..71aa3e35406b 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -1055,6 +1055,7 @@ static int trace__replay(struct trace *trace) | |||
1055 | 1055 | ||
1056 | trace->tool.sample = trace__process_sample; | 1056 | trace->tool.sample = trace__process_sample; |
1057 | trace->tool.mmap = perf_event__process_mmap; | 1057 | trace->tool.mmap = perf_event__process_mmap; |
1058 | trace->tool.mmap2 = perf_event__process_mmap2; | ||
1058 | trace->tool.comm = perf_event__process_comm; | 1059 | trace->tool.comm = perf_event__process_comm; |
1059 | trace->tool.exit = perf_event__process_exit; | 1060 | trace->tool.exit = perf_event__process_exit; |
1060 | trace->tool.fork = perf_event__process_fork; | 1061 | trace->tool.fork = perf_event__process_fork; |
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 346ee929d250..5f6f9b3271bb 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
@@ -87,7 +87,7 @@ CFLAGS += -Wall | |||
87 | CFLAGS += -Wextra | 87 | CFLAGS += -Wextra |
88 | CFLAGS += -std=gnu99 | 88 | CFLAGS += -std=gnu99 |
89 | 89 | ||
90 | EXTLIBS = -lelf -lpthread -lrt -lm | 90 | EXTLIBS = -lelf -lpthread -lrt -lm -ldl |
91 | 91 | ||
92 | ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y) | 92 | ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y) |
93 | CFLAGS += -fstack-protector-all | 93 | CFLAGS += -fstack-protector-all |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 933d14f287ca..6188d2876a71 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -792,7 +792,7 @@ static int machine__create_modules(struct machine *machine) | |||
792 | modules = path; | 792 | modules = path; |
793 | } | 793 | } |
794 | 794 | ||
795 | if (symbol__restricted_filename(path, "/proc/modules")) | 795 | if (symbol__restricted_filename(modules, "/proc/modules")) |
796 | return -1; | 796 | return -1; |
797 | 797 | ||
798 | file = fopen(modules, "r"); | 798 | file = fopen(modules, "r"); |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 20c7299a9d4e..371476cb8ddc 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -118,7 +118,6 @@ static const Dwfl_Callbacks offline_callbacks = { | |||
118 | static int debuginfo__init_offline_dwarf(struct debuginfo *self, | 118 | static int debuginfo__init_offline_dwarf(struct debuginfo *self, |
119 | const char *path) | 119 | const char *path) |
120 | { | 120 | { |
121 | Dwfl_Module *mod; | ||
122 | int fd; | 121 | int fd; |
123 | 122 | ||
124 | fd = open(path, O_RDONLY); | 123 | fd = open(path, O_RDONLY); |
@@ -129,11 +128,11 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *self, | |||
129 | if (!self->dwfl) | 128 | if (!self->dwfl) |
130 | goto error; | 129 | goto error; |
131 | 130 | ||
132 | mod = dwfl_report_offline(self->dwfl, "", "", fd); | 131 | self->mod = dwfl_report_offline(self->dwfl, "", "", fd); |
133 | if (!mod) | 132 | if (!self->mod) |
134 | goto error; | 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 | if (!self->dbg) | 136 | if (!self->dbg) |
138 | goto error; | 137 | goto error; |
139 | 138 | ||
@@ -676,37 +675,42 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
676 | } | 675 | } |
677 | 676 | ||
678 | /* Convert subprogram DIE to trace point */ | 677 | /* Convert subprogram DIE to trace point */ |
679 | static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr, | 678 | static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, |
680 | bool retprobe, struct probe_trace_point *tp) | 679 | Dwarf_Addr paddr, bool retprobe, |
680 | struct probe_trace_point *tp) | ||
681 | { | 681 | { |
682 | Dwarf_Addr eaddr, highaddr; | 682 | Dwarf_Addr eaddr, highaddr; |
683 | const char *name; | 683 | GElf_Sym sym; |
684 | 684 | const char *symbol; | |
685 | /* Copy the name of probe point */ | 685 | |
686 | name = dwarf_diename(sp_die); | 686 | /* Verify the address is correct */ |
687 | if (name) { | 687 | if (dwarf_entrypc(sp_die, &eaddr) != 0) { |
688 | if (dwarf_entrypc(sp_die, &eaddr) != 0) { | 688 | pr_warning("Failed to get entry address of %s\n", |
689 | pr_warning("Failed to get entry address of %s\n", | 689 | dwarf_diename(sp_die)); |
690 | dwarf_diename(sp_die)); | 690 | return -ENOENT; |
691 | return -ENOENT; | 691 | } |
692 | } | 692 | if (dwarf_highpc(sp_die, &highaddr) != 0) { |
693 | if (dwarf_highpc(sp_die, &highaddr) != 0) { | 693 | pr_warning("Failed to get end address of %s\n", |
694 | pr_warning("Failed to get end address of %s\n", | 694 | dwarf_diename(sp_die)); |
695 | dwarf_diename(sp_die)); | 695 | return -ENOENT; |
696 | return -ENOENT; | 696 | } |
697 | } | 697 | if (paddr > highaddr) { |
698 | if (paddr > highaddr) { | 698 | pr_warning("Offset specified is greater than size of %s\n", |
699 | pr_warning("Offset specified is greater than size of %s\n", | 699 | dwarf_diename(sp_die)); |
700 | dwarf_diename(sp_die)); | 700 | return -EINVAL; |
701 | return -EINVAL; | 701 | } |
702 | } | 702 | |
703 | tp->symbol = strdup(name); | 703 | /* Get an appropriate symbol from symtab */ |
704 | if (tp->symbol == NULL) | 704 | symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); |
705 | return -ENOMEM; | 705 | if (!symbol) { |
706 | tp->offset = (unsigned long)(paddr - eaddr); | 706 | pr_warning("Failed to find symbol at 0x%lx\n", |
707 | } else | 707 | (unsigned long)paddr); |
708 | /* This function has no name. */ | 708 | return -ENOENT; |
709 | tp->offset = (unsigned long)paddr; | 709 | } |
710 | tp->offset = (unsigned long)(paddr - sym.st_value); | ||
711 | tp->symbol = strdup(symbol); | ||
712 | if (!tp->symbol) | ||
713 | return -ENOMEM; | ||
710 | 714 | ||
711 | /* Return probe must be on the head of a subprogram */ | 715 | /* Return probe must be on the head of a subprogram */ |
712 | if (retprobe) { | 716 | if (retprobe) { |
@@ -1149,7 +1153,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1149 | tev = &tf->tevs[tf->ntevs++]; | 1153 | tev = &tf->tevs[tf->ntevs++]; |
1150 | 1154 | ||
1151 | /* Trace point should be converted from subprogram DIE */ | 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 | pf->pev->point.retprobe, &tev->point); | 1157 | pf->pev->point.retprobe, &tev->point); |
1154 | if (ret < 0) | 1158 | if (ret < 0) |
1155 | return ret; | 1159 | return ret; |
@@ -1181,7 +1185,7 @@ int debuginfo__find_trace_events(struct debuginfo *self, | |||
1181 | { | 1185 | { |
1182 | struct trace_event_finder tf = { | 1186 | struct trace_event_finder tf = { |
1183 | .pf = {.pev = pev, .callback = add_probe_trace_event}, | 1187 | .pf = {.pev = pev, .callback = add_probe_trace_event}, |
1184 | .max_tevs = max_tevs}; | 1188 | .mod = self->mod, .max_tevs = max_tevs}; |
1185 | int ret; | 1189 | int ret; |
1186 | 1190 | ||
1187 | /* Allocate result tevs array */ | 1191 | /* Allocate result tevs array */ |
@@ -1250,7 +1254,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1250 | vl = &af->vls[af->nvls++]; | 1254 | vl = &af->vls[af->nvls++]; |
1251 | 1255 | ||
1252 | /* Trace point should be converted from subprogram DIE */ | 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 | pf->pev->point.retprobe, &vl->point); | 1258 | pf->pev->point.retprobe, &vl->point); |
1255 | if (ret < 0) | 1259 | if (ret < 0) |
1256 | return ret; | 1260 | return ret; |
@@ -1289,6 +1293,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self, | |||
1289 | { | 1293 | { |
1290 | struct available_var_finder af = { | 1294 | struct available_var_finder af = { |
1291 | .pf = {.pev = pev, .callback = add_available_vars}, | 1295 | .pf = {.pev = pev, .callback = add_available_vars}, |
1296 | .mod = self->mod, | ||
1292 | .max_vls = max_vls, .externs = externs}; | 1297 | .max_vls = max_vls, .externs = externs}; |
1293 | int ret; | 1298 | int ret; |
1294 | 1299 | ||
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 17e94d0c36f9..3b7d63018960 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h | |||
@@ -23,6 +23,7 @@ static inline int is_c_varname(const char *name) | |||
23 | /* debug information structure */ | 23 | /* debug information structure */ |
24 | struct debuginfo { | 24 | struct debuginfo { |
25 | Dwarf *dbg; | 25 | Dwarf *dbg; |
26 | Dwfl_Module *mod; | ||
26 | Dwfl *dwfl; | 27 | Dwfl *dwfl; |
27 | Dwarf_Addr bias; | 28 | Dwarf_Addr bias; |
28 | }; | 29 | }; |
@@ -77,6 +78,7 @@ struct probe_finder { | |||
77 | 78 | ||
78 | struct trace_event_finder { | 79 | struct trace_event_finder { |
79 | struct probe_finder pf; | 80 | struct probe_finder pf; |
81 | Dwfl_Module *mod; /* For solving symbols */ | ||
80 | struct probe_trace_event *tevs; /* Found trace events */ | 82 | struct probe_trace_event *tevs; /* Found trace events */ |
81 | int ntevs; /* Number of trace events */ | 83 | int ntevs; /* Number of trace events */ |
82 | int max_tevs; /* Max number of trace events */ | 84 | int max_tevs; /* Max number of trace events */ |
@@ -84,6 +86,7 @@ struct trace_event_finder { | |||
84 | 86 | ||
85 | struct available_var_finder { | 87 | struct available_var_finder { |
86 | struct probe_finder pf; | 88 | struct probe_finder pf; |
89 | Dwfl_Module *mod; /* For solving symbols */ | ||
87 | struct variable_list *vls; /* Found variable lists */ | 90 | struct variable_list *vls; /* Found variable lists */ |
88 | int nvls; /* Number of variable lists */ | 91 | int nvls; /* Number of variable lists */ |
89 | int max_vls; /* Max no. of variable lists */ | 92 | int max_vls; /* Max no. of variable lists */ |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index a9c829be5216..d2a888e2e058 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -928,8 +928,33 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
928 | * to it... | 928 | * to it... |
929 | */ | 929 | */ |
930 | if (symbol_conf.demangle) { | 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 | DMGL_PARAMS | DMGL_ANSI); | 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 | if (demangled != NULL) | 958 | if (demangled != NULL) |
934 | elf_name = demangled; | 959 | elf_name = demangled; |
935 | } | 960 | } |