Symbols are needed for tools to describe instruction addresses. Pages allocated for ftrace's purposes need symbols to be created for them. Add such symbols to be visible via /proc/kallsyms. Example on x86 with CONFIG_DYNAMIC_FTRACE=y # echo function > /sys/kernel/debug/tracing/current_tracer # cat /proc/kallsyms | grep '\[__builtin__ftrace\]' ffffffffc0238000 t ftrace_trampoline [__builtin__ftrace] Note: This patch adds "__builtin__ftrace" as a module name in /proc/kallsyms for symbols for pages allocated for ftrace's purposes, even though "__builtin__ftrace" is not a module.
Showing the changes to kernel (2 of 3 files). Show all
Unified · Split
| @@ -482,6 +482,11 @@ static int get_ksymbol_mod(struct kallsym_iter *iter) · 481 unmodified lines | ||
| 482 | 482 | return 1; |
| 483 | 483 | } |
| 484 | 484 | |
| 485 | +/* | |
| 486 | + * ftrace_mod_get_kallsym() may also get symbols for pages allocated for ftrace | |
| 487 | + * purposes. In that case "__builtin__ftrace" is used as a module name, even | |
| 488 | + * though "__builtin__ftrace" is not a module. | |
| 489 | + */ | |
| 485 | 490 | static int get_ksymbol_ftrace_mod(struct kallsym_iter *iter) |
| 486 | 491 | { |
| 487 | 492 | int ret = ftrace_mod_get_kallsym(iter->pos - iter->pos_mod_end, |
| @@ -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 | 2799 | static void ftrace_startup_enable(int command) |
| 2768 | 2800 | { |
| 2769 | 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 | 2966 | synchronize_rcu_tasks(); |
| 2935 | 2967 | |
| 2936 | 2968 | free_ops: |
| 2937 | − arch_ftrace_trampoline_free(ops); | |
| 2969 | + ftrace_trampoline_free(ops); | |
| 2938 | 2970 | } |
| 2939 | 2971 | |
| 2940 | 2972 | return 0; |
| @@ -6178,6 +6210,27 @@ struct ftrace_mod_map { · 3237 unmodified lines | ||
| 6178 | 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 | 6234 | #ifdef CONFIG_MODULES |
| 6182 | 6235 | |
| 6183 | 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 | 6568 | struct ftrace_mod_map *mod_map; |
| 6516 | 6569 | struct ftrace_mod_func *mod_func; |
| 6570 | + int ret; | |
| 6517 | 6571 | |
| 6518 | 6572 | preempt_disable(); |
| 6519 | 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 | 6594 | WARN_ON(1); |
| 6541 | 6595 | break; |
| 6542 | 6596 | } |
| 6597 | + ret = ftrace_get_trampoline_kallsym(symnum, value, type, name, | |
| 6598 | + module_name, exported); | |
| 6543 | 6599 | preempt_enable(); |
| 6544 | − return -ERANGE; | |
| 6600 | + return ret; | |
| 6545 | 6601 | } |
| 6546 | 6602 | |
| 6547 | 6603 | #else |
| @@ -6553,6 +6609,18 @@ allocate_ftrace_mod_map(struct module *mod, · 5 unmodified lines | ||
| 6553 | 6609 | { |
| 6554 | 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 | 6624 | #endif /* CONFIG_MODULES */ |
| 6557 | 6625 | |
| 6558 | 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 | 6802 | static void ftrace_update_trampoline(struct ftrace_ops *ops) |
| 6735 | 6803 | { |
| 6804 | + unsigned long trampoline = ops->trampoline; | |
| 6805 | + | |
| 6736 | 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 | 6812 | void ftrace_init_trace_array(struct trace_array *tr) |