Skip to content

Commit

Permalink
Add basic support for dynamic instrumentation
Browse files Browse the repository at this point in the history
Support for instrument shared libraries is not implemented yet.
  • Loading branch information
5kg committed Sep 4, 2013
1 parent 88ed1da commit ae460fd
Show file tree
Hide file tree
Showing 10 changed files with 430 additions and 19 deletions.
30 changes: 29 additions & 1 deletion include/lttng/ust-abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,45 @@ struct lttng_ust_stream {
*/
} LTTNG_PACKED;

#define LTTNG_UST_EVENT_PADDING1 16
/*
* Either addr is used, or symbol_name and offset.
*/
#define LTTNG_UST_PROBE_PADDING 16
struct lttng_ust_probe {
uint64_t addr;

uint64_t offset;
char symbol_name[LTTNG_UST_SYM_NAME_LEN];

char padding[LTTNG_UST_PROBE_PADDING];
} LTTNG_PACKED;

/*
* Instrument target
*/
#define LTTNG_UST_TARGET_PADDING 32
struct lttng_ust_target {
uint32_t path_len;

char padding[LTTNG_UST_TARGET_PADDING];

char path[0];
} LTTNG_PACKED;

#define LTTNG_UST_EVENT_PADDING1 (16 - sizeof(struct lttng_ust_target *))
#define LTTNG_UST_EVENT_PADDING2 (LTTNG_UST_SYM_NAME_LEN + 32)
struct lttng_ust_event {
enum lttng_ust_instrumentation instrumentation;
char name[LTTNG_UST_SYM_NAME_LEN]; /* event name */

enum lttng_ust_loglevel_type loglevel_type;
int loglevel; /* value, -1: all */
struct lttng_ust_target *target;
char padding[LTTNG_UST_EVENT_PADDING1];

/* Per instrumentation type configuration */
union {
struct lttng_ust_probe probe;
char padding[LTTNG_UST_EVENT_PADDING2];
} u;
} LTTNG_PACKED;
Expand Down Expand Up @@ -273,6 +300,7 @@ struct lttng_ust_filter_bytecode {

/* Event FD commands */
#define LTTNG_UST_FILTER _UST_CMD(0xA0)
#define LTTNG_UST_TARGET _UST_CMD(0xA1)

#define LTTNG_UST_ROOT_HANDLE 0

Expand Down
19 changes: 19 additions & 0 deletions include/lttng/ust-ctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ int ustctl_add_context(int sock, struct lttng_ust_context *ctx,
struct lttng_ust_object_data **context_data);
int ustctl_set_filter(int sock, struct lttng_ust_filter_bytecode *bytecode,
struct lttng_ust_object_data *obj_data);
int ustctl_set_target(int sock, struct lttng_ust_target *target,
struct lttng_ust_object_data *obj_data);

int ustctl_enable(int sock, struct lttng_ust_object_data *object);
int ustctl_disable(int sock, struct lttng_ust_object_data *object);
Expand Down Expand Up @@ -230,6 +232,7 @@ enum ustctl_socket_type {
enum ustctl_notify_cmd {
USTCTL_NOTIFY_CMD_EVENT = 0,
USTCTL_NOTIFY_CMD_CHANNEL = 1,
USTCTL_NOTIFY_CMD_INSTRUMENT = 2,
};

enum ustctl_channel_header {
Expand Down Expand Up @@ -395,4 +398,20 @@ int ustctl_reply_register_channel(int sock,
enum ustctl_channel_header header_type,
int ret_code); /* return code. 0 ok, negative error */

/*
* Returns 0 on success, negative error value on error.
*/
int ustctl_recv_instrument_probe(int sock,
char *object_path,
char *name,
enum lttng_ust_instrumentation *instrumentation,
uint64_t *addr,
char *symbol,
uint64_t *offset);

/*
* Returns 0 on success, negative error value on error.
*/
int ustctl_reply_instrument_probe(int sock, int ret_code);

#endif /* _LTTNG_UST_CTL_H */
3 changes: 3 additions & 0 deletions include/lttng/ust-events.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ struct lttng_probe_desc {
enum lttng_enabler_type {
LTTNG_ENABLER_WILDCARD,
LTTNG_ENABLER_EVENT,
LTTNG_ENABLER_INSTRUMENT,
};

/*
Expand Down Expand Up @@ -536,6 +537,8 @@ int lttng_enabler_enable(struct lttng_enabler *enabler);
int lttng_enabler_disable(struct lttng_enabler *enabler);
int lttng_enabler_attach_bytecode(struct lttng_enabler *enabler,
struct lttng_ust_filter_bytecode_node *bytecode);
int lttng_enabler_attach_target(struct lttng_enabler *enabler,
struct lttng_ust_target *target);
int lttng_enabler_attach_context(struct lttng_enabler *enabler,
struct lttng_ust_context *ctx);

Expand Down
28 changes: 28 additions & 0 deletions include/ust-comm.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ struct ustcomm_ust_msg {
uint32_t reloc_offset;
uint64_t seqnum;
} LTTNG_PACKED filter;
struct {
uint32_t data_size; /* following target data */
} LTTNG_PACKED target;
char padding[USTCOMM_MSG_PADDING2];
} u;
} LTTNG_PACKED;
Expand Down Expand Up @@ -160,6 +163,24 @@ struct ustcomm_notify_channel_reply {
char padding[USTCOMM_NOTIFY_CHANNEL_REPLY_PADDING];
} LTTNG_PACKED;

#define USTCOMM_NOTIFY_INSTRUMENT_MSG_PADDING 32
struct ustcomm_notify_instrument_msg {
uint32_t instrumentation; /* enum lttng_ust_instrumentation */
char name[LTTNG_UST_SYM_NAME_LEN];
uint64_t addr;
char symbol[LTTNG_UST_SYM_NAME_LEN];
uint64_t offset;
uint32_t object_path_len;
char padding[USTCOMM_NOTIFY_INSTRUMENT_MSG_PADDING];
/* followed by object_path */
} LTTNG_PACKED;

#define USTCOMM_NOTIFY_INSTRUMENT_REPLY_PADDING 32
struct ustcomm_notify_instrument_reply {
int32_t ret_code; /* 0: ok, negative: error code */
char padding[USTCOMM_NOTIFY_INSTRUMENT_REPLY_PADDING];
} LTTNG_PACKED;

/*
* LTTNG_UST_TRACEPOINT_FIELD_LIST reply is followed by a
* struct lttng_ust_field_iter field.
Expand Down Expand Up @@ -231,6 +252,13 @@ int ustcomm_register_channel(int sock,
uint32_t *chan_id, /* channel id (output) */
int *header_type); /* header type (output) */

/*
* Returns 0 on success, negative error value on error.
* Returns -EPIPE or -ECONNRESET if other end has hung up.
*/
int ustcomm_instrument_probe(int sock,
const struct lttng_ust_event *uevent); /* userspace event */

int ustcomm_setsockopt_rcv_timeout(int sock, unsigned int msec);
int ustcomm_setsockopt_snd_timeout(int sock, unsigned int msec);

Expand Down
76 changes: 76 additions & 0 deletions liblttng-ust-comm/lttng-ust-comm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,82 @@ int ustcomm_register_channel(int sock,
}
}

/*
* Returns 0 on success, negative error value on error.
*/
int ustcomm_instrument_probe(int sock,
const struct lttng_ust_event *uevent) /* userspace event */
{
ssize_t len;
struct {
struct ustcomm_notify_hdr header;
struct ustcomm_notify_instrument_msg m;
} msg;
struct {
struct ustcomm_notify_hdr header;
struct ustcomm_notify_instrument_reply r;
} reply;

memset(&msg, 0, sizeof(msg));
msg.header.notify_cmd = USTCTL_NOTIFY_CMD_INSTRUMENT;
msg.m.instrumentation = uevent->instrumentation;
strncpy(msg.m.name, uevent->name, LTTNG_UST_SYM_NAME_LEN);
msg.m.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
msg.m.addr = uevent->u.probe.addr;
strncpy(msg.m.symbol, uevent->u.probe.symbol_name, LTTNG_UST_SYM_NAME_LEN);
msg.m.symbol[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
msg.m.offset = uevent->u.probe.offset;
msg.m.object_path_len = uevent->target->path_len;

len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
if (len > 0 && len != sizeof(msg)) {
return -EIO;
}
if (len < 0) {
return len;
}

len = ustcomm_send_unix_sock(sock, uevent->target->path,
uevent->target->path_len);
if (len > 0 && len != uevent->target->path_len) {
return -EIO;
}
if (len < 0) {
return len;
}

/* receive reply */
len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
switch (len) {
case 0: /* orderly shutdown */
return -EPIPE;
case sizeof(reply):
if (reply.header.notify_cmd != msg.header.notify_cmd) {
ERR("Unexpected result message command "
"expected: %u vs received: %u\n",
msg.header.notify_cmd, reply.header.notify_cmd);
return -EINVAL;
}
if (reply.r.ret_code > 0)
return -EINVAL;
if (reply.r.ret_code < 0)
return reply.r.ret_code;
DBG("Sent instrument probe notification for object \"%s\": ret_code %d\n",
uevent->target->path, reply.r.ret_code);
return 0;
default:
if (len < 0) {
/* Transport level error */
if (errno == EPIPE || errno == ECONNRESET)
len = -errno;
return len;
} else {
ERR("incorrect message size: %zd\n", len);
return len;
}
}
}

/*
* Set socket reciving timeout.
*/
Expand Down
103 changes: 103 additions & 0 deletions liblttng-ust-ctl/ustctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ int ustctl_create_event(int sock, struct lttng_ust_event *ev,
lum.cmd = LTTNG_UST_EVENT;
strncpy(lum.u.event.name, ev->name,
LTTNG_UST_SYM_NAME_LEN);
lum.u.event.u.probe.addr = ev->u.probe.addr;
lum.u.event.u.probe.offset = ev->u.probe.offset;
strncpy(lum.u.event.u.probe.symbol_name, ev->u.probe.symbol_name,
LTTNG_UST_SYM_NAME_LEN);
lum.u.event.instrumentation = ev->instrumentation;
lum.u.event.loglevel_type = ev->loglevel_type;
lum.u.event.loglevel = ev->loglevel;
Expand Down Expand Up @@ -241,6 +245,35 @@ int ustctl_add_context(int sock, struct lttng_ust_context *ctx,
return ret;
}

int ustctl_set_target(int sock, struct lttng_ust_target *target,
struct lttng_ust_object_data *obj_data)
{
struct ustcomm_ust_msg lum;
struct ustcomm_ust_reply lur;
int ret;

if (!obj_data)
return -EINVAL;

memset(&lum, 0, sizeof(lum));
lum.handle = obj_data->handle;
lum.cmd = LTTNG_UST_TARGET;
lum.u.target.data_size = sizeof(struct lttng_ust_target)
+ target->path_len;

ret = ustcomm_send_app_msg(sock, &lum);
if (ret)
return ret;
/* send var len target struct */
ret = ustcomm_send_unix_sock(sock, target, lum.u.target.data_size);
if (ret < 0) {
return ret;
}
if (ret != lum.u.target.data_size)
return -EINVAL;
return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
}

int ustctl_set_filter(int sock, struct lttng_ust_filter_bytecode *bytecode,
struct lttng_ust_object_data *obj_data)
{
Expand Down Expand Up @@ -1548,6 +1581,9 @@ int ustctl_recv_notify(int sock, enum ustctl_notify_cmd *notify_cmd)
case 1:
*notify_cmd = USTCTL_NOTIFY_CMD_CHANNEL;
break;
case 2:
*notify_cmd = USTCTL_NOTIFY_CMD_INSTRUMENT;
break;
default:
return -EINVAL;
}
Expand Down Expand Up @@ -1799,6 +1835,73 @@ int ustctl_reply_register_channel(int sock,
return 0;
}

/*
* Returns 0 on success, negative error value on error.
*/
int ustctl_recv_instrument_probe(int sock,
char *object_path,
char *name,
enum lttng_ust_instrumentation *instrumentation,
uint64_t *addr,
char *symbol,
uint64_t *offset)
{
ssize_t len;
struct ustcomm_notify_instrument_msg msg;

len = ustcomm_recv_unix_sock(sock, &msg, sizeof(msg));
if (len > 0 && len != sizeof(msg))
return -EIO;
if (len == 0)
return -EPIPE;
if (len < 0)
return len;

strncpy(name, msg.name, LTTNG_UST_SYM_NAME_LEN);
name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
*instrumentation = msg.instrumentation;
*addr = msg.addr;
strncpy(symbol, msg.symbol, LTTNG_UST_SYM_NAME_LEN);
symbol[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
*offset = msg.offset;

if (msg.object_path_len <= 0) {
return -EINVAL;
}

len = ustcomm_recv_unix_sock(sock, object_path, msg.object_path_len);
if (len > 0 && len != msg.object_path_len)
return -EIO;
if (len == 0)
return -EPIPE;
if (len < 0)
return len;

return 0;
}

/*
* Returns 0 on success, negative error value on error.
*/
int ustctl_reply_instrument_probe(int sock, int ret_code)
{
ssize_t len;
struct {
struct ustcomm_notify_hdr header;
struct ustcomm_notify_instrument_reply r;
} reply;

memset(&reply, 0, sizeof(reply));
reply.header.notify_cmd = USTCTL_NOTIFY_CMD_INSTRUMENT;
reply.r.ret_code = ret_code;
len = ustcomm_send_unix_sock(sock, &reply, sizeof(reply));
if (len > 0 && len != sizeof(reply))
return -EIO;
if (len < 0)
return len;
return 0;
}

static __attribute__((constructor))
void ustctl_init(void)
{
Expand Down
13 changes: 13 additions & 0 deletions liblttng-ust/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#ifdef __linux__

#include <sys/prctl.h>
#include <unistd.h>

#define LTTNG_UST_PROCNAME_LEN 17

Expand All @@ -34,6 +35,18 @@ void lttng_ust_getprocname(char *name)
(void) prctl(PR_GET_NAME, (unsigned long) name, 0, 0, 0);
}

static inline
int lttng_ust_getexecpath(char *path)
{
ssize_t len;

if ((len = readlink("/proc/self/exe", path, PATH_MAX)) != -1) {
path[len] = '\0';
return len;
}
return -1;
}

#elif defined(__FreeBSD__)
#include <stdlib.h>
#include <string.h>
Expand Down

0 comments on commit ae460fd

Please sign in to comment.