diff options
author | Steven Rostedt (Google) <rostedt@goodmis.org> | 2022-01-27 22:09:42 -0500 |
---|---|---|
committer | Steven Rostedt (Google) <rostedt@goodmis.org> | 2022-01-27 22:33:10 -0500 |
commit | ac040d0f6dec3234f7afd31fc44488ce0684f7e8 (patch) | |
tree | c10e3e9b831944ec9946f3ee112a146670f212fe | |
parent | 51aedca5c0a97c16d233ba8c627e7fdafaccc499 (diff) | |
download | ktrace-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.c | 181 |
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; |