Commit c1bf2145 authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-urgent-for-mingo' of...

Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent

Pull perf/urgent fixes from Arnaldo Carvalho de Melo:

 * It was possible to use an uninitialized buffer when reading
   kernel modules information and checking if the file was a
   /proc/sys/kernel/kptr_restrict'ed one, fix for this from
   Adrian Hunter.

 * The libbfd demangler doesn't handle cloned functions (e.g. symbol.clone.NUM),
   feed it unsuffixed symbol names, workaround from Andi Kleen.

 * Fix segfault in 'perf trace' when processing perf.data files with PERF_RECORD_MMAP2
   records, recently added but not handled in this tool, from David Ahern.

 * Fix libdl related build in old systems like Fedora 12, from David Ahern.

 * Make 'perf kmem' work again on non NUMA machines, fix from Jiri Olsa.

 * Fix probing symbols with optimization suffix in 'perf probe' where some
   operations that are entirely user level and involves vmlinux/DWARF were working
   but when the symbol name was fed to the kprobes tracer, the in kernel code
   would use /proc/kallsyms where the name had the suffix, from Masami Hiramatsu.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents cf3b425d de95ab53
...@@ -101,7 +101,7 @@ static int setup_cpunode_map(void) ...@@ -101,7 +101,7 @@ static int setup_cpunode_map(void)
dir1 = opendir(PATH_SYS_NODE); dir1 = opendir(PATH_SYS_NODE);
if (!dir1) if (!dir1)
return -1; return 0;
while ((dent1 = readdir(dir1)) != NULL) { while ((dent1 = readdir(dir1)) != NULL) {
if (dent1->d_type != DT_DIR || if (dent1->d_type != DT_DIR ||
......
...@@ -1055,6 +1055,7 @@ static int trace__replay(struct trace *trace) ...@@ -1055,6 +1055,7 @@ static int trace__replay(struct trace *trace)
trace->tool.sample = trace__process_sample; trace->tool.sample = trace__process_sample;
trace->tool.mmap = perf_event__process_mmap; trace->tool.mmap = perf_event__process_mmap;
trace->tool.mmap2 = perf_event__process_mmap2;
trace->tool.comm = perf_event__process_comm; trace->tool.comm = perf_event__process_comm;
trace->tool.exit = perf_event__process_exit; trace->tool.exit = perf_event__process_exit;
trace->tool.fork = perf_event__process_fork; trace->tool.fork = perf_event__process_fork;
......
...@@ -87,7 +87,7 @@ CFLAGS += -Wall ...@@ -87,7 +87,7 @@ CFLAGS += -Wall
CFLAGS += -Wextra CFLAGS += -Wextra
CFLAGS += -std=gnu99 CFLAGS += -std=gnu99
EXTLIBS = -lelf -lpthread -lrt -lm EXTLIBS = -lelf -lpthread -lrt -lm -ldl
ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y) ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y)
CFLAGS += -fstack-protector-all CFLAGS += -fstack-protector-all
......
...@@ -792,7 +792,7 @@ static int machine__create_modules(struct machine *machine) ...@@ -792,7 +792,7 @@ static int machine__create_modules(struct machine *machine)
modules = path; modules = path;
} }
if (symbol__restricted_filename(path, "/proc/modules")) if (symbol__restricted_filename(modules, "/proc/modules"))
return -1; return -1;
file = fopen(modules, "r"); file = fopen(modules, "r");
......
...@@ -118,7 +118,6 @@ static const Dwfl_Callbacks offline_callbacks = { ...@@ -118,7 +118,6 @@ static const Dwfl_Callbacks offline_callbacks = {
static int debuginfo__init_offline_dwarf(struct debuginfo *self, static int debuginfo__init_offline_dwarf(struct debuginfo *self,
const char *path) const char *path)
{ {
Dwfl_Module *mod;
int fd; int fd;
fd = open(path, O_RDONLY); fd = open(path, O_RDONLY);
...@@ -129,11 +128,11 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *self, ...@@ -129,11 +128,11 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *self,
if (!self->dwfl) if (!self->dwfl)
goto error; goto error;
mod = dwfl_report_offline(self->dwfl, "", "", fd); self->mod = dwfl_report_offline(self->dwfl, "", "", fd);
if (!mod) if (!self->mod)
goto error; goto error;
self->dbg = dwfl_module_getdwarf(mod, &self->bias); self->dbg = dwfl_module_getdwarf(self->mod, &self->bias);
if (!self->dbg) if (!self->dbg)
goto error; goto error;
...@@ -676,15 +675,15 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) ...@@ -676,15 +675,15 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
} }
/* Convert subprogram DIE to trace point */ /* Convert subprogram DIE to trace point */
static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr, static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
bool retprobe, struct probe_trace_point *tp) Dwarf_Addr paddr, bool retprobe,
struct probe_trace_point *tp)
{ {
Dwarf_Addr eaddr, highaddr; Dwarf_Addr eaddr, highaddr;
const char *name; GElf_Sym sym;
const char *symbol;
/* Copy the name of probe point */ /* Verify the address is correct */
name = dwarf_diename(sp_die);
if (name) {
if (dwarf_entrypc(sp_die, &eaddr) != 0) { if (dwarf_entrypc(sp_die, &eaddr) != 0) {
pr_warning("Failed to get entry address of %s\n", pr_warning("Failed to get entry address of %s\n",
dwarf_diename(sp_die)); dwarf_diename(sp_die));
...@@ -700,13 +699,18 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr, ...@@ -700,13 +699,18 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
dwarf_diename(sp_die)); dwarf_diename(sp_die));
return -EINVAL; return -EINVAL;
} }
tp->symbol = strdup(name);
if (tp->symbol == NULL) /* Get an appropriate symbol from symtab */
symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
if (!symbol) {
pr_warning("Failed to find symbol at 0x%lx\n",
(unsigned long)paddr);
return -ENOENT;
}
tp->offset = (unsigned long)(paddr - sym.st_value);
tp->symbol = strdup(symbol);
if (!tp->symbol)
return -ENOMEM; return -ENOMEM;
tp->offset = (unsigned long)(paddr - eaddr);
} else
/* This function has no name. */
tp->offset = (unsigned long)paddr;
/* Return probe must be on the head of a subprogram */ /* Return probe must be on the head of a subprogram */
if (retprobe) { if (retprobe) {
...@@ -1149,7 +1153,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) ...@@ -1149,7 +1153,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
tev = &tf->tevs[tf->ntevs++]; tev = &tf->tevs[tf->ntevs++];
/* Trace point should be converted from subprogram DIE */ /* Trace point should be converted from subprogram DIE */
ret = convert_to_trace_point(&pf->sp_die, pf->addr, ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
pf->pev->point.retprobe, &tev->point); pf->pev->point.retprobe, &tev->point);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1181,7 +1185,7 @@ int debuginfo__find_trace_events(struct debuginfo *self, ...@@ -1181,7 +1185,7 @@ int debuginfo__find_trace_events(struct debuginfo *self,
{ {
struct trace_event_finder tf = { struct trace_event_finder tf = {
.pf = {.pev = pev, .callback = add_probe_trace_event}, .pf = {.pev = pev, .callback = add_probe_trace_event},
.max_tevs = max_tevs}; .mod = self->mod, .max_tevs = max_tevs};
int ret; int ret;
/* Allocate result tevs array */ /* Allocate result tevs array */
...@@ -1250,7 +1254,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) ...@@ -1250,7 +1254,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
vl = &af->vls[af->nvls++]; vl = &af->vls[af->nvls++];
/* Trace point should be converted from subprogram DIE */ /* Trace point should be converted from subprogram DIE */
ret = convert_to_trace_point(&pf->sp_die, pf->addr, ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr,
pf->pev->point.retprobe, &vl->point); pf->pev->point.retprobe, &vl->point);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1289,6 +1293,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self, ...@@ -1289,6 +1293,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self,
{ {
struct available_var_finder af = { struct available_var_finder af = {
.pf = {.pev = pev, .callback = add_available_vars}, .pf = {.pev = pev, .callback = add_available_vars},
.mod = self->mod,
.max_vls = max_vls, .externs = externs}; .max_vls = max_vls, .externs = externs};
int ret; int ret;
......
...@@ -23,6 +23,7 @@ static inline int is_c_varname(const char *name) ...@@ -23,6 +23,7 @@ static inline int is_c_varname(const char *name)
/* debug information structure */ /* debug information structure */
struct debuginfo { struct debuginfo {
Dwarf *dbg; Dwarf *dbg;
Dwfl_Module *mod;
Dwfl *dwfl; Dwfl *dwfl;
Dwarf_Addr bias; Dwarf_Addr bias;
}; };
...@@ -77,6 +78,7 @@ struct probe_finder { ...@@ -77,6 +78,7 @@ struct probe_finder {
struct trace_event_finder { struct trace_event_finder {
struct probe_finder pf; struct probe_finder pf;
Dwfl_Module *mod; /* For solving symbols */
struct probe_trace_event *tevs; /* Found trace events */ struct probe_trace_event *tevs; /* Found trace events */
int ntevs; /* Number of trace events */ int ntevs; /* Number of trace events */
int max_tevs; /* Max number of trace events */ int max_tevs; /* Max number of trace events */
...@@ -84,6 +86,7 @@ struct trace_event_finder { ...@@ -84,6 +86,7 @@ struct trace_event_finder {
struct available_var_finder { struct available_var_finder {
struct probe_finder pf; struct probe_finder pf;
Dwfl_Module *mod; /* For solving symbols */
struct variable_list *vls; /* Found variable lists */ struct variable_list *vls; /* Found variable lists */
int nvls; /* Number of variable lists */ int nvls; /* Number of variable lists */
int max_vls; /* Max no. of variable lists */ int max_vls; /* Max no. of variable lists */
......
...@@ -928,8 +928,33 @@ int dso__load_sym(struct dso *dso, struct map *map, ...@@ -928,8 +928,33 @@ int dso__load_sym(struct dso *dso, struct map *map,
* to it... * to it...
*/ */
if (symbol_conf.demangle) { if (symbol_conf.demangle) {
demangled = bfd_demangle(NULL, elf_name, /*
* The demangler doesn't deal with cloned functions.
* XXXX.clone.NUM or similar
* Strip the dot part and readd it later.
*/
char *p = (char *)elf_name, *dot;
dot = strchr(elf_name, '.');
if (dot) {
p = strdup(elf_name);
if (!p)
goto new_symbol;
dot = strchr(p, '.');
*dot = 0;
}
demangled = bfd_demangle(NULL, p,
DMGL_PARAMS | DMGL_ANSI); DMGL_PARAMS | DMGL_ANSI);
if (dot)
*dot = '.';
if (demangled && dot) {
demangled = realloc(demangled, strlen(demangled) + strlen(dot) + 1);
if (!demangled)
goto new_symbol;
strcpy(demangled + (dot - p), dot);
}
if (p != elf_name)
free(p);
if (demangled != NULL) if (demangled != NULL)
elf_name = demangled; elf_name = demangled;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment