/* Internal register function - just handle k*probes and flags */
 static int __register_trace_kprobe(struct trace_kprobe *tk)
 {
-       int ret;
+       int i, ret;
 
        if (trace_probe_is_registered(&tk->tp))
                return -EINVAL;
                return -EINVAL;
        }
 
+       for (i = 0; i < tk->tp.nr_args; i++) {
+               ret = traceprobe_update_arg(&tk->tp.args[i]);
+               if (ret)
+                       return ret;
+       }
+
        /* Set/clear disabled flag according to tp->flag */
        if (trace_probe_is_enabled(&tk->tp))
                tk->rp.kp.flags &= ~KPROBE_FLAG_DISABLED;
 {
        unsigned long val;
 
+retry:
        /* 1st stage: get value from context */
        switch (code->op) {
        case FETCH_OP_REG:
                val = regs_get_kernel_argument(regs, code->param);
                break;
 #endif
+       case FETCH_NOP_SYMBOL:  /* Ignore a place holder */
+               code++;
+               goto retry;
        default:
                return -EILSEQ;
        }
 
                        if (!(flags & TPARG_FL_KERNEL))
                                return -EINVAL;
 
-                       ret = traceprobe_split_symbol_offset(arg + 1, &offset);
-                       if (ret)
-                               break;
+                       /* Preserve symbol for updating */
+                       code->op = FETCH_NOP_SYMBOL;
+                       code->data = kstrdup(arg + 1, GFP_KERNEL);
+                       if (!code->data)
+                               return -ENOMEM;
+                       if (++code == end)
+                               return -E2BIG;
 
                        code->op = FETCH_OP_IMM;
-                       code->immediate =
-                               (unsigned long)kallsyms_lookup_name(arg + 1);
-                       if (!code->immediate)
-                               return -ENOENT;
-                       code->immediate += offset;
+                       code->immediate = 0;
                }
                /* These are fetching from memory */
                if (++code == end)
                memcpy(parg->code, tmp, sizeof(*code) * (code - tmp + 1));
 
 fail:
+       if (ret) {
+               for (code = tmp; code < tmp + FETCH_INSN_MAX; code++)
+                       if (code->op == FETCH_NOP_SYMBOL)
+                               kfree(code->data);
+       }
        kfree(tmp);
 
        return ret;
 
 void traceprobe_free_probe_arg(struct probe_arg *arg)
 {
+       struct fetch_insn *code = arg->code;
+
+       while (code && code->op != FETCH_OP_END) {
+               if (code->op == FETCH_NOP_SYMBOL)
+                       kfree(code->data);
+               code++;
+       }
        kfree(arg->code);
        kfree(arg->name);
        kfree(arg->comm);
        kfree(arg->fmt);
 }
 
+int traceprobe_update_arg(struct probe_arg *arg)
+{
+       struct fetch_insn *code = arg->code;
+       long offset;
+       char *tmp;
+       char c;
+       int ret = 0;
+
+       while (code && code->op != FETCH_OP_END) {
+               if (code->op == FETCH_NOP_SYMBOL) {
+                       if (code[1].op != FETCH_OP_IMM)
+                               return -EINVAL;
+
+                       tmp = strpbrk("+-", code->data);
+                       if (tmp)
+                               c = *tmp;
+                       ret = traceprobe_split_symbol_offset(code->data,
+                                                            &offset);
+                       if (ret)
+                               return ret;
+
+                       code[1].immediate =
+                               (unsigned long)kallsyms_lookup_name(code->data);
+                       if (tmp)
+                               *tmp = c;
+                       if (!code[1].immediate)
+                               return -ENOENT;
+                       code[1].immediate += offset;
+               }
+               code++;
+       }
+       return 0;
+}
+
 /* When len=0, we just calculate the needed length */
 #define LEN_OR_ZERO (len ? len - pos : 0)
 static int __set_print_fmt(struct trace_probe *tp, char *buf, int len,
 
        // Stage 5 (loop) op
        FETCH_OP_LP_ARRAY,      /* Array: .param = loop count */
        FETCH_OP_END,
+       FETCH_NOP_SYMBOL,       /* Unresolved Symbol holder */
 };
 
 struct fetch_insn {
                        unsigned char rshift;
                };
                unsigned long immediate;
+               void *data;
        };
 };
 
 extern int traceprobe_conflict_field_name(const char *name,
                               struct probe_arg *args, int narg);
 
-extern void traceprobe_update_arg(struct probe_arg *arg);
+extern int traceprobe_update_arg(struct probe_arg *arg);
 extern void traceprobe_free_probe_arg(struct probe_arg *arg);
 
 extern int traceprobe_split_symbol_offset(char *symbol, long *offset);