module: trim exception table on init free.
[sfrench/cifs-2.6.git] / arch / sparc / mm / extable.c
index 16cc28935e398ede97a7e86fff652656bd042d21..a61c349448e1e12b28621b3590553593f2d3b799 100644 (file)
@@ -28,6 +28,10 @@ search_extable(const struct exception_table_entry *start,
         *      word 3: last insn address + 4 bytes
         *      word 4: fixup code address
         *
+        * Deleted entries are encoded as:
+        *      word 1: unused
+        *      word 2: -1
+        *
         * See asm/uaccess.h for more details.
         */
 
@@ -39,6 +43,10 @@ search_extable(const struct exception_table_entry *start,
                        continue;
                }
 
+               /* A deleted entry; see trim_init_extable */
+               if (walk->fixup == -1)
+                       continue;
+
                if (walk->insn == value)
                        return walk;
        }
@@ -57,6 +65,27 @@ search_extable(const struct exception_table_entry *start,
         return NULL;
 }
 
+#ifdef CONFIG_MODULES
+/* We could memmove them around; easier to mark the trimmed ones. */
+void trim_init_extable(struct module *m)
+{
+       unsigned int i;
+       bool range;
+
+       for (i = 0; i < m->num_exentries; i += range ? 2 : 1) {
+               range = m->extable[i].fixup == 0;
+
+               if (within_module_init(m->extable[i].insn, m)) {
+                       m->extable[i].fixup = -1;
+                       if (range)
+                               m->extable[i+1].fixup = -1;
+               }
+               if (range)
+                       i++;
+       }
+}
+#endif /* CONFIG_MODULES */
+
 /* Special extable search, which handles ranges.  Returns fixup */
 unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
 {