1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Traceprobe fetch helper inlines 4 */ 5 6 static nokprobe_inline void 7 fetch_store_raw(unsigned long val, struct fetch_insn *code, void *buf) 8 { 9 switch (code->size) { 10 case 1: 11 *(u8 *)buf = (u8)val; 12 break; 13 case 2: 14 *(u16 *)buf = (u16)val; 15 break; 16 case 4: 17 *(u32 *)buf = (u32)val; 18 break; 19 case 8: 20 //TBD: 32bit signed 21 *(u64 *)buf = (u64)val; 22 break; 23 default: 24 *(unsigned long *)buf = val; 25 } 26 } 27 28 static nokprobe_inline void 29 fetch_apply_bitfield(struct fetch_insn *code, void *buf) 30 { 31 switch (code->basesize) { 32 case 1: 33 *(u8 *)buf <<= code->lshift; 34 *(u8 *)buf >>= code->rshift; 35 break; 36 case 2: 37 *(u16 *)buf <<= code->lshift; 38 *(u16 *)buf >>= code->rshift; 39 break; 40 case 4: 41 *(u32 *)buf <<= code->lshift; 42 *(u32 *)buf >>= code->rshift; 43 break; 44 case 8: 45 *(u64 *)buf <<= code->lshift; 46 *(u64 *)buf >>= code->rshift; 47 break; 48 } 49 } 50 51 /* 52 * These functions must be defined for each callsite. 53 * Return consumed dynamic data size (>= 0), or error (< 0). 54 * If dest is NULL, don't store result and return required dynamic data size. 55 */ 56 static int 57 process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, 58 void *dest, void *base); 59 static nokprobe_inline int fetch_store_strlen(unsigned long addr); 60 static nokprobe_inline int 61 fetch_store_string(unsigned long addr, void *dest, void *base); 62 static nokprobe_inline int 63 probe_mem_read(void *dest, void *src, size_t size); 64 65 /* From the 2nd stage, routine is same */ 66 static nokprobe_inline int 67 process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val, 68 void *dest, void *base) 69 { 70 struct fetch_insn *s3 = NULL; 71 int total = 0, ret = 0, i = 0; 72 u32 loc = 0; 73 unsigned long lval = val; 74 75 stage2: 76 /* 2nd stage: dereference memory if needed */ 77 while (code->op == FETCH_OP_DEREF) { 78 lval = val; 79 ret = probe_mem_read(&val, (void *)val + code->offset, 80 sizeof(val)); 81 if (ret) 82 return ret; 83 code++; 84 } 85 86 s3 = code; 87 stage3: 88 /* 3rd stage: store value to buffer */ 89 if (unlikely(!dest)) { 90 if (code->op == FETCH_OP_ST_STRING) { 91 ret += fetch_store_strlen(val + code->offset); 92 code++; 93 goto array; 94 } else 95 return -EILSEQ; 96 } 97 98 switch (code->op) { 99 case FETCH_OP_ST_RAW: 100 fetch_store_raw(val, code, dest); 101 break; 102 case FETCH_OP_ST_MEM: 103 probe_mem_read(dest, (void *)val + code->offset, code->size); 104 break; 105 case FETCH_OP_ST_STRING: 106 loc = *(u32 *)dest; 107 ret = fetch_store_string(val + code->offset, dest, base); 108 break; 109 default: 110 return -EILSEQ; 111 } 112 code++; 113 114 /* 4th stage: modify stored value if needed */ 115 if (code->op == FETCH_OP_MOD_BF) { 116 fetch_apply_bitfield(code, dest); 117 code++; 118 } 119 120 array: 121 /* the last stage: Loop on array */ 122 if (code->op == FETCH_OP_LP_ARRAY) { 123 total += ret; 124 if (++i < code->param) { 125 code = s3; 126 if (s3->op != FETCH_OP_ST_STRING) { 127 dest += s3->size; 128 val += s3->size; 129 goto stage3; 130 } 131 code--; 132 val = lval + sizeof(char *); 133 if (dest) { 134 dest += sizeof(u32); 135 *(u32 *)dest = update_data_loc(loc, ret); 136 } 137 goto stage2; 138 } 139 code++; 140 ret = total; 141 } 142 143 return code->op == FETCH_OP_END ? ret : -EILSEQ; 144 } 145 146 /* Sum up total data length for dynamic arraies (strings) */ 147 static nokprobe_inline int 148 __get_data_size(struct trace_probe *tp, struct pt_regs *regs) 149 { 150 struct probe_arg *arg; 151 int i, len, ret = 0; 152 153 for (i = 0; i < tp->nr_args; i++) { 154 arg = tp->args + i; 155 if (unlikely(arg->dynamic)) { 156 len = process_fetch_insn(arg->code, regs, NULL, NULL); 157 if (len > 0) 158 ret += len; 159 } 160 } 161 162 return ret; 163 } 164 165 /* Store the value of each argument */ 166 static nokprobe_inline void 167 store_trace_args(void *data, struct trace_probe *tp, struct pt_regs *regs, 168 int header_size, int maxlen) 169 { 170 struct probe_arg *arg; 171 void *base = data - header_size; 172 void *dyndata = data + tp->size; 173 u32 *dl; /* Data location */ 174 int ret, i; 175 176 for (i = 0; i < tp->nr_args; i++) { 177 arg = tp->args + i; 178 dl = data + arg->offset; 179 /* Point the dynamic data area if needed */ 180 if (unlikely(arg->dynamic)) 181 *dl = make_data_loc(maxlen, dyndata - base); 182 ret = process_fetch_insn(arg->code, regs, dl, base); 183 if (unlikely(ret < 0 && arg->dynamic)) 184 *dl = make_data_loc(0, dyndata - base); 185 else 186 dyndata += ret; 187 } 188 } 189 190 static inline int 191 print_probe_args(struct trace_seq *s, struct probe_arg *args, int nr_args, 192 u8 *data, void *field) 193 { 194 void *p; 195 int i, j; 196 197 for (i = 0; i < nr_args; i++) { 198 struct probe_arg *a = args + i; 199 200 trace_seq_printf(s, " %s=", a->name); 201 if (likely(!a->count)) { 202 if (!a->type->print(s, data + a->offset, field)) 203 return -ENOMEM; 204 continue; 205 } 206 trace_seq_putc(s, '{'); 207 p = data + a->offset; 208 for (j = 0; j < a->count; j++) { 209 if (!a->type->print(s, p, field)) 210 return -ENOMEM; 211 trace_seq_putc(s, j == a->count - 1 ? '}' : ','); 212 p += a->type->size; 213 } 214 } 215 return 0; 216 } 217