aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2013-10-11 03:10:23 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-10-23 08:55:37 -0400
commit7969ec7728ba6340de8000ddb0a8833273629d6a (patch)
tree9dfcf92c7e150c1c87701a9ec874577a41e1870d /tools
parentc824c4338ac47979c69ba6f8faab33670ae179df (diff)
perf probe: Support "$vars" meta argument syntax for local variables
Support "$vars" meta argument syntax for tracing all local variables at probe point. Now you can trace all available local variables (including function parameters) at the probe point by passing $vars. # perf probe --add foo $vars This automatically finds all local variables at foo() and adds it as probe arguments. Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/20131011071023.15557.51770.stgit@udc4-manage.rcp.hitachi.co.jp Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/probe-event.c1
-rw-r--r--tools/perf/util/probe-finder.c96
-rw-r--r--tools/perf/util/probe-finder.h1
3 files changed, 89 insertions, 9 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 779b2dacd43f..9c6989ca2bea 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -47,7 +47,6 @@
47#include "session.h" 47#include "session.h"
48 48
49#define MAX_CMDLEN 256 49#define MAX_CMDLEN 256
50#define MAX_PROBE_ARGS 128
51#define PERFPROBE_GROUP "probe" 50#define PERFPROBE_GROUP "probe"
52 51
53bool probe_event_dry_run; /* Dry run flag */ 52bool probe_event_dry_run; /* Dry run flag */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index c09e0a9fdf4c..5a46be968c0b 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1136,12 +1136,78 @@ found:
1136 return ret; 1136 return ret;
1137} 1137}
1138 1138
1139struct local_vars_finder {
1140 struct probe_finder *pf;
1141 struct perf_probe_arg *args;
1142 int max_args;
1143 int nargs;
1144 int ret;
1145};
1146
1147/* Collect available variables in this scope */
1148static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
1149{
1150 struct local_vars_finder *vf = data;
1151 int tag;
1152
1153 tag = dwarf_tag(die_mem);
1154 if (tag == DW_TAG_formal_parameter ||
1155 tag == DW_TAG_variable) {
1156 if (convert_variable_location(die_mem, vf->pf->addr,
1157 vf->pf->fb_ops, NULL) == 0) {
1158 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
1159 if (vf->args[vf->nargs].var == NULL) {
1160 vf->ret = -ENOMEM;
1161 return DIE_FIND_CB_END;
1162 }
1163 pr_debug(" %s", vf->args[vf->nargs].var);
1164 vf->nargs++;
1165 }
1166 }
1167
1168 if (dwarf_haspc(die_mem, vf->pf->addr))
1169 return DIE_FIND_CB_CONTINUE;
1170 else
1171 return DIE_FIND_CB_SIBLING;
1172}
1173
1174static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf,
1175 struct perf_probe_arg *args)
1176{
1177 Dwarf_Die die_mem;
1178 int i;
1179 int n = 0;
1180 struct local_vars_finder vf = {.pf = pf, .args = args,
1181 .max_args = MAX_PROBE_ARGS, .ret = 0};
1182
1183 for (i = 0; i < pf->pev->nargs; i++) {
1184 /* var never be NULL */
1185 if (strcmp(pf->pev->args[i].var, "$vars") == 0) {
1186 pr_debug("Expanding $vars into:");
1187 vf.nargs = n;
1188 /* Special local variables */
1189 die_find_child(sc_die, copy_variables_cb, (void *)&vf,
1190 &die_mem);
1191 pr_debug(" (%d)\n", vf.nargs - n);
1192 if (vf.ret < 0)
1193 return vf.ret;
1194 n = vf.nargs;
1195 } else {
1196 /* Copy normal argument */
1197 args[n] = pf->pev->args[i];
1198 n++;
1199 }
1200 }
1201 return n;
1202}
1203
1139/* Add a found probe point into trace event list */ 1204/* Add a found probe point into trace event list */
1140static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) 1205static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1141{ 1206{
1142 struct trace_event_finder *tf = 1207 struct trace_event_finder *tf =
1143 container_of(pf, struct trace_event_finder, pf); 1208 container_of(pf, struct trace_event_finder, pf);
1144 struct probe_trace_event *tev; 1209 struct probe_trace_event *tev;
1210 struct perf_probe_arg *args;
1145 int ret, i; 1211 int ret, i;
1146 1212
1147 /* Check number of tevs */ 1213 /* Check number of tevs */
@@ -1161,21 +1227,35 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1161 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, 1227 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
1162 tev->point.offset); 1228 tev->point.offset);
1163 1229
1164 /* Find each argument */ 1230 /* Expand special probe argument if exist */
1165 tev->nargs = pf->pev->nargs; 1231 args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
1166 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 1232 if (args == NULL)
1167 if (tev->args == NULL)
1168 return -ENOMEM; 1233 return -ENOMEM;
1169 for (i = 0; i < pf->pev->nargs; i++) { 1234
1170 pf->pvar = &pf->pev->args[i]; 1235 ret = expand_probe_args(sc_die, pf, args);
1236 if (ret < 0)
1237 goto end;
1238
1239 tev->nargs = ret;
1240 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1241 if (tev->args == NULL) {
1242 ret = -ENOMEM;
1243 goto end;
1244 }
1245
1246 /* Find each argument */
1247 for (i = 0; i < tev->nargs; i++) {
1248 pf->pvar = &args[i];
1171 pf->tvar = &tev->args[i]; 1249 pf->tvar = &tev->args[i];
1172 /* Variable should be found from scope DIE */ 1250 /* Variable should be found from scope DIE */
1173 ret = find_variable(sc_die, pf); 1251 ret = find_variable(sc_die, pf);
1174 if (ret != 0) 1252 if (ret != 0)
1175 return ret; 1253 break;
1176 } 1254 }
1177 1255
1178 return 0; 1256end:
1257 free(args);
1258 return ret;
1179} 1259}
1180 1260
1181/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 1261/* Find probe_trace_events specified by perf_probe_event from debuginfo */
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 3f0c29dd6ac5..d6dab0e0a937 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -7,6 +7,7 @@
7 7
8#define MAX_PROBE_BUFFER 1024 8#define MAX_PROBE_BUFFER 1024
9#define MAX_PROBES 128 9#define MAX_PROBES 128
10#define MAX_PROBE_ARGS 128
10 11
11static inline int is_c_varname(const char *name) 12static inline int is_c_varname(const char *name)
12{ 13{