KGDB/KDB fixes and cleanups

Cleanups
    Clean up compile warnings in kgdboc.c and x86/kernel/kgdb.c
    Add module event hooks for simplified debugging with gdb
  Fixes
    Fix kdb to stop paging with 'q' on bta and dmesg
    Fix for data that scrolls off the vga console due to line wrapping
      when using the kdb pager
  New
    The debug core registers for kernel module events which allows a
      kernel aware gdb to automatically load symbols and break on entry
      to a kernel module
    Allow kgdboc=kdb to setup kdb on the vga console
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJQeB8KAAoJEIciOldedpOjpbIP/j+LXEkzXKKfi/3m79VQ87DB
 5iUmTS84t84pomHamXX175AC0gA/2mC0FbbcHpqjlhxF4awXcviCNIiTdtSOTbbu
 G102naLHY8i77X+XbHuN2utJeaRLw8rsfMMZGmjJnjfpc4LtsaH0YTkUzbt3qvba
 N6/QvknadzIrmoCJvHipdOdsSmL0YmTS22+koG4es9B5jvOqVH/W7jZs1qRlVw96
 VxG5Psx4LPB+RI+ZwF1WwbGxbtqKGwkVvkcGG1XIW7FQojHmjw+vUERQCjoFueJ5
 NkKfus98j85/+MvSTkWx3L1K46MHMCFbtJs9RWftJ8GtoNNnm7GDxasoIG2bJKyG
 HFD3IGPuKAokE/equF3eGTRHeEM0IUGwT3EnBqdKd73zud27WsHaSqC/1CPR+74v
 ojLQ2ft1QF+pEkGrhRTdQpLyVnvEmxu8q+j9z9n/HlGEVv8kZ6LGxDPjWB+um/Yi
 Cs0XAryYrL5gE5O+Vwna61luughtIYJwR7+DeVxnQYJ43x/0MtN/SoURnwvrCTEo
 9FeoMgZm1nLh6EW29ahIT/hMu4f0sM91Kiwrmc/zEWZgoB++wo1n470qQmUUrOx4
 CPD7zdmDrf6YxDG2QTHjCtVErO4aJ5zN4Dq0+YyodV545SZVn3t4qBDTVvKhq4Y6
 NIhZAxrv5RKABwtLcP9E
 =uf0L
 -----END PGP SIGNATURE-----

Merge tag 'for_linus-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb

Pull KGDB/KDB fixes and cleanups from Jason Wessel:
 "Cleanups
   - Clean up compile warnings in kgdboc.c and x86/kernel/kgdb.c
   - Add module event hooks for simplified debugging with gdb
 Fixes
   - Fix kdb to stop paging with 'q' on bta and dmesg
   - Fix for data that scrolls off the vga console due to line wrapping
     when using the kdb pager
 New
   - The debug core registers for kernel module events which allows a
     kernel aware gdb to automatically load symbols and break on entry
     to a kernel module
   - Allow kgdboc=kdb to setup kdb on the vga console"

* tag 'for_linus-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb:
  tty/console: fix warnings in drivers/tty/serial/kgdboc.c
  kdb,vt_console: Fix missed data due to pager overruns
  kdb: Fix dmesg/bta scroll to quit with 'q'
  kgdboc: Accept either kbd or kdb to activate the vga + keyboard kdb shell
  kgdb,x86: fix warning about unused variable
  mips,kgdb: fix recursive page fault with CONFIG_KPROBES
  kgdb: Add module event hooks
This commit is contained in:
Linus Torvalds 2012-10-13 11:16:58 +09:00
commit 6c536a17fa
9 changed files with 84 additions and 8 deletions

View File

@ -283,6 +283,15 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
struct pt_regs *regs = args->regs;
int trap = (regs->cp0_cause & 0x7c) >> 2;
#ifdef CONFIG_KPROBES
/*
* Return immediately if the kprobes fault notifier has set
* DIE_PAGE_FAULT.
*/
if (cmd == DIE_PAGE_FAULT)
return NOTIFY_DONE;
#endif /* CONFIG_KPROBES */
/* Userspace events, ignore. */
if (user_mode(regs))
return NOTIFY_DONE;

View File

@ -746,7 +746,9 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
{
int err;
#ifdef CONFIG_DEBUG_RODATA
char opc[BREAK_INSTR_SIZE];
#endif /* CONFIG_DEBUG_RODATA */
bpt->type = BP_BREAKPOINT;
err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,

View File

@ -97,7 +97,8 @@ static void kgdboc_restore_input(void)
static int kgdboc_register_kbd(char **cptr)
{
if (strncmp(*cptr, "kbd", 3) == 0) {
if (strncmp(*cptr, "kbd", 3) == 0 ||
strncmp(*cptr, "kdb", 3) == 0) {
if (kdb_poll_idx < KDB_POLL_FUNC_MAX) {
kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char;
kdb_poll_idx++;

View File

@ -3442,6 +3442,19 @@ int con_debug_enter(struct vc_data *vc)
kdb_set(2, setargs);
}
}
if (vc->vc_cols < 999) {
int colcount;
char cols[4];
const char *setargs[3] = {
"set",
"COLUMNS",
cols,
};
if (kdbgetintenv(setargs[0], &colcount)) {
snprintf(cols, 4, "%i", vc->vc_cols);
kdb_set(2, setargs);
}
}
#endif /* CONFIG_KGDB_KDB */
return ret;
}

View File

@ -83,8 +83,14 @@ void give_up_console(const struct consw *sw);
int con_debug_enter(struct vc_data *vc);
int con_debug_leave(void);
#else
#define con_debug_enter(vc) (0)
#define con_debug_leave() (0)
static inline int con_debug_enter(struct vc_data *vc)
{
return 0;
}
static inline int con_debug_leave(void)
{
return 0;
}
#endif
/* scroll */

View File

@ -696,6 +696,22 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
return ret;
}
/*
* GDB places a breakpoint at this function to know dynamically
* loaded objects. It's not defined static so that only one instance with this
* name exists in the kernel.
*/
static int module_event(struct notifier_block *self, unsigned long val,
void *data)
{
return 0;
}
static struct notifier_block dbg_module_load_nb = {
.notifier_call = module_event,
};
int kgdb_nmicallback(int cpu, void *regs)
{
#ifdef CONFIG_SMP
@ -824,6 +840,7 @@ static void kgdb_register_callbacks(void)
kgdb_arch_init();
if (!dbg_is_early)
kgdb_arch_late();
register_module_notifier(&dbg_module_load_nb);
register_reboot_notifier(&dbg_reboot_notifier);
atomic_notifier_chain_register(&panic_notifier_list,
&kgdb_panic_event_nb);
@ -847,6 +864,7 @@ static void kgdb_unregister_callbacks(void)
if (kgdb_io_module_registered) {
kgdb_io_module_registered = 0;
unregister_reboot_notifier(&dbg_reboot_notifier);
unregister_module_notifier(&dbg_module_load_nb);
atomic_notifier_chain_unregister(&panic_notifier_list,
&kgdb_panic_event_nb);
kgdb_arch_exit();

View File

@ -129,6 +129,8 @@ kdb_bt(int argc, const char **argv)
}
/* Now the inactive tasks */
kdb_do_each_thread(g, p) {
if (KDB_FLAG(CMD_INTERRUPT))
return 0;
if (task_curr(p))
continue;
if (kdb_bt1(p, mask, argcount, btaprompt))

View File

@ -552,6 +552,7 @@ int vkdb_printf(const char *fmt, va_list ap)
{
int diag;
int linecount;
int colcount;
int logging, saved_loglevel = 0;
int saved_trap_printk;
int got_printf_lock = 0;
@ -584,6 +585,10 @@ int vkdb_printf(const char *fmt, va_list ap)
if (diag || linecount <= 1)
linecount = 24;
diag = kdbgetintenv("COLUMNS", &colcount);
if (diag || colcount <= 1)
colcount = 80;
diag = kdbgetintenv("LOGGING", &logging);
if (diag)
logging = 0;
@ -690,7 +695,7 @@ int vkdb_printf(const char *fmt, va_list ap)
gdbstub_msg_write(kdb_buffer, retlen);
} else {
if (dbg_io_ops && !dbg_io_ops->is_console) {
len = strlen(kdb_buffer);
len = retlen;
cp = kdb_buffer;
while (len--) {
dbg_io_ops->write_char(*cp);
@ -709,11 +714,29 @@ int vkdb_printf(const char *fmt, va_list ap)
printk(KERN_INFO "%s", kdb_buffer);
}
if (KDB_STATE(PAGER) && strchr(kdb_buffer, '\n'))
kdb_nextline++;
if (KDB_STATE(PAGER)) {
/*
* Check printed string to decide how to bump the
* kdb_nextline to control when the more prompt should
* show up.
*/
int got = 0;
len = retlen;
while (len--) {
if (kdb_buffer[len] == '\n') {
kdb_nextline++;
got = 0;
} else if (kdb_buffer[len] == '\r') {
got = 0;
} else {
got++;
}
}
kdb_nextline += got / (colcount + 1);
}
/* check for having reached the LINES number of printed lines */
if (kdb_nextline == linecount) {
if (kdb_nextline >= linecount) {
char buf1[16] = "";
/* Watch out for recursion here. Any routine that calls
@ -765,7 +788,7 @@ int vkdb_printf(const char *fmt, va_list ap)
kdb_grepping_flag = 0;
kdb_printf("\n");
} else if (buf1[0] == ' ') {
kdb_printf("\n");
kdb_printf("\r");
suspend_grep = 1; /* for this recursion */
} else if (buf1[0] == '\n') {
kdb_nextline = linecount - 1;

View File

@ -2101,6 +2101,8 @@ static int kdb_dmesg(int argc, const char **argv)
}
if (!lines--)
break;
if (KDB_FLAG(CMD_INTERRUPT))
return 0;
kdb_printf("%.*s\n", (int)len - 1, buf);
}