struct probe_arg *parg = &ep->tp.args[i];
        struct ftrace_event_field *field;
        struct list_head *head;
+       int ret = -ENOENT;
 
        head = trace_get_fields(ep->event);
        list_for_each_entry(field, head, link) {
                        return 0;
                }
        }
+
+       /*
+        * Argument not found on event. But allow for comm and COMM
+        * to be used to get the current->comm.
+        */
+       if (strcmp(parg->code->data, "COMM") == 0 ||
+           strcmp(parg->code->data, "comm") == 0) {
+               parg->code->op = FETCH_OP_COMM;
+               ret = 0;
+       }
+
        kfree(parg->code->data);
        parg->code->data = NULL;
-       return -ENOENT;
+       return ret;
 }
 
 static int eprobe_event_define_fields(struct trace_event_call *event_call)
 
 static int get_eprobe_size(struct trace_probe *tp, void *rec)
 {
+       struct fetch_insn *code;
        struct probe_arg *arg;
        int i, len, ret = 0;
 
        for (i = 0; i < tp->nr_args; i++) {
                arg = tp->args + i;
-               if (unlikely(arg->dynamic)) {
+               if (arg->dynamic) {
                        unsigned long val;
 
-                       val = get_event_field(arg->code, rec);
-                       len = process_fetch_insn_bottom(arg->code + 1, val, NULL, NULL);
+                       code = arg->code;
+ retry:
+                       switch (code->op) {
+                       case FETCH_OP_TP_ARG:
+                               val = get_event_field(code, rec);
+                               break;
+                       case FETCH_OP_IMM:
+                               val = code->immediate;
+                               break;
+                       case FETCH_OP_COMM:
+                               val = (unsigned long)current->comm;
+                               break;
+                       case FETCH_OP_DATA:
+                               val = (unsigned long)code->data;
+                               break;
+                       case FETCH_NOP_SYMBOL:  /* Ignore a place holder */
+                               code++;
+                               goto retry;
+                       default:
+                               continue;
+                       }
+                       code++;
+                       len = process_fetch_insn_bottom(code, val, NULL, NULL);
                        if (len > 0)
                                ret += len;
                }
 {
        unsigned long val;
 
-       val = get_event_field(code, rec);
-       return process_fetch_insn_bottom(code + 1, val, dest, base);
+ retry:
+       switch (code->op) {
+       case FETCH_OP_TP_ARG:
+               val = get_event_field(code, rec);
+               break;
+       case FETCH_OP_IMM:
+               val = code->immediate;
+               break;
+       case FETCH_OP_COMM:
+               val = (unsigned long)current->comm;
+               break;
+       case FETCH_OP_DATA:
+               val = (unsigned long)code->data;
+               break;
+       case FETCH_NOP_SYMBOL:  /* Ignore a place holder */
+               code++;
+               goto retry;
+       default:
+               return -EILSEQ;
+       }
+       code++;
+       return process_fetch_insn_bottom(code, val, dest, base);
 }
 NOKPROBE_SYMBOL(process_fetch_insn)
 
                        trace_probe_log_err(0, BAD_ATTACH_ARG);
        }
 
+       /* Handle symbols "@" */
+       if (!ret)
+               ret = traceprobe_update_arg(&ep->tp.args[i]);
+
        return ret;
 }