Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1470262 > unrolled thread
| Started by | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| First post | 2016-08-25 18:30 +0200 |
| Last post | 2016-08-31 03:10 +0200 |
| Articles | 10 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH v2 0/3] perf probe: Introduce remote cross-arch probes Masami Hiramatsu <mhiramat@kernel.org> - 2016-08-25 18:30 +0200
[PATCH v2 3/3] perf-probe: Support probing on offline cross-arch binary Masami Hiramatsu <mhiramat@kernel.org> - 2016-08-25 18:30 +0200
Re: [PATCH v2 3/3] perf-probe: Support probing on offline cross-arch binary Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-08-31 23:00 +0200
Re: [PATCH v2 3/3] perf-probe: Support probing on offline cross-arch binary Masami Hiramatsu <mhiramat@kernel.org> - 2016-09-01 01:30 +0200
[tip:perf/core] perf probe: Support probing on offline cross-arch binary tip-bot for Masami Hiramatsu <tipbot@zytor.com> - 2016-09-05 15:30 +0200
[PATCH v2 1/3] perf-probe: Show trace event definition Masami Hiramatsu <mhiramat@kernel.org> - 2016-08-25 18:30 +0200
[tip:perf/core] perf probe: Show trace event definition tip-bot for Masami Hiramatsu <tipbot@zytor.com> - 2016-09-05 15:30 +0200
[PATCH v2 4/4] perf-probe: Ignore vmlinux Build-id when offline vmlinux given Masami Hiramatsu <mhiramat@kernel.org> - 2016-08-26 17:00 +0200
[tip:perf/core] perf probe: Ignore vmlinux Build-id when offline vmlinux given tip-bot for Masami Hiramatsu <tipbot@zytor.com> - 2016-09-05 15:30 +0200
Re: [PATCH v2 0/3] perf probe: Introduce remote cross-arch probes Masami Hiramatsu <mhiramat@kernel.org> - 2016-08-31 03:10 +0200
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-08-25 18:30 +0200 |
| Subject | [PATCH v2 0/3] perf probe: Introduce remote cross-arch probes |
| Message-ID | <sa5Hr-3mY-11@gated-at.bofh.it> |
Hi,
Here is the 2nd version of remote cross-arch probe support on perf-probe.
V1 is here:
https://lkml.org/lkml/2016/8/24/29
Currently perf-probe doesn't supoort cross/remote target. This means
we have to cross-build the perf-tools including libraries (elfutils,
libelf etc.), and to prepare vmlinux with debuginfo which can be
accessed from the target machine.
This requires too much resource for a small embededd device.
If we can analyze the debuginfo by perf-probe on host machine,
we do not need to cross-build perf-tools, nor copy vmlinux on the
device. :)
For that purpose, this series adds --definition(-D) command for
perf-probe, which shows trace event definition instead of adding
it in running kernel, according to Arnaldo's comment.
Using -D with --vmlinux(or -k)=OFFLINE-VMLINUX, perf-probe reads
the vmlinux architecture and show definition with correct
dwarf-registers.
perf probe -k <cross-vmlinux> -D <probe-point> <arguments>
Here is an example:
-----
$ perf probe --vmlinux=./vmlinux-arm --definition 'do_sys_open $params'
p:probe/do_sys_open do_sys_open+0 dfd=%r5:s32 filename=%r1:u32 flags=%r6:s32 mode=%r3:u16
-----
Here, we can get probe/do_sys_open event by "copy & paste" the
definition to target-machine's debugfs/tracing/kprobe_events.
Note that it shows definition with direct symbol name instead of
_text+offset. It is treated as an offline module.
Thanks,
---
Masami Hiramatsu (3):
perf-probe: Show trace event definition
perf-probe: Ignore vmlinux buildid if offline kernel is given
perf-probe: Support probing on offline cross-arch binary
tools/perf/Documentation/perf-probe.txt | 9 +++
tools/perf/arch/arm/include/dwarf-regs-table.h | 9 +++
tools/perf/arch/arm64/include/dwarf-regs-table.h | 13 +++++
tools/perf/arch/powerpc/include/dwarf-regs-table.h | 27 ++++++++++
tools/perf/arch/s390/include/dwarf-regs-table.h | 8 +++
tools/perf/arch/sh/include/dwarf-regs-table.h | 25 +++++++++
tools/perf/arch/sparc/include/dwarf-regs-table.h | 18 +++++++
tools/perf/arch/x86/include/dwarf-regs-table.h | 14 +++++
tools/perf/arch/xtensa/include/dwarf-regs-table.h | 8 +++
tools/perf/builtin-probe.c | 34 ++++++++++--
tools/perf/util/Build | 1
tools/perf/util/dwarf-regs.c | 55 ++++++++++++++++++++
tools/perf/util/include/dwarf-regs.h | 6 ++
tools/perf/util/probe-event.c | 50 ++++++++++++++++++
tools/perf/util/probe-event.h | 1
tools/perf/util/probe-finder.c | 27 ++++++----
tools/perf/util/probe-finder.h | 1
tools/perf/util/symbol-elf.c | 2 -
18 files changed, 289 insertions(+), 19 deletions(-)
create mode 100644 tools/perf/arch/arm/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/arm64/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/powerpc/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/s390/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/sh/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/sparc/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/x86/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/xtensa/include/dwarf-regs-table.h
create mode 100644 tools/perf/util/dwarf-regs.c
--
Masami Hiramatsu (Linaro Ltd.) <mhiramat@kernel.org>
[toc] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-08-25 18:30 +0200 |
| Subject | [PATCH v2 3/3] perf-probe: Support probing on offline cross-arch binary |
| Message-ID | <sa5Hs-3mY-21@gated-at.bofh.it> |
| In reply to | #1470262 |
Support probing on offline cross-architecture binary by
adding getting the target machine arch from ELF and
choose correct register string for the machine.
Here is an example:
-----
$ perf probe --vmlinux=./vmlinux-arm --definition 'do_sys_open $params'
p:probe/do_sys_open do_sys_open+0 dfd=%r5:s32 filename=%r1:u32 flags=%r6:s32 mode=%r3:u16
-----
Here, we can get probe/do_sys_open event by "copy & paste" from
./tracing/kprobe_events to target-machine's debugfs/tracing/kprobe_events
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
Changes from v1:
- Change the example.
---
tools/perf/arch/arm/include/dwarf-regs-table.h | 9 +++
tools/perf/arch/arm64/include/dwarf-regs-table.h | 13 +++++
tools/perf/arch/powerpc/include/dwarf-regs-table.h | 27 ++++++++++
tools/perf/arch/s390/include/dwarf-regs-table.h | 8 +++
tools/perf/arch/sh/include/dwarf-regs-table.h | 25 +++++++++
tools/perf/arch/sparc/include/dwarf-regs-table.h | 18 +++++++
tools/perf/arch/x86/include/dwarf-regs-table.h | 14 +++++
tools/perf/arch/xtensa/include/dwarf-regs-table.h | 8 +++
tools/perf/util/Build | 1
tools/perf/util/dwarf-regs.c | 55 ++++++++++++++++++++
tools/perf/util/include/dwarf-regs.h | 6 ++
tools/perf/util/probe-finder.c | 27 ++++++----
tools/perf/util/probe-finder.h | 1
13 files changed, 201 insertions(+), 11 deletions(-)
create mode 100644 tools/perf/arch/arm/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/arm64/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/powerpc/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/s390/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/sh/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/sparc/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/x86/include/dwarf-regs-table.h
create mode 100644 tools/perf/arch/xtensa/include/dwarf-regs-table.h
create mode 100644 tools/perf/util/dwarf-regs.c
diff --git a/tools/perf/arch/arm/include/dwarf-regs-table.h b/tools/perf/arch/arm/include/dwarf-regs-table.h
new file mode 100644
index 0000000..f298d03
--- /dev/null
+++ b/tools/perf/arch/arm/include/dwarf-regs-table.h
@@ -0,0 +1,9 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+static const char * const arm_regstr_tbl[] = {
+ "%r0", "%r1", "%r2", "%r3", "%r4",
+ "%r5", "%r6", "%r7", "%r8", "%r9", "%r10",
+ "%fp", "%ip", "%sp", "%lr", "%pc",
+};
+#endif
diff --git a/tools/perf/arch/arm64/include/dwarf-regs-table.h b/tools/perf/arch/arm64/include/dwarf-regs-table.h
new file mode 100644
index 0000000..2675936
--- /dev/null
+++ b/tools/perf/arch/arm64/include/dwarf-regs-table.h
@@ -0,0 +1,13 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+static const char * const aarch64_regstr_tbl[] = {
+ "%r0", "%r1", "%r2", "%r3", "%r4",
+ "%r5", "%r6", "%r7", "%r8", "%r9",
+ "%r10", "%r11", "%r12", "%r13", "%r14",
+ "%r15", "%r16", "%r17", "%r18", "%r19",
+ "%r20", "%r21", "%r22", "%r23", "%r24",
+ "%r25", "%r26", "%r27", "%r28", "%r29",
+ "%lr", "%sp",
+};
+#endif
diff --git a/tools/perf/arch/powerpc/include/dwarf-regs-table.h b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
new file mode 100644
index 0000000..db4730f
--- /dev/null
+++ b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
@@ -0,0 +1,27 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+/*
+ * Reference:
+ * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
+ * http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf
+ */
+#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg
+
+static const char * const powerpc_regstr_tbl[] = {
+ "%gpr0", "%gpr1", "%gpr2", "%gpr3", "%gpr4",
+ "%gpr5", "%gpr6", "%gpr7", "%gpr8", "%gpr9",
+ "%gpr10", "%gpr11", "%gpr12", "%gpr13", "%gpr14",
+ "%gpr15", "%gpr16", "%gpr17", "%gpr18", "%gpr19",
+ "%gpr20", "%gpr21", "%gpr22", "%gpr23", "%gpr24",
+ "%gpr25", "%gpr26", "%gpr27", "%gpr28", "%gpr29",
+ "%gpr30", "%gpr31",
+ REG_DWARFNUM_NAME(msr, 66),
+ REG_DWARFNUM_NAME(ctr, 109),
+ REG_DWARFNUM_NAME(link, 108),
+ REG_DWARFNUM_NAME(xer, 101),
+ REG_DWARFNUM_NAME(dar, 119),
+ REG_DWARFNUM_NAME(dsisr, 118),
+};
+
+#endif
diff --git a/tools/perf/arch/s390/include/dwarf-regs-table.h b/tools/perf/arch/s390/include/dwarf-regs-table.h
new file mode 100644
index 0000000..9da74a9
--- /dev/null
+++ b/tools/perf/arch/s390/include/dwarf-regs-table.h
@@ -0,0 +1,8 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+static const char * const s390_regstr_tbl[] = {
+ "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
+ "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
+};
+#endif
diff --git a/tools/perf/arch/sh/include/dwarf-regs-table.h b/tools/perf/arch/sh/include/dwarf-regs-table.h
new file mode 100644
index 0000000..3a2deaf
--- /dev/null
+++ b/tools/perf/arch/sh/include/dwarf-regs-table.h
@@ -0,0 +1,25 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+const char * const sh_regstr_tbl[] = {
+ "r0",
+ "r1",
+ "r2",
+ "r3",
+ "r4",
+ "r5",
+ "r6",
+ "r7",
+ "r8",
+ "r9",
+ "r10",
+ "r11",
+ "r12",
+ "r13",
+ "r14",
+ "r15",
+ "pc",
+ "pr",
+};
+
+#endif
diff --git a/tools/perf/arch/sparc/include/dwarf-regs-table.h b/tools/perf/arch/sparc/include/dwarf-regs-table.h
new file mode 100644
index 0000000..12c0761
--- /dev/null
+++ b/tools/perf/arch/sparc/include/dwarf-regs-table.h
@@ -0,0 +1,18 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+static const char * const sparc_regstr_tbl[] = {
+ "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
+ "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",
+ "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
+ "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7",
+ "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
+ "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
+ "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
+ "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
+ "%f32", "%f33", "%f34", "%f35", "%f36", "%f37", "%f38", "%f39",
+ "%f40", "%f41", "%f42", "%f43", "%f44", "%f45", "%f46", "%f47",
+ "%f48", "%f49", "%f50", "%f51", "%f52", "%f53", "%f54", "%f55",
+ "%f56", "%f57", "%f58", "%f59", "%f60", "%f61", "%f62", "%f63",
+};
+#endif
diff --git a/tools/perf/arch/x86/include/dwarf-regs-table.h b/tools/perf/arch/x86/include/dwarf-regs-table.h
new file mode 100644
index 0000000..39ac7cb
--- /dev/null
+++ b/tools/perf/arch/x86/include/dwarf-regs-table.h
@@ -0,0 +1,14 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+static const char * const x86_32_regstr_tbl[] = {
+ "%ax", "%cx", "%dx", "%bx", "$stack",/* Stack address instead of %sp */
+ "%bp", "%si", "%di",
+};
+
+static const char * const x86_64_regstr_tbl[] = {
+ "%ax", "dx", "%cx", "%bx", "%si", "%di",
+ "%bp", "%sp", "%r8", "%r9", "%r10", "%r11",
+ "%r12", "%r13", "%r14", "%r15",
+};
+#endif
diff --git a/tools/perf/arch/xtensa/include/dwarf-regs-table.h b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
new file mode 100644
index 0000000..aa0444a
--- /dev/null
+++ b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
@@ -0,0 +1,8 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+static const char * const xtensa_regstr_tbl[] = {
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
+ "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15",
+};
+#endif
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 91c5f6e..f1a6d17 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -98,6 +98,7 @@ endif
libperf-$(CONFIG_DWARF) += probe-finder.o
libperf-$(CONFIG_DWARF) += dwarf-aux.o
+libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o
diff --git a/tools/perf/util/dwarf-regs.c b/tools/perf/util/dwarf-regs.c
new file mode 100644
index 0000000..ce15816
--- /dev/null
+++ b/tools/perf/util/dwarf-regs.c
@@ -0,0 +1,55 @@
+/*
+ * dwarf-regs.c : Mapping of DWARF debug register numbers into register names.
+ *
+ * Written by: Masami Hiramatsu <mhiramat@kernel.org>
+ */
+
+#include <util.h>
+#include <debug.h>
+#include <dwarf-regs.h>
+#include <elf.h>
+
+/* Define const char * {arch}_register_tbl[] */
+#define DEFINE_DWARF_REGSTR_TABLE
+#include "../arch/x86/include/dwarf-regs-table.h"
+#include "../arch/arm/include/dwarf-regs-table.h"
+#include "../arch/arm64/include/dwarf-regs-table.h"
+#include "../arch/sh/include/dwarf-regs-table.h"
+#include "../arch/powerpc/include/dwarf-regs-table.h"
+#include "../arch/s390/include/dwarf-regs-table.h"
+#include "../arch/sparc/include/dwarf-regs-table.h"
+#include "../arch/xtensa/include/dwarf-regs-table.h"
+
+#define __get_dwarf_regstr(tbl, n) (((n) < ARRAY_SIZE(tbl)) ? (tbl)[(n)] : NULL)
+
+/* Return architecture dependent register string (for kprobe-tracer) */
+const char *get_dwarf_regstr(unsigned int n, unsigned int machine)
+{
+ switch (machine) {
+ case EM_NONE: /* Generic arch - use host arch */
+ return get_arch_regstr(n);
+ case EM_386:
+ return __get_dwarf_regstr(x86_32_regstr_tbl, n);
+ case EM_X86_64:
+ return __get_dwarf_regstr(x86_64_regstr_tbl, n);
+ case EM_ARM:
+ return __get_dwarf_regstr(arm_regstr_tbl, n);
+ case EM_AARCH64:
+ return __get_dwarf_regstr(aarch64_regstr_tbl, n);
+ case EM_SH:
+ return __get_dwarf_regstr(sh_regstr_tbl, n);
+ case EM_S390:
+ return __get_dwarf_regstr(s390_regstr_tbl, n);
+ case EM_PPC:
+ case EM_PPC64:
+ return __get_dwarf_regstr(powerpc_regstr_tbl, n);
+ case EM_SPARC:
+ case EM_SPARCV9:
+ return __get_dwarf_regstr(sparc_regstr_tbl, n);
+ case EM_XTENSA:
+ return __get_dwarf_regstr(xtensa_regstr_tbl, n);
+ default:
+ pr_err("ELF MACHINE %x is not supported.\n", machine);
+ }
+ return NULL;
+}
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index 07c644e..43bfd8d 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -3,6 +3,12 @@
#ifdef HAVE_DWARF_SUPPORT
const char *get_arch_regstr(unsigned int n);
+/*
+ * get_dwarf_regstr - Returns ftrace register string from DWARF regnum
+ * n: DWARF register number
+ * machine: ELF machine signature (EM_*)
+ */
+const char *get_dwarf_regstr(unsigned int n, unsigned int machine);
#endif
#ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ac4740f..508b61c 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -171,6 +171,7 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
*/
static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
+ unsigned int machine,
struct probe_trace_arg *tvar)
{
Dwarf_Attribute attr;
@@ -266,7 +267,7 @@ static_var:
if (!tvar)
return ret2;
- regs = get_arch_regstr(regn);
+ regs = get_dwarf_regstr(regn, machine);
if (!regs) {
/* This should be a bug in DWARF or this tool */
pr_warning("Mapping for the register number %u "
@@ -543,7 +544,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
dwarf_diename(vr_die));
ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
- &pf->sp_die, pf->tvar);
+ &pf->sp_die, pf->machine, pf->tvar);
if (ret == -ENOENT || ret == -EINVAL) {
pr_err("Failed to find the location of the '%s' variable at this address.\n"
" Perhaps it has been optimized out.\n"
@@ -1106,11 +1107,8 @@ 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);
@@ -1123,11 +1121,18 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
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->machine = ehdr.e_machine;
+
+#if _ELFUTILS_PREREQ(0, 142)
+ do {
+ GElf_Shdr shdr;
+
+ 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);
+ pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
+ } while (0);
#endif
ret = debuginfo__find_probe_location(dbg, pf);
@@ -1155,7 +1160,7 @@ static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
(tag == DW_TAG_variable && vf->vars)) {
if (convert_variable_location(die_mem, vf->pf->addr,
vf->pf->fb_ops, &pf->sp_die,
- NULL) == 0) {
+ pf->machine, NULL) == 0) {
vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
if (vf->args[vf->nargs].var == NULL) {
vf->ret = -ENOMEM;
@@ -1318,7 +1323,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
tag == DW_TAG_variable) {
ret = convert_variable_location(die_mem, af->pf.addr,
af->pf.fb_ops, &af->pf.sp_die,
- NULL);
+ af->pf.machine, NULL);
if (ret == 0 || ret == -ERANGE) {
int ret2;
bool externs = !af->child;
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 51137fc..f1d8558 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -80,6 +80,7 @@ struct probe_finder {
Dwarf_CFI *cfi_dbg;
#endif
Dwarf_Op *fb_ops; /* Frame base attribute */
+ unsigned int machine; /* Target machine arch */
struct perf_probe_arg *pvar; /* Current target variable */
struct probe_trace_arg *tvar; /* Current result variable */
};
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-08-31 23:00 +0200 |
| Subject | Re: [PATCH v2 3/3] perf-probe: Support probing on offline cross-arch binary |
| Message-ID | <sckM2-7eb-39@gated-at.bofh.it> |
| In reply to | #1470263 |
Em Fri, Aug 26, 2016 at 01:24:57AM +0900, Masami Hiramatsu escreveu:
> Support probing on offline cross-architecture binary by
> adding getting the target machine arch from ELF and
> choose correct register string for the machine.
>
> Here is an example:
> -----
> $ perf probe --vmlinux=./vmlinux-arm --definition 'do_sys_open $params'
> p:probe/do_sys_open do_sys_open+0 dfd=%r5:s32 filename=%r1:u32 flags=%r6:s32 mode=%r3:u16
> -----
> Here, we can get probe/do_sys_open event by "copy & paste" from
> ./tracing/kprobe_events to target-machine's debugfs/tracing/kprobe_events
Fixing the example not to refer to "tracing/kprobe_events", as it is not
there anymore, instead append what '--definition' produced to the target
machine <tracefs mountpoint>/tracing/kprobe_events file.
- Arnaldo
> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
> Changes from v1:
> - Change the example.
> ---
> tools/perf/arch/arm/include/dwarf-regs-table.h | 9 +++
> tools/perf/arch/arm64/include/dwarf-regs-table.h | 13 +++++
> tools/perf/arch/powerpc/include/dwarf-regs-table.h | 27 ++++++++++
> tools/perf/arch/s390/include/dwarf-regs-table.h | 8 +++
> tools/perf/arch/sh/include/dwarf-regs-table.h | 25 +++++++++
> tools/perf/arch/sparc/include/dwarf-regs-table.h | 18 +++++++
> tools/perf/arch/x86/include/dwarf-regs-table.h | 14 +++++
> tools/perf/arch/xtensa/include/dwarf-regs-table.h | 8 +++
> tools/perf/util/Build | 1
> tools/perf/util/dwarf-regs.c | 55 ++++++++++++++++++++
> tools/perf/util/include/dwarf-regs.h | 6 ++
> tools/perf/util/probe-finder.c | 27 ++++++----
> tools/perf/util/probe-finder.h | 1
> 13 files changed, 201 insertions(+), 11 deletions(-)
> create mode 100644 tools/perf/arch/arm/include/dwarf-regs-table.h
> create mode 100644 tools/perf/arch/arm64/include/dwarf-regs-table.h
> create mode 100644 tools/perf/arch/powerpc/include/dwarf-regs-table.h
> create mode 100644 tools/perf/arch/s390/include/dwarf-regs-table.h
> create mode 100644 tools/perf/arch/sh/include/dwarf-regs-table.h
> create mode 100644 tools/perf/arch/sparc/include/dwarf-regs-table.h
> create mode 100644 tools/perf/arch/x86/include/dwarf-regs-table.h
> create mode 100644 tools/perf/arch/xtensa/include/dwarf-regs-table.h
> create mode 100644 tools/perf/util/dwarf-regs.c
>
> diff --git a/tools/perf/arch/arm/include/dwarf-regs-table.h b/tools/perf/arch/arm/include/dwarf-regs-table.h
> new file mode 100644
> index 0000000..f298d03
> --- /dev/null
> +++ b/tools/perf/arch/arm/include/dwarf-regs-table.h
> @@ -0,0 +1,9 @@
> +#ifdef DEFINE_DWARF_REGSTR_TABLE
> +/* This is included in perf/util/dwarf-regs.c */
> +
> +static const char * const arm_regstr_tbl[] = {
> + "%r0", "%r1", "%r2", "%r3", "%r4",
> + "%r5", "%r6", "%r7", "%r8", "%r9", "%r10",
> + "%fp", "%ip", "%sp", "%lr", "%pc",
> +};
> +#endif
> diff --git a/tools/perf/arch/arm64/include/dwarf-regs-table.h b/tools/perf/arch/arm64/include/dwarf-regs-table.h
> new file mode 100644
> index 0000000..2675936
> --- /dev/null
> +++ b/tools/perf/arch/arm64/include/dwarf-regs-table.h
> @@ -0,0 +1,13 @@
> +#ifdef DEFINE_DWARF_REGSTR_TABLE
> +/* This is included in perf/util/dwarf-regs.c */
> +
> +static const char * const aarch64_regstr_tbl[] = {
> + "%r0", "%r1", "%r2", "%r3", "%r4",
> + "%r5", "%r6", "%r7", "%r8", "%r9",
> + "%r10", "%r11", "%r12", "%r13", "%r14",
> + "%r15", "%r16", "%r17", "%r18", "%r19",
> + "%r20", "%r21", "%r22", "%r23", "%r24",
> + "%r25", "%r26", "%r27", "%r28", "%r29",
> + "%lr", "%sp",
> +};
> +#endif
> diff --git a/tools/perf/arch/powerpc/include/dwarf-regs-table.h b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
> new file mode 100644
> index 0000000..db4730f
> --- /dev/null
> +++ b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
> @@ -0,0 +1,27 @@
> +#ifdef DEFINE_DWARF_REGSTR_TABLE
> +/* This is included in perf/util/dwarf-regs.c */
> +
> +/*
> + * Reference:
> + * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
> + * http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf
> + */
> +#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg
> +
> +static const char * const powerpc_regstr_tbl[] = {
> + "%gpr0", "%gpr1", "%gpr2", "%gpr3", "%gpr4",
> + "%gpr5", "%gpr6", "%gpr7", "%gpr8", "%gpr9",
> + "%gpr10", "%gpr11", "%gpr12", "%gpr13", "%gpr14",
> + "%gpr15", "%gpr16", "%gpr17", "%gpr18", "%gpr19",
> + "%gpr20", "%gpr21", "%gpr22", "%gpr23", "%gpr24",
> + "%gpr25", "%gpr26", "%gpr27", "%gpr28", "%gpr29",
> + "%gpr30", "%gpr31",
> + REG_DWARFNUM_NAME(msr, 66),
> + REG_DWARFNUM_NAME(ctr, 109),
> + REG_DWARFNUM_NAME(link, 108),
> + REG_DWARFNUM_NAME(xer, 101),
> + REG_DWARFNUM_NAME(dar, 119),
> + REG_DWARFNUM_NAME(dsisr, 118),
> +};
> +
> +#endif
> diff --git a/tools/perf/arch/s390/include/dwarf-regs-table.h b/tools/perf/arch/s390/include/dwarf-regs-table.h
> new file mode 100644
> index 0000000..9da74a9
> --- /dev/null
> +++ b/tools/perf/arch/s390/include/dwarf-regs-table.h
> @@ -0,0 +1,8 @@
> +#ifdef DEFINE_DWARF_REGSTR_TABLE
> +/* This is included in perf/util/dwarf-regs.c */
> +
> +static const char * const s390_regstr_tbl[] = {
> + "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
> + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
> +};
> +#endif
> diff --git a/tools/perf/arch/sh/include/dwarf-regs-table.h b/tools/perf/arch/sh/include/dwarf-regs-table.h
> new file mode 100644
> index 0000000..3a2deaf
> --- /dev/null
> +++ b/tools/perf/arch/sh/include/dwarf-regs-table.h
> @@ -0,0 +1,25 @@
> +#ifdef DEFINE_DWARF_REGSTR_TABLE
> +/* This is included in perf/util/dwarf-regs.c */
> +
> +const char * const sh_regstr_tbl[] = {
> + "r0",
> + "r1",
> + "r2",
> + "r3",
> + "r4",
> + "r5",
> + "r6",
> + "r7",
> + "r8",
> + "r9",
> + "r10",
> + "r11",
> + "r12",
> + "r13",
> + "r14",
> + "r15",
> + "pc",
> + "pr",
> +};
> +
> +#endif
> diff --git a/tools/perf/arch/sparc/include/dwarf-regs-table.h b/tools/perf/arch/sparc/include/dwarf-regs-table.h
> new file mode 100644
> index 0000000..12c0761
> --- /dev/null
> +++ b/tools/perf/arch/sparc/include/dwarf-regs-table.h
> @@ -0,0 +1,18 @@
> +#ifdef DEFINE_DWARF_REGSTR_TABLE
> +/* This is included in perf/util/dwarf-regs.c */
> +
> +static const char * const sparc_regstr_tbl[] = {
> + "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
> + "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",
> + "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
> + "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7",
> + "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
> + "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
> + "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
> + "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
> + "%f32", "%f33", "%f34", "%f35", "%f36", "%f37", "%f38", "%f39",
> + "%f40", "%f41", "%f42", "%f43", "%f44", "%f45", "%f46", "%f47",
> + "%f48", "%f49", "%f50", "%f51", "%f52", "%f53", "%f54", "%f55",
> + "%f56", "%f57", "%f58", "%f59", "%f60", "%f61", "%f62", "%f63",
> +};
> +#endif
> diff --git a/tools/perf/arch/x86/include/dwarf-regs-table.h b/tools/perf/arch/x86/include/dwarf-regs-table.h
> new file mode 100644
> index 0000000..39ac7cb
> --- /dev/null
> +++ b/tools/perf/arch/x86/include/dwarf-regs-table.h
> @@ -0,0 +1,14 @@
> +#ifdef DEFINE_DWARF_REGSTR_TABLE
> +/* This is included in perf/util/dwarf-regs.c */
> +
> +static const char * const x86_32_regstr_tbl[] = {
> + "%ax", "%cx", "%dx", "%bx", "$stack",/* Stack address instead of %sp */
> + "%bp", "%si", "%di",
> +};
> +
> +static const char * const x86_64_regstr_tbl[] = {
> + "%ax", "dx", "%cx", "%bx", "%si", "%di",
> + "%bp", "%sp", "%r8", "%r9", "%r10", "%r11",
> + "%r12", "%r13", "%r14", "%r15",
> +};
> +#endif
> diff --git a/tools/perf/arch/xtensa/include/dwarf-regs-table.h b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
> new file mode 100644
> index 0000000..aa0444a
> --- /dev/null
> +++ b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
> @@ -0,0 +1,8 @@
> +#ifdef DEFINE_DWARF_REGSTR_TABLE
> +/* This is included in perf/util/dwarf-regs.c */
> +
> +static const char * const xtensa_regstr_tbl[] = {
> + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
> + "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15",
> +};
> +#endif
> diff --git a/tools/perf/util/Build b/tools/perf/util/Build
> index 91c5f6e..f1a6d17 100644
> --- a/tools/perf/util/Build
> +++ b/tools/perf/util/Build
> @@ -98,6 +98,7 @@ endif
>
> libperf-$(CONFIG_DWARF) += probe-finder.o
> libperf-$(CONFIG_DWARF) += dwarf-aux.o
> +libperf-$(CONFIG_DWARF) += dwarf-regs.o
>
> libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
> libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o
> diff --git a/tools/perf/util/dwarf-regs.c b/tools/perf/util/dwarf-regs.c
> new file mode 100644
> index 0000000..ce15816
> --- /dev/null
> +++ b/tools/perf/util/dwarf-regs.c
> @@ -0,0 +1,55 @@
> +/*
> + * dwarf-regs.c : Mapping of DWARF debug register numbers into register names.
> + *
> + * Written by: Masami Hiramatsu <mhiramat@kernel.org>
> + */
> +
> +#include <util.h>
> +#include <debug.h>
> +#include <dwarf-regs.h>
> +#include <elf.h>
> +
> +/* Define const char * {arch}_register_tbl[] */
> +#define DEFINE_DWARF_REGSTR_TABLE
> +#include "../arch/x86/include/dwarf-regs-table.h"
> +#include "../arch/arm/include/dwarf-regs-table.h"
> +#include "../arch/arm64/include/dwarf-regs-table.h"
> +#include "../arch/sh/include/dwarf-regs-table.h"
> +#include "../arch/powerpc/include/dwarf-regs-table.h"
> +#include "../arch/s390/include/dwarf-regs-table.h"
> +#include "../arch/sparc/include/dwarf-regs-table.h"
> +#include "../arch/xtensa/include/dwarf-regs-table.h"
> +
> +#define __get_dwarf_regstr(tbl, n) (((n) < ARRAY_SIZE(tbl)) ? (tbl)[(n)] : NULL)
> +
> +/* Return architecture dependent register string (for kprobe-tracer) */
> +const char *get_dwarf_regstr(unsigned int n, unsigned int machine)
> +{
> + switch (machine) {
> + case EM_NONE: /* Generic arch - use host arch */
> + return get_arch_regstr(n);
> + case EM_386:
> + return __get_dwarf_regstr(x86_32_regstr_tbl, n);
> + case EM_X86_64:
> + return __get_dwarf_regstr(x86_64_regstr_tbl, n);
> + case EM_ARM:
> + return __get_dwarf_regstr(arm_regstr_tbl, n);
> + case EM_AARCH64:
> + return __get_dwarf_regstr(aarch64_regstr_tbl, n);
> + case EM_SH:
> + return __get_dwarf_regstr(sh_regstr_tbl, n);
> + case EM_S390:
> + return __get_dwarf_regstr(s390_regstr_tbl, n);
> + case EM_PPC:
> + case EM_PPC64:
> + return __get_dwarf_regstr(powerpc_regstr_tbl, n);
> + case EM_SPARC:
> + case EM_SPARCV9:
> + return __get_dwarf_regstr(sparc_regstr_tbl, n);
> + case EM_XTENSA:
> + return __get_dwarf_regstr(xtensa_regstr_tbl, n);
> + default:
> + pr_err("ELF MACHINE %x is not supported.\n", machine);
> + }
> + return NULL;
> +}
> diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
> index 07c644e..43bfd8d 100644
> --- a/tools/perf/util/include/dwarf-regs.h
> +++ b/tools/perf/util/include/dwarf-regs.h
> @@ -3,6 +3,12 @@
>
> #ifdef HAVE_DWARF_SUPPORT
> const char *get_arch_regstr(unsigned int n);
> +/*
> + * get_dwarf_regstr - Returns ftrace register string from DWARF regnum
> + * n: DWARF register number
> + * machine: ELF machine signature (EM_*)
> + */
> +const char *get_dwarf_regstr(unsigned int n, unsigned int machine);
> #endif
>
> #ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
> diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
> index ac4740f..508b61c 100644
> --- a/tools/perf/util/probe-finder.c
> +++ b/tools/perf/util/probe-finder.c
> @@ -171,6 +171,7 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
> */
> static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
> Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
> + unsigned int machine,
> struct probe_trace_arg *tvar)
> {
> Dwarf_Attribute attr;
> @@ -266,7 +267,7 @@ static_var:
> if (!tvar)
> return ret2;
>
> - regs = get_arch_regstr(regn);
> + regs = get_dwarf_regstr(regn, machine);
> if (!regs) {
> /* This should be a bug in DWARF or this tool */
> pr_warning("Mapping for the register number %u "
> @@ -543,7 +544,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
> dwarf_diename(vr_die));
>
> ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
> - &pf->sp_die, pf->tvar);
> + &pf->sp_die, pf->machine, pf->tvar);
> if (ret == -ENOENT || ret == -EINVAL) {
> pr_err("Failed to find the location of the '%s' variable at this address.\n"
> " Perhaps it has been optimized out.\n"
> @@ -1106,11 +1107,8 @@ 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);
> @@ -1123,11 +1121,18 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
> 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->machine = ehdr.e_machine;
> +
> +#if _ELFUTILS_PREREQ(0, 142)
> + do {
> + GElf_Shdr shdr;
> +
> + 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);
> + pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
> + } while (0);
> #endif
>
> ret = debuginfo__find_probe_location(dbg, pf);
> @@ -1155,7 +1160,7 @@ static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
> (tag == DW_TAG_variable && vf->vars)) {
> if (convert_variable_location(die_mem, vf->pf->addr,
> vf->pf->fb_ops, &pf->sp_die,
> - NULL) == 0) {
> + pf->machine, NULL) == 0) {
> vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
> if (vf->args[vf->nargs].var == NULL) {
> vf->ret = -ENOMEM;
> @@ -1318,7 +1323,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
> tag == DW_TAG_variable) {
> ret = convert_variable_location(die_mem, af->pf.addr,
> af->pf.fb_ops, &af->pf.sp_die,
> - NULL);
> + af->pf.machine, NULL);
> if (ret == 0 || ret == -ERANGE) {
> int ret2;
> bool externs = !af->child;
> diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
> index 51137fc..f1d8558 100644
> --- a/tools/perf/util/probe-finder.h
> +++ b/tools/perf/util/probe-finder.h
> @@ -80,6 +80,7 @@ struct probe_finder {
> Dwarf_CFI *cfi_dbg;
> #endif
> Dwarf_Op *fb_ops; /* Frame base attribute */
> + unsigned int machine; /* Target machine arch */
> struct perf_probe_arg *pvar; /* Current target variable */
> struct probe_trace_arg *tvar; /* Current result variable */
> };
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-09-01 01:30 +0200 |
| Subject | Re: [PATCH v2 3/3] perf-probe: Support probing on offline cross-arch binary |
| Message-ID | <scn7c-pj-5@gated-at.bofh.it> |
| In reply to | #1473856 |
On Wed, 31 Aug 2016 17:54:11 -0300
Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> Em Fri, Aug 26, 2016 at 01:24:57AM +0900, Masami Hiramatsu escreveu:
> > Support probing on offline cross-architecture binary by
> > adding getting the target machine arch from ELF and
> > choose correct register string for the machine.
> >
> > Here is an example:
> > -----
> > $ perf probe --vmlinux=./vmlinux-arm --definition 'do_sys_open $params'
> > p:probe/do_sys_open do_sys_open+0 dfd=%r5:s32 filename=%r1:u32 flags=%r6:s32 mode=%r3:u16
> > -----
> > Here, we can get probe/do_sys_open event by "copy & paste" from
> > ./tracing/kprobe_events to target-machine's debugfs/tracing/kprobe_events
>
> Fixing the example not to refer to "tracing/kprobe_events", as it is not
> there anymore, instead append what '--definition' produced to the target
> machine <tracefs mountpoint>/tracing/kprobe_events file.
Oops, right, it's my mistake...
Thank you,
>
> - Arnaldo
>
> > Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> > ---
> > Changes from v1:
> > - Change the example.
> > ---
> > tools/perf/arch/arm/include/dwarf-regs-table.h | 9 +++
> > tools/perf/arch/arm64/include/dwarf-regs-table.h | 13 +++++
> > tools/perf/arch/powerpc/include/dwarf-regs-table.h | 27 ++++++++++
> > tools/perf/arch/s390/include/dwarf-regs-table.h | 8 +++
> > tools/perf/arch/sh/include/dwarf-regs-table.h | 25 +++++++++
> > tools/perf/arch/sparc/include/dwarf-regs-table.h | 18 +++++++
> > tools/perf/arch/x86/include/dwarf-regs-table.h | 14 +++++
> > tools/perf/arch/xtensa/include/dwarf-regs-table.h | 8 +++
> > tools/perf/util/Build | 1
> > tools/perf/util/dwarf-regs.c | 55 ++++++++++++++++++++
> > tools/perf/util/include/dwarf-regs.h | 6 ++
> > tools/perf/util/probe-finder.c | 27 ++++++----
> > tools/perf/util/probe-finder.h | 1
> > 13 files changed, 201 insertions(+), 11 deletions(-)
> > create mode 100644 tools/perf/arch/arm/include/dwarf-regs-table.h
> > create mode 100644 tools/perf/arch/arm64/include/dwarf-regs-table.h
> > create mode 100644 tools/perf/arch/powerpc/include/dwarf-regs-table.h
> > create mode 100644 tools/perf/arch/s390/include/dwarf-regs-table.h
> > create mode 100644 tools/perf/arch/sh/include/dwarf-regs-table.h
> > create mode 100644 tools/perf/arch/sparc/include/dwarf-regs-table.h
> > create mode 100644 tools/perf/arch/x86/include/dwarf-regs-table.h
> > create mode 100644 tools/perf/arch/xtensa/include/dwarf-regs-table.h
> > create mode 100644 tools/perf/util/dwarf-regs.c
> >
> > diff --git a/tools/perf/arch/arm/include/dwarf-regs-table.h b/tools/perf/arch/arm/include/dwarf-regs-table.h
> > new file mode 100644
> > index 0000000..f298d03
> > --- /dev/null
> > +++ b/tools/perf/arch/arm/include/dwarf-regs-table.h
> > @@ -0,0 +1,9 @@
> > +#ifdef DEFINE_DWARF_REGSTR_TABLE
> > +/* This is included in perf/util/dwarf-regs.c */
> > +
> > +static const char * const arm_regstr_tbl[] = {
> > + "%r0", "%r1", "%r2", "%r3", "%r4",
> > + "%r5", "%r6", "%r7", "%r8", "%r9", "%r10",
> > + "%fp", "%ip", "%sp", "%lr", "%pc",
> > +};
> > +#endif
> > diff --git a/tools/perf/arch/arm64/include/dwarf-regs-table.h b/tools/perf/arch/arm64/include/dwarf-regs-table.h
> > new file mode 100644
> > index 0000000..2675936
> > --- /dev/null
> > +++ b/tools/perf/arch/arm64/include/dwarf-regs-table.h
> > @@ -0,0 +1,13 @@
> > +#ifdef DEFINE_DWARF_REGSTR_TABLE
> > +/* This is included in perf/util/dwarf-regs.c */
> > +
> > +static const char * const aarch64_regstr_tbl[] = {
> > + "%r0", "%r1", "%r2", "%r3", "%r4",
> > + "%r5", "%r6", "%r7", "%r8", "%r9",
> > + "%r10", "%r11", "%r12", "%r13", "%r14",
> > + "%r15", "%r16", "%r17", "%r18", "%r19",
> > + "%r20", "%r21", "%r22", "%r23", "%r24",
> > + "%r25", "%r26", "%r27", "%r28", "%r29",
> > + "%lr", "%sp",
> > +};
> > +#endif
> > diff --git a/tools/perf/arch/powerpc/include/dwarf-regs-table.h b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
> > new file mode 100644
> > index 0000000..db4730f
> > --- /dev/null
> > +++ b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
> > @@ -0,0 +1,27 @@
> > +#ifdef DEFINE_DWARF_REGSTR_TABLE
> > +/* This is included in perf/util/dwarf-regs.c */
> > +
> > +/*
> > + * Reference:
> > + * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
> > + * http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf
> > + */
> > +#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg
> > +
> > +static const char * const powerpc_regstr_tbl[] = {
> > + "%gpr0", "%gpr1", "%gpr2", "%gpr3", "%gpr4",
> > + "%gpr5", "%gpr6", "%gpr7", "%gpr8", "%gpr9",
> > + "%gpr10", "%gpr11", "%gpr12", "%gpr13", "%gpr14",
> > + "%gpr15", "%gpr16", "%gpr17", "%gpr18", "%gpr19",
> > + "%gpr20", "%gpr21", "%gpr22", "%gpr23", "%gpr24",
> > + "%gpr25", "%gpr26", "%gpr27", "%gpr28", "%gpr29",
> > + "%gpr30", "%gpr31",
> > + REG_DWARFNUM_NAME(msr, 66),
> > + REG_DWARFNUM_NAME(ctr, 109),
> > + REG_DWARFNUM_NAME(link, 108),
> > + REG_DWARFNUM_NAME(xer, 101),
> > + REG_DWARFNUM_NAME(dar, 119),
> > + REG_DWARFNUM_NAME(dsisr, 118),
> > +};
> > +
> > +#endif
> > diff --git a/tools/perf/arch/s390/include/dwarf-regs-table.h b/tools/perf/arch/s390/include/dwarf-regs-table.h
> > new file mode 100644
> > index 0000000..9da74a9
> > --- /dev/null
> > +++ b/tools/perf/arch/s390/include/dwarf-regs-table.h
> > @@ -0,0 +1,8 @@
> > +#ifdef DEFINE_DWARF_REGSTR_TABLE
> > +/* This is included in perf/util/dwarf-regs.c */
> > +
> > +static const char * const s390_regstr_tbl[] = {
> > + "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
> > + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
> > +};
> > +#endif
> > diff --git a/tools/perf/arch/sh/include/dwarf-regs-table.h b/tools/perf/arch/sh/include/dwarf-regs-table.h
> > new file mode 100644
> > index 0000000..3a2deaf
> > --- /dev/null
> > +++ b/tools/perf/arch/sh/include/dwarf-regs-table.h
> > @@ -0,0 +1,25 @@
> > +#ifdef DEFINE_DWARF_REGSTR_TABLE
> > +/* This is included in perf/util/dwarf-regs.c */
> > +
> > +const char * const sh_regstr_tbl[] = {
> > + "r0",
> > + "r1",
> > + "r2",
> > + "r3",
> > + "r4",
> > + "r5",
> > + "r6",
> > + "r7",
> > + "r8",
> > + "r9",
> > + "r10",
> > + "r11",
> > + "r12",
> > + "r13",
> > + "r14",
> > + "r15",
> > + "pc",
> > + "pr",
> > +};
> > +
> > +#endif
> > diff --git a/tools/perf/arch/sparc/include/dwarf-regs-table.h b/tools/perf/arch/sparc/include/dwarf-regs-table.h
> > new file mode 100644
> > index 0000000..12c0761
> > --- /dev/null
> > +++ b/tools/perf/arch/sparc/include/dwarf-regs-table.h
> > @@ -0,0 +1,18 @@
> > +#ifdef DEFINE_DWARF_REGSTR_TABLE
> > +/* This is included in perf/util/dwarf-regs.c */
> > +
> > +static const char * const sparc_regstr_tbl[] = {
> > + "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
> > + "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",
> > + "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
> > + "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7",
> > + "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
> > + "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
> > + "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
> > + "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
> > + "%f32", "%f33", "%f34", "%f35", "%f36", "%f37", "%f38", "%f39",
> > + "%f40", "%f41", "%f42", "%f43", "%f44", "%f45", "%f46", "%f47",
> > + "%f48", "%f49", "%f50", "%f51", "%f52", "%f53", "%f54", "%f55",
> > + "%f56", "%f57", "%f58", "%f59", "%f60", "%f61", "%f62", "%f63",
> > +};
> > +#endif
> > diff --git a/tools/perf/arch/x86/include/dwarf-regs-table.h b/tools/perf/arch/x86/include/dwarf-regs-table.h
> > new file mode 100644
> > index 0000000..39ac7cb
> > --- /dev/null
> > +++ b/tools/perf/arch/x86/include/dwarf-regs-table.h
> > @@ -0,0 +1,14 @@
> > +#ifdef DEFINE_DWARF_REGSTR_TABLE
> > +/* This is included in perf/util/dwarf-regs.c */
> > +
> > +static const char * const x86_32_regstr_tbl[] = {
> > + "%ax", "%cx", "%dx", "%bx", "$stack",/* Stack address instead of %sp */
> > + "%bp", "%si", "%di",
> > +};
> > +
> > +static const char * const x86_64_regstr_tbl[] = {
> > + "%ax", "dx", "%cx", "%bx", "%si", "%di",
> > + "%bp", "%sp", "%r8", "%r9", "%r10", "%r11",
> > + "%r12", "%r13", "%r14", "%r15",
> > +};
> > +#endif
> > diff --git a/tools/perf/arch/xtensa/include/dwarf-regs-table.h b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
> > new file mode 100644
> > index 0000000..aa0444a
> > --- /dev/null
> > +++ b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
> > @@ -0,0 +1,8 @@
> > +#ifdef DEFINE_DWARF_REGSTR_TABLE
> > +/* This is included in perf/util/dwarf-regs.c */
> > +
> > +static const char * const xtensa_regstr_tbl[] = {
> > + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
> > + "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15",
> > +};
> > +#endif
> > diff --git a/tools/perf/util/Build b/tools/perf/util/Build
> > index 91c5f6e..f1a6d17 100644
> > --- a/tools/perf/util/Build
> > +++ b/tools/perf/util/Build
> > @@ -98,6 +98,7 @@ endif
> >
> > libperf-$(CONFIG_DWARF) += probe-finder.o
> > libperf-$(CONFIG_DWARF) += dwarf-aux.o
> > +libperf-$(CONFIG_DWARF) += dwarf-regs.o
> >
> > libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
> > libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o
> > diff --git a/tools/perf/util/dwarf-regs.c b/tools/perf/util/dwarf-regs.c
> > new file mode 100644
> > index 0000000..ce15816
> > --- /dev/null
> > +++ b/tools/perf/util/dwarf-regs.c
> > @@ -0,0 +1,55 @@
> > +/*
> > + * dwarf-regs.c : Mapping of DWARF debug register numbers into register names.
> > + *
> > + * Written by: Masami Hiramatsu <mhiramat@kernel.org>
> > + */
> > +
> > +#include <util.h>
> > +#include <debug.h>
> > +#include <dwarf-regs.h>
> > +#include <elf.h>
> > +
> > +/* Define const char * {arch}_register_tbl[] */
> > +#define DEFINE_DWARF_REGSTR_TABLE
> > +#include "../arch/x86/include/dwarf-regs-table.h"
> > +#include "../arch/arm/include/dwarf-regs-table.h"
> > +#include "../arch/arm64/include/dwarf-regs-table.h"
> > +#include "../arch/sh/include/dwarf-regs-table.h"
> > +#include "../arch/powerpc/include/dwarf-regs-table.h"
> > +#include "../arch/s390/include/dwarf-regs-table.h"
> > +#include "../arch/sparc/include/dwarf-regs-table.h"
> > +#include "../arch/xtensa/include/dwarf-regs-table.h"
> > +
> > +#define __get_dwarf_regstr(tbl, n) (((n) < ARRAY_SIZE(tbl)) ? (tbl)[(n)] : NULL)
> > +
> > +/* Return architecture dependent register string (for kprobe-tracer) */
> > +const char *get_dwarf_regstr(unsigned int n, unsigned int machine)
> > +{
> > + switch (machine) {
> > + case EM_NONE: /* Generic arch - use host arch */
> > + return get_arch_regstr(n);
> > + case EM_386:
> > + return __get_dwarf_regstr(x86_32_regstr_tbl, n);
> > + case EM_X86_64:
> > + return __get_dwarf_regstr(x86_64_regstr_tbl, n);
> > + case EM_ARM:
> > + return __get_dwarf_regstr(arm_regstr_tbl, n);
> > + case EM_AARCH64:
> > + return __get_dwarf_regstr(aarch64_regstr_tbl, n);
> > + case EM_SH:
> > + return __get_dwarf_regstr(sh_regstr_tbl, n);
> > + case EM_S390:
> > + return __get_dwarf_regstr(s390_regstr_tbl, n);
> > + case EM_PPC:
> > + case EM_PPC64:
> > + return __get_dwarf_regstr(powerpc_regstr_tbl, n);
> > + case EM_SPARC:
> > + case EM_SPARCV9:
> > + return __get_dwarf_regstr(sparc_regstr_tbl, n);
> > + case EM_XTENSA:
> > + return __get_dwarf_regstr(xtensa_regstr_tbl, n);
> > + default:
> > + pr_err("ELF MACHINE %x is not supported.\n", machine);
> > + }
> > + return NULL;
> > +}
> > diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
> > index 07c644e..43bfd8d 100644
> > --- a/tools/perf/util/include/dwarf-regs.h
> > +++ b/tools/perf/util/include/dwarf-regs.h
> > @@ -3,6 +3,12 @@
> >
> > #ifdef HAVE_DWARF_SUPPORT
> > const char *get_arch_regstr(unsigned int n);
> > +/*
> > + * get_dwarf_regstr - Returns ftrace register string from DWARF regnum
> > + * n: DWARF register number
> > + * machine: ELF machine signature (EM_*)
> > + */
> > +const char *get_dwarf_regstr(unsigned int n, unsigned int machine);
> > #endif
> >
> > #ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
> > diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
> > index ac4740f..508b61c 100644
> > --- a/tools/perf/util/probe-finder.c
> > +++ b/tools/perf/util/probe-finder.c
> > @@ -171,6 +171,7 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
> > */
> > static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
> > Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
> > + unsigned int machine,
> > struct probe_trace_arg *tvar)
> > {
> > Dwarf_Attribute attr;
> > @@ -266,7 +267,7 @@ static_var:
> > if (!tvar)
> > return ret2;
> >
> > - regs = get_arch_regstr(regn);
> > + regs = get_dwarf_regstr(regn, machine);
> > if (!regs) {
> > /* This should be a bug in DWARF or this tool */
> > pr_warning("Mapping for the register number %u "
> > @@ -543,7 +544,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
> > dwarf_diename(vr_die));
> >
> > ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
> > - &pf->sp_die, pf->tvar);
> > + &pf->sp_die, pf->machine, pf->tvar);
> > if (ret == -ENOENT || ret == -EINVAL) {
> > pr_err("Failed to find the location of the '%s' variable at this address.\n"
> > " Perhaps it has been optimized out.\n"
> > @@ -1106,11 +1107,8 @@ 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);
> > @@ -1123,11 +1121,18 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
> > 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->machine = ehdr.e_machine;
> > +
> > +#if _ELFUTILS_PREREQ(0, 142)
> > + do {
> > + GElf_Shdr shdr;
> > +
> > + 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);
> > + pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
> > + } while (0);
> > #endif
> >
> > ret = debuginfo__find_probe_location(dbg, pf);
> > @@ -1155,7 +1160,7 @@ static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
> > (tag == DW_TAG_variable && vf->vars)) {
> > if (convert_variable_location(die_mem, vf->pf->addr,
> > vf->pf->fb_ops, &pf->sp_die,
> > - NULL) == 0) {
> > + pf->machine, NULL) == 0) {
> > vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
> > if (vf->args[vf->nargs].var == NULL) {
> > vf->ret = -ENOMEM;
> > @@ -1318,7 +1323,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
> > tag == DW_TAG_variable) {
> > ret = convert_variable_location(die_mem, af->pf.addr,
> > af->pf.fb_ops, &af->pf.sp_die,
> > - NULL);
> > + af->pf.machine, NULL);
> > if (ret == 0 || ret == -ERANGE) {
> > int ret2;
> > bool externs = !af->child;
> > diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
> > index 51137fc..f1d8558 100644
> > --- a/tools/perf/util/probe-finder.h
> > +++ b/tools/perf/util/probe-finder.h
> > @@ -80,6 +80,7 @@ struct probe_finder {
> > Dwarf_CFI *cfi_dbg;
> > #endif
> > Dwarf_Op *fb_ops; /* Frame base attribute */
> > + unsigned int machine; /* Target machine arch */
> > struct perf_probe_arg *pvar; /* Current target variable */
> > struct probe_trace_arg *tvar; /* Current result variable */
> > };
--
Masami Hiramatsu <mhiramat@kernel.org>
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Masami Hiramatsu <tipbot@zytor.com> |
|---|---|
| Date | 2016-09-05 15:30 +0200 |
| Subject | [tip:perf/core] perf probe: Support probing on offline cross-arch binary |
| Message-ID | <se28j-4is-41@gated-at.bofh.it> |
| In reply to | #1470263 |
Commit-ID: 293d5b43948309434568f4dcbb36cce4c3c51bd5
Gitweb: http://git.kernel.org/tip/293d5b43948309434568f4dcbb36cce4c3c51bd5
Author: Masami Hiramatsu <mhiramat@kernel.org>
AuthorDate: Fri, 26 Aug 2016 01:24:57 +0900
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 1 Sep 2016 12:41:09 -0300
perf probe: Support probing on offline cross-arch binary
Support probing on offline cross-architecture binary by adding getting
the target machine arch from ELF and choose correct register string for
the machine.
Here is an example:
-----
$ perf probe --vmlinux=./vmlinux-arm --definition 'do_sys_open $params'
p:probe/do_sys_open do_sys_open+0 dfd=%r5:s32 filename=%r1:u32 flags=%r6:s32 mode=%r3:u16
-----
Here, we can get probe/do_sys_open from above and append it to to the target
machine's tracing/kprobe_events file in the tracefs mountput, usually
/sys/kernel/debug/tracing/kprobe_events (or /sys/kernel/tracing/kprobe_events).
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/147214229717.23638.6440579792548044658.stgit@devbox
[ Add definition for EM_AARCH64 to fix the build on at least centos 6, debian 7 & ubuntu 12.04.5 ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/arch/arm/include/dwarf-regs-table.h | 9 ++++
tools/perf/arch/arm64/include/dwarf-regs-table.h | 13 +++++
tools/perf/arch/powerpc/include/dwarf-regs-table.h | 27 ++++++++++
tools/perf/arch/s390/include/dwarf-regs-table.h | 8 +++
tools/perf/arch/sh/include/dwarf-regs-table.h | 25 +++++++++
tools/perf/arch/sparc/include/dwarf-regs-table.h | 18 +++++++
tools/perf/arch/x86/include/dwarf-regs-table.h | 14 +++++
tools/perf/arch/xtensa/include/dwarf-regs-table.h | 8 +++
tools/perf/util/Build | 1 +
tools/perf/util/dwarf-regs.c | 59 ++++++++++++++++++++++
tools/perf/util/include/dwarf-regs.h | 6 +++
tools/perf/util/probe-finder.c | 27 ++++++----
tools/perf/util/probe-finder.h | 1 +
13 files changed, 205 insertions(+), 11 deletions(-)
diff --git a/tools/perf/arch/arm/include/dwarf-regs-table.h b/tools/perf/arch/arm/include/dwarf-regs-table.h
new file mode 100644
index 0000000..f298d03
--- /dev/null
+++ b/tools/perf/arch/arm/include/dwarf-regs-table.h
@@ -0,0 +1,9 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+static const char * const arm_regstr_tbl[] = {
+ "%r0", "%r1", "%r2", "%r3", "%r4",
+ "%r5", "%r6", "%r7", "%r8", "%r9", "%r10",
+ "%fp", "%ip", "%sp", "%lr", "%pc",
+};
+#endif
diff --git a/tools/perf/arch/arm64/include/dwarf-regs-table.h b/tools/perf/arch/arm64/include/dwarf-regs-table.h
new file mode 100644
index 0000000..2675936
--- /dev/null
+++ b/tools/perf/arch/arm64/include/dwarf-regs-table.h
@@ -0,0 +1,13 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+static const char * const aarch64_regstr_tbl[] = {
+ "%r0", "%r1", "%r2", "%r3", "%r4",
+ "%r5", "%r6", "%r7", "%r8", "%r9",
+ "%r10", "%r11", "%r12", "%r13", "%r14",
+ "%r15", "%r16", "%r17", "%r18", "%r19",
+ "%r20", "%r21", "%r22", "%r23", "%r24",
+ "%r25", "%r26", "%r27", "%r28", "%r29",
+ "%lr", "%sp",
+};
+#endif
diff --git a/tools/perf/arch/powerpc/include/dwarf-regs-table.h b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
new file mode 100644
index 0000000..db4730f
--- /dev/null
+++ b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
@@ -0,0 +1,27 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+/*
+ * Reference:
+ * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
+ * http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf
+ */
+#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg
+
+static const char * const powerpc_regstr_tbl[] = {
+ "%gpr0", "%gpr1", "%gpr2", "%gpr3", "%gpr4",
+ "%gpr5", "%gpr6", "%gpr7", "%gpr8", "%gpr9",
+ "%gpr10", "%gpr11", "%gpr12", "%gpr13", "%gpr14",
+ "%gpr15", "%gpr16", "%gpr17", "%gpr18", "%gpr19",
+ "%gpr20", "%gpr21", "%gpr22", "%gpr23", "%gpr24",
+ "%gpr25", "%gpr26", "%gpr27", "%gpr28", "%gpr29",
+ "%gpr30", "%gpr31",
+ REG_DWARFNUM_NAME(msr, 66),
+ REG_DWARFNUM_NAME(ctr, 109),
+ REG_DWARFNUM_NAME(link, 108),
+ REG_DWARFNUM_NAME(xer, 101),
+ REG_DWARFNUM_NAME(dar, 119),
+ REG_DWARFNUM_NAME(dsisr, 118),
+};
+
+#endif
diff --git a/tools/perf/arch/s390/include/dwarf-regs-table.h b/tools/perf/arch/s390/include/dwarf-regs-table.h
new file mode 100644
index 0000000..9da74a9
--- /dev/null
+++ b/tools/perf/arch/s390/include/dwarf-regs-table.h
@@ -0,0 +1,8 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+static const char * const s390_regstr_tbl[] = {
+ "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
+ "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
+};
+#endif
diff --git a/tools/perf/arch/sh/include/dwarf-regs-table.h b/tools/perf/arch/sh/include/dwarf-regs-table.h
new file mode 100644
index 0000000..3a2deaf
--- /dev/null
+++ b/tools/perf/arch/sh/include/dwarf-regs-table.h
@@ -0,0 +1,25 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+const char * const sh_regstr_tbl[] = {
+ "r0",
+ "r1",
+ "r2",
+ "r3",
+ "r4",
+ "r5",
+ "r6",
+ "r7",
+ "r8",
+ "r9",
+ "r10",
+ "r11",
+ "r12",
+ "r13",
+ "r14",
+ "r15",
+ "pc",
+ "pr",
+};
+
+#endif
diff --git a/tools/perf/arch/sparc/include/dwarf-regs-table.h b/tools/perf/arch/sparc/include/dwarf-regs-table.h
new file mode 100644
index 0000000..12c0761
--- /dev/null
+++ b/tools/perf/arch/sparc/include/dwarf-regs-table.h
@@ -0,0 +1,18 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+static const char * const sparc_regstr_tbl[] = {
+ "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
+ "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",
+ "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
+ "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7",
+ "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
+ "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
+ "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
+ "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
+ "%f32", "%f33", "%f34", "%f35", "%f36", "%f37", "%f38", "%f39",
+ "%f40", "%f41", "%f42", "%f43", "%f44", "%f45", "%f46", "%f47",
+ "%f48", "%f49", "%f50", "%f51", "%f52", "%f53", "%f54", "%f55",
+ "%f56", "%f57", "%f58", "%f59", "%f60", "%f61", "%f62", "%f63",
+};
+#endif
diff --git a/tools/perf/arch/x86/include/dwarf-regs-table.h b/tools/perf/arch/x86/include/dwarf-regs-table.h
new file mode 100644
index 0000000..39ac7cb
--- /dev/null
+++ b/tools/perf/arch/x86/include/dwarf-regs-table.h
@@ -0,0 +1,14 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+static const char * const x86_32_regstr_tbl[] = {
+ "%ax", "%cx", "%dx", "%bx", "$stack",/* Stack address instead of %sp */
+ "%bp", "%si", "%di",
+};
+
+static const char * const x86_64_regstr_tbl[] = {
+ "%ax", "dx", "%cx", "%bx", "%si", "%di",
+ "%bp", "%sp", "%r8", "%r9", "%r10", "%r11",
+ "%r12", "%r13", "%r14", "%r15",
+};
+#endif
diff --git a/tools/perf/arch/xtensa/include/dwarf-regs-table.h b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
new file mode 100644
index 0000000..aa0444a
--- /dev/null
+++ b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
@@ -0,0 +1,8 @@
+#ifdef DEFINE_DWARF_REGSTR_TABLE
+/* This is included in perf/util/dwarf-regs.c */
+
+static const char * const xtensa_regstr_tbl[] = {
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
+ "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15",
+};
+#endif
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 91c5f6e..f1a6d17 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -98,6 +98,7 @@ endif
libperf-$(CONFIG_DWARF) += probe-finder.o
libperf-$(CONFIG_DWARF) += dwarf-aux.o
+libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o
diff --git a/tools/perf/util/dwarf-regs.c b/tools/perf/util/dwarf-regs.c
new file mode 100644
index 0000000..62bc4a8
--- /dev/null
+++ b/tools/perf/util/dwarf-regs.c
@@ -0,0 +1,59 @@
+/*
+ * dwarf-regs.c : Mapping of DWARF debug register numbers into register names.
+ *
+ * Written by: Masami Hiramatsu <mhiramat@kernel.org>
+ */
+
+#include <util.h>
+#include <debug.h>
+#include <dwarf-regs.h>
+#include <elf.h>
+
+#ifndef EM_AARCH64
+#define EM_AARCH64 183 /* ARM 64 bit */
+#endif
+
+/* Define const char * {arch}_register_tbl[] */
+#define DEFINE_DWARF_REGSTR_TABLE
+#include "../arch/x86/include/dwarf-regs-table.h"
+#include "../arch/arm/include/dwarf-regs-table.h"
+#include "../arch/arm64/include/dwarf-regs-table.h"
+#include "../arch/sh/include/dwarf-regs-table.h"
+#include "../arch/powerpc/include/dwarf-regs-table.h"
+#include "../arch/s390/include/dwarf-regs-table.h"
+#include "../arch/sparc/include/dwarf-regs-table.h"
+#include "../arch/xtensa/include/dwarf-regs-table.h"
+
+#define __get_dwarf_regstr(tbl, n) (((n) < ARRAY_SIZE(tbl)) ? (tbl)[(n)] : NULL)
+
+/* Return architecture dependent register string (for kprobe-tracer) */
+const char *get_dwarf_regstr(unsigned int n, unsigned int machine)
+{
+ switch (machine) {
+ case EM_NONE: /* Generic arch - use host arch */
+ return get_arch_regstr(n);
+ case EM_386:
+ return __get_dwarf_regstr(x86_32_regstr_tbl, n);
+ case EM_X86_64:
+ return __get_dwarf_regstr(x86_64_regstr_tbl, n);
+ case EM_ARM:
+ return __get_dwarf_regstr(arm_regstr_tbl, n);
+ case EM_AARCH64:
+ return __get_dwarf_regstr(aarch64_regstr_tbl, n);
+ case EM_SH:
+ return __get_dwarf_regstr(sh_regstr_tbl, n);
+ case EM_S390:
+ return __get_dwarf_regstr(s390_regstr_tbl, n);
+ case EM_PPC:
+ case EM_PPC64:
+ return __get_dwarf_regstr(powerpc_regstr_tbl, n);
+ case EM_SPARC:
+ case EM_SPARCV9:
+ return __get_dwarf_regstr(sparc_regstr_tbl, n);
+ case EM_XTENSA:
+ return __get_dwarf_regstr(xtensa_regstr_tbl, n);
+ default:
+ pr_err("ELF MACHINE %x is not supported.\n", machine);
+ }
+ return NULL;
+}
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index 07c644e..43bfd8d 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -3,6 +3,12 @@
#ifdef HAVE_DWARF_SUPPORT
const char *get_arch_regstr(unsigned int n);
+/*
+ * get_dwarf_regstr - Returns ftrace register string from DWARF regnum
+ * n: DWARF register number
+ * machine: ELF machine signature (EM_*)
+ */
+const char *get_dwarf_regstr(unsigned int n, unsigned int machine);
#endif
#ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ac4740f..508b61c 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -171,6 +171,7 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
*/
static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
+ unsigned int machine,
struct probe_trace_arg *tvar)
{
Dwarf_Attribute attr;
@@ -266,7 +267,7 @@ static_var:
if (!tvar)
return ret2;
- regs = get_arch_regstr(regn);
+ regs = get_dwarf_regstr(regn, machine);
if (!regs) {
/* This should be a bug in DWARF or this tool */
pr_warning("Mapping for the register number %u "
@@ -543,7 +544,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
dwarf_diename(vr_die));
ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
- &pf->sp_die, pf->tvar);
+ &pf->sp_die, pf->machine, pf->tvar);
if (ret == -ENOENT || ret == -EINVAL) {
pr_err("Failed to find the location of the '%s' variable at this address.\n"
" Perhaps it has been optimized out.\n"
@@ -1106,11 +1107,8 @@ 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);
@@ -1123,11 +1121,18 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
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->machine = ehdr.e_machine;
+
+#if _ELFUTILS_PREREQ(0, 142)
+ do {
+ GElf_Shdr shdr;
+
+ 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);
+ pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
+ } while (0);
#endif
ret = debuginfo__find_probe_location(dbg, pf);
@@ -1155,7 +1160,7 @@ static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
(tag == DW_TAG_variable && vf->vars)) {
if (convert_variable_location(die_mem, vf->pf->addr,
vf->pf->fb_ops, &pf->sp_die,
- NULL) == 0) {
+ pf->machine, NULL) == 0) {
vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
if (vf->args[vf->nargs].var == NULL) {
vf->ret = -ENOMEM;
@@ -1318,7 +1323,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
tag == DW_TAG_variable) {
ret = convert_variable_location(die_mem, af->pf.addr,
af->pf.fb_ops, &af->pf.sp_die,
- NULL);
+ af->pf.machine, NULL);
if (ret == 0 || ret == -ERANGE) {
int ret2;
bool externs = !af->child;
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 51137fc..f1d8558 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -80,6 +80,7 @@ struct probe_finder {
Dwarf_CFI *cfi_dbg;
#endif
Dwarf_Op *fb_ops; /* Frame base attribute */
+ unsigned int machine; /* Target machine arch */
struct perf_probe_arg *pvar; /* Current target variable */
struct probe_trace_arg *tvar; /* Current result variable */
};
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-08-25 18:30 +0200 |
| Subject | [PATCH v2 1/3] perf-probe: Show trace event definition |
| Message-ID | <sa5Hs-3mY-25@gated-at.bofh.it> |
| In reply to | #1470262 |
Add --definition/-D option for showing the trace-event
definition in stdout. This can be useful in debugging
or combined with a shell script.
e.g.
----
# perf probe --definition 'do_sys_open $params'
p:probe/do_sys_open _text+2261728 dfd=%di:s32 filename=%si:u64 flags=%dx:s32 mode=%cx:u16
----
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Suggested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Documentation/perf-probe.txt | 7 +++++
tools/perf/builtin-probe.c | 26 +++++++++++++-----
tools/perf/util/probe-event.c | 46 +++++++++++++++++++++++++++++++
tools/perf/util/probe-event.h | 1 +
4 files changed, 73 insertions(+), 7 deletions(-)
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index f37d123..56db4d4 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -21,6 +21,8 @@ or
'perf probe' [options] --vars='PROBEPOINT'
or
'perf probe' [options] --funcs
+or
+'perf probe' [options] --definition='PROBE' [...]
DESCRIPTION
-----------
@@ -96,6 +98,11 @@ OPTIONS
can also list functions in a user space executable / shared library.
This also can accept a FILTER rule argument.
+-D::
+--definition=::
+ Show trace-event definition converted from given probe-event instead
+ of write it into tracing/[k,u]probe_events.
+
--filter=FILTER::
(Only for --vars and --funcs) Set filter. FILTER is a combination of glob
pattern, see FILTER PATTERN for detail.
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index ee5b421..7a3d8c4 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -326,6 +326,11 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
if (ret < 0)
goto out_cleanup;
+ if (params.command == 'D') { /* it shows definition */
+ ret = show_probe_trace_events(pevs, npevs);
+ goto out_cleanup;
+ }
+
ret = apply_perf_probe_events(pevs, npevs);
if (ret < 0)
goto out_cleanup;
@@ -454,6 +459,14 @@ out:
return ret;
}
+#ifdef HAVE_DWARF_SUPPORT
+#define PROBEDEF_STR \
+ "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT [[NAME=]ARG ...]"
+#else
+#define PROBEDEF_STR "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]"
+#endif
+
+
static int
__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
{
@@ -479,13 +492,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
opt_set_filter_with_command, DEFAULT_LIST_FILTER),
OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
opt_set_filter_with_command),
- OPT_CALLBACK('a', "add", NULL,
-#ifdef HAVE_DWARF_SUPPORT
- "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
- " [[NAME=]ARG ...]",
-#else
- "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]",
-#endif
+ OPT_CALLBACK('a', "add", NULL, PROBEDEF_STR,
"probe point definition, where\n"
"\t\tGROUP:\tGroup name (optional)\n"
"\t\tEVENT:\tEvent name\n"
@@ -503,6 +510,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
"\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
#endif
opt_add_probe_event),
+ OPT_CALLBACK('D', "definition", NULL, PROBEDEF_STR,
+ "Show trace event definition of given traceevent for k/uprobe_events.",
+ opt_add_probe_event),
OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
" with existing name"),
OPT_CALLBACK('L', "line", NULL,
@@ -548,6 +558,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE);
set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE);
+ set_option_flag(options, 'D', "definition", PARSE_OPT_EXCLUSIVE);
set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
#ifdef HAVE_DWARF_SUPPORT
set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
@@ -644,6 +655,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
}
break;
case 'a':
+ case 'D':
/* Ensure the last given target is used */
if (params.target && !params.target_used) {
pr_err(" Error: -x/-m must follow the probe definitions.\n");
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 2873396..ad7094d 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -3207,6 +3207,52 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs)
return 0;
}
+static int show_probe_trace_event(struct probe_trace_event *tev)
+{
+ char *buf = synthesize_probe_trace_command(tev);
+
+ if (!buf) {
+ pr_debug("Failed to synthesize probe trace event.\n");
+ return -EINVAL;
+ }
+
+ /* Showing definition always go stdout */
+ printf("%s\n", buf);
+ free(buf);
+
+ return 0;
+}
+
+int show_probe_trace_events(struct perf_probe_event *pevs, int npevs)
+{
+ struct strlist *namelist = strlist__new(NULL, NULL);
+ struct probe_trace_event *tev;
+ struct perf_probe_event *pev;
+ int i, j, ret = 0;
+
+ if (!namelist)
+ return -ENOMEM;
+
+ for (j = 0; j < npevs && !ret; j++) {
+ pev = &pevs[j];
+ for (i = 0; i < pev->ntevs && !ret; i++) {
+ tev = &pev->tevs[i];
+ /* Skip if the symbol is out of .text or blacklisted */
+ if (!tev->point.symbol && !pev->uprobes)
+ continue;
+
+ /* Set new name for tev (and update namelist) */
+ ret = probe_trace_event__set_name(tev, pev,
+ namelist, true);
+ if (!ret)
+ ret = show_probe_trace_event(tev);
+ }
+ }
+ strlist__delete(namelist);
+
+ return ret;
+}
+
int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs)
{
int i, ret = 0;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index f4f45db..6209408 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -147,6 +147,7 @@ int line_range__init(struct line_range *lr);
int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs);
int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs);
+int show_probe_trace_events(struct perf_probe_event *pevs, int npevs);
void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs);
int del_perf_probe_events(struct strfilter *filter);
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Masami Hiramatsu <tipbot@zytor.com> |
|---|---|
| Date | 2016-09-05 15:30 +0200 |
| Subject | [tip:perf/core] perf probe: Show trace event definition |
| Message-ID | <se28k-4is-83@gated-at.bofh.it> |
| In reply to | #1470264 |
Commit-ID: 1c20b1d15473a91e2fccecbcd2809d80ff4b4924
Gitweb: http://git.kernel.org/tip/1c20b1d15473a91e2fccecbcd2809d80ff4b4924
Author: Masami Hiramatsu <mhiramat@kernel.org>
AuthorDate: Fri, 26 Aug 2016 01:24:27 +0900
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 1 Sep 2016 09:44:13 -0300
perf probe: Show trace event definition
Add --definition/-D option for showing the trace-event definition in
stdout. This can be useful in debugging or combined with a shell script.
e.g.
----
# perf probe --definition 'do_sys_open $params'
p:probe/do_sys_open _text+2261728 dfd=%di:s32 filename=%si:u64 flags=%dx:s32 mode=%cx:u16
----
Suggested-and-Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/147214226712.23638.2240534040014013658.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Documentation/perf-probe.txt | 7 +++++
tools/perf/builtin-probe.c | 26 ++++++++++++++-----
tools/perf/util/probe-event.c | 46 +++++++++++++++++++++++++++++++++
tools/perf/util/probe-event.h | 1 +
4 files changed, 73 insertions(+), 7 deletions(-)
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index f37d123..56db4d4 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -21,6 +21,8 @@ or
'perf probe' [options] --vars='PROBEPOINT'
or
'perf probe' [options] --funcs
+or
+'perf probe' [options] --definition='PROBE' [...]
DESCRIPTION
-----------
@@ -96,6 +98,11 @@ OPTIONS
can also list functions in a user space executable / shared library.
This also can accept a FILTER rule argument.
+-D::
+--definition=::
+ Show trace-event definition converted from given probe-event instead
+ of write it into tracing/[k,u]probe_events.
+
--filter=FILTER::
(Only for --vars and --funcs) Set filter. FILTER is a combination of glob
pattern, see FILTER PATTERN for detail.
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index ee5b421..7a3d8c4 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -326,6 +326,11 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
if (ret < 0)
goto out_cleanup;
+ if (params.command == 'D') { /* it shows definition */
+ ret = show_probe_trace_events(pevs, npevs);
+ goto out_cleanup;
+ }
+
ret = apply_perf_probe_events(pevs, npevs);
if (ret < 0)
goto out_cleanup;
@@ -454,6 +459,14 @@ out:
return ret;
}
+#ifdef HAVE_DWARF_SUPPORT
+#define PROBEDEF_STR \
+ "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT [[NAME=]ARG ...]"
+#else
+#define PROBEDEF_STR "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]"
+#endif
+
+
static int
__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
{
@@ -479,13 +492,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
opt_set_filter_with_command, DEFAULT_LIST_FILTER),
OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
opt_set_filter_with_command),
- OPT_CALLBACK('a', "add", NULL,
-#ifdef HAVE_DWARF_SUPPORT
- "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
- " [[NAME=]ARG ...]",
-#else
- "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]",
-#endif
+ OPT_CALLBACK('a', "add", NULL, PROBEDEF_STR,
"probe point definition, where\n"
"\t\tGROUP:\tGroup name (optional)\n"
"\t\tEVENT:\tEvent name\n"
@@ -503,6 +510,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
"\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
#endif
opt_add_probe_event),
+ OPT_CALLBACK('D', "definition", NULL, PROBEDEF_STR,
+ "Show trace event definition of given traceevent for k/uprobe_events.",
+ opt_add_probe_event),
OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
" with existing name"),
OPT_CALLBACK('L', "line", NULL,
@@ -548,6 +558,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE);
set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE);
+ set_option_flag(options, 'D', "definition", PARSE_OPT_EXCLUSIVE);
set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
#ifdef HAVE_DWARF_SUPPORT
set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
@@ -644,6 +655,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
}
break;
case 'a':
+ case 'D':
/* Ensure the last given target is used */
if (params.target && !params.target_used) {
pr_err(" Error: -x/-m must follow the probe definitions.\n");
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 0bed2ee..4a49cb8 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -3207,6 +3207,52 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs)
return 0;
}
+static int show_probe_trace_event(struct probe_trace_event *tev)
+{
+ char *buf = synthesize_probe_trace_command(tev);
+
+ if (!buf) {
+ pr_debug("Failed to synthesize probe trace event.\n");
+ return -EINVAL;
+ }
+
+ /* Showing definition always go stdout */
+ printf("%s\n", buf);
+ free(buf);
+
+ return 0;
+}
+
+int show_probe_trace_events(struct perf_probe_event *pevs, int npevs)
+{
+ struct strlist *namelist = strlist__new(NULL, NULL);
+ struct probe_trace_event *tev;
+ struct perf_probe_event *pev;
+ int i, j, ret = 0;
+
+ if (!namelist)
+ return -ENOMEM;
+
+ for (j = 0; j < npevs && !ret; j++) {
+ pev = &pevs[j];
+ for (i = 0; i < pev->ntevs && !ret; i++) {
+ tev = &pev->tevs[i];
+ /* Skip if the symbol is out of .text or blacklisted */
+ if (!tev->point.symbol && !pev->uprobes)
+ continue;
+
+ /* Set new name for tev (and update namelist) */
+ ret = probe_trace_event__set_name(tev, pev,
+ namelist, true);
+ if (!ret)
+ ret = show_probe_trace_event(tev);
+ }
+ }
+ strlist__delete(namelist);
+
+ return ret;
+}
+
int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs)
{
int i, ret = 0;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index f4f45db..6209408 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -147,6 +147,7 @@ int line_range__init(struct line_range *lr);
int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs);
int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs);
+int show_probe_trace_events(struct perf_probe_event *pevs, int npevs);
void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs);
int del_perf_probe_events(struct strfilter *filter);
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-08-26 17:00 +0200 |
| Subject | [PATCH v2 4/4] perf-probe: Ignore vmlinux Build-id when offline vmlinux given |
| Message-ID | <saqLT-8tm-5@gated-at.bofh.it> |
| In reply to | #1470262 |
Ignore vmlinux build-id when user gives offline vmlinux if
the command does not affect running kernel.
perf-probe has several actions some of them does not change
the running kernel, like --lines, --vars, and --funcs.
e.g.
-----
$ ./perf probe -k ./vmlinux-arm -V do_sys_open:14
Available variables at do_sys_open:14
@<do_sys_open+202>
char* filename
int dfd
int fd
int flags
struct filename* tmp
struct open_flags op
umode_t mode
-----
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
tools/perf/builtin-probe.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index b4220cd..f87996b 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -611,6 +611,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
*/
symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
+ /*
+ * Except for --list, --del and --add, other command doesn't depend
+ * nor change running kernel. So if user gives offline vmlinux,
+ * ignore its buildid.
+ */
+ if (!strchr("lda", params.command) && symbol_conf.vmlinux_name)
+ symbol_conf.ignore_vmlinux_buildid = true;
+
switch (params.command) {
case 'l':
if (params.uprobes) {
@@ -655,13 +663,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
}
break;
case 'D':
- /*
- * If user gives offline vmlinux, ignore buildid, since
- * --definition doesn't change running kernel.
- */
- if (symbol_conf.vmlinux_name)
- symbol_conf.ignore_vmlinux_buildid = true;
- /* fall through */
case 'a':
/* Ensure the last given target is used */
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Masami Hiramatsu <tipbot@zytor.com> |
|---|---|
| Date | 2016-09-05 15:30 +0200 |
| Subject | [tip:perf/core] perf probe: Ignore vmlinux Build-id when offline vmlinux given |
| Message-ID | <se28j-4is-43@gated-at.bofh.it> |
| In reply to | #1470782 |
Commit-ID: e50243bbeb528e92e31e03e560b557737c9def3c
Gitweb: http://git.kernel.org/tip/e50243bbeb528e92e31e03e560b557737c9def3c
Author: Masami Hiramatsu <mhiramat@kernel.org>
AuthorDate: Fri, 26 Aug 2016 23:57:58 +0900
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 1 Sep 2016 12:42:22 -0300
perf probe: Ignore vmlinux Build-id when offline vmlinux given
Ignore vmlinux build-id when user gives offline vmlinux if the command
does not affect running kernel.
perf-probe has several actions some of them does not change the running
kernel, like --lines, --vars, and --funcs.
e.g.
-----
$ ./perf probe -k ./vmlinux-arm -V do_sys_open:14
Available variables at do_sys_open:14
@<do_sys_open+202>
char* filename
int dfd
int fd
int flags
struct filename* tmp
struct open_flags op
umode_t mode
-----
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/147222347320.5088.2582658035296667520.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-probe.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index b4220cd..f87996b 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -611,6 +611,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
*/
symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
+ /*
+ * Except for --list, --del and --add, other command doesn't depend
+ * nor change running kernel. So if user gives offline vmlinux,
+ * ignore its buildid.
+ */
+ if (!strchr("lda", params.command) && symbol_conf.vmlinux_name)
+ symbol_conf.ignore_vmlinux_buildid = true;
+
switch (params.command) {
case 'l':
if (params.uprobes) {
@@ -655,13 +663,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
}
break;
case 'D':
- /*
- * If user gives offline vmlinux, ignore buildid, since
- * --definition doesn't change running kernel.
- */
- if (symbol_conf.vmlinux_name)
- symbol_conf.ignore_vmlinux_buildid = true;
- /* fall through */
case 'a':
/* Ensure the last given target is used */
[toc] | [prev] | [next] | [standalone]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-08-31 03:10 +0200 |
| Message-ID | <sc2cp-44s-1@gated-at.bofh.it> |
| In reply to | #1470262 |
ping? On Fri, 26 Aug 2016 01:24:10 +0900 Masami Hiramatsu <mhiramat@kernel.org> wrote: > Hi, > > Here is the 2nd version of remote cross-arch probe support on perf-probe. > V1 is here: > https://lkml.org/lkml/2016/8/24/29 > > Currently perf-probe doesn't supoort cross/remote target. This means > we have to cross-build the perf-tools including libraries (elfutils, > libelf etc.), and to prepare vmlinux with debuginfo which can be > accessed from the target machine. > This requires too much resource for a small embededd device. > > If we can analyze the debuginfo by perf-probe on host machine, > we do not need to cross-build perf-tools, nor copy vmlinux on the > device. :) > > For that purpose, this series adds --definition(-D) command for > perf-probe, which shows trace event definition instead of adding > it in running kernel, according to Arnaldo's comment. > Using -D with --vmlinux(or -k)=OFFLINE-VMLINUX, perf-probe reads > the vmlinux architecture and show definition with correct > dwarf-registers. > > perf probe -k <cross-vmlinux> -D <probe-point> <arguments> > > Here is an example: > ----- > $ perf probe --vmlinux=./vmlinux-arm --definition 'do_sys_open $params' > p:probe/do_sys_open do_sys_open+0 dfd=%r5:s32 filename=%r1:u32 flags=%r6:s32 mode=%r3:u16 > ----- > Here, we can get probe/do_sys_open event by "copy & paste" the > definition to target-machine's debugfs/tracing/kprobe_events. > > Note that it shows definition with direct symbol name instead of > _text+offset. It is treated as an offline module. > > Thanks, > --- > > Masami Hiramatsu (3): > perf-probe: Show trace event definition > perf-probe: Ignore vmlinux buildid if offline kernel is given > perf-probe: Support probing on offline cross-arch binary > > > tools/perf/Documentation/perf-probe.txt | 9 +++ > tools/perf/arch/arm/include/dwarf-regs-table.h | 9 +++ > tools/perf/arch/arm64/include/dwarf-regs-table.h | 13 +++++ > tools/perf/arch/powerpc/include/dwarf-regs-table.h | 27 ++++++++++ > tools/perf/arch/s390/include/dwarf-regs-table.h | 8 +++ > tools/perf/arch/sh/include/dwarf-regs-table.h | 25 +++++++++ > tools/perf/arch/sparc/include/dwarf-regs-table.h | 18 +++++++ > tools/perf/arch/x86/include/dwarf-regs-table.h | 14 +++++ > tools/perf/arch/xtensa/include/dwarf-regs-table.h | 8 +++ > tools/perf/builtin-probe.c | 34 ++++++++++-- > tools/perf/util/Build | 1 > tools/perf/util/dwarf-regs.c | 55 ++++++++++++++++++++ > tools/perf/util/include/dwarf-regs.h | 6 ++ > tools/perf/util/probe-event.c | 50 ++++++++++++++++++ > tools/perf/util/probe-event.h | 1 > tools/perf/util/probe-finder.c | 27 ++++++---- > tools/perf/util/probe-finder.h | 1 > tools/perf/util/symbol-elf.c | 2 - > 18 files changed, 289 insertions(+), 19 deletions(-) > create mode 100644 tools/perf/arch/arm/include/dwarf-regs-table.h > create mode 100644 tools/perf/arch/arm64/include/dwarf-regs-table.h > create mode 100644 tools/perf/arch/powerpc/include/dwarf-regs-table.h > create mode 100644 tools/perf/arch/s390/include/dwarf-regs-table.h > create mode 100644 tools/perf/arch/sh/include/dwarf-regs-table.h > create mode 100644 tools/perf/arch/sparc/include/dwarf-regs-table.h > create mode 100644 tools/perf/arch/x86/include/dwarf-regs-table.h > create mode 100644 tools/perf/arch/xtensa/include/dwarf-regs-table.h > create mode 100644 tools/perf/util/dwarf-regs.c > > -- > Masami Hiramatsu (Linaro Ltd.) <mhiramat@kernel.org> -- Masami Hiramatsu <mhiramat@kernel.org>
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web