diff options
| author | Jason Wessel <jason.wessel@windriver.com> | 2010-05-20 22:04:21 -0400 |
|---|---|---|
| committer | Jason Wessel <jason.wessel@windriver.com> | 2010-05-20 22:04:21 -0400 |
| commit | 67fc4e0cb931d6b4ccf21248e4199b154478ecea (patch) | |
| tree | 4cf49d00bc9ac03c3c77d91fadd13fcabc75e0c9 /kernel | |
| parent | 5d5314d6795f3c1c0f415348ff8c51f7de042b77 (diff) | |
kdb: core for kgdb back end (2 of 2)
This patch contains the hooks and instrumentation into kernel which
live outside the kernel/debug directory, which the kdb core
will call to run commands like lsmod, dmesg, bt etc...
CC: linux-arch@vger.kernel.org
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Martin Hicks <mort@sgi.com>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/kallsyms.c | 21 | ||||
| -rw-r--r-- | kernel/module.c | 4 | ||||
| -rw-r--r-- | kernel/printk.c | 16 | ||||
| -rw-r--r-- | kernel/sched.c | 7 | ||||
| -rw-r--r-- | kernel/signal.c | 40 |
5 files changed, 86 insertions, 2 deletions
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 13aff293f4de..6f6d091b5757 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
| 18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
| 19 | #include <linux/kdb.h> | ||
| 19 | #include <linux/err.h> | 20 | #include <linux/err.h> |
| 20 | #include <linux/proc_fs.h> | 21 | #include <linux/proc_fs.h> |
| 21 | #include <linux/sched.h> /* for cond_resched */ | 22 | #include <linux/sched.h> /* for cond_resched */ |
| @@ -516,6 +517,26 @@ static int kallsyms_open(struct inode *inode, struct file *file) | |||
| 516 | return ret; | 517 | return ret; |
| 517 | } | 518 | } |
| 518 | 519 | ||
| 520 | #ifdef CONFIG_KGDB_KDB | ||
| 521 | const char *kdb_walk_kallsyms(loff_t *pos) | ||
| 522 | { | ||
| 523 | static struct kallsym_iter kdb_walk_kallsyms_iter; | ||
| 524 | if (*pos == 0) { | ||
| 525 | memset(&kdb_walk_kallsyms_iter, 0, | ||
| 526 | sizeof(kdb_walk_kallsyms_iter)); | ||
| 527 | reset_iter(&kdb_walk_kallsyms_iter, 0); | ||
| 528 | } | ||
| 529 | while (1) { | ||
| 530 | if (!update_iter(&kdb_walk_kallsyms_iter, *pos)) | ||
| 531 | return NULL; | ||
| 532 | ++*pos; | ||
| 533 | /* Some debugging symbols have no name. Ignore them. */ | ||
| 534 | if (kdb_walk_kallsyms_iter.name[0]) | ||
| 535 | return kdb_walk_kallsyms_iter.name; | ||
| 536 | } | ||
| 537 | } | ||
| 538 | #endif /* CONFIG_KGDB_KDB */ | ||
| 539 | |||
| 519 | static const struct file_operations kallsyms_operations = { | 540 | static const struct file_operations kallsyms_operations = { |
| 520 | .open = kallsyms_open, | 541 | .open = kallsyms_open, |
| 521 | .read = seq_read, | 542 | .read = seq_read, |
diff --git a/kernel/module.c b/kernel/module.c index e2564580f3f1..b751f1902476 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -77,6 +77,10 @@ | |||
| 77 | DEFINE_MUTEX(module_mutex); | 77 | DEFINE_MUTEX(module_mutex); |
| 78 | EXPORT_SYMBOL_GPL(module_mutex); | 78 | EXPORT_SYMBOL_GPL(module_mutex); |
| 79 | static LIST_HEAD(modules); | 79 | static LIST_HEAD(modules); |
| 80 | #ifdef CONFIG_KGDB_KDB | ||
| 81 | struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ | ||
| 82 | #endif /* CONFIG_KGDB_KDB */ | ||
| 83 | |||
| 80 | 84 | ||
| 81 | /* Block module loading/unloading? */ | 85 | /* Block module loading/unloading? */ |
| 82 | int modules_disabled = 0; | 86 | int modules_disabled = 0; |
diff --git a/kernel/printk.c b/kernel/printk.c index 75077ad0b537..9213b8b5bb4f 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
| @@ -413,6 +413,22 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) | |||
| 413 | return do_syslog(type, buf, len, SYSLOG_FROM_CALL); | 413 | return do_syslog(type, buf, len, SYSLOG_FROM_CALL); |
| 414 | } | 414 | } |
| 415 | 415 | ||
| 416 | #ifdef CONFIG_KGDB_KDB | ||
| 417 | /* kdb dmesg command needs access to the syslog buffer. do_syslog() | ||
| 418 | * uses locks so it cannot be used during debugging. Just tell kdb | ||
| 419 | * where the start and end of the physical and logical logs are. This | ||
| 420 | * is equivalent to do_syslog(3). | ||
| 421 | */ | ||
| 422 | void kdb_syslog_data(char *syslog_data[4]) | ||
| 423 | { | ||
| 424 | syslog_data[0] = log_buf; | ||
| 425 | syslog_data[1] = log_buf + log_buf_len; | ||
| 426 | syslog_data[2] = log_buf + log_end - | ||
| 427 | (logged_chars < log_buf_len ? logged_chars : log_buf_len); | ||
| 428 | syslog_data[3] = log_buf + log_end; | ||
| 429 | } | ||
| 430 | #endif /* CONFIG_KGDB_KDB */ | ||
| 431 | |||
| 416 | /* | 432 | /* |
| 417 | * Call the console drivers on a range of log_buf | 433 | * Call the console drivers on a range of log_buf |
| 418 | */ | 434 | */ |
diff --git a/kernel/sched.c b/kernel/sched.c index 1d93cd0ae4d3..a25c1324af54 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -7758,9 +7758,9 @@ void normalize_rt_tasks(void) | |||
| 7758 | 7758 | ||
| 7759 | #endif /* CONFIG_MAGIC_SYSRQ */ | 7759 | #endif /* CONFIG_MAGIC_SYSRQ */ |
| 7760 | 7760 | ||
| 7761 | #ifdef CONFIG_IA64 | 7761 | #if defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) |
| 7762 | /* | 7762 | /* |
| 7763 | * These functions are only useful for the IA64 MCA handling. | 7763 | * These functions are only useful for the IA64 MCA handling, or kdb. |
| 7764 | * | 7764 | * |
| 7765 | * They can only be called when the whole system has been | 7765 | * They can only be called when the whole system has been |
| 7766 | * stopped - every CPU needs to be quiescent, and no scheduling | 7766 | * stopped - every CPU needs to be quiescent, and no scheduling |
| @@ -7780,6 +7780,9 @@ struct task_struct *curr_task(int cpu) | |||
| 7780 | return cpu_curr(cpu); | 7780 | return cpu_curr(cpu); |
| 7781 | } | 7781 | } |
| 7782 | 7782 | ||
| 7783 | #endif /* defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) */ | ||
| 7784 | |||
| 7785 | #ifdef CONFIG_IA64 | ||
| 7783 | /** | 7786 | /** |
| 7784 | * set_curr_task - set the current task for a given cpu. | 7787 | * set_curr_task - set the current task for a given cpu. |
| 7785 | * @cpu: the processor in question. | 7788 | * @cpu: the processor in question. |
diff --git a/kernel/signal.c b/kernel/signal.c index dbd7fe073c55..825a3f24ad76 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -2735,3 +2735,43 @@ void __init signals_init(void) | |||
| 2735 | { | 2735 | { |
| 2736 | sigqueue_cachep = KMEM_CACHE(sigqueue, SLAB_PANIC); | 2736 | sigqueue_cachep = KMEM_CACHE(sigqueue, SLAB_PANIC); |
| 2737 | } | 2737 | } |
| 2738 | |||
| 2739 | #ifdef CONFIG_KGDB_KDB | ||
| 2740 | #include <linux/kdb.h> | ||
| 2741 | /* | ||
| 2742 | * kdb_send_sig_info - Allows kdb to send signals without exposing | ||
| 2743 | * signal internals. This function checks if the required locks are | ||
| 2744 | * available before calling the main signal code, to avoid kdb | ||
| 2745 | * deadlocks. | ||
| 2746 | */ | ||
| 2747 | void | ||
| 2748 | kdb_send_sig_info(struct task_struct *t, struct siginfo *info) | ||
| 2749 | { | ||
| 2750 | static struct task_struct *kdb_prev_t; | ||
| 2751 | int sig, new_t; | ||
| 2752 | if (!spin_trylock(&t->sighand->siglock)) { | ||
| 2753 | kdb_printf("Can't do kill command now.\n" | ||
| 2754 | "The sigmask lock is held somewhere else in " | ||
| 2755 | "kernel, try again later\n"); | ||
| 2756 | return; | ||
| 2757 | } | ||
| 2758 | spin_unlock(&t->sighand->siglock); | ||
| 2759 | new_t = kdb_prev_t != t; | ||
| 2760 | kdb_prev_t = t; | ||
| 2761 | if (t->state != TASK_RUNNING && new_t) { | ||
| 2762 | kdb_printf("Process is not RUNNING, sending a signal from " | ||
| 2763 | "kdb risks deadlock\n" | ||
| 2764 | "on the run queue locks. " | ||
| 2765 | "The signal has _not_ been sent.\n" | ||
| 2766 | "Reissue the kill command if you want to risk " | ||
| 2767 | "the deadlock.\n"); | ||
| 2768 | return; | ||
| 2769 | } | ||
| 2770 | sig = info->si_signo; | ||
| 2771 | if (send_sig_info(sig, info, t)) | ||
| 2772 | kdb_printf("Fail to deliver Signal %d to process %d.\n", | ||
| 2773 | sig, t->pid); | ||
| 2774 | else | ||
| 2775 | kdb_printf("Signal %d is sent to process %d.\n", sig, t->pid); | ||
| 2776 | } | ||
| 2777 | #endif /* CONFIG_KGDB_KDB */ | ||
