aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/erl_trace.c4
-rw-r--r--lib/runtime_tools/c_src/dyntrace.c85
-rw-r--r--lib/runtime_tools/c_src/dyntrace_lttng.h46
-rw-r--r--lib/runtime_tools/src/dyntrace.erl4
4 files changed, 136 insertions, 3 deletions
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index fa1d03c588..0842c0c0a4 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -1000,7 +1000,7 @@ erts_trace_return(Process* p, BeamInstr* fi, Eterm retval, ErtsTracer *tracer)
mfa = TUPLE3(hp, mod, name, make_small(arity));
hp += 4;
send_to_tracer_nif_raw(p, NULL, *tracer, *tracee_flags, p->common.id,
- NULL, TRACE_FUN_DEFAULT, am_return_from, mfa, retval, am_true);
+ NULL, TRACE_FUN_CALL, am_return_from, mfa, retval, am_true);
}
/* Send {trace_ts, Pid, exception_from, {Mod, Name, Arity}, {Class,Value},
@@ -1055,7 +1055,7 @@ erts_trace_exception(Process* p, BeamInstr mfa[3], Eterm class, Eterm value,
cv = TUPLE2(hp, class, value);
hp += 3;
send_to_tracer_nif_raw(p, NULL, *tracer, *tracee_flags, p->common.id,
- NULL, TRACE_FUN_DEFAULT, am_exception_from, mfa_tuple, cv, am_true);
+ NULL, TRACE_FUN_CALL, am_exception_from, mfa_tuple, cv, am_true);
}
/*
diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c
index 43d61266cc..a22b546cdd 100644
--- a/lib/runtime_tools/c_src/dyntrace.c
+++ b/lib/runtime_tools/c_src/dyntrace.c
@@ -71,6 +71,7 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM trace_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM trace_running(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM trace_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM trace_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -86,6 +87,7 @@ static ErlNifFunc nif_funcs[] = {
{"trace_procs", 6, trace_procs},
{"trace_ports", 6, trace_ports},
{"trace_running", 6, trace_running},
+ {"trace_call", 6, trace_call},
{"trace_send", 6, trace_send},
{"trace_receive", 6, trace_receive},
{"trace_garbage_collection", 6, trace_garbage_collection}
@@ -139,6 +141,12 @@ static ERL_NIF_TERM atom_send_to_non_existing_process;
static ERL_NIF_TERM atom_open;
static ERL_NIF_TERM atom_closed;
+/* 'call' */
+
+static ERL_NIF_TERM atom_call;
+static ERL_NIF_TERM atom_return_from;
+static ERL_NIF_TERM atom_exception_from;
+
static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
atom_true = enif_make_atom(env,"true");
@@ -187,6 +195,12 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
atom_open = enif_make_atom(env,"open");
atom_closed = enif_make_atom(env,"closed");
+ /* 'call' */
+
+ atom_call = enif_make_atom(env,"call");
+ atom_return_from = enif_make_atom(env,"return_from");
+ atom_exception_from = enif_make_atom(env,"exception_from");
+
return 0;
}
@@ -322,6 +336,71 @@ static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL
return atom_ok;
}
+static ERL_NIF_TERM trace_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+#ifdef HAVE_USE_DTRACE
+#elif HAVE_USE_LTTNG
+ lttng_decl_procbuf(pid);
+ unsigned int len;
+ char undef[] = "undefined";
+
+ lttng_pid_to_str(argv[2], pid);
+
+ if (argv[0] == atom_call) {
+ const ERL_NIF_TERM* tuple;
+ int arity;
+ lttng_decl_mfabuf(mfa);
+
+ if (enif_get_tuple(env, argv[3], &arity, &tuple)) {
+ if (enif_is_list(env, tuple[2])) {
+ enif_get_list_length(env, tuple[2], &len);
+ } else {
+ enif_get_uint(env, tuple[2], &len);
+ }
+ lttng_mfa_to_str(tuple[0], tuple[1], len, mfa);
+ LTTNG3(function_call, pid, mfa, 0);
+ } else {
+ LTTNG3(function_call, pid, undef, 0);
+ }
+ } else if (argv[0] == atom_return_from) {
+ const ERL_NIF_TERM* tuple;
+ int arity;
+ lttng_decl_mfabuf(mfa);
+
+ if (enif_get_tuple(env, argv[3], &arity, &tuple)) {
+ enif_get_uint(env, tuple[2], &len);
+ lttng_mfa_to_str(tuple[0], tuple[1], len, mfa);
+ LTTNG3(function_return, pid, mfa, 0);
+ } else {
+ LTTNG3(function_return, pid, undef, 0);
+ }
+ } else if (argv[0] == atom_exception_from) {
+ const ERL_NIF_TERM* tuple;
+ int arity;
+ lttng_decl_mfabuf(mfa);
+ char class[LTTNG_BUFFER_SZ];
+
+ enif_get_tuple(env, argv[4], &arity, &tuple);
+ erts_snprintf(class, LTTNG_BUFFER_SZ, "%T", tuple[0]);
+
+ if (enif_get_tuple(env, argv[3], &arity, &tuple)) {
+ enif_get_uint(env, tuple[2], &len);
+ lttng_mfa_to_str(tuple[0], tuple[1], len, mfa);
+ LTTNG3(function_exception, pid, mfa, class);
+ } else {
+ LTTNG3(function_exception, pid, undef, class);
+ }
+ } else {
+ int i;
+ erts_fprintf(stderr, "trace call:\r\n");
+ for (i = 0; i < argc; i++) {
+ erts_fprintf(stderr, " %T\r\n", argv[i]);
+ }
+ }
+#endif
+ return atom_ok;
+}
+
static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
@@ -441,7 +520,11 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
lttng_pid_to_str(argv[3], to);
if (enif_get_tuple(env, argv[4], &arity, &tuple)) {
- enif_get_list_length(env, tuple[2], &len);
+ if (enif_is_list(env, tuple[2])) {
+ enif_get_list_length(env, tuple[2], &len);
+ } else {
+ enif_get_uint(env, tuple[2], &len);
+ }
lttng_mfa_to_str(tuple[0], tuple[1], len, mfa);
LTTNG3(process_spawn, to, pid, mfa);
} else {
diff --git a/lib/runtime_tools/c_src/dyntrace_lttng.h b/lib/runtime_tools/c_src/dyntrace_lttng.h
index 2e0b921621..265af5729f 100644
--- a/lib/runtime_tools/c_src/dyntrace_lttng.h
+++ b/lib/runtime_tools/c_src/dyntrace_lttng.h
@@ -193,6 +193,52 @@ TRACEPOINT_EVENT(
)
)
+/* Call tracing */
+
+TRACEPOINT_EVENT(
+ com_ericsson_dyntrace,
+ function_call,
+ TP_ARGS(
+ char*, pid,
+ char*, mfa,
+ unsigned int, depth
+ ),
+ TP_FIELDS(
+ ctf_string(pid, pid)
+ ctf_string(entry, mfa)
+ ctf_integer(unsigned int, depth, depth)
+ )
+)
+
+TRACEPOINT_EVENT(
+ com_ericsson_dyntrace,
+ function_return,
+ TP_ARGS(
+ char*, pid,
+ char*, mfa,
+ unsigned int, depth
+ ),
+ TP_FIELDS(
+ ctf_string(pid, pid)
+ ctf_string(entry, mfa)
+ ctf_integer(unsigned int, depth, depth)
+ )
+)
+
+TRACEPOINT_EVENT(
+ com_ericsson_dyntrace,
+ function_exception,
+ TP_ARGS(
+ char*, pid,
+ char*, mfa,
+ char*, type
+ ),
+ TP_FIELDS(
+ ctf_string(pid, pid)
+ ctf_string(entry, mfa)
+ ctf_string(class, type)
+ )
+)
/* Process messages */
diff --git a/lib/runtime_tools/src/dyntrace.erl b/lib/runtime_tools/src/dyntrace.erl
index 44c5e36242..f776b601cb 100644
--- a/lib/runtime_tools/src/dyntrace.erl
+++ b/lib/runtime_tools/src/dyntrace.erl
@@ -47,6 +47,7 @@
trace_procs/6,
trace_ports/6,
trace_running/6,
+ trace_call/6,
trace_send/6,
trace_receive/6,
trace_garbage_collection/6
@@ -154,6 +155,9 @@ trace_ports(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm,
trace_running(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) ->
erlang:nif_error(nif_not_loaded).
+trace_call(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) ->
+ erlang:nif_error(nif_not_loaded).
+
trace_send(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) ->
erlang:nif_error(nif_not_loaded).