diff options
| -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 | } |
