Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libtraceevent for openSUSE:Factory 
checked in at 2026-11-03 17:51:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libtraceevent (Old)
 and      /work/SRC/openSUSE:Factory/.libtraceevent.new.1257 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libtraceevent"

Tue Nov  3 17:51:19 2026 rev:18 rq:1394334 version:1.9.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/libtraceevent/libtraceevent.changes      
2026-03-11 20:49:43.976181039 +0100
+++ /work/SRC/openSUSE:Factory/.libtraceevent.new.1257/libtraceevent.changes    
2026-11-03 17:51:21.050750622 +0100
@@ -1,0 +2,15 @@
+Sun Nov  1 21:35:03 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 1.9.1:
+  * Fix leaks and NULL check in process_int_dynamic_array()
+  * Avoid host-specific getname_flags output
+  * Handle short reads when reading BTF
+  * Avoid racing recursive builds of both libraries
+  * Reject non-text symbol arithmetic
+  * Add printable characters
+  * Parse %pB and %pa address specifiers
+  * Pretty print function parameters of enum-type
+  * utest: Fix type of args in test_btf_read
+  * utest: Read btf file in utest if mmap fails
+
+-------------------------------------------------------------------

Old:
----
  libtraceevent-1.9.0.tar.gz

New:
----
  libtraceevent-1.9.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libtraceevent.spec ++++++
--- /var/tmp/diff_new_pack.aWLvxN/_old  2026-11-03 17:51:22.413807595 +0100
+++ /var/tmp/diff_new_pack.aWLvxN/_new  2026-11-03 17:51:22.416807721 +0100
@@ -22,7 +22,7 @@
 %define sodname %{dname}%{sonum}
 
 Name:           libtraceevent
-Version:        1.9.0
+Version:        1.9.1
 Release:        0
 Summary:        Linux kernel trace event library
 License:        GPL-2.0-only AND LGPL-2.1-only

++++++ libtraceevent-1.9.0.tar.gz -> libtraceevent-1.9.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtraceevent-1.9.0/Makefile 
new/libtraceevent-1.9.1/Makefile
--- old/libtraceevent-1.9.0/Makefile    2026-02-04 19:48:50.000000000 +0100
+++ new/libtraceevent-1.9.1/Makefile    2026-10-21 16:33:05.000000000 +0200
@@ -2,7 +2,7 @@
 # libtraceevent version
 EP_VERSION = 1
 EP_PATCHLEVEL = 9
-EP_EXTRAVERSION = 0
+EP_EXTRAVERSION = 1
 EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
 
 MAKEFLAGS += --no-print-directory
@@ -208,7 +208,7 @@
 
 libs: libtraceevent.a libtraceevent.so
 
-$(LIBTRACEEVENT_STATIC): force
+$(LIBTRACEEVENT_STATIC): force $(LIBTRACEEVENT_SHARED)
        $(Q)$(call descend,$(src)/src,$@)
 
 $(LIBTRACEEVENT_SHARED): force
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtraceevent-1.9.0/meson.build 
new/libtraceevent-1.9.1/meson.build
--- old/libtraceevent-1.9.0/meson.build 2026-02-04 19:48:50.000000000 +0100
+++ new/libtraceevent-1.9.1/meson.build 2026-10-21 16:33:05.000000000 +0200
@@ -6,7 +6,7 @@
     'libtraceevent', ['c'],
     meson_version: '>= 0.58.0',
     license: 'LGPL-2.1',
-    version: '1.9.0',
+    version: '1.9.1',
     default_options: [
         'c_std=gnu99',
         'buildtype=debug',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtraceevent-1.9.0/src/event-parse.c 
new/libtraceevent-1.9.1/src/event-parse.c
--- old/libtraceevent-1.9.0/src/event-parse.c   2026-02-04 19:48:50.000000000 
+0100
+++ new/libtraceevent-1.9.1/src/event-parse.c   2026-10-21 16:33:05.000000000 
+0200
@@ -1017,6 +1017,19 @@
        return ret;
 }
 
+static bool is_kernel_text_symbol(char ch)
+{
+       switch (ch) {
+       case 'T':
+       case 't':
+       case 'W':
+       case 'w':
+               return true;
+       default:
+               return false;
+       }
+}
+
 /**
  * tep_parse_kallsyms - load functions from a read of /proc/kallsyms
  * @tep: a handle to the trace event parser
@@ -1070,6 +1083,10 @@
                 *  - x86-64 that reports per-cpu variable offsets as absolute
                 */
                if (func[0] != '$' && ch != 'A' && ch != 'a') {
+                       if (!is_kernel_text_symbol(ch)) {
+                               line = strtok_r(NULL, "\n", &next);
+                               continue;
+                       }
                        line[func_end] = 0;
                        if (mod_end) {
                                mod = line + mod_start;
@@ -3473,8 +3490,11 @@
         * the index into where the array starts.
         */
        type = read_token(event->tep, &token);
-       if (type != TEP_EVENT_ITEM)
+       if (type != TEP_EVENT_ITEM) {
+               free_token(token);
+               *tok = NULL;
                return TEP_EVENT_ERROR;
+       }
 
        /* Find the field */
        field = tep_find_field(event, token);
@@ -3490,7 +3510,7 @@
                goto out;
 
        arg->int_array.field = alloc_arg();
-       if (!arg) {
+       if (!arg->int_array.field) {
                do_warning_event(event, "%s: not enough memory!", __func__);
                goto out;
        }
@@ -3499,6 +3519,7 @@
        arg->int_array.field->dynarray.field = field;
        arg->int_array.field->dynarray.index = 0;
 
+       free_token(token);
        return read_token_item(event->tep, tok);
 out:
        free_token(token);
@@ -4580,13 +4601,16 @@
 }
 
 static unsigned long long test_for_symbol(struct tep_handle *tep,
-                                         struct tep_print_arg *arg)
+                                         struct tep_print_arg *arg,
+                                         bool *found)
 {
        unsigned long long val = 0;
        struct func_list *item = tep->funclist;
        char *func;
        int i;
 
+       *found = false;
+
        if (isdigit(arg->atom.atom[0]))
                return 0;
 
@@ -4607,10 +4631,14 @@
 
                if (strcmp(arg->atom.atom, name) == 0) {
                        val = addr;
+                       *found = true;
                        break;
                }
        }
 
+       if (!*found)
+               return 0;
+
        /*
         * This modifies the arg to hardcode the value
         * and will not loop again.
@@ -4686,13 +4714,17 @@
 }
 
 static unsigned long long
-eval_num_arg(void *data, int size, struct tep_event *event, struct 
tep_print_arg *arg)
+eval_num_arg_stat(void *data, int size, struct tep_event *event,
+                 struct tep_print_arg *arg, bool *valid)
 {
        struct tep_handle *tep = event->tep;
        unsigned long long val = 0;
        unsigned long long left, right;
        struct tep_print_arg *typearg = NULL;
        struct tep_print_arg *larg;
+       bool found = false;
+       bool left_valid = true;
+       bool right_valid = true;
        unsigned int offset;
        unsigned int field_size;
 
@@ -4702,8 +4734,11 @@
                return 0;
        case TEP_PRINT_ATOM:
                val = strtoull(arg->atom.atom, NULL, 0);
-               if (!val)
-                       val = test_for_symbol(tep, arg);
+               if (!val && !isdigit(arg->atom.atom[0])) {
+                       val = test_for_symbol(tep, arg, &found);
+                       if (!found)
+                               *valid = false;
+               }
                return val;
        case TEP_PRINT_FIELD:
                if (!arg->field.field) {
@@ -4728,7 +4763,10 @@
        case TEP_PRINT_HEX_STR:
                break;
        case TEP_PRINT_TYPE:
-               val = eval_num_arg(data, size, event, arg->typecast.item);
+               val = eval_num_arg_stat(data, size, event, arg->typecast.item,
+                                       valid);
+               if (!*valid)
+                       return 0;
                return eval_type(val, arg, 0);
        case TEP_PRINT_STRING:
        case TEP_PRINT_BSTRING:
@@ -4749,7 +4787,12 @@
                         * Arrays are special, since we don't want
                         * to read the arg as is.
                         */
-                       right = eval_num_arg(data, size, event, arg->op.right);
+                       right = eval_num_arg_stat(data, size, event,
+                                                arg->op.right, &right_valid);
+                       if (!right_valid) {
+                               *valid = false;
+                               return 0;
+                       }
 
                        /* handle typecasts */
                        larg = arg->op.left;
@@ -4797,17 +4840,34 @@
                                val = eval_type(val, typearg, 1);
                        break;
                } else if (strcmp(arg->op.op, "?") == 0) {
-                       left = eval_num_arg(data, size, event, arg->op.left);
+                       left = eval_num_arg_stat(data, size, event, 
arg->op.left,
+                                               &left_valid);
+                       if (!left_valid) {
+                               *valid = false;
+                               return 0;
+                       }
                        arg = arg->op.right;
                        if (left)
-                               val = eval_num_arg(data, size, event, 
arg->op.left);
+                               val = eval_num_arg_stat(data, size, event,
+                                                       arg->op.left, 
&left_valid);
                        else
-                               val = eval_num_arg(data, size, event, 
arg->op.right);
+                               val = eval_num_arg_stat(data, size, event,
+                                                       arg->op.right, 
&right_valid);
+                       if ((left && !left_valid) || (!left && !right_valid)) {
+                               *valid = false;
+                               return 0;
+                       }
                        break;
                }
  default_op:
-               left = eval_num_arg(data, size, event, arg->op.left);
-               right = eval_num_arg(data, size, event, arg->op.right);
+               left = eval_num_arg_stat(data, size, event, arg->op.left,
+                                        &left_valid);
+               right = eval_num_arg_stat(data, size, event, arg->op.right,
+                                         &right_valid);
+               if (!left_valid || !right_valid) {
+                       *valid = false;
+                       return 0;
+               }
                switch (arg->op.op[0]) {
                case '!':
                        switch (arg->op.op[1]) {
@@ -4922,6 +4982,15 @@
        return 0;
 }
 
+static unsigned long long
+eval_num_arg(void *data, int size, struct tep_event *event,
+            struct tep_print_arg *arg)
+{
+       bool valid = true;
+
+       return eval_num_arg_stat(data, size, event, arg, &valid);
+}
+
 struct flag {
        const char *name;
        unsigned long long value;
@@ -5350,6 +5419,7 @@
        case TEP_PRINT_INT_ARRAY: {
                void *num;
                int el_size;
+               int is_print = 0;
 
                len = 0;
 
@@ -5384,7 +5454,20 @@
                                trace_seq_putc(s, ',');
 
                        if (el_size == 1) {
-                               trace_seq_printf(s, "0x%x", *(uint8_t *)num);
+                               int ch = *(uint8_t *)num;
+
+                               trace_seq_printf(s, "0x%x", ch);
+
+                               if (!is_print)
+                                       is_print = 1;
+
+                               /*
+                                * Only print string if all characters are
+                                * printable
+                                */
+                               if (is_print && !isprint(ch) && !isspace(ch))
+                                       is_print = -1;
+
                        } else if (el_size == 2) {
                                trace_seq_printf(s, "0x%x", *(uint16_t *)num);
                        } else if (el_size == 4) {
@@ -5400,6 +5483,19 @@
                        num += el_size;
                }
                trace_seq_putc(s, '}');
+
+               if (is_print == 1) {
+                       char *p = data + offset;
+
+                       trace_seq_puts(s, " \"");
+                       for (i = 0; i < len; i++) {
+                               if (p[i] == '\n')
+                                       trace_seq_puts(s, "\\n");
+                               else
+                                       trace_seq_putc(s, p[i]);
+                       }
+                       trace_seq_putc(s, '"');
+               }
                break;
        }
        case TEP_PRINT_TYPE:
@@ -6607,9 +6703,14 @@
                          struct tep_print_arg *arg, bool raw)
 {
        struct func_map *func;
+       bool valid = true;
        unsigned long long val;
 
-       val = eval_num_arg(data, size, event, arg);
+       val = eval_num_arg_stat(data, size, event, arg, &valid);
+       if (!valid) {
+               trace_seq_puts(s, "INVALID");
+               return 0;
+       }
        func = find_func(event->tep, val);
        if (func) {
                trace_seq_puts(s, func->func);
@@ -6631,11 +6732,84 @@
        return 0;
 }
 
+static int print_function_backtrace(struct trace_seq *s,
+                                   void *data, int size,
+                                   struct tep_event *event,
+                                   struct tep_print_arg *arg, bool raw)
+{
+       struct func_map *func = NULL;
+       unsigned long long lookup;
+       unsigned long long val;
+
+       val = eval_num_arg(data, size, event, arg);
+       lookup = val ? val - 1 : 0;
+       func = val ? find_func(event->tep, lookup) : NULL;
+
+       if (func) {
+               trace_seq_puts(s, func->func);
+               trace_seq_printf(s, "+0x%llx", lookup - func->addr);
+       }
+
+       if (!func || raw) {
+               if (raw)
+                       trace_seq_puts(s, " (");
+               if (event->tep->long_size == 4)
+                       trace_seq_printf(s, "0x%lx", (long)val);
+               else
+                       trace_seq_printf(s, "0x%llx", (long long)val);
+               if (raw)
+                       trace_seq_puts(s, ")");
+       }
+
+       return 0;
+}
+
+static int print_addr_ref_arg(struct trace_seq *s, const char *format,
+                             void *data, int size,
+                             struct tep_event *event,
+                             struct tep_print_arg *arg)
+{
+       struct tep_format_field *field;
+       struct tep_handle *tep = event->tep;
+       unsigned long long val;
+       int width;
+       int ret = 0;
+
+       while (arg->type == TEP_PRINT_TYPE)
+               arg = arg->typecast.item;
+
+       if (arg->type != TEP_PRINT_FIELD) {
+               trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
+               return ret;
+       }
+
+       field = arg->field.field;
+       if (!field) {
+               field = tep_find_any_field(event, arg->field.name);
+               if (!field) {
+                       do_warning_event(event, "%s: field %s not found",
+                                        __func__, arg->field.name);
+                       return ret;
+               }
+               arg->field.field = field;
+       }
+
+       val = tep_read_number(tep, data + field->offset, field->size);
+       width = field->size * 2;
+       trace_seq_printf(s, "0x%0*llx", width, val);
+
+       if (format[1] == 'p' || format[1] == 'd')
+               ret++;
+
+       return ret;
+}
+
 static int print_arg_pointer(struct trace_seq *s, const char *format, int plen,
                             void *data, int size,
                             struct tep_event *event, struct tep_print_arg *arg,
                             bool raw)
 {
+       bool valid = true;
        unsigned long long val;
        int ret = 1;
 
@@ -6652,12 +6826,18 @@
        }
 
        switch (*format) {
+       case 'B':
+               ret += print_function_backtrace(s, data, size, event, arg, raw);
+               break;
        case 'F':
        case 'f':
        case 'S':
        case 's':
                ret += print_function(s, format, data, size, event, arg, raw);
                break;
+       case 'a':
+               ret += print_addr_ref_arg(s, format, data, size, event, arg);
+               break;
        case 'M':
        case 'm':
                ret += print_mac_arg(s, format, data, size, event, arg);
@@ -6674,7 +6854,11 @@
                break;
        default:
                ret = 0;
-               val = eval_num_arg(data, size, event, arg);
+               val = eval_num_arg_stat(data, size, event, arg, &valid);
+               if (!valid) {
+                       trace_seq_puts(s, "INVALID");
+                       break;
+               }
                trace_seq_printf(s, "%p", (void *)(intptr_t)val);
                break;
        }
@@ -6687,9 +6871,14 @@
                            void *data, int size, int ls,
                            struct tep_event *event, struct tep_print_arg *arg)
 {
+       bool valid = true;
        unsigned long long val;
 
-       val = eval_num_arg(data, size, event, arg);
+       val = eval_num_arg_stat(data, size, event, arg, &valid);
+       if (!valid) {
+               trace_seq_puts(s, "INVALID");
+               return 0;
+       }
 
        switch (ls) {
        case -2:
@@ -6752,12 +6941,24 @@
        int loop;
 
        switch (*format) {
+       case 'B':
+               ret++;
+               break;
        case 'F':
        case 'S':
        case 'f':
        case 's':
                ret++;
                break;
+       case 'a':
+               switch (format[1]) {
+               case 'p':
+               case 'd':
+                       ret++;
+                       break;
+               }
+               ret++;
+               break;
        case 'M':
        case 'm':
                /* [mM]R , [mM]F */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtraceevent-1.9.0/src/kbuffer-parse.c 
new/libtraceevent-1.9.1/src/kbuffer-parse.c
--- old/libtraceevent-1.9.0/src/kbuffer-parse.c 2026-02-04 19:48:50.000000000 
+0100
+++ new/libtraceevent-1.9.1/src/kbuffer-parse.c 2026-10-21 16:33:05.000000000 
+0200
@@ -849,7 +849,7 @@
 int kbuffer_missed_events(struct kbuffer *kbuf)
 {
        /* Only the first event can have missed events */
-       if (kbuf->curr)
+       if (kbuf->curr != kbuf->first)
                return 0;
 
        return kbuf->lost_events;
@@ -1014,7 +1014,7 @@
         * If reading the first event and there are lost events, add it
         * to the buffer.
         */
-       if (!save_curr && kbuf->lost_events) {
+       if (save_curr == kbuf->first && kbuf->lost_events) {
                unsigned long long cnt_8;
                unsigned int cnt_4;
                int word_size;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtraceevent-1.9.0/src/trace-btf.c 
new/libtraceevent-1.9.1/src/trace-btf.c
--- old/libtraceevent-1.9.0/src/trace-btf.c     2026-02-04 19:48:50.000000000 
+0100
+++ new/libtraceevent-1.9.1/src/trace-btf.c     2026-10-21 16:33:05.000000000 
+0200
@@ -32,6 +32,16 @@
 #define REALLOC_SIZE (1 << 10)
 #define REALLOC_MASK (REALLOC_SIZE - 1)
 
+#define for_each_enum(enum_type, member)                               \
+       member = btf_enum(enum_type);                                   \
+       for (int __i = 0; __i < BTF_INFO_VLEN((enum_type)->info);       \
+               __i++, member++)
+
+static inline struct btf_enum *btf_enum(struct btf_type *t)
+{
+       return (struct btf_enum *)(t + 1);
+}
+
 static const char *btf_name(struct tep_btf *btf, int off)
 {
        if (off < btf->hdr->str_len)
@@ -546,6 +556,7 @@
        struct tep_btf *btf = tep->btf;
        struct btf_type *type = tep_btf_find_func(btf, func);
        struct btf_param *param;
+       struct btf_enum *enump;
        unsigned long long arg;
        unsigned int encode;
        const char *param_name;
@@ -628,6 +639,13 @@
                        break;
                case BTF_KIND_ENUM:
                        trace_seq_printf(s, "%lld", arg);
+                       for_each_enum(t, enump) {
+                               if (arg == enump->val) {
+                                       trace_seq_printf(s, " [%s]",
+                                               btf_name(btf, enump->name_off));
+                                       break;
+                               }
+                       }
                        break;
                default:
                        /* This does not handle complex arguments */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libtraceevent-1.9.0/utest/traceevent-utest.c 
new/libtraceevent-1.9.1/utest/traceevent-utest.c
--- old/libtraceevent-1.9.0/utest/traceevent-utest.c    2026-02-04 
19:48:50.000000000 +0100
+++ new/libtraceevent-1.9.1/utest/traceevent-utest.c    2026-10-21 
16:33:05.000000000 +0200
@@ -8,14 +8,18 @@
  */
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <time.h>
 #include <dirent.h>
 #include <ftw.h>
+#include <string.h>
 
 #include <sys/mman.h>
+#include <stdint.h>
 
 #include <CUnit/CUnit.h>
 #include <CUnit/Basic.h>
@@ -182,6 +186,126 @@
 };
 static void *sizeof_event_data = (void *)sizeof_data;
 
+static const char symbol_kallsyms[] =
+       "0000000000001000 T _stext\n"
+       "0000000000001020 T do_work\n"
+       "0000000000001100 T end_text\n"
+       "0000000000002000 D jiffies\n";
+
+#define SYMBOL_ARITH_FMT "caller=do_work+0x0"
+static const char symbol_arith_event[] =
+       "name: symbol_arith\n"
+       "ID: 24\n"
+       "format:\n"
+       "\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n"
+       "\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\tsigned:0;\n"
+       "\tfield:unsigned char 
common_preempt_count;\toffset:3;\tsize:1;\tsigned:0;\n"
+       "\tfield:int common_pid;\toffset:4;\tsize:4;\tsigned:1;\n"
+       "\n"
+       "\tfield:unsigned int caller_off;\toffset:8;\tsize:4;\tsigned:0;\n"
+       "\n"
+       "print fmt: \"caller=%pS\", REC->caller_off + _stext\n";
+
+static char symbol_arith_data[] = {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+       /* common type */               24, 0x00,
+#else
+       /* common type */               0x00, 24,
+#endif
+       /* common flags */              0x00,
+       /* common_preempt_count */      0x00,
+       /* common_pid */                0x00, 0x00, 0x00, 0x00,
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+       /* caller_off */                0x20, 0x00, 0x00, 0x00,
+#else
+       /* caller_off */                0x00, 0x00, 0x00, 0x20,
+#endif
+};
+
+#define JIFFIES_ARITH_FMT "age=INVALID"
+static const char jiffies_arith_event[] =
+       "name: jiffies_arith\n"
+       "ID: 25\n"
+       "format:\n"
+       "\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n"
+       "\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\tsigned:0;\n"
+       "\tfield:unsigned char 
common_preempt_count;\toffset:3;\tsize:1;\tsigned:0;\n"
+       "\tfield:int common_pid;\toffset:4;\tsize:4;\tsigned:1;\n"
+       "\n"
+       "\tfield:unsigned long dirtied_when;\toffset:8;\tsize:8;\tsigned:0;\n"
+       "\n"
+       "print fmt: \"age=%lu\", (jiffies - REC->dirtied_when) / 250\n";
+
+static char jiffies_arith_data[] = {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+       /* common type */               25, 0x00,
+#else
+       /* common type */               0x00, 25,
+#endif
+       /* common flags */              0x00,
+       /* common_preempt_count */      0x00,
+       /* common_pid */                0x00, 0x00, 0x00, 0x00,
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+       /* dirtied_when */              0xf4, 0x01, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00,
+#else
+       /* dirtied_when */              0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x01, 0xf4,
+#endif
+};
+
+static const char pointer_backtrace_event[] =
+       "name: pointer_backtrace_event\n"
+       "ID: 40\n"
+       "format:\n"
+       "\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n"
+       "\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\tsigned:0;\n"
+       "\tfield:unsigned char 
common_preempt_count;\toffset:3;\tsize:1;\tsigned:0;\n"
+       "\tfield:int common_pid;\toffset:4;\tsize:4;\tsigned:1;\n"
+       "\n"
+       "\tfield:unsigned long long ptr;\toffset:8;\tsize:8;\tsigned:0;\n"
+       "\n"
+       "print fmt: \"ptr=%pB\", REC->ptr\n";
+
+static const char phys_addr_event[] =
+       "name: phys_addr_event\n"
+       "ID: 41\n"
+       "format:\n"
+       "\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n"
+       "\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\tsigned:0;\n"
+       "\tfield:unsigned char 
common_preempt_count;\toffset:3;\tsize:1;\tsigned:0;\n"
+       "\tfield:int common_pid;\toffset:4;\tsize:4;\tsigned:1;\n"
+       "\n"
+       "\tfield:unsigned long long phys;\toffset:8;\tsize:8;\tsigned:0;\n"
+       "\n"
+       "print fmt: \"phys=%pap\", REC->phys\n";
+
+static const char phys_addr_plain_event[] =
+       "name: phys_addr_plain_event\n"
+       "ID: 43\n"
+       "format:\n"
+       "\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n"
+       "\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\tsigned:0;\n"
+       "\tfield:unsigned char 
common_preempt_count;\toffset:3;\tsize:1;\tsigned:0;\n"
+       "\tfield:int common_pid;\toffset:4;\tsize:4;\tsigned:1;\n"
+       "\n"
+       "\tfield:unsigned long long phys;\toffset:8;\tsize:8;\tsigned:0;\n"
+       "\n"
+       "print fmt: \"phys=%pa\", REC->phys\n";
+
+static const char dma_addr_event[] =
+       "name: dma_addr_event\n"
+       "ID: 42\n"
+       "format:\n"
+       "\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n"
+       "\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\tsigned:0;\n"
+       "\tfield:unsigned char 
common_preempt_count;\toffset:3;\tsize:1;\tsigned:0;\n"
+       "\tfield:int common_pid;\toffset:4;\tsize:4;\tsigned:1;\n"
+       "\n"
+       "\tfield:unsigned int dma;\toffset:8;\tsize:4;\tsigned:0;\n"
+       "\n"
+       "print fmt: \"dma=%pad\", REC->dma\n";
+
 DECL_CPUMASK_EVENT_DATA(full, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
 #define CPUMASK_FULL     "ARRAY[ff, ff, ff, ff, ff, ff, ff, ff]"
 #define CPUMASK_FULL_FMT "cpumask=0-63"
@@ -380,14 +504,165 @@
        test_parse_sizeof(0, 5, "sizeof_undef", SIZEOF_LONG0_FMT);
 }
 
+static void parse_symbol_event(const char *format, const char *system,
+                              void *data, int size, const char *expected)
+{
+       struct tep_handle *tep;
+       struct tep_event *event;
+       struct tep_record record;
+
+       tep = tep_alloc();
+       CU_TEST(tep != NULL);
+       if (!tep)
+               return;
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+       tep_set_file_bigendian(tep, TEP_BIG_ENDIAN);
+#endif
+
+       record.data = data;
+       record.size = size;
+
+       CU_TEST(tep_parse_kallsyms(tep, symbol_kallsyms) == 0);
+       CU_TEST(tep_parse_format(tep, &event, format, strlen(format),
+                                system) == TEP_ERRNO__SUCCESS);
+
+       trace_seq_reset(test_seq);
+       tep_print_event(tep, test_seq, &record, "%s", TEP_PRINT_INFO);
+       trace_seq_do_printf(test_seq);
+       CU_TEST(strcmp(test_seq->buffer, expected) == 0);
+
+       tep_free(tep);
+}
+
+static void test_parse_symbol_arith(void)
+{
+       parse_symbol_event(symbol_arith_event, "symbol_arith",
+                          symbol_arith_data, sizeof(symbol_arith_data),
+                          SYMBOL_ARITH_FMT);
+}
+
+static void test_parse_jiffies_arith(void)
+{
+       parse_symbol_event(jiffies_arith_event, "jiffies_arith",
+                          jiffies_arith_data, sizeof(jiffies_arith_data),
+                          JIFFIES_ARITH_FMT);
+}
+
+static void parse_pointer_event(const char *format, const char *system,
+                               void *data, int size, const char *expected)
+{
+       struct tep_event *event;
+       struct tep_record record;
+
+       record.data = data;
+       record.size = size;
+
+       CU_TEST(tep_parse_format(test_tep, &event, format, strlen(format),
+                                system) == TEP_ERRNO__SUCCESS);
+
+       trace_seq_reset(test_seq);
+       tep_print_event(test_tep, test_seq, &record, "%s", TEP_PRINT_INFO);
+       trace_seq_do_printf(test_seq);
+       CU_TEST(strcmp(test_seq->buffer, expected) == 0);
+}
+
+static void test_parse_pointer_backtrace(void)
+{
+       unsigned char data[16] = { 0 };
+       unsigned short type = 40;
+       uint64_t ptr = 0x1001ULL;
+
+       memcpy(data, &type, sizeof(type));
+       memcpy(data + 8, &ptr, sizeof(ptr));
+
+       parse_pointer_event(pointer_backtrace_event, "ptr_backtrace",
+                           data, sizeof(data), "ptr=test_func+0x0");
+}
+
+static void test_parse_phys_addr(void)
+{
+       unsigned char data[16] = { 0 };
+       unsigned short type = 41;
+       uint64_t phys = 0x123456789abcdef0ULL;
+
+       memcpy(data, &type, sizeof(type));
+       memcpy(data + 8, &phys, sizeof(phys));
+
+       parse_pointer_event(phys_addr_event, "ptr_phys",
+                           data, sizeof(data),
+                           "phys=0x123456789abcdef0");
+}
+
+static void test_parse_phys_addr_plain(void)
+{
+       unsigned char data[16] = { 0 };
+       unsigned short type = 43;
+       uint64_t phys = 0x123456789abcdef0ULL;
+
+       memcpy(data, &type, sizeof(type));
+       memcpy(data + 8, &phys, sizeof(phys));
+
+       parse_pointer_event(phys_addr_plain_event, "ptr_phys_plain",
+                           data, sizeof(data),
+                           "phys=0x123456789abcdef0");
+}
+
+static void test_parse_dma_addr(void)
+{
+       unsigned char data[12] = { 0 };
+       unsigned short type = 42;
+       uint32_t dma = 0x1234abcdU;
+
+       memcpy(data, &type, sizeof(type));
+       memcpy(data + 8, &dma, sizeof(dma));
+
+       parse_pointer_event(dma_addr_event, "ptr_dma",
+                           data, sizeof(data), "dma=0x1234abcd");
+}
+
+static int read_full(int fd, void *buf, size_t size)
+{
+       char *data = buf;
+       size_t total = 0;
+
+       while (total < size) {
+               ssize_t ret;
+
+               ret = read(fd, data + total, size - total);
+               if (ret < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       return -1;
+               }
+               if (!ret)
+                       return -1;
+               total += ret;
+       }
+
+       return 0;
+}
+
+static bool output_has_extra_args(const char *output, const char *prefix)
+{
+       size_t len = strlen(output);
+       size_t plen = strlen(prefix);
+
+       return len > plen + 3 && strncmp(output, prefix, plen) == 0 &&
+              output[plen] == ',' && strcmp(output + len - 2, ")\n") == 0;
+}
+
 static void test_btf_read(void)
 {
-       unsigned long args[] = {0x7ffe7d33f3d0, 0, 0, 0, 0, 0};
+       uint64_t args[] = {0x7ffe7d33f3d0, 0, 0, 0, 0, 0};
        const char *func = "getname_flags";
+       const char *expected = "getname_flags(filename=0x7ffe7d33f3d0, 
flags=0)\n";
+       const char *expected_prefix = "getname_flags(filename=0x7ffe7d33f3d0, 
flags=0";
        struct trace_seq *s = test_seq;
        struct stat st;
        void *buf;
        int fd, nr = 6;
+       bool malloced = false;
 
        fd = open("/sys/kernel/btf/vmlinux", O_RDONLY);
        if (fd < 0) {
@@ -397,22 +672,47 @@
        CU_TEST(fstat(fd, &st) == 0);
 
        buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-       CU_TEST(buf != MAP_FAILED);
+       if (buf == MAP_FAILED) {
+               int ret;
 
+               malloced = true;
+               buf = malloc(st.st_size);
+               if (buf == NULL) {
+                       printf("[FAILED TO ALLOCATE MEMORY FOR BTF FILE 
CONTENTS] ...");
+                       close(fd);
+                       return;
+               }
+               CU_TEST((ret = read_full(fd, buf, st.st_size)) == 0);
+               if (ret < 0) {
+                       free(buf);
+                       close(fd);
+                       return;
+               }
+       }
        CU_TEST(tep_load_btf(test_tep, buf, st.st_size) == 0);
 
-       munmap(buf, st.st_size);
+       if (malloced) {
+               free(buf);
+       } else {
+               munmap(buf, st.st_size);
+       }
        close(fd);
 
        trace_seq_init(s);
        trace_seq_printf(s, "%s(", func);
 
-       CU_TEST(tep_btf_print_args(test_tep, s, args, nr, sizeof(long), func) 
== 0);
+       CU_TEST(tep_btf_print_args(test_tep, s, args, nr, sizeof(*args), func) 
== 0);
 
        trace_seq_puts(s, ")\n");
        trace_seq_terminate(s);
 
-       CU_TEST(strcmp(s->buffer, "getname_flags(filename=0x7ffe7d33f3d0, 
flags=0)\n") == 0);
+       if (strcmp(s->buffer, expected) != 0 &&
+           output_has_extra_args(s->buffer, expected_prefix)) {
+               printf("[KERNEL BTF HAS EXTRA getname_flags ARGS] ...");
+               return;
+       }
+
+       CU_TEST(strcmp(s->buffer, expected) == 0);
 }
 
 static int test_suite_destroy(void)
@@ -429,6 +729,10 @@
        test_tep = tep_alloc();
        if (!test_tep)
                return 1;
+       if (tep_register_function(test_tep, "test_func", 0x1000, NULL))
+               return 1;
+       if (tep_register_function(test_tep, "test_func_end", 0x2000, NULL))
+               return 1;
 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
        tep_set_file_bigendian(test_tep, TEP_BIG_ENDIAN);
 #endif
@@ -466,6 +770,18 @@
                    test_parse_sizeof4);
        CU_add_test(suite, "parse sizeof() no long size defined",
                    test_parse_sizeof_undef);
+       CU_add_test(suite, "parse symbol arithmetic",
+                   test_parse_symbol_arith);
+       CU_add_test(suite, "reject non-text symbol arithmetic",
+                   test_parse_jiffies_arith);
+       CU_add_test(suite, "parse %pB pointer format",
+                   test_parse_pointer_backtrace);
+       CU_add_test(suite, "parse %pap pointer format",
+                   test_parse_phys_addr);
+       CU_add_test(suite, "parse %pa pointer format",
+                   test_parse_phys_addr_plain);
+       CU_add_test(suite, "parse %pad pointer format",
+                   test_parse_dma_addr);
        CU_add_test(suite, "read BTF",
                    test_btf_read);
 }

Reply via email to