Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'probes-v6.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull kprobes cleanup updates from Masami Hiramatsu:
"These are probe events cleanups, no new features but improve
readability:

- Rename print_probe_args() to trace_probe_print_args() and
un-inline it

- Introduce a set of default data fetch functions for dynamic
probe events

- Extract common code of data fetch process of dynamic probe events"

* tag 'probes-v6.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
kernel/trace: extract common part in process_fetch_insn
kernel/trace: Provide default impelentations defined in trace_probe_tmpl.h
kernel/trace: Introduce trace_probe_print_args and use it in *probes

+96 -185
+9 -74
kernel/trace/trace_eprobe.c
··· 311 311 312 312 trace_seq_putc(s, ')'); 313 313 314 - if (print_probe_args(s, tp->args, tp->nr_args, 314 + if (trace_probe_print_args(s, tp->args, tp->nr_args, 315 315 (u8 *)&field[1], field) < 0) 316 316 goto out; 317 317 ··· 320 320 return trace_handle_return(s); 321 321 } 322 322 323 - static unsigned long get_event_field(struct fetch_insn *code, void *rec) 323 + static nokprobe_inline unsigned long 324 + get_event_field(struct fetch_insn *code, void *rec) 324 325 { 325 326 struct ftrace_event_field *field = code->data; 326 327 unsigned long val; ··· 396 395 case FETCH_OP_TP_ARG: 397 396 val = get_event_field(code, rec); 398 397 break; 399 - case FETCH_OP_IMM: 400 - val = code->immediate; 401 - break; 402 - case FETCH_OP_COMM: 403 - val = (unsigned long)current->comm; 404 - break; 405 - case FETCH_OP_DATA: 406 - val = (unsigned long)code->data; 407 - break; 408 398 case FETCH_NOP_SYMBOL: /* Ignore a place holder */ 409 399 code++; 410 400 goto retry; 411 401 default: 412 - continue; 402 + if (process_common_fetch_insn(code, &val) < 0) 403 + continue; 413 404 } 414 405 code++; 415 406 len = process_fetch_insn_bottom(code, val, NULL, NULL); ··· 421 428 void *base) 422 429 { 423 430 unsigned long val; 431 + int ret; 424 432 425 433 retry: 426 434 switch (code->op) { 427 435 case FETCH_OP_TP_ARG: 428 436 val = get_event_field(code, rec); 429 437 break; 430 - case FETCH_OP_IMM: 431 - val = code->immediate; 432 - break; 433 - case FETCH_OP_COMM: 434 - val = (unsigned long)current->comm; 435 - break; 436 - case FETCH_OP_DATA: 437 - val = (unsigned long)code->data; 438 - break; 439 438 case FETCH_NOP_SYMBOL: /* Ignore a place holder */ 440 439 code++; 441 440 goto retry; 442 441 default: 443 - return -EILSEQ; 442 + ret = process_common_fetch_insn(code, &val); 443 + if (ret < 0) 444 + return ret; 444 445 } 445 446 code++; 446 447 return process_fetch_insn_bottom(code, val, dest, base); 447 448 } 448 449 NOKPROBE_SYMBOL(process_fetch_insn) 449 - 450 - /* Return the length of string -- including null terminal byte */ 451 - static nokprobe_inline int 452 - fetch_store_strlen_user(unsigned long addr) 453 - { 454 - return kern_fetch_store_strlen_user(addr); 455 - } 456 - 457 - /* Return the length of string -- including null terminal byte */ 458 - static nokprobe_inline int 459 - fetch_store_strlen(unsigned long addr) 460 - { 461 - return kern_fetch_store_strlen(addr); 462 - } 463 - 464 - /* 465 - * Fetch a null-terminated string from user. Caller MUST set *(u32 *)buf 466 - * with max length and relative data location. 467 - */ 468 - static nokprobe_inline int 469 - fetch_store_string_user(unsigned long addr, void *dest, void *base) 470 - { 471 - return kern_fetch_store_string_user(addr, dest, base); 472 - } 473 - 474 - /* 475 - * Fetch a null-terminated string. Caller MUST set *(u32 *)buf with max 476 - * length and relative data location. 477 - */ 478 - static nokprobe_inline int 479 - fetch_store_string(unsigned long addr, void *dest, void *base) 480 - { 481 - return kern_fetch_store_string(addr, dest, base); 482 - } 483 - 484 - static nokprobe_inline int 485 - probe_mem_read_user(void *dest, void *src, size_t size) 486 - { 487 - const void __user *uaddr = (__force const void __user *)src; 488 - 489 - return copy_from_user_nofault(dest, uaddr, size); 490 - } 491 - 492 - static nokprobe_inline int 493 - probe_mem_read(void *dest, void *src, size_t size) 494 - { 495 - #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE 496 - if ((unsigned long)src < TASK_SIZE) 497 - return probe_mem_read_user(dest, src, size); 498 - #endif 499 - return copy_from_kernel_nofault(dest, src, size); 500 - } 501 450 502 451 /* eprobe handler */ 503 452 static inline void
+3 -3
kernel/trace/trace_events_synth.c
··· 448 448 data_offset = struct_size(entry, fields, event->n_u64); 449 449 data_offset += data_size; 450 450 451 - len = kern_fetch_store_strlen((unsigned long)str_val); 451 + len = fetch_store_strlen((unsigned long)str_val); 452 452 453 453 data_offset |= len << 16; 454 454 *(u32 *)&entry->fields[*n_u64] = data_offset; 455 455 456 - ret = kern_fetch_store_string((unsigned long)str_val, &entry->fields[*n_u64], entry); 456 + ret = fetch_store_string((unsigned long)str_val, &entry->fields[*n_u64], entry); 457 457 458 458 (*n_u64)++; 459 459 } else { ··· 542 542 len = *((unsigned long *)str_val); 543 543 len *= sizeof(unsigned long); 544 544 } else { 545 - len = kern_fetch_store_strlen((unsigned long)str_val); 545 + len = fetch_store_strlen((unsigned long)str_val); 546 546 } 547 547 548 548 fields_size += len;
+6 -66
kernel/trace/trace_kprobe.c
··· 1218 1218 .release = seq_release, 1219 1219 }; 1220 1220 1221 - /* Kprobe specific fetch functions */ 1222 - 1223 - /* Return the length of string -- including null terminal byte */ 1224 - static nokprobe_inline int 1225 - fetch_store_strlen_user(unsigned long addr) 1226 - { 1227 - return kern_fetch_store_strlen_user(addr); 1228 - } 1229 - 1230 - /* Return the length of string -- including null terminal byte */ 1231 - static nokprobe_inline int 1232 - fetch_store_strlen(unsigned long addr) 1233 - { 1234 - return kern_fetch_store_strlen(addr); 1235 - } 1236 - 1237 - /* 1238 - * Fetch a null-terminated string from user. Caller MUST set *(u32 *)buf 1239 - * with max length and relative data location. 1240 - */ 1241 - static nokprobe_inline int 1242 - fetch_store_string_user(unsigned long addr, void *dest, void *base) 1243 - { 1244 - return kern_fetch_store_string_user(addr, dest, base); 1245 - } 1246 - 1247 - /* 1248 - * Fetch a null-terminated string. Caller MUST set *(u32 *)buf with max 1249 - * length and relative data location. 1250 - */ 1251 - static nokprobe_inline int 1252 - fetch_store_string(unsigned long addr, void *dest, void *base) 1253 - { 1254 - return kern_fetch_store_string(addr, dest, base); 1255 - } 1256 - 1257 - static nokprobe_inline int 1258 - probe_mem_read_user(void *dest, void *src, size_t size) 1259 - { 1260 - const void __user *uaddr = (__force const void __user *)src; 1261 - 1262 - return copy_from_user_nofault(dest, uaddr, size); 1263 - } 1264 - 1265 - static nokprobe_inline int 1266 - probe_mem_read(void *dest, void *src, size_t size) 1267 - { 1268 - #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE 1269 - if ((unsigned long)src < TASK_SIZE) 1270 - return probe_mem_read_user(dest, src, size); 1271 - #endif 1272 - return copy_from_kernel_nofault(dest, src, size); 1273 - } 1274 - 1275 1221 /* Note that we don't verify it, since the code does not come from user space */ 1276 1222 static int 1277 1223 process_fetch_insn(struct fetch_insn *code, void *rec, void *dest, ··· 1225 1279 { 1226 1280 struct pt_regs *regs = rec; 1227 1281 unsigned long val; 1282 + int ret; 1228 1283 1229 1284 retry: 1230 1285 /* 1st stage: get value from context */ ··· 1242 1295 case FETCH_OP_RETVAL: 1243 1296 val = regs_return_value(regs); 1244 1297 break; 1245 - case FETCH_OP_IMM: 1246 - val = code->immediate; 1247 - break; 1248 - case FETCH_OP_COMM: 1249 - val = (unsigned long)current->comm; 1250 - break; 1251 - case FETCH_OP_DATA: 1252 - val = (unsigned long)code->data; 1253 - break; 1254 1298 #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API 1255 1299 case FETCH_OP_ARG: 1256 1300 val = regs_get_kernel_argument(regs, code->param); ··· 1251 1313 code++; 1252 1314 goto retry; 1253 1315 default: 1254 - return -EILSEQ; 1316 + ret = process_common_fetch_insn(code, &val); 1317 + if (ret < 0) 1318 + return ret; 1255 1319 } 1256 1320 code++; 1257 1321 ··· 1364 1424 1365 1425 trace_seq_putc(s, ')'); 1366 1426 1367 - if (print_probe_args(s, tp->args, tp->nr_args, 1427 + if (trace_probe_print_args(s, tp->args, tp->nr_args, 1368 1428 (u8 *)&field[1], field) < 0) 1369 1429 goto out; 1370 1430 ··· 1399 1459 1400 1460 trace_seq_putc(s, ')'); 1401 1461 1402 - if (print_probe_args(s, tp->args, tp->nr_args, 1462 + if (trace_probe_print_args(s, tp->args, tp->nr_args, 1403 1463 (u8 *)&field[1], field) < 0) 1404 1464 goto out; 1405 1465
+27
kernel/trace/trace_probe.c
··· 1239 1239 1240 1240 return ret; 1241 1241 } 1242 + 1243 + int trace_probe_print_args(struct trace_seq *s, struct probe_arg *args, int nr_args, 1244 + u8 *data, void *field) 1245 + { 1246 + void *p; 1247 + int i, j; 1248 + 1249 + for (i = 0; i < nr_args; i++) { 1250 + struct probe_arg *a = args + i; 1251 + 1252 + trace_seq_printf(s, " %s=", a->name); 1253 + if (likely(!a->count)) { 1254 + if (!a->type->print(s, data + a->offset, field)) 1255 + return -ENOMEM; 1256 + continue; 1257 + } 1258 + trace_seq_putc(s, '{'); 1259 + p = data + a->offset; 1260 + for (j = 0; j < a->count; j++) { 1261 + if (!a->type->print(s, p, field)) 1262 + return -ENOMEM; 1263 + trace_seq_putc(s, j == a->count - 1 ? '}' : ','); 1264 + p += a->type->size; 1265 + } 1266 + } 1267 + return 0; 1268 + }
+2
kernel/trace/trace_probe.h
··· 349 349 bool trace_probe_match_command_args(struct trace_probe *tp, 350 350 int argc, const char **argv); 351 351 int trace_probe_create(const char *raw_command, int (*createfn)(int, const char **)); 352 + int trace_probe_print_args(struct trace_seq *s, struct probe_arg *args, int nr_args, 353 + u8 *data, void *field); 352 354 353 355 #define trace_probe_for_each_link(pos, tp) \ 354 356 list_for_each_entry(pos, &(tp)->event->files, list)
+24 -6
kernel/trace/trace_probe_kernel.h
··· 12 12 */ 13 13 /* Return the length of string -- including null terminal byte */ 14 14 static nokprobe_inline int 15 - kern_fetch_store_strlen_user(unsigned long addr) 15 + fetch_store_strlen_user(unsigned long addr) 16 16 { 17 17 const void __user *uaddr = (__force const void __user *)addr; 18 18 int ret; ··· 29 29 30 30 /* Return the length of string -- including null terminal byte */ 31 31 static nokprobe_inline int 32 - kern_fetch_store_strlen(unsigned long addr) 32 + fetch_store_strlen(unsigned long addr) 33 33 { 34 34 int ret, len = 0; 35 35 u8 c; 36 36 37 37 #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE 38 38 if (addr < TASK_SIZE) 39 - return kern_fetch_store_strlen_user(addr); 39 + return fetch_store_strlen_user(addr); 40 40 #endif 41 41 42 42 do { ··· 63 63 * with max length and relative data location. 64 64 */ 65 65 static nokprobe_inline int 66 - kern_fetch_store_string_user(unsigned long addr, void *dest, void *base) 66 + fetch_store_string_user(unsigned long addr, void *dest, void *base) 67 67 { 68 68 const void __user *uaddr = (__force const void __user *)addr; 69 69 int maxlen = get_loc_len(*(u32 *)dest); ··· 86 86 * length and relative data location. 87 87 */ 88 88 static nokprobe_inline int 89 - kern_fetch_store_string(unsigned long addr, void *dest, void *base) 89 + fetch_store_string(unsigned long addr, void *dest, void *base) 90 90 { 91 91 int maxlen = get_loc_len(*(u32 *)dest); 92 92 void *__dest; ··· 94 94 95 95 #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE 96 96 if ((unsigned long)addr < TASK_SIZE) 97 - return kern_fetch_store_string_user(addr, dest, base); 97 + return fetch_store_string_user(addr, dest, base); 98 98 #endif 99 99 100 100 if (unlikely(!maxlen)) ··· 110 110 set_data_loc(ret, dest, __dest, base, maxlen); 111 111 112 112 return ret; 113 + } 114 + 115 + static nokprobe_inline int 116 + probe_mem_read_user(void *dest, void *src, size_t size) 117 + { 118 + const void __user *uaddr = (__force const void __user *)src; 119 + 120 + return copy_from_user_nofault(dest, uaddr, size); 121 + } 122 + 123 + static nokprobe_inline int 124 + probe_mem_read(void *dest, void *src, size_t size) 125 + { 126 + #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE 127 + if ((unsigned long)src < TASK_SIZE) 128 + return probe_mem_read_user(dest, src, size); 129 + #endif 130 + return copy_from_kernel_nofault(dest, src, size); 113 131 } 114 132 115 133 #endif /* __TRACE_PROBE_KERNEL_H_ */
+20 -28
kernel/trace/trace_probe_tmpl.h
··· 98 98 return sprint_symbol(__dest, addr); 99 99 } 100 100 101 + /* common part of process_fetch_insn*/ 102 + static nokprobe_inline int 103 + process_common_fetch_insn(struct fetch_insn *code, unsigned long *val) 104 + { 105 + switch (code->op) { 106 + case FETCH_OP_IMM: 107 + *val = code->immediate; 108 + break; 109 + case FETCH_OP_COMM: 110 + *val = (unsigned long)current->comm; 111 + break; 112 + case FETCH_OP_DATA: 113 + *val = (unsigned long)code->data; 114 + break; 115 + default: 116 + return -EILSEQ; 117 + } 118 + return 0; 119 + } 120 + 101 121 /* From the 2nd stage, routine is same */ 102 122 static nokprobe_inline int 103 123 process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val, ··· 272 252 maxlen -= ret; 273 253 } 274 254 } 275 - } 276 - 277 - static inline int 278 - print_probe_args(struct trace_seq *s, struct probe_arg *args, int nr_args, 279 - u8 *data, void *field) 280 - { 281 - void *p; 282 - int i, j; 283 - 284 - for (i = 0; i < nr_args; i++) { 285 - struct probe_arg *a = args + i; 286 - 287 - trace_seq_printf(s, " %s=", a->name); 288 - if (likely(!a->count)) { 289 - if (!a->type->print(s, data + a->offset, field)) 290 - return -ENOMEM; 291 - continue; 292 - } 293 - trace_seq_putc(s, '{'); 294 - p = data + a->offset; 295 - for (j = 0; j < a->count; j++) { 296 - if (!a->type->print(s, p, field)) 297 - return -ENOMEM; 298 - trace_seq_putc(s, j == a->count - 1 ? '}' : ','); 299 - p += a->type->size; 300 - } 301 - } 302 - return 0; 303 255 }
+5 -8
kernel/trace/trace_uprobe.c
··· 220 220 { 221 221 struct pt_regs *regs = rec; 222 222 unsigned long val; 223 + int ret; 223 224 224 225 /* 1st stage: get value from context */ 225 226 switch (code->op) { ··· 236 235 case FETCH_OP_RETVAL: 237 236 val = regs_return_value(regs); 238 237 break; 239 - case FETCH_OP_IMM: 240 - val = code->immediate; 241 - break; 242 238 case FETCH_OP_COMM: 243 239 val = FETCH_TOKEN_COMM; 244 - break; 245 - case FETCH_OP_DATA: 246 - val = (unsigned long)code->data; 247 240 break; 248 241 case FETCH_OP_FOFFS: 249 242 val = translate_user_vaddr(code->immediate); 250 243 break; 251 244 default: 252 - return -EILSEQ; 245 + ret = process_common_fetch_insn(code, &val); 246 + if (ret < 0) 247 + return ret; 253 248 } 254 249 code++; 255 250 ··· 1039 1042 data = DATAOF_TRACE_ENTRY(entry, false); 1040 1043 } 1041 1044 1042 - if (print_probe_args(s, tu->tp.args, tu->tp.nr_args, data, entry) < 0) 1045 + if (trace_probe_print_args(s, tu->tp.args, tu->tp.nr_args, data, entry) < 0) 1043 1046 goto out; 1044 1047 1045 1048 trace_seq_putc(s, '\n');