Commit 102a92ce authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents cb490d63 580df49e
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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;
+3 −0
Original line number Diff line number Diff line
@@ -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).
+37 −25
Original line number Diff line number Diff line
@@ -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 @@ found:
	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;
+4 −1
Original line number Diff line number Diff line
@@ -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 */
+10 −0
Original line number Diff line number Diff line
@@ -311,6 +311,16 @@ int perf_stat_process_counter(struct perf_stat_config *config,

	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)
		zero_per_pkg(counter);