From 141ddf2856b853516b4170ef8104afe85e6efe68 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 18 Mar 2016 16:01:54 -0400 Subject: [PATCH] Implement enumeration type Signed-off-by: Mathieu Desnoyers --- lttng-events.c | 112 +++++++++++++++++++++++++-- lttng-events.h | 15 ++-- lttng-syscalls.c | 13 ++++ probes/lttng-events-nowrite.h | 8 ++ probes/lttng-events-reset.h | 18 +++++ probes/lttng-events-write.h | 16 ++++ probes/lttng-tracepoint-event-impl.h | 101 ++++++++++++++++++++++++ probes/lttng-tracepoint-event.h | 2 + 8 files changed, 273 insertions(+), 12 deletions(-) diff --git a/lttng-events.c b/lttng-events.c index 0c72015f..5307b722 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -1863,6 +1863,110 @@ int _lttng_sequence_compound_statedump(struct lttng_session *session, return ret; } +/* + * Must be called with sessions_mutex held. + */ +static +int _lttng_enum_statedump(struct lttng_session *session, + const struct lttng_event_field *field, + size_t nesting) +{ + const struct lttng_enum_desc *enum_desc; + const struct lttng_integer_type *container_type; + int ret; + unsigned int i, nr_entries; + + enum_desc = field->type.u.basic.enumeration.desc; + container_type = &field->type.u.basic.enumeration.container_type; + nr_entries = enum_desc->nr_entries; + + ret = print_tabs(session, nesting); + if (ret) + goto end; + ret = lttng_metadata_printf(session, + "enum : integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u; } {\n", + container_type->size, + container_type->alignment, + container_type->signedness, + (container_type->encoding == lttng_encode_none) + ? "none" + : (container_type->encoding == lttng_encode_UTF8) + ? "UTF8" + : "ASCII", + container_type->base); + if (ret) + goto end; + /* Dump all entries */ + for (i = 0; i < nr_entries; i++) { + const struct lttng_enum_entry *entry = &enum_desc->entries[i]; + int j, len; + + ret = print_tabs(session, nesting + 1); + if (ret) + goto end; + ret = lttng_metadata_printf(session, + "\""); + if (ret) + goto end; + len = strlen(entry->string); + /* Escape the character '"' */ + for (j = 0; j < len; j++) { + char c = entry->string[j]; + + switch (c) { + case '"': + ret = lttng_metadata_printf(session, + "\\\""); + break; + case '\\': + ret = lttng_metadata_printf(session, + "\\\\"); + break; + default: + ret = lttng_metadata_printf(session, + "%c", c); + break; + } + if (ret) + goto end; + } + ret = lttng_metadata_printf(session, + "\" = "); + if (ret) + goto end; + if (entry->start.signedness) + ret = lttng_metadata_printf(session, + "%lld", (long long) entry->start.value); + else + ret = lttng_metadata_printf(session, + "%llu", entry->start.value); + if (ret) + goto end; + if (entry->start.signedness == entry->end.signedness && + entry->start.value == entry->end.value) { + ret = lttng_metadata_printf(session, + ",\n"); + } else { + if (entry->end.signedness) { + ret = lttng_metadata_printf(session, + " ... %lld,\n", (long long) entry->end.value); + } else { + ret = lttng_metadata_printf(session, + " ... %llu,\n", entry->end.value); + } + } + if (ret) + goto end; + } + ret = print_tabs(session, nesting); + if (ret) + goto end; + ret = lttng_metadata_printf(session, "} _%s;\n", + field->name); +end: + return ret; +} + /* * Must be called with sessions_mutex held. */ @@ -1897,13 +2001,7 @@ int _lttng_field_statedump(struct lttng_session *session, field->name); break; case atype_enum: - ret = print_tabs(session, nesting); - if (ret) - return ret; - ret = lttng_metadata_printf(session, - "%s _%s;\n", - field->type.u.basic.enumeration.name, - field->name); + ret = _lttng_enum_statedump(session, field, nesting); break; case atype_array: { diff --git a/lttng-events.h b/lttng-events.h index 5d0ef4dc..9c8f03b8 100644 --- a/lttng-events.h +++ b/lttng-events.h @@ -69,8 +69,13 @@ enum channel_type { METADATA_CHANNEL, }; +struct lttng_enum_value { + unsigned long long value; + unsigned int signedness:1; +}; + struct lttng_enum_entry { - unsigned long long start, end; /* start and end are inclusive */ + struct lttng_enum_value start, end; /* start and end are inclusive */ const char *string; }; @@ -101,7 +106,8 @@ struct lttng_integer_type { union _lttng_basic_type { struct lttng_integer_type integer; struct { - const char *name; + const struct lttng_enum_desc *desc; /* Enumeration mapping */ + struct lttng_integer_type container_type; } enumeration; struct { enum lttng_string_encodings encoding; @@ -149,11 +155,10 @@ struct lttng_type { } u; }; -struct lttng_enum { +struct lttng_enum_desc { const char *name; - struct lttng_type container_type; const struct lttng_enum_entry *entries; - unsigned int len; + unsigned int nr_entries; }; /* Event field description */ diff --git a/lttng-syscalls.c b/lttng-syscalls.c index a3149d0d..080355f4 100644 --- a/lttng-syscalls.c +++ b/lttng-syscalls.c @@ -132,6 +132,9 @@ struct user_msghdr; LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_entry_##_name, PARAMS(_fields)) #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \ LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_entry_##_template, syscall_entry_##_name) +/* Enumerations only defined at first inclusion. */ +#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) \ + LTTNG_TRACEPOINT_ENUM(_name, PARAMS(_values)) #undef TRACE_SYSTEM #define TRACE_SYSTEM syscall_entry_integers #define TRACE_INCLUDE_FILE syscalls_integers @@ -143,6 +146,7 @@ struct user_msghdr; #include #undef TRACE_INCLUDE_FILE #undef TRACE_SYSTEM +#undef SC_LTTNG_TRACEPOINT_ENUM #undef SC_LTTNG_TRACEPOINT_EVENT_CODE #undef SC_LTTNG_TRACEPOINT_EVENT #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS @@ -164,6 +168,8 @@ struct user_msghdr; #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \ LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_entry_##_template, \ compat_syscall_entry_##_name) +/* Enumerations only defined at inital inclusion (not here). */ +#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) #define TRACE_SYSTEM compat_syscall_entry_integers #define TRACE_INCLUDE_FILE compat_syscalls_integers #include @@ -174,6 +180,7 @@ struct user_msghdr; #include #undef TRACE_INCLUDE_FILE #undef TRACE_SYSTEM +#undef SC_LTTNG_TRACEPOINT_ENUM #undef SC_LTTNG_TRACEPOINT_EVENT_CODE #undef SC_LTTNG_TRACEPOINT_EVENT #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS @@ -208,6 +215,8 @@ struct user_msghdr; #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \ LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_exit_##_template, \ syscall_exit_##_name) +/* Enumerations only defined at inital inclusion (not here). */ +#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) #define TRACE_SYSTEM syscall_exit_integers #define TRACE_INCLUDE_FILE syscalls_integers #include @@ -218,6 +227,7 @@ struct user_msghdr; #include #undef TRACE_INCLUDE_FILE #undef TRACE_SYSTEM +#undef SC_LTTNG_TRACEPOINT_ENUM #undef SC_LTTNG_TRACEPOINT_EVENT_CODE #undef SC_LTTNG_TRACEPOINT_EVENT #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS @@ -240,6 +250,8 @@ struct user_msghdr; #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \ LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_exit_##_template, \ compat_syscall_exit_##_name) +/* Enumerations only defined at inital inclusion (not here). */ +#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) #define TRACE_SYSTEM compat_syscall_exit_integers #define TRACE_INCLUDE_FILE compat_syscalls_integers #include @@ -250,6 +262,7 @@ struct user_msghdr; #include #undef TRACE_INCLUDE_FILE #undef TRACE_SYSTEM +#undef SC_LTTNG_TRACEPOINT_ENUM #undef SC_LTTNG_TRACEPOINT_EVENT_CODE #undef SC_LTTNG_TRACEPOINT_EVENT #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS diff --git a/probes/lttng-events-nowrite.h b/probes/lttng-events-nowrite.h index 20034f38..ff30759d 100644 --- a/probes/lttng-events-nowrite.h +++ b/probes/lttng-events-nowrite.h @@ -69,6 +69,10 @@ #define ctf_string_nowrite(_item, _user_src) \ _ctf_string(_item, _user_src, 0, 1) +#undef ctf_enum_nowrite +#define ctf_enum_nowrite(_name, _type, _item, _src) \ + _ctf_enum(_name, _type, _item, _src, 0, 1) + /* user src */ #undef ctf_user_integer_nowrite #define ctf_user_integer_nowrite(_type, _item, _user_src) \ @@ -116,3 +120,7 @@ #undef ctf_user_string_nowrite #define ctf_user_string_nowrite(_item, _user_src) \ _ctf_string(_item, _user_src, 1, 1) + +#undef ctf_user_enum_nowrite +#define ctf_user_enum_nowrite(_name, _type, _item, _src) \ + _ctf_enum(_name, _type, _item, _src, 1, 1) diff --git a/probes/lttng-events-reset.h b/probes/lttng-events-reset.h index 3b39233c..a3bef9e2 100644 --- a/probes/lttng-events-reset.h +++ b/probes/lttng-events-reset.h @@ -32,6 +32,9 @@ #undef LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP_NOARGS #define LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP_NOARGS(_template, _name, _map) +#undef LTTNG_TRACEPOINT_ENUM +#define LTTNG_TRACEPOINT_ENUM(_name, _values) + #undef TP_PROTO #define TP_PROTO(args...) @@ -84,6 +87,9 @@ #undef _ctf_string #define _ctf_string(_item, _src, _user, _nowrite) +#undef _ctf_enum +#define _ctf_enum(_name, _type, _item, _src, _nowrite) + /* "write" */ #undef ctf_integer #define ctf_integer(_type, _item, _src) @@ -130,6 +136,9 @@ #undef ctf_string #define ctf_string(_item, _src) +#undef ctf_enum +#define ctf_enum(_name, _type, _item, _src) + #undef ctf_custom_field #define ctf_custom_field(_type, _item, _code) @@ -170,6 +179,9 @@ #undef ctf_string_nowrite #define ctf_string_nowrite(_item, _src) +#undef ctf_enum_nowrite +#define ctf_enum_nowrite(_name, _type, _item, _src) + /* "user" - "write" */ #undef ctf_user_integer #define ctf_user_integer(_type, _item, _user_src) @@ -207,6 +219,9 @@ #undef ctf_user_string #define ctf_user_string(_item, _user_src) +#undef ctf_user_enum +#define ctf_user_enum(_name, _type, _item, _src) + /* "user" - "nowrite" */ #undef ctf_user_integer_nowrite #define ctf_user_integer_nowrite(_type, _item, _user_src) @@ -234,3 +249,6 @@ #undef ctf_user_string_nowrite #define ctf_user_string_nowrite(_item, _user_src) + +#undef ctf_user_enum_nowrite +#define ctf_user_enum_nowrite(_name, _type, _item, _src) diff --git a/probes/lttng-events-write.h b/probes/lttng-events-write.h index a1f25237..5db66eb7 100644 --- a/probes/lttng-events-write.h +++ b/probes/lttng-events-write.h @@ -79,6 +79,10 @@ #define ctf_string(_item, _src) \ _ctf_string(_item, _src, 0, 0) +#undef ctf_enum +#define ctf_enum(_name, _type, _item, _src) \ + _ctf_enum(_name, _type, _item, _src, 0, 0) + /* user src */ #undef ctf_user_integer #define ctf_user_integer(_type, _item, _src) \ @@ -132,6 +136,10 @@ #define ctf_user_string(_item, _src) \ _ctf_string(_item, _src, 1, 0) +#undef ctf_user_enum +#define ctf_user_enum(_name, _type, _item, _src) \ + _ctf_enum(_name, _type, _item, _src, 1, 0) + /* types */ #undef ctf_integer_type #define ctf_integer_type(_type, _src) \ @@ -189,6 +197,10 @@ #define ctf_string_type(_src) \ ctf_string(unused, _src) +#undef ctf_enum_type +#define ctf_enum_type(_name, _type, _src) \ + ctf_enum(_name, _type, unused, _src) + /* user src types */ #undef ctf_user_integer_type #define ctf_user_integer_type(_type, _src) \ @@ -245,3 +257,7 @@ #undef ctf_user_string_type #define ctf_user_string_type(_src) \ ctf_user_string(unused, _src) + +#undef ctf_user_enum_type +#define ctf_user_enum_type(_name, _type, _src) \ + ctf_user_enum(_name, _type, unused, _src) diff --git a/probes/lttng-tracepoint-event-impl.h b/probes/lttng-tracepoint-event-impl.h index fbedea1c..aa16475d 100644 --- a/probes/lttng-tracepoint-event-impl.h +++ b/probes/lttng-tracepoint-event-impl.h @@ -179,6 +179,59 @@ void __event_template_proto___##_name(void); #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) +/* + * Stage 1.2 of tracepoint event generation + * + * Unfolding the enums + */ +#include /* Reset all macros within TRACE_EVENT */ + +/* Enumeration entry (single value) */ +#undef ctf_enum_value +#define ctf_enum_value(_string, _value) \ + { \ + .start = { \ + .signedness = lttng_is_signed_type(__typeof__(_value)), \ + .value = lttng_is_signed_type(__typeof__(_value)) ? \ + (long long) (_value) : (_value), \ + }, \ + .end = { \ + .signedness = lttng_is_signed_type(__typeof__(_value)), \ + .value = lttng_is_signed_type(__typeof__(_value)) ? \ + (long long) (_value) : (_value), \ + }, \ + .string = (_string), \ + }, + +/* Enumeration entry (range) */ +#undef ctf_enum_range +#define ctf_enum_range(_string, _range_start, _range_end) \ + { \ + .start = { \ + .signedness = lttng_is_signed_type(__typeof__(_range_start)), \ + .value = lttng_is_signed_type(__typeof__(_range_start)) ? \ + (long long) (_range_start) : (_range_start), \ + }, \ + .end = { \ + .signedness = lttng_is_signed_type(__typeof__(_range_end)), \ + .value = lttng_is_signed_type(__typeof__(_range_end)) ? \ + (long long) (_range_end) : (_range_end), \ + }, \ + .string = (_string), \ + }, + +#undef TP_ENUM_VALUES +#define TP_ENUM_VALUES(...) \ + __VA_ARGS__ + +#undef LTTNG_TRACEPOINT_ENUM +#define LTTNG_TRACEPOINT_ENUM(_name, _values) \ + const struct lttng_enum_entry __enum_values__##_name[] = { \ + _values \ + }; + +#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) + /* * Stage 2 of the trace events. * @@ -303,6 +356,31 @@ void __event_template_proto___##_name(void); .user = _user, \ }, +#undef _ctf_enum +#define _ctf_enum(_name, _type, _item, _src, _user, _nowrite) \ + { \ + .name = #_item, \ + .type = { \ + .atype = atype_enum, \ + .u = { \ + .basic = { \ + .enumeration = { \ + .desc = &__enum_##_name, \ + .container_type = { \ + .size = sizeof(_type) * CHAR_BIT, \ + .alignment = lttng_alignof(_type) * CHAR_BIT, \ + .signedness = lttng_is_signed_type(_type), \ + .reverse_byte_order = 0, \ + .base = 10, \ + .encoding = lttng_encode_none, \ + }, \ + }, \ + }, \ + }, \ + }, \ + .nowrite = _nowrite, \ + .user = _user, \ + }, #undef ctf_custom_field #define ctf_custom_field(_type, _item, _code) \ @@ -329,6 +407,14 @@ void __event_template_proto___##_name(void); #define LTTNG_TRACEPOINT_EVENT_CLASS_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \ LTTNG_TRACEPOINT_EVENT_CLASS_CODE_NOARGS(_name, _locvar, _code_pre, PARAMS(_fields), _code_post) +#undef LTTNG_TRACEPOINT_ENUM +#define LTTNG_TRACEPOINT_ENUM(_name, _values) \ + static const struct lttng_enum_desc __enum_##_name = { \ + .name = #_name, \ + .entries = __enum_values__##_name, \ + .nr_entries = ARRAY_SIZE(__enum_values__##_name), \ + }; + #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) /* @@ -417,6 +503,10 @@ static void __event_probe__##_name(void *__data); strlen(_src) + 1; \ } +#undef _ctf_enum +#define _ctf_enum(_name, _type, _item, _src, _user, _nowrite) \ + _ctf_integer_ext(_type, _item, _src, __BYTE_ORDER, 10, _user, _nowrite) + #undef ctf_align #define ctf_align(_type) \ __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); @@ -628,6 +718,10 @@ error: \ __stack_data += sizeof(void *); \ } +#undef _ctf_enum +#define _ctf_enum(_name, _type, _item, _src, _user, _nowrite) \ + _ctf_integer_ext(_type, _item, _src, __BYTE_ORDER, 10, _user, _nowrite) + #undef TP_PROTO #define TP_PROTO(...) __VA_ARGS__ @@ -699,6 +793,10 @@ void __event_prepare_filter_stack__##_name(char *__stack_data, \ #undef _ctf_string #define _ctf_string(_item, _src, _user, _nowrite) +#undef _ctf_enum +#define _ctf_enum(_name, _type, _item, _src, _user, _nowrite) \ + _ctf_integer_ext(_type, _item, _src, __BYTE_ORDER, 10, _user, _nowrite) + #undef ctf_align #define ctf_align(_type) \ __event_align = max_t(size_t, __event_align, lttng_alignof(_type)); @@ -935,6 +1033,9 @@ static inline size_t __event_get_align__##_name(void *__tp_locvar) \ __get_dynamic_len(dest)); \ } +#undef _ctf_enum +#define _ctf_enum(_name, _type, _item, _src, _user, _nowrite) \ + _ctf_integer_ext(_type, _item, _src, __BYTE_ORDER, 10, _user, _nowrite) #undef ctf_align #define ctf_align(_type) \ diff --git a/probes/lttng-tracepoint-event.h b/probes/lttng-tracepoint-event.h index fc3417cd..e934b4ba 100644 --- a/probes/lttng-tracepoint-event.h +++ b/probes/lttng-tracepoint-event.h @@ -59,4 +59,6 @@ #define LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP_NOARGS(_template, _name, _map) \ _LTTNG_INSTRUMENTATION(DECLARE_TRACE_NOARGS(name)) +#define LTTNG_TRACEPOINT_ENUM(_name, _values) + #endif /* LTTNG_TRACEPOINT_EVENT_H */ -- 2.34.1