bug.c 4.9 KB
Newer Older
1 2 3 4 5 6 7
/*
  Generic support for BUG()

  This respects the following config options:

  CONFIG_BUG - emit BUG traps.  Nothing happens without this.
  CONFIG_GENERIC_BUG - enable this code.
8 9
  CONFIG_GENERIC_BUG_RELATIVE_POINTERS - use 32-bit pointers relative to
	the containing struct bug_entry for bug_addr and file.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
  CONFIG_DEBUG_BUGVERBOSE - emit full file+line information for each BUG

  CONFIG_BUG and CONFIG_DEBUG_BUGVERBOSE are potentially user-settable
  (though they're generally always on).

  CONFIG_GENERIC_BUG is set by each architecture using this code.

  To use this, your architecture must:

  1. Set up the config options:
     - Enable CONFIG_GENERIC_BUG if CONFIG_BUG

  2. Implement BUG (and optionally BUG_ON, WARN, WARN_ON)
     - Define HAVE_ARCH_BUG
     - Implement BUG() to generate a faulting instruction
     - NOTE: struct bug_entry does not have "file" or "line" entries
       when CONFIG_DEBUG_BUGVERBOSE is not enabled, so you must generate
       the values accordingly.

  3. Implement the trap
     - In the illegal instruction trap handler (typically), verify
       that the fault was in kernel mode, and call report_bug()
     - report_bug() will return whether it was a false alarm, a warning,
       or an actual bug.
     - You must implement the is_valid_bugaddr(bugaddr) callback which
       returns true if the eip is a real kernel address, and it points
       to the expected BUG trap instruction.

    Jeremy Fitzhardinge <jeremy@goop.org> 2006
 */
40 41 42

#define pr_fmt(fmt) fmt

43 44
#include <linux/list.h>
#include <linux/module.h>
45
#include <linux/kernel.h>
46
#include <linux/bug.h>
47
#include <linux/sched.h>
48
#include <linux/rculist.h>
49

50
extern struct bug_entry __start___bug_table[], __stop___bug_table[];
51

52 53 54 55 56 57 58 59 60
static inline unsigned long bug_addr(const struct bug_entry *bug)
{
#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
	return bug->bug_addr;
#else
	return (unsigned long)bug + bug->bug_addr_disp;
#endif
}

61
#ifdef CONFIG_MODULES
62
/* Updates are protected by module mutex */
63 64
static LIST_HEAD(module_bug_list);

65
static struct bug_entry *module_find_bug(unsigned long bugaddr)
66 67
{
	struct module *mod;
68
	struct bug_entry *bug = NULL;
69

70
	rcu_read_lock_sched();
71
	list_for_each_entry_rcu(mod, &module_bug_list, bug_list) {
72 73
		unsigned i;

74
		bug = mod->bug_table;
75
		for (i = 0; i < mod->num_bugs; ++i, ++bug)
76
			if (bugaddr == bug_addr(bug))
77
				goto out;
78
	}
79 80
	bug = NULL;
out:
81
	rcu_read_unlock_sched();
82 83

	return bug;
84 85
}

86 87
void module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
			 struct module *mod)
88 89 90 91
{
	char *secstrings;
	unsigned int i;

92 93
	lockdep_assert_held(&module_mutex);

94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
	mod->bug_table = NULL;
	mod->num_bugs = 0;

	/* Find the __bug_table section, if present */
	secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
	for (i = 1; i < hdr->e_shnum; i++) {
		if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table"))
			continue;
		mod->bug_table = (void *) sechdrs[i].sh_addr;
		mod->num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);
		break;
	}

	/*
	 * Strictly speaking this should have a spinlock to protect against
	 * traversals, but since we only traverse on BUG()s, a spinlock
	 * could potentially lead to deadlock and thus be counter-productive.
111 112
	 * Thus, this uses RCU to safely manipulate the bug list, since BUG
	 * must run in non-interruptive state.
113
	 */
114
	list_add_rcu(&mod->bug_list, &module_bug_list);
115 116 117 118
}

void module_bug_cleanup(struct module *mod)
{
119
	lockdep_assert_held(&module_mutex);
120
	list_del_rcu(&mod->bug_list);
121 122 123 124
}

#else

125
static inline struct bug_entry *module_find_bug(unsigned long bugaddr)
126 127 128 129 130
{
	return NULL;
}
#endif

131
struct bug_entry *find_bug(unsigned long bugaddr)
132
{
133
	struct bug_entry *bug;
134 135

	for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
136
		if (bugaddr == bug_addr(bug))
137 138 139 140 141
			return bug;

	return module_find_bug(bugaddr);
}

142
enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
143
{
144
	struct bug_entry *bug;
145
	const char *file;
146
	unsigned line, warning, once, done;
147 148 149 150 151 152 153 154 155 156 157 158

	if (!is_valid_bugaddr(bugaddr))
		return BUG_TRAP_TYPE_NONE;

	bug = find_bug(bugaddr);

	file = NULL;
	line = 0;
	warning = 0;

	if (bug) {
#ifdef CONFIG_DEBUG_BUGVERBOSE
159
#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
160
		file = bug->file;
161 162 163
#else
		file = (const char *)bug + bug->file_disp;
#endif
164 165 166
		line = bug->line;
#endif
		warning = (bug->flags & BUGFLAG_WARNING) != 0;
167 168 169 170 171 172 173 174 175 176 177 178
		once = (bug->flags & BUGFLAG_ONCE) != 0;
		done = (bug->flags & BUGFLAG_DONE) != 0;

		if (warning && once) {
			if (done)
				return BUG_TRAP_TYPE_WARN;

			/*
			 * Since this is the only store, concurrency is not an issue.
			 */
			bug->flags |= BUGFLAG_DONE;
		}
179 180 181 182
	}

	if (warning) {
		/* this is a WARN_ON rather than BUG/BUG_ON */
183 184
		__warn(file, line, (void *)bugaddr, BUG_GET_TAINT(bug), regs,
		       NULL);
185 186 187
		return BUG_TRAP_TYPE_WARN;
	}

188
	printk(KERN_DEFAULT "------------[ cut here ]------------\n");
189

190
	if (file)
191
		pr_crit("kernel BUG at %s:%u!\n", file, line);
192
	else
193 194
		pr_crit("Kernel BUG at %p [verbose debug info unavailable]\n",
			(void *)bugaddr);
195 196 197

	return BUG_TRAP_TYPE_BUG;
}