char padding[LTTNG_UST_ABI_EVENT_NOTIFIER_NOTIFICATION_PADDING];
} __attribute__((packed));
-#define LTTNG_UST_ABI_COUNTER_DIMENSION_MAX 4
-
enum lttng_ust_abi_key_token_type {
LTTNG_UST_ABI_KEY_TOKEN_STRING = 0, /* arg: strtab_offset. */
LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME = 1, /* no arg. */
LTTNG_UST_ABI_COUNTER_BITNESS_64 = 1,
};
-#define LTTNG_UST_ABI_KEY_ARG_PADDING1 256
-#define LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX 256
+#define LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX 4096
+
+struct lttng_ust_abi_counter_key_string {
+ uint32_t string_len; /* string length (includes \0) */
+ char str[]; /* Null-terminated string. */
+} __attribute__((packed));
+
struct lttng_ust_abi_key_token {
- uint32_t type; /* enum lttng_ust_key_token_type */
- union {
- char string[LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX];
- char padding[LTTNG_UST_ABI_KEY_ARG_PADDING1];
- } arg;
+ uint32_t len; /* length of this structure. */
+ uint32_t type; /* enum lttng_ust_key_token_type */
+
+ /* Followed by a struct lttng_ust_abi_counter_key_string for LTTNG_UST_ABI_KEY_TOKEN_STRING. */
} __attribute__((packed));
-#define LTTNG_UST_ABI_NR_KEY_TOKEN 4
struct lttng_ust_abi_counter_key_dimension {
+ uint32_t len; /* length of this structure */
uint32_t nr_key_tokens;
- struct lttng_ust_abi_key_token key_tokens[LTTNG_UST_ABI_NR_KEY_TOKEN];
-} __attribute__((packed));
-#define LTTNG_UST_ABI_COUNTER_DIMENSION_MAX 4
-struct lttng_ust_abi_counter_key {
- uint32_t nr_dimensions;
- struct lttng_ust_abi_counter_key_dimension key_dimensions[LTTNG_UST_ABI_COUNTER_DIMENSION_MAX];
+ /* Followed by a variable-length array of key tokens */
} __attribute__((packed));
-#define LTTNG_UST_ABI_COUNTER_EVENT_PADDING1 16
+#define LTTNG_UST_ABI_COUNTER_EVENT_MAX_LEN 4096U
struct lttng_ust_abi_counter_event {
+ uint32_t len; /* length of this structure */
+
struct lttng_ust_abi_event event;
- struct lttng_ust_abi_counter_key key;
- char padding[LTTNG_UST_ABI_COUNTER_EVENT_PADDING1];
+ uint32_t number_key_dimensions; /* array of dimensions is an array of var. len. elements. */
+
+ /* Followed by a variable-length array of key dimensions */
} __attribute__((packed));
enum lttng_ust_abi_counter_dimension_flags {
uint32_t elem_len; /* array stride (size of lttng_ust_abi_counter_dimension) */
} __attribute__((packed));
-struct lttng_ust_abi_counter_value {
- uint32_t number_dimensions;
- uint64_t dimension_indexes[LTTNG_UST_ABI_COUNTER_DIMENSION_MAX];
- int64_t value;
-} __attribute__((packed));
-
#define LTTNG_UST_ABI_COUNTER_DATA_MAX_LEN 4096U
struct lttng_ust_abi_counter {
uint64_t len;
int lttng_ust_ctl_counter_create_event(int sock,
struct lttng_ust_abi_counter_event *counter_event,
+ size_t counter_event_len,
struct lttng_ust_abi_object_data *counter_data,
struct lttng_ust_abi_object_data **counter_event_data);
struct {
int shm_fd;
} counter_shm;
+ struct {
+ uint32_t len;
+ } counter_event;
};
struct lttng_ust_abi_objd_ops {
LTTNG_KEY_TOKEN_PROVIDER_NAME = 2,
};
-#define LTTNG_KEY_TOKEN_STRING_LEN_MAX LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX
+#define LTTNG_KEY_TOKEN_STRING_LEN_MAX 4096
struct lttng_key_token {
enum lttng_key_token_type type;
union {
} arg;
};
-#define LTTNG_NR_KEY_TOKEN LTTNG_UST_ABI_NR_KEY_TOKEN
+#define LTTNG_NR_KEY_TOKEN 8
struct lttng_counter_key_dimension {
size_t nr_key_tokens;
struct lttng_key_token key_tokens[LTTNG_NR_KEY_TOKEN];
};
-#define LTTNG_COUNTER_DIMENSION_MAX LTTNG_UST_ABI_COUNTER_DIMENSION_MAX
+#define LTTNG_COUNTER_DIMENSION_MAX 4
struct lttng_counter_key {
size_t nr_dimensions;
struct lttng_counter_key_dimension key_dimensions[LTTNG_COUNTER_DIMENSION_MAX];
*/
int lttng_ust_ctl_counter_create_event(int sock,
struct lttng_ust_abi_counter_event *counter_event,
+ size_t counter_event_len,
struct lttng_ust_abi_object_data *counter_data,
struct lttng_ust_abi_object_data **_counter_event_data)
{
memset(&lum, 0, sizeof(lum));
lum.handle = counter_data->handle;
lum.cmd = LTTNG_UST_ABI_COUNTER_EVENT;
- lum.u.counter_event.len = sizeof(*counter_event);
+ lum.u.counter_event.len = counter_event_len;
ret = ustcomm_send_app_cmd(sock, &lum, &lur);
if (ret) {
free(counter_event_data);
return ret;
}
/* Send struct lttng_ust_counter_event */
- len = ustcomm_send_unix_sock(sock, counter_event, sizeof(*counter_event));
- if (len != sizeof(*counter_event)) {
+ len = ustcomm_send_unix_sock(sock, counter_event, counter_event_len);
+ if (len != counter_event_len) {
free(counter_event_data);
if (len < 0)
return len;
*/
struct lttng_event_counter_enabler *lttng_event_counter_enabler_create(
enum lttng_enabler_format_type format_type,
- const struct lttng_ust_abi_event *event_param,
- const struct lttng_ust_abi_counter_key *key,
+ const struct lttng_ust_abi_counter_event *counter_event,
+ const struct lttng_counter_key *key,
struct lttng_ust_channel_counter *chan)
__attribute__((visibility("hidden")));
lttng_session_destroy(session_priv->pub);
}
-static
-int copy_counter_key(struct lttng_counter_key *key,
- const struct lttng_ust_abi_counter_key *key_param)
-{
- size_t i, j, nr_dimensions;
-
- nr_dimensions = key_param->nr_dimensions;
- if (nr_dimensions > LTTNG_UST_ABI_COUNTER_DIMENSION_MAX)
- return -EINVAL;
- key->nr_dimensions = nr_dimensions;
- for (i = 0; i < nr_dimensions; i++) {
- const struct lttng_ust_abi_counter_key_dimension *udim =
- &key_param->key_dimensions[i];
- struct lttng_counter_key_dimension *dim =
- &key->key_dimensions[i];
- size_t nr_key_tokens;
-
- nr_key_tokens = udim->nr_key_tokens;
- if (!nr_key_tokens || nr_key_tokens > LTTNG_UST_ABI_NR_KEY_TOKEN)
- return -EINVAL;
- dim->nr_key_tokens = nr_key_tokens;
- for (j = 0; j < nr_key_tokens; j++) {
- const struct lttng_ust_abi_key_token *utoken =
- &udim->key_tokens[j];
- struct lttng_key_token *token =
- &dim->key_tokens[j];
-
- switch (utoken->type) {
- case LTTNG_UST_ABI_KEY_TOKEN_STRING:
- {
- size_t len;
-
- token->type = LTTNG_UST_ABI_KEY_TOKEN_STRING;
- len = strnlen(utoken->arg.string, LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX);
- if (!len || len >= LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX)
- return -EINVAL;
- strcpy(token->arg.string, utoken->arg.string);
- break;
- }
- case LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME:
- token->type = LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME;
- break;
- case LTTNG_UST_ABI_KEY_TOKEN_PROVIDER_NAME:
- token->type = LTTNG_UST_ABI_KEY_TOKEN_PROVIDER_NAME;
- break;
- default:
- return -EINVAL;
- }
- }
- }
- return 0;
-}
-
/*
* Enabler management.
*/
struct lttng_event_counter_enabler *lttng_event_counter_enabler_create(
enum lttng_enabler_format_type format_type,
- const struct lttng_ust_abi_event *event_param,
- const struct lttng_ust_abi_counter_key *key,
+ const struct lttng_ust_abi_counter_event *counter_event,
+ const struct lttng_counter_key *key,
struct lttng_ust_channel_counter *chan)
{
struct lttng_event_counter_enabler *event_enabler;
event_enabler->parent.parent.format_type = format_type;
CDS_INIT_LIST_HEAD(&event_enabler->parent.parent.filter_bytecode_head);
CDS_INIT_LIST_HEAD(&event_enabler->parent.parent.excluder_head);
- memcpy(&event_enabler->parent.parent.event_param, event_param,
+ memcpy(&event_enabler->parent.parent.event_param, &counter_event->event,
sizeof(event_enabler->parent.parent.event_param));
event_enabler->chan = chan;
- if (key) {
- if (copy_counter_key(&event_enabler->key, key)) {
- free(event_enabler);
- return NULL;
- }
- }
+ memcpy(&event_enabler->key, key, sizeof(struct lttng_counter_key));
/* ctx left NULL */
event_enabler->parent.parent.enabled = 0;
- event_enabler->parent.parent.user_token = event_param->token;
+ event_enabler->parent.parent.user_token = counter_event->event.token;
event_enabler->parent.chan = chan->parent;
cds_list_add(&event_enabler->parent.node, &event_enabler->chan->parent->session->priv->enablers_head);
lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session);
return ret;
}
+static
+int copy_counter_key(struct lttng_counter_key *internal_key,
+ unsigned long arg, size_t arg_len,
+ const struct lttng_ust_abi_counter_event *counter_event)
+{
+ size_t i, j, nr_dimensions, offset = 0;
+ char *addr = (char *)arg;
+ int ret;
+
+ nr_dimensions = counter_event->number_key_dimensions;
+ if (nr_dimensions != 1)
+ return -EINVAL;
+ internal_key->nr_dimensions = nr_dimensions;
+ offset += counter_event->len;
+ for (i = 0; i < nr_dimensions; i++) {
+ const struct lttng_ust_abi_counter_key_dimension *abi_dim;
+ struct lttng_ust_abi_counter_key_dimension dim;
+ struct lttng_counter_key_dimension *internal_dim = &internal_key->key_dimensions[i];
+ size_t nr_key_tokens;
+
+ abi_dim = (const struct lttng_ust_abi_counter_key_dimension *)(addr + offset);
+ offset += abi_dim->len;
+ if (offset > arg_len || abi_dim->len < lttng_ust_offsetofend(struct lttng_ust_abi_counter_key_dimension, nr_key_tokens))
+ return -EINVAL;
+ ret = copy_abi_struct(&dim, sizeof(dim), abi_dim, abi_dim->len);
+ if (ret)
+ return ret;
+ nr_key_tokens = dim.nr_key_tokens;
+ if (!nr_key_tokens || nr_key_tokens > LTTNG_NR_KEY_TOKEN)
+ return -EINVAL;
+ internal_dim->nr_key_tokens = nr_key_tokens;
+ for (j = 0; j < nr_key_tokens; j++) {
+ const struct lttng_ust_abi_key_token *abi_token;
+ struct lttng_ust_abi_key_token token;
+ struct lttng_key_token *internal_token = &internal_dim->key_tokens[j];
+
+ abi_token = (const struct lttng_ust_abi_key_token *)(addr + offset);
+ offset += abi_token->len;
+ if (offset > arg_len || abi_token->len < lttng_ust_offsetofend(struct lttng_ust_abi_key_token, type))
+ return -EINVAL;
+ ret = copy_abi_struct(&token, sizeof(token), abi_token, abi_token->len);
+ if (ret)
+ return ret;
+ switch (token.type) {
+ case LTTNG_UST_ABI_KEY_TOKEN_STRING:
+ {
+ const struct lttng_ust_abi_counter_key_string *abi_key_string;
+
+ abi_key_string = (const struct lttng_ust_abi_counter_key_string *)(addr + offset);
+ offset += sizeof(struct lttng_ust_abi_counter_key_string);
+ if (offset > arg_len)
+ return -EINVAL;
+ internal_token->type = LTTNG_KEY_TOKEN_STRING;
+ if (!abi_key_string->string_len || abi_key_string->string_len > LTTNG_KEY_TOKEN_STRING_LEN_MAX)
+ return -EINVAL;
+ offset += abi_key_string->string_len;
+ if (offset > arg_len)
+ return -EINVAL;
+ if (abi_key_string->str[abi_key_string->string_len - 1] != '\0' ||
+ strlen(abi_key_string->str) + 1 != abi_key_string->string_len)
+ return -EINVAL;
+ memcpy(internal_token->arg.string, abi_key_string->str, abi_key_string->string_len);
+ break;
+ }
+ case LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME:
+ internal_token->type = LTTNG_KEY_TOKEN_EVENT_NAME;
+ break;
+ case LTTNG_UST_ABI_KEY_TOKEN_PROVIDER_NAME:
+ internal_token->type = LTTNG_KEY_TOKEN_PROVIDER_NAME;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ }
+ return 0;
+}
+
static
int lttng_abi_create_event_counter_enabler(int channel_objd,
struct lttng_ust_channel_counter *channel,
- struct lttng_ust_abi_event *event_param,
- const struct lttng_ust_abi_counter_key *key_param,
- void *owner,
- enum lttng_enabler_format_type format_type)
+ unsigned long arg, size_t arg_len, void *owner)
{
+ struct lttng_ust_abi_counter_event *abi_counter_event = (struct lttng_ust_abi_counter_event *)arg;
+ struct lttng_ust_abi_counter_event counter_event = {};
+ struct lttng_counter_key counter_key = {};
struct lttng_event_counter_enabler *enabler;
+ enum lttng_enabler_format_type format_type;
int event_objd, ret;
- event_param->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
+ if (arg_len < lttng_ust_offsetofend(struct lttng_ust_abi_counter_event, number_key_dimensions)) {
+ return -EINVAL;
+ }
+ if (arg_len < abi_counter_event->len ||
+ abi_counter_event->len < lttng_ust_offsetofend(struct lttng_ust_abi_counter_event, number_key_dimensions)) {
+ return -EINVAL;
+ }
+ ret = copy_abi_struct(&counter_event, sizeof(counter_event),
+ abi_counter_event, abi_counter_event->len);
+ if (ret) {
+ return ret;
+ }
+ counter_event.event.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
+ if (strutils_is_star_glob_pattern(counter_event.event.name)) {
+ format_type = LTTNG_ENABLER_FORMAT_STAR_GLOB;
+ } else {
+ format_type = LTTNG_ENABLER_FORMAT_EVENT;
+ }
+ ret = copy_counter_key(&counter_key, arg, arg_len, &counter_event);
+ if (ret) {
+ return ret;
+ }
event_objd = objd_alloc(NULL, <tng_event_enabler_ops, owner,
"event enabler");
if (event_objd < 0) {
* We tolerate no failure path after event creation. It will stay
* invariant for the rest of the session.
*/
- enabler = lttng_event_counter_enabler_create(format_type, event_param,
- key_param, channel);
+ enabler = lttng_event_counter_enabler_create(format_type, &counter_event, &counter_key, channel);
if (!enabler) {
ret = -ENOMEM;
goto event_error;
}
case LTTNG_UST_ABI_COUNTER_EVENT:
{
- struct lttng_ust_abi_counter_event *counter_event_param =
- (struct lttng_ust_abi_counter_event *) arg;
- struct lttng_ust_abi_event *event_param = &counter_event_param->event;
- struct lttng_ust_abi_counter_key *key_param = &counter_event_param->key;
-
- if (strutils_is_star_glob_pattern(event_param->name)) {
- /*
- * If the event name is a star globbing pattern,
- * we create the special star globbing enabler.
- */
- return lttng_abi_create_event_counter_enabler(objd, counter,
- event_param, key_param, owner,
- LTTNG_ENABLER_FORMAT_STAR_GLOB);
- } else {
- return lttng_abi_create_event_counter_enabler(objd, counter,
- event_param, key_param, owner,
- LTTNG_ENABLER_FORMAT_EVENT);
- }
+ return lttng_abi_create_event_counter_enabler(objd, counter,
+ arg, uargs->counter_event.len, owner);
}
case LTTNG_UST_ABI_ENABLE:
return lttng_channel_enable(counter->parent);
union lttng_ust_abi_args args;
char ctxstr[LTTNG_UST_ABI_SYM_NAME_LEN]; /* App context string. */
ssize_t len;
+ struct lttng_ust_abi_counter_event *counter_event = NULL;
memset(&lur, 0, sizeof(lur));
case LTTNG_UST_ABI_COUNTER_EVENT:
{
/* Receive struct lttng_ust_abi_counter_event */
- struct lttng_ust_abi_counter_event counter_event;
-
- if (sizeof(counter_event) != lum->u.counter_event.len) {
- DBG("incorrect counter event data message size: %u", lum->u.counter_event.len);
+ if (lum->u.counter_event.len > LTTNG_UST_ABI_COUNTER_EVENT_MAX_LEN) {
+ DBG("counter event data message too large: %u", lum->u.counter_event.len);
ret = -EINVAL;
goto error;
}
- len = ustcomm_recv_unix_sock(sock, &counter_event, sizeof(counter_event));
+ args.counter_event.len = lum->u.counter_event.len;
+ counter_event = zmalloc(lum->u.counter_event.len);
+ if (!counter_event) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ len = ustcomm_recv_unix_sock(sock, counter_event, lum->u.counter_event.len);
switch (len) {
case 0: /* orderly shutdown */
ret = 0;
goto error;
default:
- if (len == sizeof(counter_event)) {
+ if (len == lum->u.counter_event.len) {
DBG("counter event data received");
break;
} else if (len < 0) {
}
if (ops->cmd)
ret = ops->cmd(lum->handle, lum->cmd,
- (unsigned long) &counter_event,
+ (unsigned long) counter_event,
&args, sock_info);
else
ret = -ENOSYS;
error:
ust_unlock();
+ free(counter_event);
return ret;
}