Skip to content

Commit 9a96940

Browse files
author
Ingo Molnar
committed
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>
2 parents b37a05c + 270bde1 commit 9a96940

File tree

4 files changed

+53
-26
lines changed

4 files changed

+53
-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 */

0 commit comments

Comments
 (0)