[PATCH] Updated KDB non Intel patch
Marc Esipovich
marc at mucom.co.il
Mon Apr 3 16:27:16 PDT 2000
I think the following feature could be useful to module programmers, it
adds the ability to list and unload kernel modules from within the
debugger.
Marc.
-------------- next part --------------
*** kdb.c.orig Sat Mar 18 11:27:13 2000
--- kdb.c Sun Mar 19 08:07:34 2000
***************
*** 26,31 ****
--- 26,38 ----
#include "kdbsupport.h"
#include "kdb_io.h"
+ /* For rmmod/lsmod */
+ #include <linux/module.h>
+ #include <linux/mm.h>
+ #include <asm/pgtable.h>
+ extern struct module *module_list;
+ extern void vfree(void * addr);
+
volatile int kdb_active = 0;
volatile int kdb_flags = 0;
spinlock_t kdb_lock = SPIN_LOCK_UNLOCKED;
*************** kdb(int reason, int error, struct pt_reg
*** 723,729 ****
}
if (reason != KDB_REASON_DEBUG) {
! kdb_printf("Entering kdb ");
#if defined(__SMP__)
kdb_printf("on processor %d ", smp_processor_id());
#endif
--- 730,736 ----
}
if (reason != KDB_REASON_DEBUG) {
! kdb_printf("\nEntering kdb ");
#if defined(__SMP__)
kdb_printf("on processor %d ", smp_processor_id());
#endif
*************** kdb(int reason, int error, struct pt_reg
*** 737,743 ****
*/
diag = kdb_db_trap(regs);
if (diag == 0) {
! kdb_printf("Entering kdb ");
#if defined(__SMP__)
kdb_printf("on processor %d ", smp_processor_id());
#endif
--- 744,750 ----
*/
diag = kdb_db_trap(regs);
if (diag == 0) {
! kdb_printf("\nEntering kdb ");
#if defined(__SMP__)
kdb_printf("on processor %d ", smp_processor_id());
#endif
*************** kdb_reboot(int argc, const char **argv,
*** 1380,1385 ****
--- 1387,1583 ----
return 0;
}
+
+ /*
+ * Taken directly from kernel/module.c
+ *
+ * Look for a module by name, ignoring modules marked for deletion.
+ */
+ static struct module *
+ find_module(const char *name)
+ {
+ struct module *mod;
+
+ for (mod = module_list; mod ; mod = mod->next) {
+ if (mod->flags & MOD_DELETED)
+ continue;
+ if (!strcmp(mod->name, name))
+ break;
+ }
+
+ return mod;
+ }
+
+ /*
+ * Free the given module.
+ */
+ static void
+ free_module(struct module *mod, int tag_freed)
+ {
+ struct module_ref *dep;
+ unsigned i;
+ #if defined(CONFIG_KDB)
+ struct module_symbol *s;
+ #endif
+
+ /* Let the module clean up. */
+
+ mod->flags |= MOD_DELETED;
+ if (mod->flags & MOD_RUNNING)
+ {
+ if(mod->cleanup)
+ mod->cleanup();
+ mod->flags &= ~MOD_RUNNING;
+ }
+ #if defined(CONFIG_KDB)
+ /*
+ * Remove symbols from kernel debugger
+ */
+ for(i=0,s=mod->syms; i<mod->nsyms; i++, s++){
+ kdbdelmodsym(s->name);
+ }
+ #endif
+
+ /* Remove the module from the dependency lists. */
+ for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
+ struct module_ref **pp;
+ for (pp = &dep->dep->refs; *pp != dep; pp = &(*pp)->next_ref)
+ continue;
+ *pp = dep->next_ref;
+ if (tag_freed && dep->dep->refs == NULL)
+ dep->dep->flags |= MOD_JUST_FREED;
+ }
+
+ /* And from the main module list. */
+ if (mod == module_list) {
+ module_list = mod->next;
+ } else {
+ struct module *p;
+ for (p = module_list; p->next != mod; p = p->next)
+ continue;
+ p->next = mod->next;
+ }
+
+ /* And free the memory. */
+ module_unmap(mod);
+ }
+
+ /*
+ * kdb_lsmod
+ *
+ * This function implements the 'lsmod' command. Lists currently
+ * loaded kernel modules.
+ *
+ * Mostly taken from userland lsmod.
+ *
+ * Inputs:
+ * argc argument count
+ * argv argument vector
+ * envp environment vector
+ * regs registers at time kdb was entered.
+ * Outputs:
+ * None.
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ * Locking:
+ * none.
+ * Remarks:
+ *
+ */
+
+ int
+ kdb_lsmod(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ struct module *mod;
+ struct module_ref *mr;
+
+ if (argc != 0)
+ return KDB_ARGCOUNT;
+
+ kdb_printf("Module Size Used by\n");
+ for (mod = module_list; mod && mod->next ;mod = mod->next) {
+ kdb_printf("%-20s%8lu%4ld ", mod->name, mod->size, mod->uc.usecount);
+
+ if (mod->flags & MOD_DELETED)
+ kdb_printf(" (deleted)");
+ else if (mod->flags & 64)
+ kdb_printf(" (initializing)");
+ else if (!(mod->flags & MOD_RUNNING))
+ kdb_printf(" (uninitialized)");
+ else {
+ if (mod->flags & MOD_AUTOCLEAN)
+ kdb_printf(" (autoclean)");
+ if (!(mod->flags & MOD_USED_ONCE))
+ kdb_printf(" (unused)");
+ }
+
+ if (mod->refs) {
+ int i = 0;
+
+ kdb_printf(" [ ");
+
+ mr = mod->refs;
+ while (mr) {
+ kdb_printf("%s ", mr->ref->name);
+ mr = mr->next_ref;
+ }
+
+ kdb_printf("]");
+ }
+
+ kdb_printf("\n");
+ }
+
+ return 0;
+ }
+
+ /*
+ * kdb_rmmod
+ *
+ * This function implements the 'rmmod' command. Removes a given
+ * kernel module.
+ *
+ * Inputs:
+ * argc argument count
+ * argv argument vector
+ * envp environment vector
+ * regs registers at time kdb was entered.
+ * Outputs:
+ * None.
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ * Locking:
+ * none.
+ * Remarks:
+ *
+ */
+
+ int
+ kdb_rmmod(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ struct module *mod;
+
+
+ if (argc != 1)
+ return KDB_ARGCOUNT;
+
+ kdb_printf("Attempting to remove module: [%s]\n", argv[1]);
+ if ((mod = find_module(argv[1])) == NULL) {
+ kdb_printf("Unable to find a module by that name\n");
+ return 0;
+ }
+
+ if (mod->refs != NULL || __MOD_IN_USE(mod)) {
+ kdb_printf("Module is in use, unable to unload\n");
+ return 0;
+ }
+
+ free_module(mod, 0);
+ kdb_printf("Module successfully unloaded\n");
+
+ return 0;
+ }
+
/*
* kdb_env
*
*************** kdb_inittab(void)
*** 1856,1861 ****
--- 2054,2061 ----
#endif /* __SMP__ */
kdb_register("ps", kdb_ps, "", "Display active task list", 0);
kdb_register("reboot", kdb_reboot, "", "Reboot the machine immediately", 0);
+ kdb_register("lsmod", kdb_lsmod, "", "List loaded kernel modules", 0);
+ kdb_register("rmmod", kdb_rmmod, "<modname>", "Remove given kernel module", 1);
#if defined(CONFIG_MAGIC_SYSRQ)
kdb_register("sr", kdb_sr, "<key>", "Magic SysRq key", 0);
#endif
More information about the kdb
mailing list