History

ftrace: Add symbols for ftrace trampolines

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.

Adrian Hunter committed 6 years ago

Commit fc0ea791 parent 3e46bb43 files · +88 −6Browse files

Unified · Split

3 files
  1. include/linux/ftrace.h +8 −4
  2. kernel/kallsyms.c +5 −0
  3. kernel/trace/ftrace.c +75 −2
include/linux/ftrace.h+8−4
@@ -58,9 +58,6 @@ struct ftrace_direct_func; · 57 unmodified lines
58const char *58const char *
59ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,59ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
60 unsigned long *off, char **modname, char *sym);60 unsigned long *off, char **modname, char *sym);
61int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value,
62 char *type, char *name,
63 char *module_name, int *exported);
64#else61#else
65static inline const char *62static inline const char *
66ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,63ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
@@ -68,6 +65,13 @@ ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, · 1 unmodified line
68{65{
69 return NULL;66 return NULL;
70}67}
68#endif
69
70#if defined(CONFIG_FUNCTION_TRACER) && defined(CONFIG_DYNAMIC_FTRACE)
71int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value,
72 char *type, char *name,
73 char *module_name, int *exported);
74#else
71static inline int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value,75static inline int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value,
72 char *type, char *name,76 char *type, char *name,
73 char *module_name, int *exported)77 char *module_name, int *exported)
@@ -76,7 +80,6 @@ static inline int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *val · 2 unmodified lines
76}80}
77#endif81#endif
78 82
79
80#ifdef CONFIG_FUNCTION_TRACER83#ifdef CONFIG_FUNCTION_TRACER
81 84
82extern int ftrace_enabled;85extern int ftrace_enabled;
@@ -207,6 +210,7 @@ struct ftrace_ops { · 124 unmodified lines
207 struct ftrace_ops_hash old_hash;210 struct ftrace_ops_hash old_hash;
208 unsigned long trampoline;211 unsigned long trampoline;
209 unsigned long trampoline_size;212 unsigned long trampoline_size;
213 struct list_head list;
210#endif214#endif
211};215};
212 216
kernel/kallsyms.c+5−0
@@ -482,6 +482,11 @@ static int get_ksymbol_mod(struct kallsym_iter *iter) · 481 unmodified lines
482 return 1;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 */
485static int get_ksymbol_ftrace_mod(struct kallsym_iter *iter)490static int get_ksymbol_ftrace_mod(struct kallsym_iter *iter)
486{491{
487 int ret = ftrace_mod_get_kallsym(iter->pos - iter->pos_mod_end,492 int ret = ftrace_mod_get_kallsym(iter->pos - iter->pos_mod_end,
kernel/trace/ftrace.c+75−2
@@ -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 */
2768static LIST_HEAD(ftrace_ops_trampoline_list);
2769
2770static 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
2776static 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
2790static 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
2767static void ftrace_startup_enable(int command)2799static 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
6213static 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_MODULES6234#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#else6603#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}
6612int 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
6558struct ftrace_init_func {6626struct ftrace_init_func {
@@ -6733,7 +6801,12 @@ void __weak arch_ftrace_update_trampoline(struct ftrace_ops *ops) · 174 unmodified lines
6733 6801
6734static void ftrace_update_trampoline(struct ftrace_ops *ops)6802static 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
6739void ftrace_init_trace_array(struct trace_array *tr)6812void ftrace_init_trace_array(struct trace_array *tr)