diff options
| author | David S. Miller <davem@davemloft.net> | 2009-12-05 18:22:26 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-12-05 18:22:26 -0500 |
| commit | 28b4d5cc17c20786848cdc07b7ea237a309776bb (patch) | |
| tree | bae406a4b17229dcce7c11be5073f7a67665e477 /kernel/trace/trace_syscalls.c | |
| parent | d29cecda036f251aee4947f47eea0fe9ed8cc931 (diff) | |
| parent | 96fa2b508d2d3fe040cf4ef2fffb955f0a537ea1 (diff) | |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Conflicts:
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/wireless/ray_cs.c
Diffstat (limited to 'kernel/trace/trace_syscalls.c')
| -rw-r--r-- | kernel/trace/trace_syscalls.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 527e17eae575..ddee9c593732 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c | |||
| @@ -14,6 +14,69 @@ static int sys_refcount_exit; | |||
| 14 | static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls); | 14 | static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls); |
| 15 | static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls); | 15 | static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls); |
| 16 | 16 | ||
| 17 | extern unsigned long __start_syscalls_metadata[]; | ||
| 18 | extern unsigned long __stop_syscalls_metadata[]; | ||
| 19 | |||
| 20 | static struct syscall_metadata **syscalls_metadata; | ||
| 21 | |||
| 22 | static struct syscall_metadata *find_syscall_meta(unsigned long syscall) | ||
| 23 | { | ||
| 24 | struct syscall_metadata *start; | ||
| 25 | struct syscall_metadata *stop; | ||
| 26 | char str[KSYM_SYMBOL_LEN]; | ||
| 27 | |||
| 28 | |||
| 29 | start = (struct syscall_metadata *)__start_syscalls_metadata; | ||
| 30 | stop = (struct syscall_metadata *)__stop_syscalls_metadata; | ||
| 31 | kallsyms_lookup(syscall, NULL, NULL, NULL, str); | ||
| 32 | |||
| 33 | for ( ; start < stop; start++) { | ||
| 34 | /* | ||
| 35 | * Only compare after the "sys" prefix. Archs that use | ||
| 36 | * syscall wrappers may have syscalls symbols aliases prefixed | ||
| 37 | * with "SyS" instead of "sys", leading to an unwanted | ||
| 38 | * mismatch. | ||
| 39 | */ | ||
| 40 | if (start->name && !strcmp(start->name + 3, str + 3)) | ||
| 41 | return start; | ||
| 42 | } | ||
| 43 | return NULL; | ||
| 44 | } | ||
| 45 | |||
| 46 | static struct syscall_metadata *syscall_nr_to_meta(int nr) | ||
| 47 | { | ||
| 48 | if (!syscalls_metadata || nr >= NR_syscalls || nr < 0) | ||
| 49 | return NULL; | ||
| 50 | |||
| 51 | return syscalls_metadata[nr]; | ||
| 52 | } | ||
| 53 | |||
| 54 | int syscall_name_to_nr(char *name) | ||
| 55 | { | ||
| 56 | int i; | ||
| 57 | |||
| 58 | if (!syscalls_metadata) | ||
| 59 | return -1; | ||
| 60 | |||
| 61 | for (i = 0; i < NR_syscalls; i++) { | ||
| 62 | if (syscalls_metadata[i]) { | ||
| 63 | if (!strcmp(syscalls_metadata[i]->name, name)) | ||
| 64 | return i; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | return -1; | ||
| 68 | } | ||
| 69 | |||
| 70 | void set_syscall_enter_id(int num, int id) | ||
| 71 | { | ||
| 72 | syscalls_metadata[num]->enter_id = id; | ||
| 73 | } | ||
| 74 | |||
| 75 | void set_syscall_exit_id(int num, int id) | ||
| 76 | { | ||
| 77 | syscalls_metadata[num]->exit_id = id; | ||
| 78 | } | ||
| 79 | |||
| 17 | enum print_line_t | 80 | enum print_line_t |
| 18 | print_syscall_enter(struct trace_iterator *iter, int flags) | 81 | print_syscall_enter(struct trace_iterator *iter, int flags) |
| 19 | { | 82 | { |
| @@ -375,6 +438,29 @@ struct trace_event event_syscall_exit = { | |||
| 375 | .trace = print_syscall_exit, | 438 | .trace = print_syscall_exit, |
| 376 | }; | 439 | }; |
| 377 | 440 | ||
| 441 | int __init init_ftrace_syscalls(void) | ||
| 442 | { | ||
| 443 | struct syscall_metadata *meta; | ||
| 444 | unsigned long addr; | ||
| 445 | int i; | ||
| 446 | |||
| 447 | syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * | ||
| 448 | NR_syscalls, GFP_KERNEL); | ||
| 449 | if (!syscalls_metadata) { | ||
| 450 | WARN_ON(1); | ||
| 451 | return -ENOMEM; | ||
| 452 | } | ||
| 453 | |||
| 454 | for (i = 0; i < NR_syscalls; i++) { | ||
| 455 | addr = arch_syscall_addr(i); | ||
| 456 | meta = find_syscall_meta(addr); | ||
| 457 | syscalls_metadata[i] = meta; | ||
| 458 | } | ||
| 459 | |||
| 460 | return 0; | ||
| 461 | } | ||
| 462 | core_initcall(init_ftrace_syscalls); | ||
| 463 | |||
| 378 | #ifdef CONFIG_EVENT_PROFILE | 464 | #ifdef CONFIG_EVENT_PROFILE |
| 379 | 465 | ||
| 380 | static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls); | 466 | static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls); |
