--- ./ddb/db_command.c.orig 2008-08-19 00:56:41.000000000 +0200 +++ ./ddb/db_command.c 2008-08-24 20:59:41.000000000 +0200 @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -76,78 +77,68 @@ static db_cmdfcn_t db_watchdog; /* + * Array containing all command 'tables'. See ddb.h. + */ +static struct command_table db_command_tables[DB_COMMAND_TABLES_SIZE] = { + STAILQ_HEAD_INITIALIZER(db_command_tables[DB_COMMAND_TABLES_DEFAULT]), + STAILQ_HEAD_INITIALIZER(db_command_tables[DB_COMMAND_TABLES_SHOW]), + STAILQ_HEAD_INITIALIZER(db_command_tables[DB_COMMAND_TABLES_SHOW_ALL]) +}; + +/* * 'show' commands */ static struct command db_show_all_cmds[] = { - { "procs", db_ps, 0, 0 }, - { (char *)0 } -}; - -static struct command_table db_show_all_table = { - db_show_all_cmds + { { NULL }, "procs", db_ps, 0, 0 } }; static struct command db_show_cmds[] = { - { "all", 0, 0, &db_show_all_table }, - { "registers", db_show_regs, 0, 0 }, - { "breaks", db_listbreak_cmd, 0, 0 }, - { "threads", db_show_threads, 0, 0 }, - { (char *)0, } + { { NULL }, "all", 0, 0, &db_command_tables[DB_COMMAND_TABLES_SHOW_ALL] }, + { { NULL }, "registers", db_show_regs, 0, 0 }, + { { NULL }, "breaks", db_listbreak_cmd, 0, 0 }, + { { NULL }, "threads", db_show_threads, 0, 0 } }; -static struct command_table db_show_table = { - db_show_cmds, - SET_BEGIN(db_show_cmd_set), - SET_LIMIT(db_show_cmd_set) -}; - static struct command db_commands[] = { - { "print", db_print_cmd, 0, 0 }, - { "p", db_print_cmd, 0, 0 }, - { "examine", db_examine_cmd, CS_SET_DOT, 0 }, - { "x", db_examine_cmd, CS_SET_DOT, 0 }, - { "search", db_search_cmd, CS_OWN|CS_SET_DOT, 0 }, - { "set", db_set_cmd, CS_OWN, 0 }, - { "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, - { "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, - { "delete", db_delete_cmd, 0, 0 }, - { "d", db_delete_cmd, 0, 0 }, - { "break", db_breakpoint_cmd, 0, 0 }, - { "b", db_breakpoint_cmd, 0, 0 }, - { "dwatch", db_deletewatch_cmd, 0, 0 }, - { "watch", db_watchpoint_cmd, CS_MORE,0 }, - { "dhwatch", db_deletehwatch_cmd, 0, 0 }, - { "hwatch", db_hwatchpoint_cmd, 0, 0 }, - { "step", db_single_step_cmd, 0, 0 }, - { "s", db_single_step_cmd, 0, 0 }, - { "continue", db_continue_cmd, 0, 0 }, - { "c", db_continue_cmd, 0, 0 }, - { "until", db_trace_until_call_cmd,0, 0 }, - { "next", db_trace_until_matching_cmd,0, 0 }, - { "match", db_trace_until_matching_cmd,0, 0 }, - { "trace", db_stack_trace, CS_OWN, 0 }, - { "t", db_stack_trace, CS_OWN, 0 }, - { "alltrace", db_stack_trace_all, 0, 0 }, - { "where", db_stack_trace, CS_OWN, 0 }, - { "bt", db_stack_trace, CS_OWN, 0 }, - { "call", db_fncall, CS_OWN, 0 }, - { "show", 0, 0, &db_show_table }, - { "ps", db_ps, 0, 0 }, - { "gdb", db_gdb, 0, 0 }, - { "halt", db_halt, 0, 0 }, - { "reboot", db_reset, 0, 0 }, - { "reset", db_reset, 0, 0 }, - { "kill", db_kill, CS_OWN, 0 }, - { "watchdog", db_watchdog, 0, 0 }, - { "thread", db_set_thread, CS_OWN, 0 }, - { (char *)0, } -}; - -static struct command_table db_command_table = { - db_commands, - SET_BEGIN(db_cmd_set), - SET_LIMIT(db_cmd_set) + { { NULL }, "print", db_print_cmd, 0, 0 }, + { { NULL }, "p", db_print_cmd, 0, 0 }, + { { NULL }, "examine", db_examine_cmd, CS_SET_DOT, 0 }, + { { NULL }, "x", db_examine_cmd, CS_SET_DOT, 0 }, + { { NULL }, "search", db_search_cmd, CS_OWN|CS_SET_DOT, 0 }, + { { NULL }, "set", db_set_cmd, CS_OWN, 0 }, + { { NULL }, "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, + { { NULL }, "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, + { { NULL }, "delete", db_delete_cmd, 0, 0 }, + { { NULL }, "d", db_delete_cmd, 0, 0 }, + { { NULL }, "break", db_breakpoint_cmd, 0, 0 }, + { { NULL }, "b", db_breakpoint_cmd, 0, 0 }, + { { NULL }, "dwatch", db_deletewatch_cmd, 0, 0 }, + { { NULL }, "watch", db_watchpoint_cmd, CS_MORE,0 }, + { { NULL }, "dhwatch", db_deletehwatch_cmd, 0, 0 }, + { { NULL }, "hwatch", db_hwatchpoint_cmd, 0, 0 }, + { { NULL }, "step", db_single_step_cmd, 0, 0 }, + { { NULL }, "s", db_single_step_cmd, 0, 0 }, + { { NULL }, "continue", db_continue_cmd, 0, 0 }, + { { NULL }, "c", db_continue_cmd, 0, 0 }, + { { NULL }, "until", db_trace_until_call_cmd,0, 0 }, + { { NULL }, "next", db_trace_until_matching_cmd,0, 0 }, + { { NULL }, "match", db_trace_until_matching_cmd,0, 0 }, + { { NULL }, "trace", db_stack_trace, CS_OWN, 0 }, + { { NULL }, "t", db_stack_trace, CS_OWN, 0 }, + { { NULL }, "alltrace", db_stack_trace_all, 0, 0 }, + { { NULL }, "where", db_stack_trace, CS_OWN, 0 }, + { { NULL }, "bt", db_stack_trace, CS_OWN, 0 }, + { { NULL }, "call", db_fncall, CS_OWN, 0 }, + { { NULL }, "show", 0, 0, &db_command_tables[DB_COMMAND_TABLES_SHOW] }, + { { NULL }, "ps", db_ps, 0, 0 }, + { { NULL }, "gdb", db_gdb, 0, 0 }, + { { NULL }, "halt", db_halt, 0, 0 }, + { { NULL }, "reboot", db_reset, 0, 0 }, + { { NULL }, "reset", db_reset, 0, 0 }, + { { NULL }, "kill", db_kill, CS_OWN, 0 }, + { { NULL }, "watchdog", db_watchdog, 0, 0 }, + { { NULL }, "thread", db_set_thread, CS_OWN, 0 } }; static struct command *db_last_command = 0; @@ -189,6 +180,73 @@ struct command_table *cmd_table); /* + * Initialize command tables using the commands declared above. + */ +void +db_cmd_init() +{ + int cnt; + + for (cnt=0; cnt<(sizeof(db_commands) / sizeof(struct command)); cnt++) + STAILQ_INSERT_TAIL(&db_command_tables[DB_COMMAND_TABLES_DEFAULT], + &(db_commands[cnt]), + next); + for (cnt=0; cnt<(sizeof(db_show_cmds) / sizeof(struct command)); cnt++) + STAILQ_INSERT_TAIL(&db_command_tables[DB_COMMAND_TABLES_SHOW], + &(db_show_cmds[cnt]), + next); + for (cnt=0; cnt<(sizeof(db_show_all_cmds) / sizeof(struct command)); cnt++) + STAILQ_INSERT_TAIL(&db_command_tables[DB_COMMAND_TABLES_SHOW_ALL], + &(db_show_all_cmds[cnt]), + next); +} + +/* + * Called by modules through SYSINIT to extend the command set. + */ +void db_command_register(list_index, cmd) + int list_index; + struct command *cmd; +{ + if (list_index >= DB_COMMAND_TABLES_SIZE) + panic("Attempting to add a debugger command to an invalid list!"); + +#if 0 + /* Check that the command is not already present. */ + struct command *scmd; + STAILQ_FOREACH(scmd, &(db_command_tables[list_index]), next) { + if (!strcmp(cmd->name, scmd->name)) + panic("The command %s already exists!", cmd->name); + } +#endif + + if (cmd != NULL) { + STAILQ_INSERT_TAIL(&(db_command_tables[list_index]), + cmd, next); + } +} + +/* + * Called by SYSUNINIT. Revert what has been done above. + */ +void db_command_unregister(table_index, command_name) + int table_index; + char *command_name; +{ + struct command *cmd; + + STAILQ_FOREACH(cmd, &(db_command_tables[table_index]), next) { + if (!strcmp(command_name,cmd->name)) { + STAILQ_REMOVE(&(db_command_tables[table_index]), + cmd, + command, + next); + break; + } + } +} + +/* * Helper function to match a single command. */ static void @@ -236,23 +294,15 @@ struct command_table *table; struct command **cmdp; /* out */ { - struct command *cmd; - struct command **aux_cmdp; - int result = CMD_NONE; + struct command *cmd; + int result = CMD_NONE; - for (cmd = table->table; cmd->name != 0; cmd++) { - db_cmd_match(name, cmd, cmdp, &result); + STAILQ_FOREACH(cmd,table,next) { + db_cmd_match(name,cmd,cmdp,&result); if (result == CMD_UNIQUE) - return (CMD_UNIQUE); + break; } - if (table->aux_tablep != NULL) - for (aux_cmdp = table->aux_tablep; - aux_cmdp < table->aux_tablep_end; - aux_cmdp++) { - db_cmd_match(name, *aux_cmdp, cmdp, &result); - if (result == CMD_UNIQUE) - return (CMD_UNIQUE); - } + if (result == CMD_NONE) { /* check for 'help' */ if (name[0] == 'h' && name[1] == 'e' @@ -266,19 +316,11 @@ db_cmd_list(table) struct command_table *table; { - register struct command *cmd; - register struct command **aux_cmdp; + register struct command *cmd; - for (cmd = table->table; cmd->name != 0; cmd++) { - db_printf("%-12s", cmd->name); - db_end_line(12); - } - if (table->aux_tablep == NULL) - return; - for (aux_cmdp = table->aux_tablep; aux_cmdp < table->aux_tablep_end; - aux_cmdp++) { - db_printf("%-12s", (*aux_cmdp)->name); - db_end_line(12); + STAILQ_FOREACH(cmd, table, next) { + db_printf("%-12s", cmd->name); + db_end_line(12); } } @@ -287,7 +329,7 @@ struct command **last_cmdp; /* IN_OUT */ struct command_table *cmd_table; { - struct command *cmd; + struct command *cmd = NULL; int t; char modif[TOK_STRING_SIZE]; db_expr_t addr, count; @@ -450,7 +492,7 @@ db_printf("db> "); (void) db_read_line(); - db_command(&db_last_command, &db_command_table); + db_command(&db_last_command, &(db_command_tables[DB_COMMAND_TABLES_DEFAULT])); } } --- ./ddb/ddb.h.orig 2008-08-19 01:04:24.000000000 +0200 +++ ./ddb/ddb.h 2008-08-23 21:53:28.000000000 +0200 @@ -39,6 +39,9 @@ #include /* type definitions */ +#include /* STAILQ_* */ +#include /* SYSINIT */ + #ifndef DB_MAXARGS #define DB_MAXARGS 10 #endif @@ -53,23 +56,38 @@ char *modif); #define DB_COMMAND(cmd_name, func_name) \ - DB_FUNC(cmd_name, func_name, db_cmd_set, 0, NULL) + DB_FUNC(cmd_name, func_name, DB_COMMAND_TABLES_DEFAULT, 0, NULL) #define DB_SHOW_COMMAND(cmd_name, func_name) \ - DB_FUNC(cmd_name, func_name, db_show_cmd_set, 0, NULL) + DB_FUNC(cmd_name, func_name, DB_COMMAND_TABLES_SHOW, 0, NULL) +#define DB_SHOW_ALL_COMMAND(cmd_name, func_name) \ + DB_FUNC(cmd_name, func_name, DB_COMMAND_TABLES_SHOW_ALL, 0, NULL) -#define DB_SET(cmd_name, func_name, set, flag, more) \ -static const struct command __CONCAT(cmd_name,_cmd) = { \ - __STRING(cmd_name), \ - func_name, \ - flag, \ - more \ -}; \ -TEXT_SET(set, __CONCAT(cmd_name,_cmd)) +/* + * At the moment, there are three command "tables" on the system: + * - One for simple commands, whose list one can get by typing 'help' + * at debugger prompt. + * - One for sub-commands of 'show'. + * - The last one for sub-commands of 'show all'. + * All these tables are stored in an array, and the constants defined + * hereafter give the offset in the array at which the head for each + * table can be found. + */ +enum { + DB_COMMAND_TABLES_DEFAULT, + DB_COMMAND_TABLES_SHOW, + DB_COMMAND_TABLES_SHOW_ALL, + DB_COMMAND_TABLES_SIZE +}; + +struct command; -#define DB_FUNC(cmd_name, func_name, set, flag, more) \ +/* + * Declare the function func_name, which is handling db command + * cmd_name) + */ +#define DB_FUNC(cmd_name, func_name, list, flag, more) \ static db_cmdfcn_t func_name; \ - \ -DB_SET(cmd_name, func_name, set, flag, more); \ +DB_SET(cmd_name, func_name, list, flag, more); \ \ static void \ func_name(addr, have_addr, count, modif) \ @@ -78,6 +96,35 @@ db_expr_t count; \ char *modif; +/* + * Add command 'cmd_name' to the command table, along + * with the SYSINIT functions to load and unload it. + */ +#define DB_SET(cmd_name, func_name, list, flag, more) \ +static struct command __CONCAT(cmd_name,_cmd) = { \ + { NULL }, \ + __STRING(cmd_name), \ + func_name, \ + flag, \ + more \ +}; \ + \ +static void __CONCAT(cmd_name,_db_cmd_add)(void*); \ +static void __CONCAT(cmd_name,_db_cmd_rm)(void*); \ + \ +static void __CONCAT(cmd_name,_db_cmd_add)(void *arg __unused) \ +{ \ + db_command_register(list, &__CONCAT(cmd_name,_cmd)); \ +} \ + \ +static void __CONCAT(cmd_name,_db_cmd_rm)(void *arg __unused) \ +{ \ + db_command_unregister(list,__STRING(cmd_name)); \ +} \ + \ +SYSINIT(cmd_name, SI_SUB_KLD, SI_ORDER_ANY, __CONCAT(cmd_name,_db_cmd_add), NULL); \ +SYSUNINIT(cmd_name, SI_SUB_KLD, SI_ORDER_ANY, __CONCAT(cmd_name,_db_cmd_rm), NULL); + extern db_expr_t db_maxoff; extern int db_indent; extern int db_inst_count; @@ -124,6 +171,9 @@ int db_trace_thread(struct thread *, int); int db_value_of_name(const char *name, db_expr_t *valuep); int db_write_bytes(vm_offset_t addr, size_t size, char *data); +void db_cmd_init(void); +void db_command_register(int, struct command *); +void db_command_unregister(int, char *); db_cmdfcn_t db_breakpoint_cmd; db_cmdfcn_t db_continue_cmd; @@ -147,17 +197,17 @@ db_cmdfcn_t db_write_cmd; /* - * Command table. + * Declare command table type. It is actually a linked list, so + * as to allow for runtime extensions to the table. */ -struct command; - -struct command_table { - struct command *table; - struct command **aux_tablep; - struct command **aux_tablep_end; -}; +STAILQ_HEAD(command_table, command); +/* + * Command table entry. + */ struct command { + STAILQ_ENTRY(command) /* Pointer to the next entry in the */ + next; /* command table */ char * name; /* command name */ db_cmdfcn_t *fcn; /* function to call */ int flag; /* extra info: */ --- ./ddb/db_main.c.orig 2008-08-20 00:35:51.000000000 +0200 +++ ./ddb/db_main.c 2008-08-20 00:36:37.000000000 +0200 @@ -182,6 +182,8 @@ } } db_add_symbol_table(NULL, NULL, "kld", NULL); + + db_cmd_init(); return (1); /* We're the default debugger. */ } --- ./dev/aic7xxx/aic79xx_osm.c.orig 2008-08-21 02:42:04.000000000 +0200 +++ ./dev/aic7xxx/aic79xx_osm.c 2008-08-21 02:42:33.000000000 +0200 @@ -1423,7 +1423,7 @@ } } -DB_FUNC(ahd_out, ahd_ddb_out, db_cmd_set, CS_MORE, NULL) +DB_FUNC(ahd_out, ahd_ddb_out, DB_COMMAND_TABLES_DEFAULT, CS_MORE, NULL) { db_expr_t old_value; db_expr_t new_value; --- ./gnu/fs/xfs/FreeBSD/support/kdb.c.orig 2008-08-24 16:47:00.000000000 +0200 +++ ./gnu/fs/xfs/FreeBSD/support/kdb.c 2008-08-24 16:47:30.000000000 +0200 @@ -12,7 +12,7 @@ #include #ifdef DDB -DB_FUNC(xfs, xfs_ddb_cmd, db_cmd_set, CS_MORE, NULL) +DB_FUNC(xfs, xfs_ddb_cmd, DB_COMMAND_TABLES_DEFAULT, CS_MORE, NULL) { db_error("No commands registered.\n"); } --- ./kern/subr_sleepqueue.c.orig 2008-08-23 15:54:34.000000000 +0200 +++ ./kern/subr_sleepqueue.c 2008-08-21 21:49:13.000000000 +0200 @@ -983,5 +983,5 @@ } /* Alias 'show sleepqueue' to 'show sleepq'. */ -DB_SET(sleepqueue, db_show_sleepqueue, db_show_cmd_set, 0, NULL); +DB_SET(sleepqueue, db_show_sleepqueue, DB_COMMAND_TABLES_SHOW, 0, NULL); #endif