80 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* drivers/android/kernel_debugger.c
 | 
						|
 *
 | 
						|
 * Guts of the kernel debugger.
 | 
						|
 * Needs something to actually push commands to it.
 | 
						|
 *
 | 
						|
 * Copyright (C) 2007-2008 Google, Inc.
 | 
						|
 *
 | 
						|
 * This software is licensed under the terms of the GNU General Public
 | 
						|
 * License version 2, as published by the Free Software Foundation, and
 | 
						|
 * may be copied, distributed, and modified under those terms.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 * GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/ctype.h>
 | 
						|
#include <linux/device.h>
 | 
						|
#include <linux/sched.h>
 | 
						|
#include <linux/spinlock.h>
 | 
						|
#include <linux/sysrq.h>
 | 
						|
#include <linux/kernel_debugger.h>
 | 
						|
 | 
						|
#define dprintf(fmt...) (ctxt->printf(ctxt->cookie, fmt))
 | 
						|
 | 
						|
static void do_ps(struct kdbg_ctxt *ctxt)
 | 
						|
{
 | 
						|
	struct task_struct *g, *p;
 | 
						|
	unsigned state;
 | 
						|
	static const char stat_nam[] = "RSDTtZX";
 | 
						|
 | 
						|
	dprintf("pid   ppid  prio task            pc\n");
 | 
						|
	read_lock(&tasklist_lock);
 | 
						|
	do_each_thread(g, p) {
 | 
						|
		state = p->state ? __ffs(p->state) + 1 : 0;
 | 
						|
		dprintf("%5d %5d %4d ", p->pid, p->parent->pid, p->prio);
 | 
						|
		dprintf("%-13.13s %c", p->comm,
 | 
						|
			state >= sizeof(stat_nam) ? '?' : stat_nam[state]);
 | 
						|
		if (state == TASK_RUNNING)
 | 
						|
			dprintf(" running\n");
 | 
						|
		else
 | 
						|
			dprintf(" %08lx\n", thread_saved_pc(p));
 | 
						|
	} while_each_thread(g, p);
 | 
						|
	read_unlock(&tasklist_lock);
 | 
						|
}
 | 
						|
 | 
						|
int log_buf_copy(char *dest, int idx, int len);
 | 
						|
extern int do_syslog(int type, char __user *bug, int count);
 | 
						|
static void do_sysrq(struct kdbg_ctxt *ctxt, char rq)
 | 
						|
{
 | 
						|
	char buf[128];
 | 
						|
	int ret;
 | 
						|
	int idx = 0;
 | 
						|
	do_syslog(5 /* clear */, NULL, 0);
 | 
						|
	__handle_sysrq(rq, NULL, 0);
 | 
						|
	while (1) {
 | 
						|
		ret = log_buf_copy(buf, idx, sizeof(buf) - 1);
 | 
						|
		if (ret <= 0)
 | 
						|
			break;
 | 
						|
		buf[ret] = 0;
 | 
						|
		dprintf("%s", buf);
 | 
						|
		idx += ret;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
int kernel_debugger(struct kdbg_ctxt *ctxt, char *cmd)
 | 
						|
{
 | 
						|
	if (!strcmp(cmd, "ps"))
 | 
						|
		do_ps(ctxt);
 | 
						|
	if (!strcmp(cmd, "sysrq"))
 | 
						|
		do_sysrq(ctxt, 'h');
 | 
						|
	if (!strncmp(cmd, "sysrq ", 6))
 | 
						|
		do_sysrq(ctxt, cmd[6]);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 |