index.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Userspace indexing of printk formats
  4. */
  5. #include <linux/debugfs.h>
  6. #include <linux/module.h>
  7. #include <linux/printk.h>
  8. #include <linux/slab.h>
  9. #include <linux/string_helpers.h>
  10. #include "internal.h"
  11. extern struct pi_entry *__start_printk_index[];
  12. extern struct pi_entry *__stop_printk_index[];
  13. /* The base dir for module formats, typically debugfs/printk/index/ */
  14. static struct dentry *dfs_index;
  15. static struct pi_entry *pi_get_entry(const struct module *mod, loff_t pos)
  16. {
  17. struct pi_entry **entries;
  18. unsigned int nr_entries;
  19. #ifdef CONFIG_MODULES
  20. if (mod) {
  21. entries = mod->printk_index_start;
  22. nr_entries = mod->printk_index_size;
  23. } else
  24. #endif
  25. {
  26. /* vmlinux, comes from linker symbols */
  27. entries = __start_printk_index;
  28. nr_entries = __stop_printk_index - __start_printk_index;
  29. }
  30. if (pos >= nr_entries)
  31. return NULL;
  32. return entries[pos];
  33. }
  34. static void *pi_next(struct seq_file *s, void *v, loff_t *pos)
  35. {
  36. const struct module *mod = s->file->f_inode->i_private;
  37. struct pi_entry *entry = pi_get_entry(mod, *pos);
  38. (*pos)++;
  39. return entry;
  40. }
  41. static void *pi_start(struct seq_file *s, loff_t *pos)
  42. {
  43. /*
  44. * Make show() print the header line. Do not update *pos because
  45. * pi_next() still has to return the entry at index 0 later.
  46. */
  47. if (*pos == 0)
  48. return SEQ_START_TOKEN;
  49. return pi_next(s, NULL, pos);
  50. }
  51. /*
  52. * We need both ESCAPE_ANY and explicit characters from ESCAPE_SPECIAL in @only
  53. * because otherwise ESCAPE_NAP will cause double quotes and backslashes to be
  54. * ignored for quoting.
  55. */
  56. #define seq_escape_printf_format(s, src) \
  57. seq_escape_str(s, src, ESCAPE_ANY | ESCAPE_NAP | ESCAPE_APPEND, "\"\\")
  58. static int pi_show(struct seq_file *s, void *v)
  59. {
  60. const struct pi_entry *entry = v;
  61. int level = LOGLEVEL_DEFAULT;
  62. enum printk_info_flags flags = 0;
  63. u16 prefix_len = 0;
  64. if (v == SEQ_START_TOKEN) {
  65. seq_puts(s, "# <level/flags> filename:line function \"format\"\n");
  66. return 0;
  67. }
  68. if (!entry->fmt)
  69. return 0;
  70. if (entry->level)
  71. printk_parse_prefix(entry->level, &level, &flags);
  72. else
  73. prefix_len = printk_parse_prefix(entry->fmt, &level, &flags);
  74. if (flags & LOG_CONT) {
  75. /*
  76. * LOGLEVEL_DEFAULT here means "use the same level as the
  77. * message we're continuing from", not the default message
  78. * loglevel, so don't display it as such.
  79. */
  80. if (level == LOGLEVEL_DEFAULT)
  81. seq_puts(s, "<c>");
  82. else
  83. seq_printf(s, "<%d,c>", level);
  84. } else
  85. seq_printf(s, "<%d>", level);
  86. seq_printf(s, " %s:%d %s \"", entry->file, entry->line, entry->func);
  87. if (entry->subsys_fmt_prefix)
  88. seq_escape_printf_format(s, entry->subsys_fmt_prefix);
  89. seq_escape_printf_format(s, entry->fmt + prefix_len);
  90. seq_puts(s, "\"\n");
  91. return 0;
  92. }
  93. static void pi_stop(struct seq_file *p, void *v) { }
  94. static const struct seq_operations dfs_index_sops = {
  95. .start = pi_start,
  96. .next = pi_next,
  97. .show = pi_show,
  98. .stop = pi_stop,
  99. };
  100. DEFINE_SEQ_ATTRIBUTE(dfs_index);
  101. #ifdef CONFIG_MODULES
  102. static const char *pi_get_module_name(struct module *mod)
  103. {
  104. return mod ? mod->name : "vmlinux";
  105. }
  106. #else
  107. static const char *pi_get_module_name(struct module *mod)
  108. {
  109. return "vmlinux";
  110. }
  111. #endif
  112. static void pi_create_file(struct module *mod)
  113. {
  114. debugfs_create_file(pi_get_module_name(mod), 0444, dfs_index,
  115. mod, &dfs_index_fops);
  116. }
  117. #ifdef CONFIG_MODULES
  118. static void pi_remove_file(struct module *mod)
  119. {
  120. debugfs_lookup_and_remove(pi_get_module_name(mod), dfs_index);
  121. }
  122. static int pi_module_notify(struct notifier_block *nb, unsigned long op,
  123. void *data)
  124. {
  125. struct module *mod = data;
  126. switch (op) {
  127. case MODULE_STATE_COMING:
  128. pi_create_file(mod);
  129. break;
  130. case MODULE_STATE_GOING:
  131. pi_remove_file(mod);
  132. break;
  133. default: /* we don't care about other module states */
  134. break;
  135. }
  136. return NOTIFY_OK;
  137. }
  138. static struct notifier_block module_printk_fmts_nb = {
  139. .notifier_call = pi_module_notify,
  140. };
  141. static void __init pi_setup_module_notifier(void)
  142. {
  143. register_module_notifier(&module_printk_fmts_nb);
  144. }
  145. #else
  146. static inline void __init pi_setup_module_notifier(void) { }
  147. #endif
  148. static int __init pi_init(void)
  149. {
  150. struct dentry *dfs_root = debugfs_create_dir("printk", NULL);
  151. dfs_index = debugfs_create_dir("index", dfs_root);
  152. pi_setup_module_notifier();
  153. pi_create_file(NULL);
  154. return 0;
  155. }
  156. /* debugfs comes up on core and must be initialised first */
  157. postcore_initcall(pi_init);