forked from Minki/linux
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf tooling fixes from Thomas Gleixner: "Another round of fixes for the perf tooling side: - Prevent a NULL pointer dereference in tracepoint error handling - Fix a thread handling bug in the intel_pt error handling code - Search both .eh_frame and .debug_frame sections as toolchains seem to have random choices of storing the CFI information - Fix the perf state interval output values, which got broken when fixing the overall output" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf stat: Fix interval output values perf probe: Search both .eh_frame and .debug_frame sections for probe location perf tools: Fix thread lifetime related segfaut in intel_pt perf tools: tracepoint_error() can receive e=NULL, robustify it
This commit is contained in:
commit
102a92ce28
@ -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 @@ found:
|
|||||||
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 */
|
||||||
|
@ -311,6 +311,16 @@ int perf_stat_process_counter(struct perf_stat_config *config,
|
|||||||
|
|
||||||
aggr->val = aggr->ena = aggr->run = 0;
|
aggr->val = aggr->ena = aggr->run = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We calculate counter's data every interval,
|
||||||
|
* and the display code shows ps->res_stats
|
||||||
|
* avg value. We need to zero the stats for
|
||||||
|
* interval mode, otherwise overall avg running
|
||||||
|
* averages will be shown for each interval.
|
||||||
|
*/
|
||||||
|
if (config->interval)
|
||||||
|
init_stats(ps->res_stats);
|
||||||
|
|
||||||
if (counter->per_pkg)
|
if (counter->per_pkg)
|
||||||
zero_per_pkg(counter);
|
zero_per_pkg(counter);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user