mirror of https://gitee.com/openkylin/linux.git
perf/urgent fixes:
- 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: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWsjJzAAoJENZQFvNTUqpAF2EP/2UJGz/mi7O3wu90YO7BnglD WizS/Y4fTLDfoz9+hwiUscHMvBOpAYMRbGX73AyHCP5qPsv1fRyW5jPCyCqpvDWB TU86CX0t9CEXAj3mKTwShqIXiY9Hmf0lOwxAxY+Y5I12utirqHzZreilBhNvHStz ESYXpTKsDNdU08Zu7nLmKqIlFLnRvY+7sL55+rgcw7DWaIcivpAF8b8RX7iJyoJk fL7dkebXDtZvQpBZ4A8TniACjqebfpg1BSiZ7c9NDIs7YMB+2VPDzXrySP2Oq3q6 u8rZtwn8/0idZ5Es2LWU68QXJL0Z6q7p74BZ+/IO1jSTviegu8CQTfIHRfyx+ur4 IZroUuEPDz9tFw7q8tUt/D48Qbh7rOIFBYUHtbq9e0g1WfW2g0NzP/EseNQxkica uZdfn98cHZyeGiNLhRAjqTwGmZTlV7EoNh6282i7PwyJ9J5nOs36f3Tuo1bekVp+ qtugNbE2xebwwCiBSAHbsQcIrKnyL+bcgSrDzKAP5kBz9r58TQad+CUNQ/IHyhdr q66RYEy3cdmotcPKtK5jxNMYoSoJzlGEpX3FKXZNHkpRIkNp1vZA6MlSIiHOo/A8 eUg6O55XBRJLYdZ/Q2Vb1t1X83g2789o4tgW0tOUtwBwCW7AIQq7w2m08aUCbQf5 2/HaTdhyxMx6ra34dzS1 =0cG5 -----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: - 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: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
9a969403c3
|
@ -2068,6 +2068,15 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto err_free_queues;
|
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);
|
err = thread__set_comm(pt->unknown_thread, "unknown", 0);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_delete_thread;
|
goto err_delete_thread;
|
||||||
|
|
|
@ -399,6 +399,9 @@ static void tracepoint_error(struct parse_events_error *e, int err,
|
||||||
{
|
{
|
||||||
char help[BUFSIZ];
|
char help[BUFSIZ];
|
||||||
|
|
||||||
|
if (!e)
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We get error directly from syscall errno ( > 0),
|
* We get error directly from syscall errno ( > 0),
|
||||||
* or from encoded pointer's error ( < 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;
|
pf->fb_ops = NULL;
|
||||||
#if _ELFUTILS_PREREQ(0, 142)
|
#if _ELFUTILS_PREREQ(0, 142)
|
||||||
} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
|
} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
|
||||||
pf->cfi != NULL) {
|
(pf->cfi_eh != NULL || pf->cfi_dbg != NULL)) {
|
||||||
if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
|
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) {
|
dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
|
||||||
pr_warning("Failed to get call frame on 0x%jx\n",
|
pr_warning("Failed to get call frame on 0x%jx\n",
|
||||||
(uintmax_t)pf->addr);
|
(uintmax_t)pf->addr);
|
||||||
|
@ -1015,8 +1016,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
|
||||||
return DWARF_CB_OK;
|
return DWARF_CB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find probe points from debuginfo */
|
static int debuginfo__find_probe_location(struct debuginfo *dbg,
|
||||||
static int debuginfo__find_probes(struct debuginfo *dbg,
|
|
||||||
struct probe_finder *pf)
|
struct probe_finder *pf)
|
||||||
{
|
{
|
||||||
struct perf_probe_point *pp = &pf->pev->point;
|
struct perf_probe_point *pp = &pf->pev->point;
|
||||||
|
@ -1025,27 +1025,6 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
|
||||||
Dwarf_Die *diep;
|
Dwarf_Die *diep;
|
||||||
int ret = 0;
|
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;
|
off = 0;
|
||||||
pf->lcache = intlist__new(NULL);
|
pf->lcache = intlist__new(NULL);
|
||||||
if (!pf->lcache)
|
if (!pf->lcache)
|
||||||
|
@ -1108,6 +1087,39 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
|
||||||
return ret;
|
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 local_vars_finder {
|
||||||
struct probe_finder *pf;
|
struct probe_finder *pf;
|
||||||
struct perf_probe_arg *args;
|
struct perf_probe_arg *args;
|
||||||
|
|
|
@ -76,7 +76,10 @@ struct probe_finder {
|
||||||
|
|
||||||
/* For variable searching */
|
/* For variable searching */
|
||||||
#if _ELFUTILS_PREREQ(0, 142)
|
#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
|
#endif
|
||||||
Dwarf_Op *fb_ops; /* Frame base attribute */
|
Dwarf_Op *fb_ops; /* Frame base attribute */
|
||||||
struct perf_probe_arg *pvar; /* Current target variable */
|
struct perf_probe_arg *pvar; /* Current target variable */
|
||||||
|
|
Loading…
Reference in New Issue