Messages in this thread | | | Subject | Re: [RFC PATCH v2 09/15] perf probe: Support $params without debuginfo | From | He Kuang <> | Date | Mon, 25 May 2015 16:33:09 +0800 |
| |
hi,
On 2015/5/24 16:49, Masami Hiramatsu wrote: > On 2015/05/24 17:28, He Kuang wrote: >> When probing at function entry, fallback $params to calling regs if no >> debuginfo is provided. >> >> Before this path: >> $ perf probe -v --add='generic_perform_write $params' >> ... >> Added new event: >> Writing event: p:probe/generic_perform_write _stext+1246632 $params >> [86152.161204] Parse error at argument[0]. (-22) >> Failed to write event: Invalid argument >> Error: Failed to add events. Reason: Invalid argument (Code: -22) >> >> After this patch: >> $ perf probe -v --add='generic_perform_write $params' >> ... >> Could not open debuginfo. Try to use symbols. >> ... >> Added new event: >> Writing event: p:probe/generic_perform_write _stext+1246632 %di %si %dx %cx %r8 %r9 >> probe:generic_perform_write (on generic_perform_write with $params) >> >> You can now use it in all perf tools, such as: >> >> perf record -e probe:generic_perform_write -aR sleep 1 >> >> $ perf record -e probe:generic_perform_write dd if=/dev/zero of=/mnt/data/test bs=4k count=3 > > NAK, this should not work on x86-32 and we don't know how many registers are used. > I think $params special handler should be used only with debuginfo, since $params > ensures user to save function parameters with its name. If we can't do that, we > should accept that. > > If you need to handle register arguments, you should introduce new $regparams instead
Yes, $regparam is more appropriate.
> of $params. (however, that still not work correctly on x86-32) > > Hmm, we also need $regs to record all registers.
Right, I learnt regparm(3) is mandatory in x86_32, according to rules, the first three args will go to regparm(ax, dx, cx). But we should not refer arg1~3 to ax, dx, cx because of 64bit parameters (other reasons?).
Consider this keyword is used for generating bpf prologue which fetches formal parameters when no debuginfo is provided, for this purpose, we can: 1) We just help fetch the $regs or $regparms(If the keyword is $regparms, ax/dx/cx is fetched, nothing related to args) to bpf arglists and leave the rest things to bpf prog writer.
2) Keep that on platforms like x86_64 and skip this feature on platforms like x86_32.
or any other suggestions?
Thanks
> > Thank you, > > >> >> $ perf script >> dd 1149 [000] 18574.762652: probe:generic_perform_write: (ffffffff81130770) arg1=0xffff88007c37f600 arg2=0xffff88007ca87e70 arg3=0x0 arg4=0x0 arg5=0x556062e3 arg6=0x12a8010 >> dd 1149 [000] 18574.762652: probe:generic_perform_write: (ffffffff81130770) arg1=0xffff88007c37f600 arg2=0xffff88007ca87e70 arg3=0x1000 arg4=0x0 arg5=0x556062e3 arg6=0x12a8010 >> dd 1149 [000] 18574.762652: probe:generic_perform_write: (ffffffff81130770) arg1=0xffff88007c37f600 arg2=0xffff88007ca87e70 arg3=0x2000 arg4=0x0 arg5=0x556062e3 arg6=0x12a8010 >> >> Signed-off-by: He Kuang <hekuang@huawei.com> >> --- >> tools/perf/util/probe-event.c | 42 ++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 42 insertions(+) >> >> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c >> index d05b77c..7f9f431 100644 >> --- a/tools/perf/util/probe-event.c >> +++ b/tools/perf/util/probe-event.c >> @@ -46,6 +46,7 @@ >> #include "probe-event.h" >> #include "probe-finder.h" >> #include "session.h" >> +#include <dwarf-regs.h> >> >> #define MAX_CMDLEN 256 >> #define PERFPROBE_GROUP "probe" >> @@ -286,6 +287,14 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) >> clear_probe_trace_event(tevs + i); >> } >> >> +static bool perf_probe_is_function_entry(struct perf_probe_event *pev) >> +{ >> + if (pev->point.file || pev->point.line || pev->point.lazy_line) >> + return false; >> + >> + return true; >> +} >> + >> #ifdef HAVE_DWARF_SUPPORT >> /* >> * Some binaries like glibc have special symbols which are on the symbol >> @@ -1225,6 +1234,33 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) >> return 0; >> } >> >> +static char *parse_perf_probe_param(void) >> +{ >> + int i = 0; >> + struct strbuf sb; >> + bool first = true; >> + const char *reg_str; >> + >> + strbuf_init(&sb, 16); >> + >> + while (1) { >> + reg_str = get_arch_calling_reg_str(i++); >> + if (!reg_str) >> + break; >> + >> + if (first) { >> + strbuf_addf(&sb, "%s", reg_str); >> + first = false; >> + } else >> + strbuf_addf(&sb, " %s", reg_str); >> + } >> + >> + if (first) >> + strbuf_add(&sb, "", 1); >> + >> + return strbuf_detach(&sb, NULL); >> +} >> + >> /* Parse perf-probe event argument */ >> static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) >> { >> @@ -2543,6 +2579,12 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, >> goto nomem_out; >> } >> for (i = 0; i < tev->nargs; i++) { >> + if (perf_probe_is_function_entry(pev) && >> + !strcmp(pev->args[i].var, "$params")) { >> + tev->args[i].value = parse_perf_probe_param(); >> + continue; >> + } >> + >> if (pev->args[i].name) >> tev->args[i].name = >> strdup_or_goto(pev->args[i].name, >> > >
| |