2009-10-09 05:17:38 +08:00
|
|
|
#ifndef _PROBE_FINDER_H
|
|
|
|
#define _PROBE_FINDER_H
|
|
|
|
|
2010-02-25 21:35:42 +08:00
|
|
|
#include <stdbool.h>
|
2009-12-28 07:37:00 +08:00
|
|
|
#include "util.h"
|
2014-02-06 13:32:09 +08:00
|
|
|
#include "intlist.h"
|
2010-03-17 06:06:12 +08:00
|
|
|
#include "probe-event.h"
|
2009-12-28 07:37:00 +08:00
|
|
|
|
2009-12-17 06:16:19 +08:00
|
|
|
#define MAX_PROBE_BUFFER 1024
|
|
|
|
#define MAX_PROBES 128
|
2013-10-11 15:10:23 +08:00
|
|
|
#define MAX_PROBE_ARGS 128
|
2009-10-09 05:17:38 +08:00
|
|
|
|
perf probe: Support $params special probe argument
$params is similar to $vars but matches only function parameters not
local variables.
Thus, this is useful for tracing function parameter changing or tracing
function call with parameters.
Testing it:
# perf probe tcp_sendmsg '$params'
Added new event:
probe:tcp_sendmsg (on tcp_sendmsg with $params)
You can now use it in all perf tools, such as:
perf record -e probe:tcp_sendmsg -aR sleep 1
# perf probe -l
probe:tcp_sendmsg (on tcp_sendmsg@acme/git/linux/net/ipv4/tcp.c with iocb sk msg size)
# perf record -a -e probe:*
press some random letters to generate TCP (sshd) traffic...
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.223 MB perf.data (6 samples) ]
# perf script
sshd 6385 [2] 3.907529: probe:tcp_sendmsg: iocb=0xffff8800ac4cfe70 sk=0xffff88042196c140 msg=0xffff8800ac4cfda8 size=0x24
sshd 6385 [2] 4.138973: probe:tcp_sendmsg: iocb=0xffff8800ac4cfe70 sk=0xffff88042196c140 msg=0xffff8800ac4cfda8 size=0x24
sshd 6385 [2] 4.378966: probe:tcp_sendmsg: iocb=0xffff8800ac4cfe70 sk=0xffff88042196c140 msg=0xffff8800ac4cfda8 size=0x24
sshd 6385 [2] 4.603681: probe:tcp_sendmsg: iocb=0xffff8800ac4cfe70 sk=0xffff88042196c140 msg=0xffff8800ac4cfda8 size=0x24
sshd 6385 [2] 4.818455: probe:tcp_sendmsg: iocb=0xffff8800ac4cfe70 sk=0xffff88042196c140 msg=0xffff8800ac4cfda8 size=0x24
sshd 6385 [2] 5.043603: probe:tcp_sendmsg: iocb=0xffff8800ac4cfe70 sk=0xffff88042196c140 msg=0xffff8800ac4cfda8 size=0x24
# cat /sys/kernel/debug/tracing/events/probe/tcp_sendmsg/format
name: tcp_sendmsg
ID: 1927
format:
field:unsigned short common_type; offset:0; size:2; signed:0;
field:unsigned char common_flags; offset:2; size:1; signed:0;
field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
field:int common_pid; offset:4; size:4; signed:1;
field:unsigned long __probe_ip; offset:8; size:8; signed:0;
field:u64 iocb; offset:16; size:8; signed:0;
field:u64 sk; offset:24; size:8; signed:0;
field:u64 msg; offset:32; size:8; signed:0;
field:u64 size; offset:40; size:8; signed:0;
print fmt: "(%lx) iocb=0x%Lx sk=0x%Lx msg=0x%Lx size=0x%Lx", REC->__probe_ip, REC->iocb, REC->sk, REC->msg, REC->size
#
Do some system wide tracing of this probe + write syscalls:
# perf trace -e write --ev probe:* --filter-pids 6385
462.612 (0.010 ms): bash/19153 write(fd: 1</dev/pts/1>, buf: 0x7f7556c78000, count: 29 ) = 29
462.701 (0.027 ms): sshd/19152 write(fd: 3<socket:[63117]>, buf: 0x7f78dd12e160, count: 68 ) ...
462.701 ( ): probe:tcp_sendmsg:(ffffffff8163db30) iocb=0xffff8803ebec7e70 sk=0xffff88042196ab80 msg=0xffff8803ebec7da8 size=0x44)
462.710 (0.035 ms): sshd/19152 ... [continued]: write()) = 68
462.787 (0.009 ms): bash/19153 write(fd: 2</dev/pts/1>, buf: 0x7f7556c77000, count: 22 ) = 22
462.865 (0.002 ms): sshd/19152 write(fd: 3<socket:[63117]>, buf: 0x7f78dd12e160, count: 68 ) ...
462.865 ( ): probe:tcp_sendmsg:(ffffffff8163db30) iocb=0xffff8803ebec7e70 sk=0xffff88042196ab80 msg=0xffff8803ebec7da8 size=0x44)
462.873 (0.010 ms): sshd/19152 ... [continued]: write()) = 68
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Hemant Kumar <hemant@linux.vnet.ibm.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20150506124653.4961.59806.stgit@localhost.localdomain
[ Add some examples to the changelog message showing how to use it ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-05-06 20:46:53 +08:00
|
|
|
#define PROBE_ARG_VARS "$vars"
|
|
|
|
#define PROBE_ARG_PARAMS "$params"
|
|
|
|
|
2009-10-09 05:17:38 +08:00
|
|
|
static inline int is_c_varname(const char *name)
|
|
|
|
{
|
|
|
|
/* TODO */
|
|
|
|
return isalpha(name[0]) || name[0] == '_';
|
|
|
|
}
|
|
|
|
|
2013-09-30 18:07:11 +08:00
|
|
|
#ifdef HAVE_DWARF_SUPPORT
|
2011-06-27 15:27:39 +08:00
|
|
|
|
|
|
|
#include "dwarf-aux.h"
|
|
|
|
|
|
|
|
/* TODO: export debuginfo data structure even if no dwarf support */
|
|
|
|
|
|
|
|
/* debug information structure */
|
|
|
|
struct debuginfo {
|
|
|
|
Dwarf *dbg;
|
2013-09-25 21:16:16 +08:00
|
|
|
Dwfl_Module *mod;
|
2011-06-27 15:27:39 +08:00
|
|
|
Dwfl *dwfl;
|
|
|
|
Dwarf_Addr bias;
|
|
|
|
};
|
|
|
|
|
2014-02-06 13:32:27 +08:00
|
|
|
/* This also tries to open distro debuginfo */
|
2016-03-24 02:06:35 +08:00
|
|
|
struct debuginfo *debuginfo__new(const char *path);
|
|
|
|
void debuginfo__delete(struct debuginfo *dbg);
|
2011-06-27 15:27:39 +08:00
|
|
|
|
2010-07-29 22:13:51 +08:00
|
|
|
/* Find probe_trace_events specified by perf_probe_event from debuginfo */
|
2016-03-24 02:06:35 +08:00
|
|
|
int debuginfo__find_trace_events(struct debuginfo *dbg,
|
|
|
|
struct perf_probe_event *pev,
|
|
|
|
struct probe_trace_event **tevs);
|
2010-03-17 06:06:12 +08:00
|
|
|
|
2010-03-17 06:06:19 +08:00
|
|
|
/* Find a perf_probe_point from debuginfo */
|
2016-03-24 02:06:35 +08:00
|
|
|
int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
|
|
|
|
struct perf_probe_point *ppt);
|
2010-03-17 06:06:19 +08:00
|
|
|
|
2017-01-11 14:01:57 +08:00
|
|
|
int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
|
|
|
|
bool adjust_offset);
|
|
|
|
|
2010-10-21 18:13:23 +08:00
|
|
|
/* Find a line range */
|
2016-03-24 02:06:35 +08:00
|
|
|
int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr);
|
2009-10-09 05:17:38 +08:00
|
|
|
|
2010-10-21 18:13:23 +08:00
|
|
|
/* Find available variables */
|
2016-03-24 02:06:35 +08:00
|
|
|
int debuginfo__find_available_vars_at(struct debuginfo *dbg,
|
|
|
|
struct perf_probe_event *pev,
|
|
|
|
struct variable_list **vls);
|
2009-10-09 05:17:38 +08:00
|
|
|
|
2015-03-13 13:18:40 +08:00
|
|
|
/* Find a src file from a DWARF tag path */
|
|
|
|
int get_real_path(const char *raw_path, const char *comp_dir,
|
|
|
|
char **new_path);
|
|
|
|
|
2009-10-09 05:17:38 +08:00
|
|
|
struct probe_finder {
|
2010-03-17 06:06:12 +08:00
|
|
|
struct perf_probe_event *pev; /* Target probe event */
|
2010-10-21 18:13:23 +08:00
|
|
|
|
|
|
|
/* Callback when a probe point is found */
|
2011-08-11 19:02:59 +08:00
|
|
|
int (*callback)(Dwarf_Die *sc_die, struct probe_finder *pf);
|
2009-10-09 05:17:38 +08:00
|
|
|
|
|
|
|
/* For function searching */
|
perf tools: Reorganize some structs to save space
Using 'pahole --packable' I found some structs that could be reorganized
to eliminate alignment holes, in some cases getting them to be cacheline
multiples.
[acme@doppio linux-2.6-tip]$ codiff perf.old ~/bin/perf
builtin-annotate.c:
struct perf_session | -8
struct perf_header | -8
2 structs changed
builtin-diff.c:
struct sample_data | -8
1 struct changed
diff__process_sample_event | -8
1 function changed, 8 bytes removed, diff: -8
builtin-sched.c:
struct sched_atom | -8
1 struct changed
builtin-timechart.c:
struct per_pid | -8
1 struct changed
cmd_timechart | -16
1 function changed, 16 bytes removed, diff: -16
builtin-probe.c:
struct perf_probe_point | -8
struct perf_probe_event | -8
2 structs changed
opt_add_probe_event | -3
1 function changed, 3 bytes removed, diff: -3
util/probe-finder.c:
struct probe_finder | -8
1 struct changed
find_kprobe_trace_events | -16
1 function changed, 16 bytes removed, diff: -16
/home/acme/bin/perf:
4 functions changed, 43 bytes removed, diff: -43
[acme@doppio linux-2.6-tip]$
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2010-04-05 23:53:45 +08:00
|
|
|
int lno; /* Line number */
|
2010-02-25 21:35:42 +08:00
|
|
|
Dwarf_Addr addr; /* Address */
|
2010-03-17 06:06:12 +08:00
|
|
|
const char *fname; /* Real file name */
|
2010-02-25 21:35:42 +08:00
|
|
|
Dwarf_Die cu_die; /* Current CU */
|
perf probe: Add fastpath to do lookup by function name
v3 -> v2:
- Make pubname_search_cb more generic
- Add fastpath to find_probes also
v2 -> v1:
- Don't compare file names with cu_find_realpath(...), instead, compare
them with the name returned by dwarf_decl_file(sp_die)
The vmlinux file may have thousands of CUs.
We can lookup function name from .debug_pubnames section
to avoid the slow loop on CUs.
1. Improvement data for find_line_range
./perf stat -e cycles -r 10 -- ./perf probe -k /home/mlin/vmlinux \
-s /home/mlin/linux-2.6 \
--line csum_partial_copy_to_user > tmp.log
before patch applied
=====================
847,988,276 cycles
0.355075856 seconds time elapsed
after patch applied
=====================
206,102,622 cycles
0.086883555 seconds time elapsed
2. Improvement data for find_probes
./perf stat -e cycles -r 10 -- ./perf probe -k /home/mlin/vmlinux \
-s /home/mlin/linux-2.6 \
--vars csum_partial_copy_to_user > tmp.log
before patch applied
=====================
848,490,844 cycles
0.355307901 seconds time elapsed
after patch applied
=====================
205,684,469 cycles
0.086694010 seconds time elapsed
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: linux-kernel <linux-kernel@vger.kernel.org>
LKML-Reference: <1301041668.14111.52.camel@minggr.sh.intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-03-25 16:27:48 +08:00
|
|
|
Dwarf_Die sp_die;
|
2014-02-06 13:32:09 +08:00
|
|
|
struct intlist *lcache; /* Line cache for lazy match */
|
2009-10-09 05:17:38 +08:00
|
|
|
|
|
|
|
/* For variable searching */
|
2010-05-11 01:12:07 +08:00
|
|
|
#if _ELFUTILS_PREREQ(0, 142)
|
perf probe: Search both .eh_frame and .debug_frame sections for probe location
'perf probe' through debuginfo__find_probes() in util/probe-finder.c
checks for the functions' frame descriptions in either .eh_frame section
of an ELF or the .debug_frame.
The check is based on whether either one of these sections is present.
Depending on distro, toolchain defaults, architetcutre, build flags,
etc., CFI might be found in either .eh_frame and/or .debug_frame.
Sometimes, it may happen that, .eh_frame, even if present, may not be
complete and may miss some descriptions.
Therefore, to be sure, to find the CFI covering an address we will
always have to investigate both if available.
For e.g., in powerpc, this may happen:
$ gcc -g bin.c -o bin
$ objdump --dwarf ./bin
<1><145>: Abbrev Number: 7 (DW_TAG_subprogram)
<146> DW_AT_external : 1
<146> DW_AT_name : (indirect string, offset: 0x9e): main
<14a> DW_AT_decl_file : 1
<14b> DW_AT_decl_line : 39
<14c> DW_AT_prototyped : 1
<14c> DW_AT_type : <0x57>
<150> DW_AT_low_pc : 0x100007b8
If the .eh_frame and .debug_frame are checked for the same binary, we
will find that, .eh_frame (although present) doesn't contain a
description for "main" function.
But, .debug_frame has a description:
000000d8 00000024 00000000 FDE cie=00000000 pc=100007b8..10000838
DW_CFA_advance_loc: 16 to 100007c8
DW_CFA_def_cfa_offset: 144
DW_CFA_offset_extended_sf: r65 at cfa+16
...
Due to this (since, perf checks whether .eh_frame is present and goes on
searching for that address inside that frame), perf is unable to process
the probes:
# perf probe -x ./bin main
Failed to get call frame on 0x100007b8
Error: Failed to add events.
To avoid this issue, we need to check both the sections (.eh_frame and
.debug_frame), which is done in this patch.
Note that, we can always force everything into both .eh_frame and
.debug_frame by:
$ gcc bin.c -fasynchronous-unwind-tables -fno-dwarf2-cfi-asm -g -o bin
Signed-off-by: Hemant Kumar <hemant@linux.vnet.ibm.com>
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Mark Wielaard <mjw@redhat.com>
Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1454426806-13974-1-git-send-email-hemant@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2016-02-02 23:26:46 +08:00
|
|
|
/* Call Frame Information from .eh_frame */
|
|
|
|
Dwarf_CFI *cfi_eh;
|
|
|
|
/* Call Frame Information from .debug_frame */
|
|
|
|
Dwarf_CFI *cfi_dbg;
|
2010-05-11 01:12:07 +08:00
|
|
|
#endif
|
2010-02-25 21:35:42 +08:00
|
|
|
Dwarf_Op *fb_ops; /* Frame base attribute */
|
2016-08-26 00:24:57 +08:00
|
|
|
unsigned int machine; /* Target machine arch */
|
2010-03-17 06:06:12 +08:00
|
|
|
struct perf_probe_arg *pvar; /* Current target variable */
|
2010-07-29 22:13:51 +08:00
|
|
|
struct probe_trace_arg *tvar; /* Current result variable */
|
2009-10-09 05:17:38 +08:00
|
|
|
};
|
2010-01-06 22:45:34 +08:00
|
|
|
|
2010-10-21 18:13:23 +08:00
|
|
|
struct trace_event_finder {
|
|
|
|
struct probe_finder pf;
|
2013-09-25 21:16:16 +08:00
|
|
|
Dwfl_Module *mod; /* For solving symbols */
|
2010-10-21 18:13:23 +08:00
|
|
|
struct probe_trace_event *tevs; /* Found trace events */
|
|
|
|
int ntevs; /* Number of trace events */
|
|
|
|
int max_tevs; /* Max number of trace events */
|
|
|
|
};
|
|
|
|
|
|
|
|
struct available_var_finder {
|
|
|
|
struct probe_finder pf;
|
2013-09-25 21:16:16 +08:00
|
|
|
Dwfl_Module *mod; /* For solving symbols */
|
2010-10-21 18:13:23 +08:00
|
|
|
struct variable_list *vls; /* Found variable lists */
|
|
|
|
int nvls; /* Number of variable lists */
|
|
|
|
int max_vls; /* Max no. of variable lists */
|
2010-10-21 18:13:35 +08:00
|
|
|
bool child; /* Search child scopes */
|
2010-10-21 18:13:23 +08:00
|
|
|
};
|
|
|
|
|
2010-01-06 22:45:34 +08:00
|
|
|
struct line_finder {
|
2010-02-25 21:35:42 +08:00
|
|
|
struct line_range *lr; /* Target line range */
|
|
|
|
|
|
|
|
const char *fname; /* File name */
|
|
|
|
int lno_s; /* Start line number */
|
|
|
|
int lno_e; /* End line number */
|
|
|
|
Dwarf_Die cu_die; /* Current CU */
|
perf probe: Add fastpath to do lookup by function name
v3 -> v2:
- Make pubname_search_cb more generic
- Add fastpath to find_probes also
v2 -> v1:
- Don't compare file names with cu_find_realpath(...), instead, compare
them with the name returned by dwarf_decl_file(sp_die)
The vmlinux file may have thousands of CUs.
We can lookup function name from .debug_pubnames section
to avoid the slow loop on CUs.
1. Improvement data for find_line_range
./perf stat -e cycles -r 10 -- ./perf probe -k /home/mlin/vmlinux \
-s /home/mlin/linux-2.6 \
--line csum_partial_copy_to_user > tmp.log
before patch applied
=====================
847,988,276 cycles
0.355075856 seconds time elapsed
after patch applied
=====================
206,102,622 cycles
0.086883555 seconds time elapsed
2. Improvement data for find_probes
./perf stat -e cycles -r 10 -- ./perf probe -k /home/mlin/vmlinux \
-s /home/mlin/linux-2.6 \
--vars csum_partial_copy_to_user > tmp.log
before patch applied
=====================
848,490,844 cycles
0.355307901 seconds time elapsed
after patch applied
=====================
205,684,469 cycles
0.086694010 seconds time elapsed
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: linux-kernel <linux-kernel@vger.kernel.org>
LKML-Reference: <1301041668.14111.52.camel@minggr.sh.intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-03-25 16:27:48 +08:00
|
|
|
Dwarf_Die sp_die;
|
2010-01-06 22:45:34 +08:00
|
|
|
int found;
|
|
|
|
};
|
|
|
|
|
2013-09-30 18:07:11 +08:00
|
|
|
#endif /* HAVE_DWARF_SUPPORT */
|
2009-10-09 05:17:38 +08:00
|
|
|
|
|
|
|
#endif /*_PROBE_FINDER_H */
|