Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2   Generic support for BUG()
  3 
  4   This respects the following config options:
  5 
  6   CONFIG_BUG - emit BUG traps.  Nothing happens without this.
  7   CONFIG_GENERIC_BUG - enable this code.
  8   CONFIG_DEBUG_BUGVERBOSE - emit full file+line information for each BUG
  9 
 10   CONFIG_BUG and CONFIG_DEBUG_BUGVERBOSE are potentially user-settable
 11   (though they're generally always on).
 12 
 13   CONFIG_GENERIC_BUG is set by each architecture using this code.
 14 
 15   To use this, your architecture must:
 16 
 17   1. Set up the config options:
 18      - Enable CONFIG_GENERIC_BUG if CONFIG_BUG
 19 
 20   2. Implement BUG (and optionally BUG_ON, WARN, WARN_ON)
 21      - Define HAVE_ARCH_BUG
 22      - Implement BUG() to generate a faulting instruction
 23      - NOTE: struct bug_entry does not have "file" or "line" entries
 24        when CONFIG_DEBUG_BUGVERBOSE is not enabled, so you must generate
 25        the values accordingly.
 26 
 27   3. Implement the trap
 28      - In the illegal instruction trap handler (typically), verify
 29        that the fault was in kernel mode, and call report_bug()
 30      - report_bug() will return whether it was a false alarm, a warning,
 31        or an actual bug.
 32      - You must implement the is_valid_bugaddr(bugaddr) callback which
 33        returns true if the eip is a real kernel address, and it points
 34        to the expected BUG trap instruction.
 35 
 36     Jeremy Fitzhardinge <jeremy@goop.org> 2006
 37  */
 38 #include <linux/list.h>
 39 #include <linux/module.h>
 40 #include <linux/bug.h>
 41 #include <linux/sched.h>
 42 
 43 extern const struct bug_entry __start___bug_table[], __stop___bug_table[];
 44 
 45 #ifdef CONFIG_MODULES
 46 static LIST_HEAD(module_bug_list);
 47 
 48 static const struct bug_entry *module_find_bug(unsigned long bugaddr)
 49 {
 50         struct module *mod;
 51 
 52         list_for_each_entry(mod, &module_bug_list, bug_list) {
 53                 const struct bug_entry *bug = mod->bug_table;
 54                 unsigned i;
 55 
 56                 for (i = 0; i < mod->num_bugs; ++i, ++bug)
 57                         if (bugaddr == bug->bug_addr)
 58                                 return bug;
 59         }
 60         return NULL;
 61 }
 62 
 63 int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
 64                         struct module *mod)
 65 {
 66         char *secstrings;
 67         unsigned int i;
 68 
 69         mod->bug_table = NULL;
 70         mod->num_bugs = 0;
 71 
 72         /* Find the __bug_table section, if present */
 73         secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
 74         for (i = 1; i < hdr->e_shnum; i++) {
 75                 if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table"))
 76                         continue;
 77                 mod->bug_table = (void *) sechdrs[i].sh_addr;
 78                 mod->num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);
 79                 break;
 80         }
 81 
 82         /*
 83          * Strictly speaking this should have a spinlock to protect against
 84          * traversals, but since we only traverse on BUG()s, a spinlock
 85          * could potentially lead to deadlock and thus be counter-productive.
 86          */
 87         list_add(&mod->bug_list, &module_bug_list);
 88 
 89         return 0;
 90 }
 91 
 92 void module_bug_cleanup(struct module *mod)
 93 {
 94         list_del(&mod->bug_list);
 95 }
 96 
 97 #else
 98 
 99 static inline const struct bug_entry *module_find_bug(unsigned long bugaddr)
100 {
101         return NULL;
102 }
103 #endif
104 
105 const struct bug_entry *find_bug(unsigned long bugaddr)
106 {
107         const struct bug_entry *bug;
108 
109         for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
110                 if (bugaddr == bug->bug_addr)
111                         return bug;
112 
113         return module_find_bug(bugaddr);
114 }
115 
116 enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
117 {
118         const struct bug_entry *bug;
119         const char *file;
120         unsigned line, warning;
121 
122         if (!is_valid_bugaddr(bugaddr))
123                 return BUG_TRAP_TYPE_NONE;
124 
125         bug = find_bug(bugaddr);
126 
127         printk(KERN_EMERG "------------[ cut here ]------------\n");
128 
129         file = NULL;
130         line = 0;
131         warning = 0;
132 
133         if (bug) {
134 #ifdef CONFIG_DEBUG_BUGVERBOSE
135                 file = bug->file;
136                 line = bug->line;
137 #endif
138                 warning = (bug->flags & BUGFLAG_WARNING) != 0;
139         }
140 
141         if (warning) {
142                 /* this is a WARN_ON rather than BUG/BUG_ON */
143                 if (file)
144                         printk(KERN_ERR "Badness at %s:%u\n",
145                                file, line);
146                 else
147                         printk(KERN_ERR "Badness at %p "
148                                "[verbose debug info unavailable]\n",
149                                (void *)bugaddr);
150 
151                 show_regs(regs);
152                 return BUG_TRAP_TYPE_WARN;
153         }
154 
155         if (file)
156                 printk(KERN_CRIT "kernel BUG at %s:%u!\n",
157                        file, line);
158         else
159                 printk(KERN_CRIT "Kernel BUG at %p "
160                        "[verbose debug info unavailable]\n",
161                        (void *)bugaddr);
162 
163         return BUG_TRAP_TYPE_BUG;
164 }
165 
  This page was automatically generated by the LXR engine.