|
@@ -848,6 +848,7 @@ static void free_arg(struct print_arg *arg)
|
|
|
free(arg->bitmask.bitmask);
|
|
|
break;
|
|
|
case PRINT_DYNAMIC_ARRAY:
|
|
|
+ case PRINT_DYNAMIC_ARRAY_LEN:
|
|
|
free(arg->dynarray.index);
|
|
|
break;
|
|
|
case PRINT_OP:
|
|
@@ -2728,6 +2729,42 @@ process_dynamic_array(struct event_format *event, struct print_arg *arg, char **
|
|
|
return EVENT_ERROR;
|
|
|
}
|
|
|
|
|
|
+static enum event_type
|
|
|
+process_dynamic_array_len(struct event_format *event, struct print_arg *arg,
|
|
|
+ char **tok)
|
|
|
+{
|
|
|
+ struct format_field *field;
|
|
|
+ enum event_type type;
|
|
|
+ char *token;
|
|
|
+
|
|
|
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
|
|
|
+ goto out_free;
|
|
|
+
|
|
|
+ arg->type = PRINT_DYNAMIC_ARRAY_LEN;
|
|
|
+
|
|
|
+ /* Find the field */
|
|
|
+ field = pevent_find_field(event, token);
|
|
|
+ if (!field)
|
|
|
+ goto out_free;
|
|
|
+
|
|
|
+ arg->dynarray.field = field;
|
|
|
+ arg->dynarray.index = 0;
|
|
|
+
|
|
|
+ if (read_expected(EVENT_DELIM, ")") < 0)
|
|
|
+ goto out_err;
|
|
|
+
|
|
|
+ type = read_token(&token);
|
|
|
+ *tok = token;
|
|
|
+
|
|
|
+ return type;
|
|
|
+
|
|
|
+ out_free:
|
|
|
+ free_token(token);
|
|
|
+ out_err:
|
|
|
+ *tok = NULL;
|
|
|
+ return EVENT_ERROR;
|
|
|
+}
|
|
|
+
|
|
|
static enum event_type
|
|
|
process_paren(struct event_format *event, struct print_arg *arg, char **tok)
|
|
|
{
|
|
@@ -2975,6 +3012,10 @@ process_function(struct event_format *event, struct print_arg *arg,
|
|
|
free_token(token);
|
|
|
return process_dynamic_array(event, arg, tok);
|
|
|
}
|
|
|
+ if (strcmp(token, "__get_dynamic_array_len") == 0) {
|
|
|
+ free_token(token);
|
|
|
+ return process_dynamic_array_len(event, arg, tok);
|
|
|
+ }
|
|
|
|
|
|
func = find_func_handler(event->pevent, token);
|
|
|
if (func) {
|
|
@@ -3655,14 +3696,25 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
|
|
|
goto out_warning_op;
|
|
|
}
|
|
|
break;
|
|
|
+ case PRINT_DYNAMIC_ARRAY_LEN:
|
|
|
+ offset = pevent_read_number(pevent,
|
|
|
+ data + arg->dynarray.field->offset,
|
|
|
+ arg->dynarray.field->size);
|
|
|
+ /*
|
|
|
+ * The total allocated length of the dynamic array is
|
|
|
+ * stored in the top half of the field, and the offset
|
|
|
+ * is in the bottom half of the 32 bit field.
|
|
|
+ */
|
|
|
+ val = (unsigned long long)(offset >> 16);
|
|
|
+ break;
|
|
|
case PRINT_DYNAMIC_ARRAY:
|
|
|
/* Without [], we pass the address to the dynamic data */
|
|
|
offset = pevent_read_number(pevent,
|
|
|
data + arg->dynarray.field->offset,
|
|
|
arg->dynarray.field->size);
|
|
|
/*
|
|
|
- * The actual length of the dynamic array is stored
|
|
|
- * in the top half of the field, and the offset
|
|
|
+ * The total allocated length of the dynamic array is
|
|
|
+ * stored in the top half of the field, and the offset
|
|
|
* is in the bottom half of the 32 bit field.
|
|
|
*/
|
|
|
offset &= 0xffff;
|