[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