| @@ -2764,6 +2764,38 @@ void __weak arch_ftrace_trampoline_free(struct ftrace_ops *ops) · 2763 unmodified lines |
| 2764 | { | 2764 | { |
| 2765 | } | 2765 | } |
| 2766 | | 2766 | |
| | 2767 | /* List of trace_ops that have allocated trampolines */ |
| | 2768 | static LIST_HEAD(ftrace_ops_trampoline_list); |
| | 2769 | |
| | 2770 | static void ftrace_add_trampoline_to_kallsyms(struct ftrace_ops *ops) |
| | 2771 | { |
| | 2772 | lockdep_assert_held(&ftrace_lock); |
| | 2773 | list_add_rcu(&ops->list, &ftrace_ops_trampoline_list); |
| | 2774 | } |
| | 2775 | |
| | 2776 | static void ftrace_remove_trampoline_from_kallsyms(struct ftrace_ops *ops) |
| | 2777 | { |
| | 2778 | lockdep_assert_held(&ftrace_lock); |
| | 2779 | list_del_rcu(&ops->list); |
| | 2780 | } |
| | 2781 | |
| | 2782 | /* |
| | 2783 | * "__builtin__ftrace" is used as a module name in /proc/kallsyms for symbols |
| | 2784 | * for pages allocated for ftrace purposes, even though "__builtin__ftrace" is |
| | 2785 | * not a module. |
| | 2786 | */ |
| | 2787 | #define FTRACE_TRAMPOLINE_MOD "__builtin__ftrace" |
| | 2788 | #define FTRACE_TRAMPOLINE_SYM "ftrace_trampoline" |
| | 2789 | |
| | 2790 | static void ftrace_trampoline_free(struct ftrace_ops *ops) |
| | 2791 | { |
| | 2792 | if (ops && (ops->flags & FTRACE_OPS_FL_ALLOC_TRAMP) && |
| | 2793 | ops->trampoline) |
| | 2794 | ftrace_remove_trampoline_from_kallsyms(ops); |
| | 2795 | |
| | 2796 | arch_ftrace_trampoline_free(ops); |
| | 2797 | } |
| | 2798 | |
| 2767 | static void ftrace_startup_enable(int command) | 2799 | static void ftrace_startup_enable(int command) |
| 2768 | { | 2800 | { |
| 2769 | if (saved_ftrace_func != ftrace_trace_function) { | 2801 | if (saved_ftrace_func != ftrace_trace_function) { |
| @@ -2934,7 +2966,7 @@ int ftrace_shutdown(struct ftrace_ops *ops, int command) · 164 unmodified lines |
| 2934 | synchronize_rcu_tasks(); | 2966 | synchronize_rcu_tasks(); |
| 2935 | | 2967 | |
| 2936 | free_ops: | 2968 | free_ops: |
| 2937 | arch_ftrace_trampoline_free(ops); | 2969 | ftrace_trampoline_free(ops); |
| 2938 | } | 2970 | } |
| 2939 | | 2971 | |
| 2940 | return 0; | 2972 | return 0; |
| @@ -6178,6 +6210,27 @@ struct ftrace_mod_map { · 3237 unmodified lines |
| 6178 | unsigned int num_funcs; | 6210 | unsigned int num_funcs; |
| 6179 | }; | 6211 | }; |
| 6180 | | 6212 | |
| | 6213 | static int ftrace_get_trampoline_kallsym(unsigned int symnum, |
| | 6214 | unsigned long *value, char *type, |
| | 6215 | char *name, char *module_name, |
| | 6216 | int *exported) |
| | 6217 | { |
| | 6218 | struct ftrace_ops *op; |
| | 6219 | |
| | 6220 | list_for_each_entry_rcu(op, &ftrace_ops_trampoline_list, list) { |
| | 6221 | if (!op->trampoline || symnum--) |
| | 6222 | continue; |
| | 6223 | *value = op->trampoline; |
| | 6224 | *type = 't'; |
| | 6225 | strlcpy(name, FTRACE_TRAMPOLINE_SYM, KSYM_NAME_LEN); |
| | 6226 | strlcpy(module_name, FTRACE_TRAMPOLINE_MOD, MODULE_NAME_LEN); |
| | 6227 | *exported = 0; |
| | 6228 | return 0; |
| | 6229 | } |
| | 6230 | |
| | 6231 | return -ERANGE; |
| | 6232 | } |
| | 6233 | |
| 6181 | #ifdef CONFIG_MODULES | 6234 | #ifdef CONFIG_MODULES |
| 6182 | | 6235 | |
| 6183 | #define next_to_ftrace_page(p) container_of(p, struct ftrace_page, next) | 6236 | #define next_to_ftrace_page(p) container_of(p, struct ftrace_page, next) |
| @@ -6514,6 +6567,7 @@ int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value, · 330 unmodified lines |
| 6514 | { | 6567 | { |
| 6515 | struct ftrace_mod_map *mod_map; | 6568 | struct ftrace_mod_map *mod_map; |
| 6516 | struct ftrace_mod_func *mod_func; | 6569 | struct ftrace_mod_func *mod_func; |
| | 6570 | int ret; |
| 6517 | | 6571 | |
| 6518 | preempt_disable(); | 6572 | preempt_disable(); |
| 6519 | list_for_each_entry_rcu(mod_map, &ftrace_mod_maps, list) { | 6573 | list_for_each_entry_rcu(mod_map, &ftrace_mod_maps, list) { |
| @@ -6540,8 +6594,10 @@ int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value, · 20 unmodified lines |
| 6540 | WARN_ON(1); | 6594 | WARN_ON(1); |
| 6541 | break; | 6595 | break; |
| 6542 | } | 6596 | } |
| | 6597 | ret = ftrace_get_trampoline_kallsym(symnum, value, type, name, |
| | 6598 | module_name, exported); |
| 6543 | preempt_enable(); | 6599 | preempt_enable(); |
| 6544 | return -ERANGE; | 6600 | return ret; |
| 6545 | } | 6601 | } |
| 6546 | | 6602 | |
| 6547 | #else | 6603 | #else |
| @@ -6553,6 +6609,18 @@ allocate_ftrace_mod_map(struct module *mod, · 5 unmodified lines |
| 6553 | { | 6609 | { |
| 6554 | return NULL; | 6610 | return NULL; |
| 6555 | } | 6611 | } |
| | 6612 | int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value, |
| | 6613 | char *type, char *name, char *module_name, |
| | 6614 | int *exported) |
| | 6615 | { |
| | 6616 | int ret; |
| | 6617 | |
| | 6618 | preempt_disable(); |
| | 6619 | ret = ftrace_get_trampoline_kallsym(symnum, value, type, name, |
| | 6620 | module_name, exported); |
| | 6621 | preempt_enable(); |
| | 6622 | return ret; |
| | 6623 | } |
| 6556 | #endif /* CONFIG_MODULES */ | 6624 | #endif /* CONFIG_MODULES */ |
| 6557 | | 6625 | |
| 6558 | struct ftrace_init_func { | 6626 | struct ftrace_init_func { |
| @@ -6733,7 +6801,12 @@ void __weak arch_ftrace_update_trampoline(struct ftrace_ops *ops) · 174 unmodified lines |
| 6733 | | 6801 | |
| 6734 | static void ftrace_update_trampoline(struct ftrace_ops *ops) | 6802 | static void ftrace_update_trampoline(struct ftrace_ops *ops) |
| 6735 | { | 6803 | { |
| | 6804 | unsigned long trampoline = ops->trampoline; |
| | 6805 | |
| 6736 | arch_ftrace_update_trampoline(ops); | 6806 | arch_ftrace_update_trampoline(ops); |
| | 6807 | if (ops->trampoline && ops->trampoline != trampoline && |
| | 6808 | (ops->flags & FTRACE_OPS_FL_ALLOC_TRAMP)) |
| | 6809 | ftrace_add_trampoline_to_kallsyms(ops); |
| 6737 | } | 6810 | } |
| 6738 | | 6811 | |
| 6739 | void ftrace_init_trace_array(struct trace_array *tr) | 6812 | void ftrace_init_trace_array(struct trace_array *tr) |