Skip to content

Commit 102a92c

Browse files
committed
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
2 parents cb490d6 + 580df49 commit 102a92c

File tree

5 files changed

+63
-26
lines changed

5 files changed

+63
-26
lines changed

tools/perf/util/intel-pt.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2068,6 +2068,15 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
20682068
err = -ENOMEM;
20692069
goto err_free_queues;
20702070
}
2071+
2072+
/*
2073+
* Since this thread will not be kept in any rbtree not in a
2074+
* list, initialize its list node so that at thread__put() the
2075+
* current thread lifetime assuption is kept and we don't segfault
2076+
* at list_del_init().
2077+
*/
2078+
INIT_LIST_HEAD(&pt->unknown_thread->node);
2079+
20712080
err = thread__set_comm(pt->unknown_thread, "unknown", 0);
20722081
if (err)
20732082
goto err_delete_thread;

tools/perf/util/parse-events.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,9 @@ static void tracepoint_error(struct parse_events_error *e, int err,
399399
{
400400
char help[BUFSIZ];
401401

402+
if (!e)
403+
return;
404+
402405
/*
403406
* We get error directly from syscall errno ( > 0),
404407
* or from encoded pointer's error ( < 0).

tools/perf/util/probe-finder.c

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -686,8 +686,9 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
686686
pf->fb_ops = NULL;
687687
#if _ELFUTILS_PREREQ(0, 142)
688688
} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
689-
pf->cfi != NULL) {
690-
if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
689+
(pf->cfi_eh != NULL || pf->cfi_dbg != NULL)) {
690+
if ((dwarf_cfi_addrframe(pf->cfi_eh, pf->addr, &frame) != 0 &&
691+
(dwarf_cfi_addrframe(pf->cfi_dbg, pf->addr, &frame) != 0)) ||
691692
dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
692693
pr_warning("Failed to get call frame on 0x%jx\n",
693694
(uintmax_t)pf->addr);
@@ -1015,8 +1016,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
10151016
return DWARF_CB_OK;
10161017
}
10171018

1018-
/* Find probe points from debuginfo */
1019-
static int debuginfo__find_probes(struct debuginfo *dbg,
1019+
static int debuginfo__find_probe_location(struct debuginfo *dbg,
10201020
struct probe_finder *pf)
10211021
{
10221022
struct perf_probe_point *pp = &pf->pev->point;
@@ -1025,27 +1025,6 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
10251025
Dwarf_Die *diep;
10261026
int ret = 0;
10271027

1028-
#if _ELFUTILS_PREREQ(0, 142)
1029-
Elf *elf;
1030-
GElf_Ehdr ehdr;
1031-
GElf_Shdr shdr;
1032-
1033-
/* Get the call frame information from this dwarf */
1034-
elf = dwarf_getelf(dbg->dbg);
1035-
if (elf == NULL)
1036-
return -EINVAL;
1037-
1038-
if (gelf_getehdr(elf, &ehdr) == NULL)
1039-
return -EINVAL;
1040-
1041-
if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
1042-
shdr.sh_type == SHT_PROGBITS) {
1043-
pf->cfi = dwarf_getcfi_elf(elf);
1044-
} else {
1045-
pf->cfi = dwarf_getcfi(dbg->dbg);
1046-
}
1047-
#endif
1048-
10491028
off = 0;
10501029
pf->lcache = intlist__new(NULL);
10511030
if (!pf->lcache)
@@ -1108,6 +1087,39 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
11081087
return ret;
11091088
}
11101089

1090+
/* Find probe points from debuginfo */
1091+
static int debuginfo__find_probes(struct debuginfo *dbg,
1092+
struct probe_finder *pf)
1093+
{
1094+
int ret = 0;
1095+
1096+
#if _ELFUTILS_PREREQ(0, 142)
1097+
Elf *elf;
1098+
GElf_Ehdr ehdr;
1099+
GElf_Shdr shdr;
1100+
1101+
if (pf->cfi_eh || pf->cfi_dbg)
1102+
return debuginfo__find_probe_location(dbg, pf);
1103+
1104+
/* Get the call frame information from this dwarf */
1105+
elf = dwarf_getelf(dbg->dbg);
1106+
if (elf == NULL)
1107+
return -EINVAL;
1108+
1109+
if (gelf_getehdr(elf, &ehdr) == NULL)
1110+
return -EINVAL;
1111+
1112+
if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
1113+
shdr.sh_type == SHT_PROGBITS)
1114+
pf->cfi_eh = dwarf_getcfi_elf(elf);
1115+
1116+
pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
1117+
#endif
1118+
1119+
ret = debuginfo__find_probe_location(dbg, pf);
1120+
return ret;
1121+
}
1122+
11111123
struct local_vars_finder {
11121124
struct probe_finder *pf;
11131125
struct perf_probe_arg *args;

tools/perf/util/probe-finder.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,10 @@ struct probe_finder {
7676

7777
/* For variable searching */
7878
#if _ELFUTILS_PREREQ(0, 142)
79-
Dwarf_CFI *cfi; /* Call Frame Information */
79+
/* Call Frame Information from .eh_frame */
80+
Dwarf_CFI *cfi_eh;
81+
/* Call Frame Information from .debug_frame */
82+
Dwarf_CFI *cfi_dbg;
8083
#endif
8184
Dwarf_Op *fb_ops; /* Frame base attribute */
8285
struct perf_probe_arg *pvar; /* Current target variable */

tools/perf/util/stat.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,16 @@ int perf_stat_process_counter(struct perf_stat_config *config,
311311

312312
aggr->val = aggr->ena = aggr->run = 0;
313313

314+
/*
315+
* We calculate counter's data every interval,
316+
* and the display code shows ps->res_stats
317+
* avg value. We need to zero the stats for
318+
* interval mode, otherwise overall avg running
319+
* averages will be shown for each interval.
320+
*/
321+
if (config->interval)
322+
init_stats(ps->res_stats);
323+
314324
if (counter->per_pkg)
315325
zero_per_pkg(counter);
316326

0 commit comments

Comments
 (0)