Skip to content

Commit

Permalink
kdb: core for kgdb back end (2 of 2)
Browse files Browse the repository at this point in the history
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: [email protected]
Signed-off-by: Jason Wessel <[email protected]>
Signed-off-by: Martin Hicks <[email protected]>
  • Loading branch information
jwessel committed May 21, 2010
1 parent 5d5314d commit 67fc4e0
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 3 deletions.
1 change: 1 addition & 0 deletions arch/arm/include/asm/kmap_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ enum km_type {
KM_SOFTIRQ1,
KM_L1_CACHE,
KM_L2_CACHE,
KM_KDB,
KM_TYPE_NR
};

Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/kmap_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum km_type {
KM_SOFTIRQ1,
KM_PPC_SYNC_PAGE,
KM_PPC_SYNC_ICACHE,
KM_KDB,
KM_TYPE_NR
};

Expand Down
3 changes: 2 additions & 1 deletion include/asm-generic/kmap_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ KMAP_D(15) KM_UML_USERCOPY,
KMAP_D(16) KM_IRQ_PTE,
KMAP_D(17) KM_NMI,
KMAP_D(18) KM_NMI_PTE,
KMAP_D(19) KM_TYPE_NR
KMAP_D(19) KM_KDB,
KMAP_D(20) KM_TYPE_NR
};

#undef KMAP_D
Expand Down
2 changes: 2 additions & 0 deletions init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/idr.h>
#include <linux/kdb.h>
#include <linux/ftrace.h>
#include <linux/async.h>
#include <linux/kmemcheck.h>
Expand Down Expand Up @@ -675,6 +676,7 @@ asmlinkage void __init start_kernel(void)
buffer_init();
key_init();
security_init();
kdb_init(KDB_INIT_FULL);
vfs_caches_init(totalram_pages);
signals_init();
/* rootfs populating might need page-writeback */
Expand Down
21 changes: 21 additions & 0 deletions kernel/kallsyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/fs.h>
#include <linux/kdb.h>
#include <linux/err.h>
#include <linux/proc_fs.h>
#include <linux/sched.h> /* for cond_resched */
Expand Down Expand Up @@ -516,6 +517,26 @@ static int kallsyms_open(struct inode *inode, struct file *file)
return ret;
}

#ifdef CONFIG_KGDB_KDB
const char *kdb_walk_kallsyms(loff_t *pos)
{
static struct kallsym_iter kdb_walk_kallsyms_iter;
if (*pos == 0) {
memset(&kdb_walk_kallsyms_iter, 0,
sizeof(kdb_walk_kallsyms_iter));
reset_iter(&kdb_walk_kallsyms_iter, 0);
}
while (1) {
if (!update_iter(&kdb_walk_kallsyms_iter, *pos))
return NULL;
++*pos;
/* Some debugging symbols have no name. Ignore them. */
if (kdb_walk_kallsyms_iter.name[0])
return kdb_walk_kallsyms_iter.name;
}
}
#endif /* CONFIG_KGDB_KDB */

static const struct file_operations kallsyms_operations = {
.open = kallsyms_open,
.read = seq_read,
Expand Down
4 changes: 4 additions & 0 deletions kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@
DEFINE_MUTEX(module_mutex);
EXPORT_SYMBOL_GPL(module_mutex);
static LIST_HEAD(modules);
#ifdef CONFIG_KGDB_KDB
struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
#endif /* CONFIG_KGDB_KDB */


/* Block module loading/unloading? */
int modules_disabled = 0;
Expand Down
16 changes: 16 additions & 0 deletions kernel/printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,22 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
}

#ifdef CONFIG_KGDB_KDB
/* kdb dmesg command needs access to the syslog buffer. do_syslog()
* uses locks so it cannot be used during debugging. Just tell kdb
* where the start and end of the physical and logical logs are. This
* is equivalent to do_syslog(3).
*/
void kdb_syslog_data(char *syslog_data[4])
{
syslog_data[0] = log_buf;
syslog_data[1] = log_buf + log_buf_len;
syslog_data[2] = log_buf + log_end -
(logged_chars < log_buf_len ? logged_chars : log_buf_len);
syslog_data[3] = log_buf + log_end;
}
#endif /* CONFIG_KGDB_KDB */

/*
* Call the console drivers on a range of log_buf
*/
Expand Down
7 changes: 5 additions & 2 deletions kernel/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -7758,9 +7758,9 @@ void normalize_rt_tasks(void)

#endif /* CONFIG_MAGIC_SYSRQ */

#ifdef CONFIG_IA64
#if defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB)
/*
* These functions are only useful for the IA64 MCA handling.
* These functions are only useful for the IA64 MCA handling, or kdb.
*
* They can only be called when the whole system has been
* stopped - every CPU needs to be quiescent, and no scheduling
Expand All @@ -7780,6 +7780,9 @@ struct task_struct *curr_task(int cpu)
return cpu_curr(cpu);
}

#endif /* defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) */

#ifdef CONFIG_IA64
/**
* set_curr_task - set the current task for a given cpu.
* @cpu: the processor in question.
Expand Down
40 changes: 40 additions & 0 deletions kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -2735,3 +2735,43 @@ void __init signals_init(void)
{
sigqueue_cachep = KMEM_CACHE(sigqueue, SLAB_PANIC);
}

#ifdef CONFIG_KGDB_KDB
#include <linux/kdb.h>
/*
* kdb_send_sig_info - Allows kdb to send signals without exposing
* signal internals. This function checks if the required locks are
* available before calling the main signal code, to avoid kdb
* deadlocks.
*/
void
kdb_send_sig_info(struct task_struct *t, struct siginfo *info)
{
static struct task_struct *kdb_prev_t;
int sig, new_t;
if (!spin_trylock(&t->sighand->siglock)) {
kdb_printf("Can't do kill command now.\n"
"The sigmask lock is held somewhere else in "
"kernel, try again later\n");
return;
}
spin_unlock(&t->sighand->siglock);
new_t = kdb_prev_t != t;
kdb_prev_t = t;
if (t->state != TASK_RUNNING && new_t) {
kdb_printf("Process is not RUNNING, sending a signal from "
"kdb risks deadlock\n"
"on the run queue locks. "
"The signal has _not_ been sent.\n"
"Reissue the kill command if you want to risk "
"the deadlock.\n");
return;
}
sig = info->si_signo;
if (send_sig_info(sig, info, t))
kdb_printf("Fail to deliver Signal %d to process %d.\n",
sig, t->pid);
else
kdb_printf("Signal %d is sent to process %d.\n", sig, t->pid);
}
#endif /* CONFIG_KGDB_KDB */

0 comments on commit 67fc4e0

Please sign in to comment.