Skip to content

Commit

Permalink
Merge branch 'auto-args'
Browse files Browse the repository at this point in the history
It's cumbersome to specify arguments of every function.  Since some
functions are well-known, provide `--auto-args` option to enable
recording argument of those functions.

Each function can be specified using -A or -R option and will override
the automatics arguments/return value (if any).

Closes #173.

Signed-off-by: Namhyung Kim <namhyung@gmail.com>
  • Loading branch information
namhyung committed Nov 12, 2017
2 parents da5d986 + 0ad8900 commit aeeb2b3
Show file tree
Hide file tree
Showing 29 changed files with 1,437 additions and 108 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ TAGS
tags
cscope.*
*.pyc
*.sw[opn]
*.patch
*.orig
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ LIBMCOUNT_UTILS_SRCS += $(srcdir)/utils/symbol.c $(srcdir)/utils/debug.c
LIBMCOUNT_UTILS_SRCS += $(srcdir)/utils/rbtree.c $(srcdir)/utils/filter.c
LIBMCOUNT_UTILS_SRCS += $(srcdir)/utils/demangle.c $(srcdir)/utils/utils.c
LIBMCOUNT_UTILS_SRCS += $(srcdir)/utils/script.c $(srcdir)/utils/script-python.c
LIBMCOUNT_UTILS_SRCS += $(srcdir)/utils/auto-args.c
LIBMCOUNT_UTILS_OBJS := $(patsubst $(srcdir)/utils/%.c,$(objdir)/libmcount/%.op,$(LIBMCOUNT_UTILS_SRCS))

LIBMCOUNT_NOP_SRCS := $(srcdir)/libmcount/mcount-nop.c
Expand Down Expand Up @@ -194,6 +195,9 @@ $(filter-out $(objdir)/uftrace.o,$(UFTRACE_OBJS)): $(objdir)/%.o: $(srcdir)/%.c
$(objdir)/version.h: PHONY
@$(srcdir)/misc/version.sh $@ $(VERSION_GIT)

$(srcdir)/utils/auto-args.h: $(srcdir)/misc/prototypes.h $(srcdir)/misc/gen-autoargs.py
$(QUIET_GEN)$(srcdir)/misc/gen-autoargs.py -i $< -o $@

$(objdir)/uftrace: $(UFTRACE_OBJS) $(UFTRACE_ARCH_OBJS) $(objdir)/libtraceevent/libtraceevent.a
$(QUIET_LINK)$(CC) $(UFTRACE_CFLAGS) -o $@ $(UFTRACE_OBJS) $(UFTRACE_ARCH_OBJS) $(UFTRACE_LDFLAGS)

Expand Down
3 changes: 2 additions & 1 deletion cmd-dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,8 @@ static void get_feature_string(char *buf, size_t sz, uint64_t feature_mask)
bool first = true;
const char *feat_str[] = { "PLTHOOK", "TASK_SESSION", "KERNEL",
"ARGUMENT", "RETVAL", "SYM_REL_ADDR",
"MAX_STACK", "EVENT", "PERF_EVENT" };
"MAX_STACK", "EVENT", "PERF_EVENT",
"AUTO_ARGS" };

/* feat_str should match to enum uftrace_feat_bits */
for (i = 0; i < FEAT_BIT_MAX; i++) {
Expand Down
85 changes: 26 additions & 59 deletions cmd-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "uftrace.h"
#include "libmcount/mcount.h"
#include "utils/utils.h"
#include "utils/filter.h"

#define BUILD_ID_SIZE 20
#define BUILD_ID_STR_SIZE (BUILD_ID_SIZE * 2 + 1)
Expand Down Expand Up @@ -657,60 +658,15 @@ static int read_loadinfo(void *arg)
static int fill_arg_spec(void *arg)
{
struct fill_handler_arg *fha = arg;
char *argspec = NULL;
char *retspec = NULL;
int n = 0;
char *argspec = fha->opts->args;
char *retspec = fha->opts->retval;
int n;

/* extract argspec (and retspec) in trigger action */
if (fha->opts->trigger) {
char *pos, *tmp, *str, *act;

str = tmp = xstrdup(fha->opts->trigger);

while ((pos = strsep(&tmp, ";")) != NULL) {
char *name = pos;
char *args = NULL;
char *rval = NULL;

act = strchr(name, '@');
if (act == NULL)
continue;

*act++ = '\0';

while ((pos = strsep(&act, ",")) != NULL) {
if (!strncasecmp(pos, "arg", 3) ||
!strncasecmp(pos, "fparg", 5))
args = strjoin(args, pos, ",");
if (!strncasecmp(pos, "retval", 6))
rval = "retval";
}

if (args) {
xasprintf(&act, "%s@%s", name, args);
argspec = strjoin(argspec, act, ";");
free(act);
}
if (rval) {
xasprintf(&act, "%s@retval", name);
retspec = strjoin(retspec, act, ";");
free(act);
}
}

free(str);
}

if (fha->opts->args)
argspec = strjoin(argspec, fha->opts->args, ";");
if (fha->opts->retval)
retspec = strjoin(retspec, fha->opts->retval, ";");

n = !!argspec + !!retspec;
if (n == 0)
n = extract_trigger_args(&argspec, &retspec, fha->opts->trigger);
if (n == 0 && !fha->opts->auto_args)
return -1;

dprintf(fha->fd, "argspec:lines=%d\n", n);
dprintf(fha->fd, "argspec:lines=%d\n", n + 2 + !!fha->opts->auto_args);
if (argspec) {
dprintf(fha->fd, "argspec:%s\n", argspec);
free(argspec);
Expand All @@ -720,6 +676,12 @@ static int fill_arg_spec(void *arg)
free(retspec);
}

dprintf(fha->fd, "argauto:%s\n", get_auto_argspec_str());
dprintf(fha->fd, "retauto:%s\n", get_auto_retspec_str());

if (fha->opts->auto_args)
dprintf(fha->fd, "auto-args:1\n");

return 0;
}

Expand Down Expand Up @@ -752,13 +714,16 @@ static int read_arg_spec(void *arg)
if (getline(&buf, &len, handle->fp) < 0)
goto out;

if (strncmp(&buf[3], "spec:", 5))
goto out;

if (!strncmp(buf, "arg", 3))
if (!strncmp(buf, "argspec:", 8))
info->argspec = copy_info_str(&buf[8]);
else if (!strncmp(buf, "ret", 3))
else if (!strncmp(buf, "retspec:", 8))
info->retspec = copy_info_str(&buf[8]);
else if (!strncmp(buf, "argauto:", 8))
info->autoarg = copy_info_str(&buf[8]);
else if (!strncmp(buf, "retauto:", 8))
info->autoret = copy_info_str(&buf[8]);
else if (!strncmp(buf, "auto-args:1", 11))
info->auto_args_enabled = 1;
else
goto out;
}
Expand Down Expand Up @@ -882,7 +847,7 @@ int read_uftrace_info(uint64_t info_mask, struct ftrace_file_handle *handle)
continue;

if (read_handlers[i].handler(handle) < 0) {
pr_dbg("error during read ftrace info (%x)\n",
pr_dbg("error during read uftrace info (%x)\n",
(1U << read_handlers[i].bit));
return -1;
}
Expand Down Expand Up @@ -1003,8 +968,10 @@ int command_info(int argc, char *argv[], struct opts *opts)
pr_out("\n");
}

if (handle.hdr.info_mask & (1UL << ARG_SPEC))
pr_out(fmt, "arguments/retval", handle.info.argspec);
if (handle.hdr.info_mask & (1UL << ARG_SPEC)) {
pr_out(fmt, "arguments", handle.info.argspec);
pr_out(fmt, "return values", handle.info.retspec);
}

if (handle.hdr.info_mask & (1UL << EXIT_STATUS)) {
int status = handle.info.exit_status;
Expand Down
13 changes: 10 additions & 3 deletions cmd-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ static bool can_use_fast_libmcount(struct opts *opts)
return false;
if (getenv("UFTRACE_FILTER") || getenv("UFTRACE_TRIGGER") ||
getenv("UFTRACE_ARGUMENT") || getenv("UFTRACE_RETVAL") ||
getenv("UFTRACE_PATCH") || getenv("UFTRACE_SCRIPT"))
getenv("UFTRACE_PATCH") || getenv("UFTRACE_SCRIPT") ||
getenv("UFTRACE_AUTO_ARGS"))
return false;
return true;
}
Expand Down Expand Up @@ -153,6 +154,9 @@ static void setup_child_environ(struct opts *opts, int pfd)
}
}

if (opts->auto_args)
setenv("UFTRACE_AUTO_ARGS", "1", 1);

if (opts->patch) {
char *patch_str = uftrace_clear_kernel(opts->patch);

Expand Down Expand Up @@ -291,16 +295,19 @@ static uint64_t calc_feat_mask(struct opts *opts)
/* save mcount_max_stack */
features |= MAX_STACK;

/* provide automatic argument/return value spec */
features |= AUTO_ARGS;

if (opts->libcall)
features |= PLTHOOK;

if (opts->kernel)
features |= KERNEL;

if (opts->args)
if (opts->args || opts->auto_args)
features |= ARGUMENT;

if (opts->retval)
if (opts->retval || opts->auto_args)
features |= RETVAL;

if (opts->event)
Expand Down
3 changes: 3 additions & 0 deletions doc/uftrace-live.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ OPTIONS
-R *SPEC*, \--retval=*SPEC*
: Record function return value. This option can be used more than once. See *ARGUMENTS*.

\--auto-args
: Automatically record arguments and return values of well-known library functions. Recommend to use it with `--nest-libcall`.

-f *FIELD*, \--output-fields=*FIELD*
: Customize field in the output. Possible values are: duration, tid, time, delta, elapsed and addr. Multiple fields can be set by using comma. Special field of 'none' can be used (solely) to hide all fields. Default is 'duration,tid'. See *FIELDS*.

Expand Down
3 changes: 3 additions & 0 deletions doc/uftrace-record.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ OPTIONS
-R *SPEC*, \--retval=*SPEC*
: Record function return values. This option can be used more than once. See *ARGUMENTS*.

\--auto-args
: Automatically record arguments and return values of well-known library functions. Recommend to use it with `--nest-libcall`.

\--num-thread=*NUM*
: Use NUM threads to record trace data. Default is 1/4 of online CPUs (but when full kernel tracing is enabled, it will use the full number of CPUs).

Expand Down
15 changes: 13 additions & 2 deletions libmcount/mcount.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,21 @@ static void mcount_filter_init(void)

load_module_symtabs(&symtabs);

setup_auto_args();

uftrace_setup_filter(filter_str, &symtabs, &mcount_triggers,
&mcount_filter_mode, false);
uftrace_setup_trigger(trigger_str, &symtabs, &mcount_triggers,
&mcount_filter_mode, false);
uftrace_setup_argument(argument_str, &symtabs, &mcount_triggers);
uftrace_setup_retval(retval_str, &symtabs, &mcount_triggers);
uftrace_setup_argument(argument_str, &symtabs, &mcount_triggers, false);
uftrace_setup_retval(retval_str, &symtabs, &mcount_triggers, false);

if (getenv("UFTRACE_AUTO_ARGS")) {
uftrace_setup_argument(get_auto_argspec_str(), &symtabs,
&mcount_triggers, true);
uftrace_setup_retval(get_auto_retspec_str(), &symtabs,
&mcount_triggers, true);
}

if (getenv("UFTRACE_DEPTH"))
mcount_depth = strtol(getenv("UFTRACE_DEPTH"), NULL, 0);
Expand Down Expand Up @@ -294,6 +303,8 @@ static void mcount_finish(void)
close(pfd);
pfd = -1;
}

finish_auto_args();
}

static bool mcount_check_rstack(struct mcount_thread_data *mtdp)
Expand Down
12 changes: 11 additions & 1 deletion libmcount/record.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#define SHMEM_SESSION_FMT "/uftrace-%s-%d-%03d" /* session-id, tid, seq */

#define ARG_STR_MAX 98

static struct mcount_shmem_buffer *allocate_shmem_buffer(char *buf, size_t size,
int tid, int idx)
{
Expand Down Expand Up @@ -278,7 +280,15 @@ static unsigned save_to_argbuf(void *argbuf, struct list_head *args_spec,
len = 0;
for (i = 0; i < max_size - total_size; i++) {
dst[i] = str[i];
if (!str[i])

/* truncate long string */
if (i > ARG_STR_MAX) {
dst[i-3] = '.';
dst[i-2] = '.';
dst[i-1] = '.';
dst[i] = '\0';
}
if (!dst[i])
break;
len++;
}
Expand Down
Loading

0 comments on commit aeeb2b3

Please sign in to comment.