mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 22:31:32 +00:00
perf/urgent fixes:
. 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: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iQIcBAABAgAGBQJSQxkrAAoJENZQFvNTUqpAcpcP/1uI+TT7SNnLJL16aVOO/Vy/ AIOfElMk9PkALA3HPKDP+uiVlz0MInaCCy7+D+taLUv5SPUNpvnr2XVGWZxLQLfN f8Ynt6t1MkKL+4PXQfqj+CM4cR3CBKvP2Xgld7aU7YfMp8JZOP7m4Ni2Oz8EZG0B 1H/6WeOV1dKtZCDIDa55+OcrGCh3wj3ikhIs3HvxhEWbghbRIUaLeMy5V75J8G3C hP7lH0cidU5LiAMs/0jYEM+J/ePf7ne6Prnt4V+miQxNtD6FjFcXmiXTg0rKpu7g fk3lCBzsr9oBA1aBkiXAT3DH/cmcMtqDO7GVVeYlLWyLU5DtbtC2J4qpqc8xWsR7 KfegPiLrvAp74vIFwN2MgQM24RrtWouNNkXkqETcCnwaBuUOXBePK0mzgPhGsFCE sYOGzbXl23Tiv1eKhafbgKb5rUPMW/UkEh8qRT7uEU+V0g/8PC2BLNvZvziuUxg0 WsArk63wSuC6w/N6IOjgih3ggAHfKOziqtanBd0XJ5oh+238/dOWzOPV2iMO43TF dvXfwBY+FhaBzH43VIo3hVcwXtTgRjhQ/7S9NIlotJ+S2ClX9dlH26m1loPDwDib QoP3t2AlYWZqA7t6RAGmhuquKJeht90IgkB1hgP/eCdaWG5Viiy9svCleHDmzVLO POoNQSkhPO0nTRdskTjD =0bM3 -----END PGP SIGNATURE----- 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: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
c1bf21455d
@ -101,7 +101,7 @@ static int setup_cpunode_map(void)
|
||||
|
||||
dir1 = opendir(PATH_SYS_NODE);
|
||||
if (!dir1)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
while ((dent1 = readdir(dir1)) != NULL) {
|
||||
if (dent1->d_type != DT_DIR ||
|
||||
|
@ -1055,6 +1055,7 @@ static int trace__replay(struct trace *trace)
|
||||
|
||||
trace->tool.sample = trace__process_sample;
|
||||
trace->tool.mmap = perf_event__process_mmap;
|
||||
trace->tool.mmap2 = perf_event__process_mmap2;
|
||||
trace->tool.comm = perf_event__process_comm;
|
||||
trace->tool.exit = perf_event__process_exit;
|
||||
trace->tool.fork = perf_event__process_fork;
|
||||
|
@ -87,7 +87,7 @@ CFLAGS += -Wall
|
||||
CFLAGS += -Wextra
|
||||
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)
|
||||
CFLAGS += -fstack-protector-all
|
||||
|
@ -792,7 +792,7 @@ static int machine__create_modules(struct machine *machine)
|
||||
modules = path;
|
||||
}
|
||||
|
||||
if (symbol__restricted_filename(path, "/proc/modules"))
|
||||
if (symbol__restricted_filename(modules, "/proc/modules"))
|
||||
return -1;
|
||||
|
||||
file = fopen(modules, "r");
|
||||
|
@ -118,7 +118,6 @@ static const Dwfl_Callbacks offline_callbacks = {
|
||||
static int debuginfo__init_offline_dwarf(struct debuginfo *self,
|
||||
const char *path)
|
||||
{
|
||||
Dwfl_Module *mod;
|
||||
int fd;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
@ -129,11 +128,11 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *self,
|
||||
if (!self->dwfl)
|
||||
goto error;
|
||||
|
||||
mod = dwfl_report_offline(self->dwfl, "", "", fd);
|
||||
if (!mod)
|
||||
self->mod = dwfl_report_offline(self->dwfl, "", "", fd);
|
||||
if (!self->mod)
|
||||
goto error;
|
||||
|
||||
self->dbg = dwfl_module_getdwarf(mod, &self->bias);
|
||||
self->dbg = dwfl_module_getdwarf(self->mod, &self->bias);
|
||||
if (!self->dbg)
|
||||
goto error;
|
||||
|
||||
@ -676,37 +675,42 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
|
||||
}
|
||||
|
||||
/* Convert subprogram DIE to trace point */
|
||||
static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
|
||||
bool retprobe, struct probe_trace_point *tp)
|
||||
static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
|
||||
Dwarf_Addr paddr, bool retprobe,
|
||||
struct probe_trace_point *tp)
|
||||
{
|
||||
Dwarf_Addr eaddr, highaddr;
|
||||
const char *name;
|
||||
GElf_Sym sym;
|
||||
const char *symbol;
|
||||
|
||||
/* Copy the name of probe point */
|
||||
name = dwarf_diename(sp_die);
|
||||
if (name) {
|
||||
if (dwarf_entrypc(sp_die, &eaddr) != 0) {
|
||||
pr_warning("Failed to get entry address of %s\n",
|
||||
dwarf_diename(sp_die));
|
||||
return -ENOENT;
|
||||
}
|
||||
if (dwarf_highpc(sp_die, &highaddr) != 0) {
|
||||
pr_warning("Failed to get end address of %s\n",
|
||||
dwarf_diename(sp_die));
|
||||
return -ENOENT;
|
||||
}
|
||||
if (paddr > highaddr) {
|
||||
pr_warning("Offset specified is greater than size of %s\n",
|
||||
dwarf_diename(sp_die));
|
||||
return -EINVAL;
|
||||
}
|
||||
tp->symbol = strdup(name);
|
||||
if (tp->symbol == NULL)
|
||||
return -ENOMEM;
|
||||
tp->offset = (unsigned long)(paddr - eaddr);
|
||||
} else
|
||||
/* This function has no name. */
|
||||
tp->offset = (unsigned long)paddr;
|
||||
/* Verify the address is correct */
|
||||
if (dwarf_entrypc(sp_die, &eaddr) != 0) {
|
||||
pr_warning("Failed to get entry address of %s\n",
|
||||
dwarf_diename(sp_die));
|
||||
return -ENOENT;
|
||||
}
|
||||
if (dwarf_highpc(sp_die, &highaddr) != 0) {
|
||||
pr_warning("Failed to get end address of %s\n",
|
||||
dwarf_diename(sp_die));
|
||||
return -ENOENT;
|
||||
}
|
||||
if (paddr > highaddr) {
|
||||
pr_warning("Offset specified is greater than size of %s\n",
|
||||
dwarf_diename(sp_die));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 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 probe must be on the head of a subprogram */
|
||||
if (retprobe) {
|
||||
@ -1149,7 +1153,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
|
||||
tev = &tf->tevs[tf->ntevs++];
|
||||
|
||||
/* 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);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -1181,7 +1185,7 @@ int debuginfo__find_trace_events(struct debuginfo *self,
|
||||
{
|
||||
struct trace_event_finder tf = {
|
||||
.pf = {.pev = pev, .callback = add_probe_trace_event},
|
||||
.max_tevs = max_tevs};
|
||||
.mod = self->mod, .max_tevs = max_tevs};
|
||||
int ret;
|
||||
|
||||
/* Allocate result tevs array */
|
||||
@ -1250,7 +1254,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
|
||||
vl = &af->vls[af->nvls++];
|
||||
|
||||
/* 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);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -1289,6 +1293,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self,
|
||||
{
|
||||
struct available_var_finder af = {
|
||||
.pf = {.pev = pev, .callback = add_available_vars},
|
||||
.mod = self->mod,
|
||||
.max_vls = max_vls, .externs = externs};
|
||||
int ret;
|
||||
|
||||
|
@ -23,6 +23,7 @@ static inline int is_c_varname(const char *name)
|
||||
/* debug information structure */
|
||||
struct debuginfo {
|
||||
Dwarf *dbg;
|
||||
Dwfl_Module *mod;
|
||||
Dwfl *dwfl;
|
||||
Dwarf_Addr bias;
|
||||
};
|
||||
@ -77,6 +78,7 @@ struct probe_finder {
|
||||
|
||||
struct trace_event_finder {
|
||||
struct probe_finder pf;
|
||||
Dwfl_Module *mod; /* For solving symbols */
|
||||
struct probe_trace_event *tevs; /* Found trace events */
|
||||
int ntevs; /* Number of trace events */
|
||||
int max_tevs; /* Max number of trace events */
|
||||
@ -84,6 +86,7 @@ struct trace_event_finder {
|
||||
|
||||
struct available_var_finder {
|
||||
struct probe_finder pf;
|
||||
Dwfl_Module *mod; /* For solving symbols */
|
||||
struct variable_list *vls; /* Found variable lists */
|
||||
int nvls; /* Number 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,
|
||||
* to it...
|
||||
*/
|
||||
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);
|
||||
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)
|
||||
elf_name = demangled;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user