Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

script: Support native C/C++ shared object scripting #1205

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ endif
prefix ?= /usr/local
bindir = $(prefix)/bin
libdir = $(prefix)/lib/uftrace
incdir = $(prefix)/include/uftrace
etcdir = $(prefix)/etc
mandir = $(prefix)/share/man
docdir = $(srcdir)/doc
Expand Down Expand Up @@ -211,7 +212,7 @@ PYTHON_OBJS := $(patsubst $(srcdir)/%.c,$(objdir)/%.op,$(PYTHON_SRCS))

UFTRACE_ARCH_OBJS := $(objdir)/arch/$(ARCH)/uftrace.o

UFTRACE_HDRS := $(filter-out $(srcdir)/version.h,$(wildcard $(srcdir)/*.h $(srcdir)/utils/*.h))
UFTRACE_HDRS := $(filter-out $(srcdir)/version.h,$(wildcard $(srcdir)/*.h $(srcdir)/utils/*.h $(srcdir)/include/uftrace/*.h))
UFTRACE_HDRS += $(srcdir)/libmcount/mcount.h $(wildcard $(srcdir)/arch/$(ARCH)/*.h)

LIBMCOUNT_SRCS := $(filter-out %-nop.c,$(wildcard $(srcdir)/libmcount/*.c))
Expand All @@ -223,7 +224,8 @@ LIBMCOUNT_FAST_SINGLE_OBJS := $(patsubst $(objdir)/%.op,$(objdir)/%-fast-single.
LIBMCOUNT_UTILS_SRCS += $(srcdir)/utils/debug.c $(srcdir)/utils/regs.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 $(srcdir)/utils/script-luajit.c
LIBMCOUNT_UTILS_SRCS += $(srcdir)/utils/script.c $(srcdir)/utils/script-python.c
LIBMCOUNT_UTILS_SRCS += $(srcdir)/utils/script-luajit.c $(srcdir)/utils/script-native.c
LIBMCOUNT_UTILS_SRCS += $(srcdir)/utils/auto-args.c $(srcdir)/utils/dwarf.c
LIBMCOUNT_UTILS_SRCS += $(srcdir)/utils/hashmap.c $(srcdir)/utils/argspec.c
LIBMCOUNT_UTILS_SRCS += $(srcdir)/utils/tracefs.c $(srcdir)/utils/socket.c
Expand Down Expand Up @@ -362,6 +364,7 @@ endif
install: all
$(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(bindir)
$(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(libdir)
$(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(incdir)
$(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(completiondir)
ifneq ($(wildcard $(elfdir)/lib/libelf.so),)
ifeq ($(wildcard $(prefix)/lib/libelf.so),)
Expand All @@ -383,6 +386,8 @@ ifneq ($(findstring HAVE_LIBPYTHON, $(COMMON_CFLAGS)), )
$(Q)$(INSTALL) $(srcdir)/python/uftrace.py $(DESTDIR)$(libdir)/uftrace.py
$(Q)$(INSTALL) $(objdir)/python/uftrace_python.so $(DESTDIR)$(libdir)/uftrace_python.so
endif
$(call QUIET_INSTALL, headers)
$(Q)$(INSTALL) -m 644 $(srcdir)/include/uftrace/script.h $(DESTDIR)$(incdir)/script.h
$(call QUIET_INSTALL, bash-completion)
$(Q)$(INSTALL) -m 644 $(srcdir)/misc/bash-completion.sh $(DESTDIR)$(completiondir)/uftrace
@$(MAKE) -sC $(docdir) install DESTDIR=$(DESTDIR)$(mandir)
Expand Down
75 changes: 38 additions & 37 deletions cmds/script.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ static int run_script_for_rstack(struct uftrace_data *handle, struct uftrace_tas
task->timestamp = rstack->time;

if (rstack->type == UFTRACE_ENTRY) {
struct script_context sc_ctx = {
struct uftrace_script_context sc_ctx = {
0,
};
struct uftrace_fstack *fstack;
Expand All @@ -63,23 +63,23 @@ static int run_script_for_rstack(struct uftrace_data *handle, struct uftrace_tas
if (!script_match_filter(symname))
goto out;

sc_ctx.tid = task->tid;
sc_ctx.depth = depth; /* display depth */
sc_ctx.timestamp = rstack->time;
sc_ctx.address = rstack->addr;
sc_ctx.name = symname;
sc_ctx.base.tid = task->tid;
sc_ctx.base.depth = depth; /* display depth */
sc_ctx.base.timestamp = rstack->time;
sc_ctx.base.address = rstack->addr;
sc_ctx.base.name = symname;

if (tr.flags & TRIGGER_FL_ARGUMENT && opts->show_args) {
sc_ctx.argbuf = task->args.data;
sc_ctx.arglen = task->args.len;
sc_ctx.argspec = task->args.args;
sc_ctx.args.argbuf = task->args.data;
sc_ctx.args.arglen = task->args.len;
sc_ctx.args.argspec = task->args.args;
}

/* script hooking for function entry */
script_uftrace_entry(&sc_ctx);
}
else if (rstack->type == UFTRACE_EXIT) {
struct script_context sc_ctx = {
struct uftrace_script_context sc_ctx = {
0,
};
struct uftrace_fstack *fstack;
Expand All @@ -99,17 +99,17 @@ static int run_script_for_rstack(struct uftrace_data *handle, struct uftrace_tas
rstack->depth = depth;

/* setup context for script execution */
sc_ctx.tid = task->tid;
sc_ctx.depth = rstack->depth;
sc_ctx.timestamp = rstack->time;
sc_ctx.duration = fstack->total_time;
sc_ctx.address = rstack->addr;
sc_ctx.name = symname;
sc_ctx.base.tid = task->tid;
sc_ctx.base.depth = rstack->depth;
sc_ctx.base.timestamp = rstack->time;
sc_ctx.base.duration = fstack->total_time;
sc_ctx.base.address = rstack->addr;
sc_ctx.base.name = symname;

if (rstack->more && opts->show_args) {
sc_ctx.argbuf = task->args.data;
sc_ctx.arglen = task->args.len;
sc_ctx.argspec = task->args.args;
sc_ctx.args.argbuf = task->args.data;
sc_ctx.args.arglen = task->args.len;
sc_ctx.args.argspec = task->args.args;
}

/* script hooking for function exit */
Expand All @@ -119,20 +119,22 @@ static int run_script_for_rstack(struct uftrace_data *handle, struct uftrace_tas
fstack_exit(task);
}
else if (rstack->type == UFTRACE_EVENT) {
struct script_context sc_ctx = {
.tid = task->tid,
.depth = rstack->depth,
.timestamp = rstack->time,
.address = rstack->addr,
struct uftrace_script_context sc_ctx = {
0,
};

sc_ctx.name = event_get_name(handle, rstack->addr);
sc_ctx.argbuf = event_get_data_str(rstack->addr, task->args.data, false);
sc_ctx.base.tid = task->tid;
sc_ctx.base.depth = rstack->depth;
sc_ctx.base.timestamp = rstack->time;
sc_ctx.base.address = rstack->addr;

sc_ctx.base.name = event_get_name(handle, rstack->addr);
sc_ctx.args.argbuf = event_get_data_str(rstack->addr, task->args.data, false);

script_uftrace_event(&sc_ctx);

free(sc_ctx.name);
free(sc_ctx.argbuf);
free(sc_ctx.base.name);
free(sc_ctx.args.argbuf);
}
else if (rstack->type == UFTRACE_LOST) {
/* Do nothing as of now */
Expand All @@ -145,18 +147,15 @@ static int run_script_for_rstack(struct uftrace_data *handle, struct uftrace_tas

int command_script(int argc, char *argv[], struct uftrace_opts *opts)
{
int ret;
int ret, i;
struct uftrace_data handle;
struct uftrace_task_reader *task;
struct script_info info = {
struct uftrace_script_info info = {
.api_version = SCRIPT_API_VERSION,
.name = opts->script_file,
.version = UFTRACE_VERSION,
};

if (!SCRIPT_ENABLED) {
pr_warn("script command is not supported due to missing libpython2.7.so\n");
return -1;
}
char *cmds = NULL;

if (!opts->script_file) {
pr_out("Usage: uftrace script (-S|--script) <script_file>\n");
Expand Down Expand Up @@ -193,7 +192,9 @@ int command_script(int argc, char *argv[], struct uftrace_opts *opts)

fstack_setup_filters(opts, &handle);

strv_copy(&info.cmds, argc, argv);
for (i = 0; i < argc; i++)
cmds = strjoin(cmds, argv[i], "\n");
info.cmds = cmds;

/* initialize script */
if (script_init(&info, opts->patt_type) < 0) {
Expand All @@ -218,7 +219,7 @@ int command_script(int argc, char *argv[], struct uftrace_opts *opts)

close_data_file(opts, &handle);

strv_free(&info.cmds);
free(cmds);

return ret;
}
2 changes: 2 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ fi

bindir=${bindir:-${prefix}/bin}
libdir=${libdir:-${prefix}/lib/uftrace}
incdir=${incdir:-${prefix}/include/uftrace}
etcdir=${etcdir:-${prefix}/etc}
mandir=${mandir:-${prefix}/share/man}

Expand Down Expand Up @@ -271,6 +272,7 @@ cat >$output <<EOF
override prefix := $prefix
override bindir := $bindir
override libdir := $libdir
override incdir := $incdir
override mandir := $mandir
override etcdir := $etcdir
EOF
Expand Down
28 changes: 28 additions & 0 deletions include/uftrace/script.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef UFTRACE_INCLUDE_SCRIPT_H
#define UFTRACE_INCLUDE_SCRIPT_H

#include <stdbool.h>
#include <stdint.h>

#define SCRIPT_API_VERSION 1

/* informantion passed during initialization */
struct uftrace_script_info {
int api_version;
char *name;
char *version;
bool record;
const char *cmds;
};

/* base context information passed to script */
struct uftrace_script_base_ctx {
int tid;
int depth;
uint64_t timestamp;
uint64_t duration; /* exit only */
unsigned long address;
char *name;
};

#endif /* UFTRACE_INCLUDE_SCRIPT_H */
54 changes: 28 additions & 26 deletions libmcount/mcount.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ static void mcount_trace_finish(bool send_msg)
goto unlock;

/* dtor for script support */
if (SCRIPT_ENABLED && script_str)
if (script_str)
script_uftrace_end();

/* notify to uftrace that we're finished */
Expand Down Expand Up @@ -929,31 +929,31 @@ enum filter_result mcount_entry_filter_check(struct mcount_thread_data *mtdp, un
return FILTER_IN;
}

static int script_save_context(struct script_context *sc_ctx, struct mcount_thread_data *mtdp,
struct mcount_ret_stack *rstack, char *symname, bool has_arg_retval,
struct list_head *pargs)
static int script_save_context(struct uftrace_script_context *sc_ctx,
struct mcount_thread_data *mtdp, struct mcount_ret_stack *rstack,
char *symname, bool has_arg_retval, struct list_head *pargs)
{
if (!script_match_filter(symname))
return -1;

sc_ctx->tid = mcount_gettid(mtdp);
sc_ctx->depth = rstack->depth;
sc_ctx->address = rstack->child_ip;
sc_ctx->name = symname;
sc_ctx->timestamp = rstack->start_time;
sc_ctx->base.tid = mcount_gettid(mtdp);
sc_ctx->base.depth = rstack->depth;
sc_ctx->base.address = rstack->child_ip;
sc_ctx->base.name = symname;
sc_ctx->base.timestamp = rstack->start_time;
if (rstack->end_time)
sc_ctx->duration = rstack->end_time - rstack->start_time;
sc_ctx->base.duration = rstack->end_time - rstack->start_time;

if (has_arg_retval) {
unsigned *argbuf = get_argbuf(mtdp, rstack);

sc_ctx->arglen = argbuf[0];
sc_ctx->argbuf = &argbuf[1];
sc_ctx->argspec = pargs;
sc_ctx->args.arglen = argbuf[0];
sc_ctx->args.argbuf = &argbuf[1];
sc_ctx->args.argspec = pargs;
}
else {
/* prevent access to arguments */
sc_ctx->arglen = 0;
sc_ctx->args.arglen = 0;
}

return 0;
Expand All @@ -962,7 +962,7 @@ static int script_save_context(struct script_context *sc_ctx, struct mcount_thre
static void script_hook_entry(struct mcount_thread_data *mtdp, struct mcount_ret_stack *rstack,
struct uftrace_trigger *tr)
{
struct script_context sc_ctx;
struct uftrace_script_context sc_ctx;
unsigned long entry_addr = rstack->child_ip;
struct uftrace_symbol *sym = find_symtabs(&mcount_sym_info, entry_addr);
char *symname = symbol_getname(sym, entry_addr);
Expand All @@ -982,7 +982,7 @@ static void script_hook_entry(struct mcount_thread_data *mtdp, struct mcount_ret

static void script_hook_exit(struct mcount_thread_data *mtdp, struct mcount_ret_stack *rstack)
{
struct script_context sc_ctx;
struct uftrace_script_context sc_ctx;
unsigned long entry_addr = rstack->child_ip;
struct uftrace_symbol *sym = find_symtabs(&mcount_sym_info, entry_addr);
char *symname = symbol_getname(sym, entry_addr);
Expand Down Expand Up @@ -1089,7 +1089,7 @@ void mcount_entry_filter_record(struct mcount_thread_data *mtdp, struct mcount_r
}

/* script hooking for function entry */
if (SCRIPT_ENABLED && script_str)
if (script_str)
script_hook_entry(mtdp, rstack, tr);

#define FLAGS_TO_CHECK (TRIGGER_FL_RECOVER | TRIGGER_FL_TRACE_ON | TRIGGER_FL_TRACE_OFF)
Expand Down Expand Up @@ -1139,7 +1139,7 @@ void mcount_exit_filter_record(struct mcount_thread_data *mtdp, struct mcount_re
mtdp->record_idx--;

if (!mcount_enabled)
return;
goto out;

if (!(rstack->flags & MCOUNT_FL_RETVAL))
retval = NULL;
Expand Down Expand Up @@ -1183,8 +1183,9 @@ void mcount_exit_filter_record(struct mcount_thread_data *mtdp, struct mcount_re
mtdp->nr_events = k; /* invalidate sync events */
}

out:
/* script hooking for function exit */
if (SCRIPT_ENABLED && script_str)
if (script_str)
script_hook_exit(mtdp, rstack);
}
}
Expand Down Expand Up @@ -1693,7 +1694,7 @@ static void atfork_prepare_handler(void)
};

/* call script atfork preparation routine */
if (SCRIPT_ENABLED && script_str)
if (script_str)
script_atfork_prepare();

uftrace_send_message(UFTRACE_MSG_FORK_START, &tmsg, sizeof(tmsg));
Expand Down Expand Up @@ -1745,7 +1746,8 @@ static void atfork_child_handler(void)

static void mcount_script_init(enum uftrace_pattern_type patt_type)
{
struct script_info info = {
struct uftrace_script_info info = {
.api_version = SCRIPT_API_VERSION,
.name = script_str,
.version = UFTRACE_VERSION,
.record = true,
Expand All @@ -1754,12 +1756,12 @@ static void mcount_script_init(enum uftrace_pattern_type patt_type)

cmds_str = getenv("UFTRACE_ARGS");
if (cmds_str)
strv_split(&info.cmds, cmds_str, "\n");
info.cmds = cmds_str;

if (script_init(&info, patt_type) < 0)
script_str = NULL;

strv_free(&info.cmds);
else if (!info.record)
mcount_enabled = false;
}

/**
Expand Down Expand Up @@ -2208,7 +2210,7 @@ static __used void mcount_startup(void)
mcount_hook_functions();

/* initialize script binding */
if (SCRIPT_ENABLED && script_str)
if (script_str)
mcount_script_init(patt_type);

compiler_barrier();
Expand Down Expand Up @@ -2238,7 +2240,7 @@ static void mcount_cleanup(void)

mcount_filter_finish();

if (SCRIPT_ENABLED && script_str)
if (script_str)
script_finish();
script_str = NULL;

Expand Down
Loading