return -EINVAL;
 }
 
+static int __parse_imm_string(char *str, char **pbuf, int offs)
+{
+       size_t len = strlen(str);
+
+       if (str[len - 1] != '"') {
+               trace_probe_log_err(offs + len, IMMSTR_NO_CLOSE);
+               return -EINVAL;
+       }
+       *pbuf = kstrndup(str, len - 1, GFP_KERNEL);
+       return 0;
+}
+
 /* Recursive argument parser */
 static int
 parse_probe_arg(char *arg, const struct fetch_type *type,
                        ret = parse_probe_arg(arg, t2, &code, end, flags, offs);
                        if (ret)
                                break;
-                       if (code->op == FETCH_OP_COMM) {
+                       if (code->op == FETCH_OP_COMM ||
+                           code->op == FETCH_OP_DATA) {
                                trace_probe_log_err(offs, COMM_CANT_DEREF);
                                return -EINVAL;
                        }
                }
                break;
        case '\\':      /* Immediate value */
-               ret = str_to_immediate(arg + 1, &code->immediate);
-               if (ret)
-                       trace_probe_log_err(offs + 1, BAD_IMM);
-               else
-                       code->op = FETCH_OP_IMM;
+               if (arg[1] == '"') {    /* Immediate string */
+                       ret = __parse_imm_string(arg + 2, &tmp, offs + 2);
+                       if (ret)
+                               break;
+                       code->op = FETCH_OP_DATA;
+                       code->data = tmp;
+               } else {
+                       ret = str_to_immediate(arg + 1, &code->immediate);
+                       if (ret)
+                               trace_probe_log_err(offs + 1, BAD_IMM);
+                       else
+                               code->op = FETCH_OP_IMM;
+               }
                break;
        }
        if (!ret && code->op == FETCH_OP_NOP) {
                }
        }
 
-       /* Since $comm can not be dereferred, we can find $comm by strcmp */
-       if (strcmp(arg, "$comm") == 0) {
+       /*
+        * Since $comm and immediate string can not be dereferred,
+        * we can find those by strcmp.
+        */
+       if (strcmp(arg, "$comm") == 0 || strncmp(arg, "\\\"", 2) == 0) {
                /* The type of $comm must be "string", and not an array. */
                if (parg->count || (t && strcmp(t, "string")))
                        return -EINVAL;
        if (!strcmp(parg->type->name, "string") ||
            !strcmp(parg->type->name, "ustring")) {
                if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_UDEREF &&
-                   code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM) {
+                   code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM &&
+                   code->op != FETCH_OP_DATA) {
                        trace_probe_log_err(offset + (t ? (t - arg) : 0),
                                            BAD_STRING);
                        ret = -EINVAL;
                if ((code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM) ||
                     parg->count) {
                        /*
-                        * IMM and COMM is pointing actual address, those must
-                        * be kept, and if parg->count != 0, this is an array
-                        * of string pointers instead of string address itself.
+                        * IMM, DATA and COMM is pointing actual address, those
+                        * must be kept, and if parg->count != 0, this is an
+                        * array of string pointers instead of string address
+                        * itself.
                         */
                        code++;
                        if (code->op != FETCH_OP_NOP) {
 fail:
        if (ret) {
                for (code = tmp; code < tmp + FETCH_INSN_MAX; code++)
-                       if (code->op == FETCH_NOP_SYMBOL)
+                       if (code->op == FETCH_NOP_SYMBOL ||
+                           code->op == FETCH_OP_DATA)
                                kfree(code->data);
        }
        kfree(tmp);
        struct fetch_insn *code = arg->code;
 
        while (code && code->op != FETCH_OP_END) {
-               if (code->op == FETCH_NOP_SYMBOL)
+               if (code->op == FETCH_NOP_SYMBOL ||
+                   code->op == FETCH_OP_DATA)
                        kfree(code->data);
                code++;
        }
 
        FETCH_OP_COMM,          /* Current comm */
        FETCH_OP_ARG,           /* Function argument : .param */
        FETCH_OP_FOFFS,         /* File offset: .immediate */
+       FETCH_OP_DATA,          /* Allocated data: .data */
        // Stage 2 (dereference) op
        FETCH_OP_DEREF,         /* Dereference: .offset */
        FETCH_OP_UDEREF,        /* User-space Dereference: .offset */
        C(BAD_REG_NAME,         "Invalid register name"),               \
        C(BAD_MEM_ADDR,         "Invalid memory address"),              \
        C(BAD_IMM,              "Invalid immediate value"),             \
+       C(IMMSTR_NO_CLOSE,      "String is not closed with '\"'"),      \
        C(FILE_ON_KPROBE,       "File offset is not available with kprobe"), \
        C(BAD_FILE_OFFS,        "Invalid file offset value"),           \
        C(SYM_ON_UPROBE,        "Symbol is not available with uprobe"), \