summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt (Google) <rostedt@goodmis.org>2022-01-27 22:09:42 -0500
committerSteven Rostedt (Google) <rostedt@goodmis.org>2022-01-27 22:33:10 -0500
commitac040d0f6dec3234f7afd31fc44488ce0684f7e8 (patch)
treec10e3e9b831944ec9946f3ee112a146670f212fe
parent51aedca5c0a97c16d233ba8c627e7fdafaccc499 (diff)
downloadktrace-ac040d0f6dec3234f7afd31fc44488ce0684f7e8.tar.gz
ktrace: Add code to create a kprobe
Add the code to create a kprobe. It only prints the command for now, but will later actually create it. Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
-rw-r--r--src/create.c181
1 files changed, 131 insertions, 50 deletions
diff --git a/src/create.c b/src/create.c
index d66cc34..d1ba688 100644
--- a/src/create.c
+++ b/src/create.c
@@ -11,55 +11,16 @@ static void create_usage(struct ccli *ccli)
" <type> : kprobe, eprobe, synthetic_event\n");
}
-static int create_kprobe(struct ccli *ccli, void *data,
- int argc, char **argv)
-{
- return 0;
-}
-
-static int add_event_var(struct ccli *ccli, struct tep_handle *tep,
- char **command, struct tep_event *event,
- char *line)
+static int add_type_offset(struct ccli *ccli, char *p, char **pvar, char *line)
{
- struct tep_format_field *field;
long long offset;
- bool neg;
- char *fname;
+ char *var = *pvar;
char *type;
- char *var;
char *tmp;
char *end;
- char *p;
- char ch;
- int ret;
-
- p = strchr(line, '=');
- if (!p) {
- ccli_printf(ccli, "Invalid variable '%s'\n", line);
- return -1;
- }
-
- *p = '\0';
- fname = p + 1;
- for (p++; *p; p++) {
- if (*p == '.' || *p == '-')
- break;
- }
- ch = *p;
- *p = '\0';
-
- field = tep_find_any_field(event, fname);
- if (!field) {
- ccli_printf(ccli, "# Cannot find field '%s' for event '%s'\n",
- fname, event->name);
- return -1;
- }
-
- ret = asprintf(&var, "$%s", fname);
- if (ret < 0)
- return -1;
+ bool neg;
+ int ret = 0;
- *p = ch;
for (; *p; p++) {
switch(*p) {
case '.':
@@ -72,14 +33,14 @@ static int add_event_var(struct ccli *ccli, struct tep_handle *tep,
if (*p == '.') {
ccli_printf(ccli, "# Two types can not be togethe '%s'\n",
line);
- goto out;
+ return -1;
}
if (strncmp(type, "string", 6) == 0 ||
strncmp(type, "ustring", 7) == 0) {
if (*p) {
ccli_printf(ccli, "# Strings can not be deferenced '%s'\n",
type);
- goto out;
+ return -1;
}
ret = asprintf(&tmp, "+0(%s):%.*s",
var, (int)(p - type),
@@ -90,7 +51,7 @@ static int add_event_var(struct ccli *ccli, struct tep_handle *tep,
type);
}
if (ret < 0)
- goto out;
+ return -1;
free(var);
var = tmp;
/* We need to compare current p again */
@@ -101,7 +62,7 @@ static int add_event_var(struct ccli *ccli, struct tep_handle *tep,
if (*p != '>') {
ccli_printf(ccli, "# Invalid variable '%s'\n",
type);
- goto out;
+ return -1;
}
p++;
if (*p == '-') {
@@ -112,15 +73,135 @@ static int add_event_var(struct ccli *ccli, struct tep_handle *tep,
ret = asprintf(&tmp, "%s%llu(%s)",
neg ? "-" : "+", offset, var);
if (ret < 0)
- goto out;
+ return -1;
free(var);
var = tmp;
break;
}
}
- /* Finished */
- ret = asprintf(&tmp, "%s %s=%s", *command, line, var);
+ *pvar = var;
+ return ret;
+}
+
+static int add_var(struct ccli *ccli, char **command, char *line)
+{
+ char *sym;
+ char *var;
+ char *tmp;
+ char *p;
+ char ch;
+ int ret;
+
+ p = strchr(line, '=');
+ if (!p) {
+ ccli_printf(ccli, "Invalid variable '%s'\n", line);
+ return -1;
+ }
+
+ *p = '\0';
+ sym = p + 1;
+ for (p++; *p; p++) {
+ if (*p == '.' || *p == '-')
+ break;
+ }
+ ch = *p;
+ *p = '\0';
+
+ var = strdup(sym);
+ if (!var)
+ return -1;
+
+ *p = ch;
+ ret = add_type_offset(ccli, p, &var, line);
+
+ if (ret >= 0)
+ ret = asprintf(&tmp, "%s %s=%s", *command, line, var);
+
+ free(var);
+ if (ret < 0)
+ return -1;
+ free(*command);
+ *command = tmp;
+ return 0;
+}
+
+static int create_kprobe(struct ccli *ccli, void *data,
+ int argc, char **argv)
+{
+ char *command;
+ char *sym;
+ char *name;
+ int ret;
+ int i;
+
+ if (argc < 3) {
+ ccli_printf(ccli, "# usage: create kprobe name function/address fields\n");
+ return 0;
+ }
+
+ name = argv[0];
+ sym = argv[1];
+
+ ret = asprintf(&command, "k:%s %s", name, sym);
+ if (ret < 0)
+ return 0;
+
+ for (i = 2 ; i < argc; i++ ) {
+ ret = add_var(ccli, &command, argv[i]);
+ if (ret < 0)
+ goto out;
+ }
+ ccli_printf(ccli, "# echo '%s' >> %s/dynamic_events\n",
+ command, tracefs_tracing_dir());
out:
+ free(command);
+ return 0;
+}
+
+static int add_event_var(struct ccli *ccli, struct tep_handle *tep,
+ char **command, struct tep_event *event,
+ char *line)
+{
+ struct tep_format_field *field;
+ char *fname;
+ char *var;
+ char *tmp;
+ char *p;
+ char ch;
+ int ret;
+
+ p = strchr(line, '=');
+ if (!p) {
+ ccli_printf(ccli, "Invalid variable '%s'\n", line);
+ return -1;
+ }
+
+ *p = '\0';
+ fname = p + 1;
+ for (p++; *p; p++) {
+ if (*p == '.' || *p == '-')
+ break;
+ }
+ ch = *p;
+ *p = '\0';
+
+ field = tep_find_any_field(event, fname);
+ if (!field) {
+ ccli_printf(ccli, "# Cannot find field '%s' for event '%s'\n",
+ fname, event->name);
+ return -1;
+ }
+
+ ret = asprintf(&var, "$%s", fname);
+ if (ret < 0)
+ return -1;
+
+ *p = ch;
+ ret = add_type_offset(ccli, p, &var, line);
+
+ if (ret >= 0)
+ ret = asprintf(&tmp, "%s %s=%s", *command, line, var);
+
free(var);
if (ret < 0)
return -1;