Commit 9a969403 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:

 - tracepoint_error() can receive e=NULL, robustify it, fixes a problem noticed
   with a very specific combination: Machine with Intel PT (e.g. Broadwell),
   kernel with no perf_event_attr.context_switch feature (e.g. 4.2) and unreadable
   tracefs (for instance !root users), making the fallback from
   perf_event_attr.context_switch to the sched:sched_switch tracepoint to fail
   reading its info from tracefs, fix it. (Adrian Hunter)

 - Fix segfault in intel PT, by making it follow the 'struct thread' lifetime cycle
   checking expectations, noticed for instance, when processing perf.data files with
   Intel PT data using 'perf script' and when exiting 'perf report' (Adrian Hunter)

 - Fix CFI usage from .eh_frame and .debug_frame, which sometimes requires that we
   fallback from .eh_frame to .debug_frame in architectures such as PowerPC (Hemant Kumar)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents b37a05c0 270bde1e
......@@ -2068,6 +2068,15 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
err = -ENOMEM;
goto err_free_queues;
}
/*
* Since this thread will not be kept in any rbtree not in a
* list, initialize its list node so that at thread__put() the
* current thread lifetime assuption is kept and we don't segfault
* at list_del_init().
*/
INIT_LIST_HEAD(&pt->unknown_thread->node);
err = thread__set_comm(pt->unknown_thread, "unknown", 0);
if (err)
goto err_delete_thread;
......
......@@ -399,6 +399,9 @@ static void tracepoint_error(struct parse_events_error *e, int err,
{
char help[BUFSIZ];
if (!e)
return;
/*
* We get error directly from syscall errno ( > 0),
* or from encoded pointer's error ( < 0).
......
......@@ -686,8 +686,9 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
pf->fb_ops = NULL;
#if _ELFUTILS_PREREQ(0, 142)
} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
pf->cfi != NULL) {
if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
(pf->cfi_eh != NULL || pf->cfi_dbg != NULL)) {
if ((dwarf_cfi_addrframe(pf->cfi_eh, pf->addr, &frame) != 0 &&
(dwarf_cfi_addrframe(pf->cfi_dbg, pf->addr, &frame) != 0)) ||
dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
pr_warning("Failed to get call frame on 0x%jx\n",
(uintmax_t)pf->addr);
......@@ -1015,8 +1016,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
return DWARF_CB_OK;
}
/* Find probe points from debuginfo */
static int debuginfo__find_probes(struct debuginfo *dbg,
static int debuginfo__find_probe_location(struct debuginfo *dbg,
struct probe_finder *pf)
{
struct perf_probe_point *pp = &pf->pev->point;
......@@ -1025,27 +1025,6 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
Dwarf_Die *diep;
int ret = 0;
#if _ELFUTILS_PREREQ(0, 142)
Elf *elf;
GElf_Ehdr ehdr;
GElf_Shdr shdr;
/* Get the call frame information from this dwarf */
elf = dwarf_getelf(dbg->dbg);
if (elf == NULL)
return -EINVAL;
if (gelf_getehdr(elf, &ehdr) == NULL)
return -EINVAL;
if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
shdr.sh_type == SHT_PROGBITS) {
pf->cfi = dwarf_getcfi_elf(elf);
} else {
pf->cfi = dwarf_getcfi(dbg->dbg);
}
#endif
off = 0;
pf->lcache = intlist__new(NULL);
if (!pf->lcache)
......@@ -1108,6 +1087,39 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
return ret;
}
/* Find probe points from debuginfo */
static int debuginfo__find_probes(struct debuginfo *dbg,
struct probe_finder *pf)
{
int ret = 0;
#if _ELFUTILS_PREREQ(0, 142)
Elf *elf;
GElf_Ehdr ehdr;
GElf_Shdr shdr;
if (pf->cfi_eh || pf->cfi_dbg)
return debuginfo__find_probe_location(dbg, pf);
/* Get the call frame information from this dwarf */
elf = dwarf_getelf(dbg->dbg);
if (elf == NULL)
return -EINVAL;
if (gelf_getehdr(elf, &ehdr) == NULL)
return -EINVAL;
if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
shdr.sh_type == SHT_PROGBITS)
pf->cfi_eh = dwarf_getcfi_elf(elf);
pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
#endif
ret = debuginfo__find_probe_location(dbg, pf);
return ret;
}
struct local_vars_finder {
struct probe_finder *pf;
struct perf_probe_arg *args;
......
......@@ -76,7 +76,10 @@ struct probe_finder {
/* For variable searching */
#if _ELFUTILS_PREREQ(0, 142)
Dwarf_CFI *cfi; /* Call Frame Information */
/* Call Frame Information from .eh_frame */
Dwarf_CFI *cfi_eh;
/* Call Frame Information from .debug_frame */
Dwarf_CFI *cfi_dbg;
#endif
Dwarf_Op *fb_ops; /* Frame base attribute */
struct perf_probe_arg *pvar; /* Current target variable */
......
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