]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/trace/trace_probe_tmpl.h
Merge branch 'for-linus-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/ibft
[linux.git] / kernel / trace / trace_probe_tmpl.h
index c30c61f12dddff4b1e791751c2029a34bd182b93..e5282828f4a60583e2c471f0c71efdf867969b2c 100644 (file)
@@ -59,8 +59,13 @@ process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs,
 static nokprobe_inline int fetch_store_strlen(unsigned long addr);
 static nokprobe_inline int
 fetch_store_string(unsigned long addr, void *dest, void *base);
+static nokprobe_inline int fetch_store_strlen_user(unsigned long addr);
+static nokprobe_inline int
+fetch_store_string_user(unsigned long addr, void *dest, void *base);
 static nokprobe_inline int
 probe_mem_read(void *dest, void *src, size_t size);
+static nokprobe_inline int
+probe_mem_read_user(void *dest, void *src, size_t size);
 
 /* From the 2nd stage, routine is same */
 static nokprobe_inline int
@@ -74,14 +79,21 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val,
 
 stage2:
        /* 2nd stage: dereference memory if needed */
-       while (code->op == FETCH_OP_DEREF) {
-               lval = val;
-               ret = probe_mem_read(&val, (void *)val + code->offset,
-                                       sizeof(val));
+       do {
+               if (code->op == FETCH_OP_DEREF) {
+                       lval = val;
+                       ret = probe_mem_read(&val, (void *)val + code->offset,
+                                            sizeof(val));
+               } else if (code->op == FETCH_OP_UDEREF) {
+                       lval = val;
+                       ret = probe_mem_read_user(&val,
+                                (void *)val + code->offset, sizeof(val));
+               } else
+                       break;
                if (ret)
                        return ret;
                code++;
-       }
+       } while (1);
 
        s3 = code;
 stage3:
@@ -91,6 +103,10 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val,
                        ret = fetch_store_strlen(val + code->offset);
                        code++;
                        goto array;
+               } else if (code->op == FETCH_OP_ST_USTRING) {
+                       ret += fetch_store_strlen_user(val + code->offset);
+                       code++;
+                       goto array;
                } else
                        return -EILSEQ;
        }
@@ -102,10 +118,17 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val,
        case FETCH_OP_ST_MEM:
                probe_mem_read(dest, (void *)val + code->offset, code->size);
                break;
+       case FETCH_OP_ST_UMEM:
+               probe_mem_read_user(dest, (void *)val + code->offset, code->size);
+               break;
        case FETCH_OP_ST_STRING:
                loc = *(u32 *)dest;
                ret = fetch_store_string(val + code->offset, dest, base);
                break;
+       case FETCH_OP_ST_USTRING:
+               loc = *(u32 *)dest;
+               ret = fetch_store_string_user(val + code->offset, dest, base);
+               break;
        default:
                return -EILSEQ;
        }
@@ -123,7 +146,8 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val,
                total += ret;
                if (++i < code->param) {
                        code = s3;
-                       if (s3->op != FETCH_OP_ST_STRING) {
+                       if (s3->op != FETCH_OP_ST_STRING &&
+                           s3->op != FETCH_OP_ST_USTRING) {
                                dest += s3->size;
                                val += s3->size;
                                goto stage3;