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 */ | ||