LCOV - code coverage report
Current view: top level - lib - bug.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 44 0.0 %
Date: 2014-02-18 Functions: 0 4 0.0 %
Branches: 0 24 0.0 %

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

Generated by: LCOV version 1.9