Browse Source

C-based ftrace entry parser

master
Denis Tereshkin 6 months ago
parent
commit
8217e259b9
  1. 93
      src/ftracetool.c
  2. 3
      src/ftracetool.scm

93
src/ftracetool.c

@ -17,6 +17,12 @@
#define CLEANUP(f) __attribute__((cleanup(f))) #define CLEANUP(f) __attribute__((cleanup(f)))
enum Error_codes
{
ER_COMMENT = 10000,
ER_PARSE_ERROR = 20000,
};
static const char gs_ftracetool_scm[] = { static const char gs_ftracetool_scm[] = {
#include "ftracetool_scm.h" #include "ftracetool_scm.h"
}; };
@ -312,7 +318,8 @@ static int parse_ftrace_entry(const char *str,
char *pid_buf, char *pid_buf,
char *timestamp_buf, char *timestamp_buf,
char *probe_id_buf, char *probe_id_buf,
char *args_buf) char **args,
size_t *args_num)
{ {
// skip whitespaces // skip whitespaces
while (isspace(*str)) while (isspace(*str))
@ -321,7 +328,11 @@ static int parse_ftrace_entry(const char *str,
} }
if (!*str) if (!*str)
{ {
return -1; return ER_PARSE_ERROR + 1;
}
if (*str == '#')
{
return ER_COMMENT;
} }
char *out = comm_buf; char *out = comm_buf;
@ -329,14 +340,14 @@ static int parse_ftrace_entry(const char *str,
{ {
if (!*str) if (!*str)
{ {
return -2; return ER_PARSE_ERROR + 2;
} }
// TODO check out buf overflow // TODO check out buf overflow
*out++ = *str++; *out++ = *str++;
} }
if (!*str) if (!*str)
{ {
return -3; return ER_PARSE_ERROR + 3;
} }
*out = 0; *out = 0;
str++; // Skip '- str++; // Skip '-
@ -346,7 +357,7 @@ static int parse_ftrace_entry(const char *str,
{ {
if (!*str) if (!*str)
{ {
return -4; return ER_PARSE_ERROR + 4;
} }
// TODO check out buf overflow // TODO check out buf overflow
@ -361,12 +372,12 @@ static int parse_ftrace_entry(const char *str,
} }
if (!*str) if (!*str)
{ {
return -5; return ER_PARSE_ERROR + 5;
} }
str++; str++;
if (!*str) if (!*str)
{ {
return -6; return ER_PARSE_ERROR + 6;
} }
// skip whitespaces && flags // skip whitespaces && flags
@ -376,7 +387,7 @@ static int parse_ftrace_entry(const char *str,
} }
if (!*str) if (!*str)
{ {
return -7; return ER_PARSE_ERROR + 7;
} }
out = timestamp_buf; out = timestamp_buf;
@ -384,7 +395,7 @@ static int parse_ftrace_entry(const char *str,
{ {
if (!*str) if (!*str)
{ {
return -8; return ER_PARSE_ERROR + 8;
} }
// TODO check out buf overflow // TODO check out buf overflow
@ -394,7 +405,7 @@ static int parse_ftrace_entry(const char *str,
if (*str != ':') if (*str != ':')
{ {
return -9; return ER_PARSE_ERROR + 9;
} }
str++; str++;
// skip whitespaces // skip whitespaces
@ -404,7 +415,7 @@ static int parse_ftrace_entry(const char *str,
} }
if (!*str) if (!*str)
{ {
return -10; return ER_PARSE_ERROR + 10;
} }
out = probe_id_buf; out = probe_id_buf;
@ -412,7 +423,7 @@ static int parse_ftrace_entry(const char *str,
{ {
if (!*str) if (!*str)
{ {
return -11; return ER_PARSE_ERROR + 11;
} }
// TODO check out buf overflow // TODO check out buf overflow
*out++ = *str++; *out++ = *str++;
@ -426,25 +437,44 @@ static int parse_ftrace_entry(const char *str,
} }
if (!*str) if (!*str)
{ {
return -12; return ER_PARSE_ERROR + 12;
} }
str++; str++;
if (!*str) if (!*str)
{ {
return -13; return ER_PARSE_ERROR + 13;
} }
out = args_buf; size_t arg_num = 0;
while (*str) while (*str)
{ {
const char *start = NULL;
while (*str && *str != '=')
{
str++;
}
if (!*str) if (!*str)
{ {
return -14; break;
} }
// TODO check out buf overflow start = str + 1;
*out++ = *str++; while (*str && *str != ' ')
{
str++;
} }
*out = 0; const char *end = str;
const size_t string_length = end - start + 2;
args[arg_num] = calloc(1, string_length);
if (!args[arg_num])
{
return ER_PARSE_ERROR + 15;
}
memcpy(args[arg_num], start, string_length - 1);
arg_num++;
}
*args_num = arg_num;
return 0; return 0;
} }
@ -452,7 +482,6 @@ static int parse_ftrace_entry(const char *str,
static sexp static sexp
sexp_parse_ftrace_entry_stub(sexp ctx, sexp self, sexp_sint_t n, sexp arg0) sexp_parse_ftrace_entry_stub(sexp ctx, sexp self, sexp_sint_t n, sexp arg0)
{ {
sexp res;
int ret = 0; int ret = 0;
if (!sexp_stringp(arg0)) if (!sexp_stringp(arg0))
{ {
@ -462,15 +491,23 @@ sexp_parse_ftrace_entry_stub(sexp ctx, sexp self, sexp_sint_t n, sexp arg0)
char pid_buf[32]; char pid_buf[32];
char timestamp_buf[64]; char timestamp_buf[64];
char probe_id_buf[64]; char probe_id_buf[64];
char args[128]; char *args[128];
size_t args_num = 0;
ret = parse_ftrace_entry(sexp_string_data(arg0), ret = parse_ftrace_entry(sexp_string_data(arg0),
comm_buf, comm_buf,
pid_buf, pid_buf,
timestamp_buf, timestamp_buf,
probe_id_buf, probe_id_buf,
args); args,
&args_num);
if (ret == ER_COMMENT)
{
return SEXP_FALSE;
}
if (ret) if (ret)
{ {
fprintf(stderr, "parse_ftrace_entry failed with %d\n", ret);
fprintf(stderr, "%s\n", sexp_string_data(arg0));
return SEXP_FALSE; return SEXP_FALSE;
} }
unsigned long pid = atoi(pid_buf); unsigned long pid = atoi(pid_buf);
@ -479,6 +516,14 @@ sexp_parse_ftrace_entry_stub(sexp ctx, sexp self, sexp_sint_t n, sexp arg0)
char *frac = dot + 1; char *frac = dot + 1;
double timestamp = atol(timestamp_buf) + atol(frac) / 1000000.; double timestamp = atol(timestamp_buf) + atol(frac) / 1000000.;
sexp prev = SEXP_NULL;
sexp head = SEXP_NULL;
for (ssize_t arg_num = args_num - 1; arg_num >= 0; arg_num--)
{
head = sexp_cons(ctx, sexp_c_string(ctx, args[arg_num], -1), prev);
prev = head;
}
return sexp_cons( return sexp_cons(
ctx, ctx,
sexp_c_string(ctx, comm_buf, -1), sexp_c_string(ctx, comm_buf, -1),
@ -488,9 +533,7 @@ sexp_parse_ftrace_entry_stub(sexp ctx, sexp self, sexp_sint_t n, sexp arg0)
sexp_make_flonum(ctx, timestamp), sexp_make_flonum(ctx, timestamp),
sexp_cons(ctx, sexp_cons(ctx,
sexp_c_string(ctx, probe_id_buf, -1), sexp_c_string(ctx, probe_id_buf, -1),
sexp_cons(ctx, sexp_cons(ctx, head, SEXP_NULL)))));
sexp_c_string(ctx, args, -1),
SEXP_NULL)))));
} }
static int register_lookup_symbol_in_file(sexp ctx) static int register_lookup_symbol_in_file(sexp ctx)

3
src/ftracetool.scm

@ -243,8 +243,7 @@
(timestamp (list-ref match 2)) (timestamp (list-ref match 2))
(probe-name (list-ref match 3)) (probe-name (list-ref match 3))
(args (list-ref match 4)) (args (list-ref match 4))
(parsed-args (parse-arguments args)) (trace-event (make-trace-event timestamp probe-name pid args)))
(trace-event (make-trace-event timestamp probe-name pid (parse-arguments args))))
(loop (read-line p) (cons trace-event events) (+ 1 n))) (loop (read-line p) (cons trace-event events) (+ 1 n)))
(loop (read-line p) events n))))))))))) (loop (read-line p) events n)))))))))))

Loading…
Cancel
Save