diff options
-rw-r--r-- | arch/x86/include/asm/ftrace.h | 7 | ||||
-rw-r--r-- | arch/x86/kernel/ftrace.c | 63 |
2 files changed, 70 insertions, 0 deletions
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h index db24c2278be0..bd2c6511c887 100644 --- a/arch/x86/include/asm/ftrace.h +++ b/arch/x86/include/asm/ftrace.h | |||
@@ -28,6 +28,13 @@ | |||
28 | 28 | ||
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | /* FIXME: I don't want to stay hardcoded */ | ||
32 | #ifdef CONFIG_X86_64 | ||
33 | # define FTRACE_SYSCALL_MAX 296 | ||
34 | #else | ||
35 | # define FTRACE_SYSCALL_MAX 333 | ||
36 | #endif | ||
37 | |||
31 | #ifdef CONFIG_FUNCTION_TRACER | 38 | #ifdef CONFIG_FUNCTION_TRACER |
32 | #define MCOUNT_ADDR ((long)(mcount)) | 39 | #define MCOUNT_ADDR ((long)(mcount)) |
33 | #define MCOUNT_INSN_SIZE 5 /* sizeof mcount call */ | 40 | #define MCOUNT_INSN_SIZE 5 /* sizeof mcount call */ |
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index a85da1764b1c..1d0d7f42efe3 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c | |||
@@ -453,3 +453,66 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) | |||
453 | } | 453 | } |
454 | } | 454 | } |
455 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | 455 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |
456 | |||
457 | #ifdef CONFIG_FTRACE_SYSCALLS | ||
458 | |||
459 | extern unsigned long __start_syscalls_metadata[]; | ||
460 | extern unsigned long __stop_syscalls_metadata[]; | ||
461 | extern unsigned long *sys_call_table; | ||
462 | |||
463 | static struct syscall_metadata **syscalls_metadata; | ||
464 | |||
465 | static struct syscall_metadata *find_syscall_meta(unsigned long *syscall) | ||
466 | { | ||
467 | struct syscall_metadata *start; | ||
468 | struct syscall_metadata *stop; | ||
469 | char str[KSYM_SYMBOL_LEN]; | ||
470 | |||
471 | |||
472 | start = (struct syscall_metadata *)__start_syscalls_metadata; | ||
473 | stop = (struct syscall_metadata *)__stop_syscalls_metadata; | ||
474 | kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str); | ||
475 | |||
476 | for ( ; start < stop; start++) { | ||
477 | if (start->name && !strcmp(start->name, str)) | ||
478 | return start; | ||
479 | } | ||
480 | return NULL; | ||
481 | } | ||
482 | |||
483 | struct syscall_metadata *syscall_nr_to_meta(int nr) | ||
484 | { | ||
485 | if (!syscalls_metadata || nr >= FTRACE_SYSCALL_MAX || nr < 0) | ||
486 | return NULL; | ||
487 | |||
488 | return syscalls_metadata[nr]; | ||
489 | } | ||
490 | |||
491 | void arch_init_ftrace_syscalls(void) | ||
492 | { | ||
493 | int i; | ||
494 | struct syscall_metadata *meta; | ||
495 | unsigned long **psys_syscall_table = &sys_call_table; | ||
496 | static atomic_t refs; | ||
497 | |||
498 | if (atomic_inc_return(&refs) != 1) | ||
499 | goto end; | ||
500 | |||
501 | syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * | ||
502 | FTRACE_SYSCALL_MAX, GFP_KERNEL); | ||
503 | if (!syscalls_metadata) { | ||
504 | WARN_ON(1); | ||
505 | return; | ||
506 | } | ||
507 | |||
508 | for (i = 0; i < FTRACE_SYSCALL_MAX; i++) { | ||
509 | meta = find_syscall_meta(psys_syscall_table[i]); | ||
510 | syscalls_metadata[i] = meta; | ||
511 | } | ||
512 | return; | ||
513 | |||
514 | /* Paranoid: avoid overflow */ | ||
515 | end: | ||
516 | atomic_dec(&refs); | ||
517 | } | ||
518 | #endif | ||