C(INVALID_SORT_FIELD,   "Sort field must be a key or a val"),   \
        C(INVALID_STR_OPERAND,  "String type can not be an operand in expression"), \
        C(EXPECT_NUMBER,        "Expecting numeric literal"),           \
-       C(UNARY_MINUS_SUBEXPR,  "Unary minus not supported in sub-expressions"), \
-       C(SYM_OFFSET_SUBEXPR,   ".sym-offset not supported in sub-expressions"),
+       C(UNARY_MINUS_SUBEXPR,  "Unary minus not supported in sub-expressions"),
 
 #undef C
 #define C(a, b)                HIST_ERR_##a
         */
        minus_op = strrchr(str, '-');
        if (minus_op) {
-               /* Unfortunately, the modifier ".sym-offset" can confuse things. */
-               if (minus_op - str >= 4 && !strncmp(minus_op - 4, ".sym-offset", 11))
-                       goto out;
-
                /*
                 * Unary minus is not supported in sub-expressions. If
                 * present, it is always the next root operator.
                        *flags |= HIST_FIELD_FL_HEX;
                else if (strcmp(modifier, "sym") == 0)
                        *flags |= HIST_FIELD_FL_SYM;
-               else if (strcmp(modifier, "sym-offset") == 0)
+               /*
+                * 'sym-offset' occurrences in the trigger string are modified
+                * to 'symXoffset' to simplify arithmetic expression parsing.
+                */
+               else if (strcmp(modifier, "symXoffset") == 0)
                        *flags |= HIST_FIELD_FL_SYM_OFFSET;
                else if ((strcmp(modifier, "execname") == 0) &&
                         (strcmp(field_name, "common_pid") == 0))
                return ERR_PTR(-EINVAL);
        }
 
-       /*
-        * ".sym-offset" in expressions has no effect on their evaluation,
-        * but can confuse operator parsing.
-        */
-       if (*n_subexprs == 0) {
-               sep = strstr(str, ".sym-offset");
-               if (sep) {
-                       *sep = '\0';
-                       if (strpbrk(str, "+-/*") || strpbrk(sep + 11, "+-/*")) {
-                               *sep = '.';
-                               hist_err(file->tr, HIST_ERR_SYM_OFFSET_SUBEXPR,
-                                        errpos(sep));
-                               return ERR_PTR(-EINVAL);
-                       }
-                       *sep = '.';
-               }
-       }
-
        field_op = contains_operator(str, &sep);
 
        if (field_op == FIELD_OP_NONE)
        struct synth_event *se;
        const char *se_name;
        bool remove = false;
-       char *trigger, *p;
+       char *trigger, *p, *start;
        int ret = 0;
 
        lockdep_assert_held(&event_mutex);
                trigger = strstrip(trigger);
        }
 
+       /*
+        * To simplify arithmetic expression parsing, replace occurrences of
+        * '.sym-offset' modifier with '.symXoffset'
+        */
+       start = strstr(trigger, ".sym-offset");
+       while (start) {
+               *(start + 4) = 'X';
+               start = strstr(start + 11, ".sym-offset");
+       };
+
        attrs = parse_hist_trigger_attrs(file->tr, trigger);
        if (IS_ERR(attrs))
                return PTR_ERR(attrs);