⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kgdb-stub.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 3 页
字号:
	while (i--)		*scan++ = 0;	*scan++ = (value >> 24) & 0xff;	*scan++ = (value >> 16) & 0xff;	*scan++ = (value >> 8) & 0xff;	*scan++ = (value & 0xff);}/* Return a task structure ptr for a particular pid */static struct task_struct * get_thread(int pid){	struct task_struct *thread;	/* Use PID_MAX w/gdb for pid 0 */	if (pid == PID_MAX) pid = 0;	/* First check via PID */	thread = find_task_by_pid(pid);	if (thread)		return thread;	/* Start at the start */	thread = init_tasks[0];	/* Walk along the linked list of tasks */	do {		if (thread->pid == pid)			return thread;		thread = thread->next_task;	} while (thread != init_tasks[0]);	return NULL;}#endif /* CONFIG_KGDB_THREAD */void kgdb_msg(const char * msg){	const char *emsg;	for (emsg = msg; *emsg; emsg++) ;	remcomOutBuffer[0] = 'O';	mem2hex(msg, remcomOutBuffer+1, emsg-msg);	if (kgdb_active()) kgdb_put_packet(remcomOutBuffer);}static void send_ok_msg(void){	kgdb_put_packet("OK");}static void send_err_msg(void){	kgdb_put_packet("E01");}static void send_empty_msg(void){	kgdb_put_packet("");}static void send_signal_msg(const int signum){#ifndef CONFIG_KGDB_THREAD	remcomOutBuffer[0] = 'S';	remcomOutBuffer[1] =  hexchars[(signum >> 4) & 0xf];	remcomOutBuffer[2] =  hexchars[signum % 16];	remcomOutBuffer[3] = 0;#else /* CONFIG_KGDB_THREAD */	int threadid;	threadref thref;	char *out = remcomOutBuffer;	const char *tstring = "thread";	*out++ = 'T';	*out++ = hexchars[(signum >> 4) & 0xf];	*out++ = hexchars[signum % 16];	while (*tstring) {                *out++ = *tstring++;	}	*out++ = ':';	threadid = trapped_thread->pid;	if (threadid == 0) threadid = PID_MAX;	int_to_threadref(&thref, threadid);	pack_threadid(out, &thref);	out += BUF_THREAD_ID_SIZE;	*out++ = ';';	*out = 0;#endif /* CONFIG_KGDB_THREAD */	kgdb_put_packet(remcomOutBuffer);}static void send_regs_msg(void){#ifdef CONFIG_KGDB_THREAD	if (!current_thread)		kregs2gregs(&kgdb_regs, gdb_regs);	else		tregs2gregs(current_thread, gdb_regs);#else	kregs2gregs(&kgdb_regs, gdb_regs);#endif	mem2hex((const char *)gdb_regs, remcomOutBuffer, GDB_REGBYTES);	kgdb_put_packet(remcomOutBuffer);}/* Set register contents - currently can't set other thread's registers */static void set_regs_msg(void){#ifdef CONFIG_KGDB_THREAD	if (!current_thread) {#endif		kregs2gregs(&kgdb_regs, gdb_regs);		hex2mem(&remcomInBuffer[1], (char *) gdb_regs, GDB_REGBYTES);		gregs2kregs(gdb_regs, &kgdb_regs);		send_ok_msg();#ifdef CONFIG_KGDB_THREAD	} else		send_err_msg();#endif}/* The following provides support for recovery from bus * errors during kgdb memory read/write operations. */void kgdb_handle_bus_error(void){	kgdb_longjmp(fault_jmp_buf, 1);}/* Read memory due to 'm' message */static void read_mem_msg(void){	char *ptr;	int addr;	int length;	/* Jmp, disable bus error handler */	if (kgdb_setjmp(fault_jmp_buf) == 0) {		kgdb_fault_expected = 1;		/* Walk through, have m<addr>,<length> */		ptr = &remcomInBuffer[1];		if (hex2int(&ptr, &addr) && (*ptr++ == ','))			if (hex2int(&ptr, &length)) {				ptr = 0;				if (length * 2 > BUFMAX)					length = BUFMAX / 2;				mem2hex((char *) addr, remcomOutBuffer, length);			}		if (ptr)			send_err_msg();		else			kgdb_put_packet(remcomOutBuffer);	} else		send_err_msg();	/* Restore bus error handler */	kgdb_fault_expected = 0;}/* Write memory due to 'M' or 'X' message */static void write_mem_msg(int binary){	char *ptr;	int addr;	int length;	if (kgdb_setjmp(fault_jmp_buf) == 0) {		kgdb_fault_expected = 1;		/* Walk through, have M<addr>,<length>:<data> */		ptr = &remcomInBuffer[1];		if (hex2int(&ptr, &addr) && (*ptr++ == ','))			if (hex2int(&ptr, &length) && (*ptr++ == ':')) {				if (binary)					ebin2mem(ptr, (char*)addr, length);				else					hex2mem(ptr, (char*)addr, length);				ptr = 0;				/*				 * Trap breakpoints				 */				if(length == 4 && !(addr & 0x3) &&					*((unsigned *)addr) == GDB_BREAKINST)					*((unsigned *)addr) = KGDB_BREAKINST;				send_ok_msg();			}		if (ptr)			send_err_msg();	} else		send_err_msg();	/* Restore bus error handler */	kgdb_fault_expected = 0;}static void continue_msg(void){        /* Try to read optional parameter, PC unchanged if none */        char *ptr = &remcomInBuffer[1];        int addr;        if (hex2int(&ptr, &addr))                kgdb_regs.ARM_pc = addr;	strcpy(remcomOutBuffer, "OK");	kgdb_put_packet(remcomOutBuffer);}static void continue_with_sig_msg(void){        int signal;        char *ptr = &remcomInBuffer[1];        int addr;        /* Report limitation */        kgdb_msg("Cannot force signal in kgdb, continuing anyway.\n");        /* Signal */        hex2int(&ptr, &signal);        if (*ptr == ';')                ptr++;        /* Optional address */        if (hex2int(&ptr, &addr))                kgdb_regs.ARM_pc = addr;	strcpy(remcomOutBuffer, "OK");	kgdb_put_packet(remcomOutBuffer);}void do_single_step(void){	step_addr = (unsigned int *) get_next_pc(&kgdb_regs);	step_instr = *step_addr;	*step_addr = KGDB_BREAKINST;}static void undo_single_step(void){	if (step_addr != NULL) {		*step_addr = step_instr;		step_addr = NULL;		step_instr = 0;	}}static void step_msg(void){        continue_msg();        do_single_step();}static void step_with_sig_msg(void){        continue_with_sig_msg();        do_single_step();}/* Set the status for a thread */void set_thread_msg(void){#ifndef CONFIG_KGDB_THREAD	strcpy(remcomOutBuffer, "OK");	kgdb_put_packet(remcomOutBuffer);#else	int threadid;	struct task_struct *thread = NULL;	char *ptr;	switch (remcomInBuffer[1]) {       	/* To select which thread for gG etc messages, i.e. supported */	case 'g':		ptr = &remcomInBuffer[2];		hex2int(&ptr, &threadid);		thread = get_thread(threadid);		/* If we haven't found it */		if (!thread) {			send_err_msg();			break;		}		/* Set current_thread (or not) */		if (thread == trapped_thread)			current_thread = NULL;		else			current_thread = thread;		send_ok_msg();		break;	/* To select which thread for cCsS messages, i.e. unsupported */	case 'c':		send_ok_msg();		break;	default:		send_empty_msg();		break;	}#endif}#ifdef CONFIG_KGDB_THREAD/* Is a thread alive? */static void thread_status_msg(void){	char *ptr;	int threadid;	struct task_struct *thread = NULL;	ptr = &remcomInBuffer[1];	hex2int(&ptr, &threadid);	thread = get_thread(threadid);	if (thread)		send_ok_msg();	else		send_err_msg();}/* Send the current thread ID */static void thread_id_msg(void){	int threadid;	threadref thref;	remcomOutBuffer[0] = 'Q';	remcomOutBuffer[1] = 'C';	if (current_thread)		threadid = current_thread->pid;	else if (trapped_thread)		threadid = trapped_thread->pid;	else /* Impossible, but just in case! */	{		send_err_msg();		return;	}	/* Translate pid 0 to PID_MAX for gdb */	if (threadid == 0) threadid = PID_MAX;	int_to_threadref(&thref, threadid);	pack_threadid(remcomOutBuffer + 2, &thref);	remcomOutBuffer[2 + BUF_THREAD_ID_SIZE] = '\0';	kgdb_put_packet(remcomOutBuffer);}/* Send thread info */static void thread_info_msg(void){	struct task_struct *thread = NULL;	int threadid;	char *pos;	threadref thref;	/* Start with 'm' */	remcomOutBuffer[0] = 'm';	pos = &remcomOutBuffer[1];	/* For all possible thread IDs - this will overrun if > 44 threads! */	/* Start at 1 and include PID_MAX (since GDB won't use pid 0...) */	for (threadid = 1; threadid <= PID_MAX; threadid++) {		read_lock(&tasklist_lock);		thread = get_thread(threadid);		read_unlock(&tasklist_lock);		/* If it's a valid thread */		if (thread) {			int_to_threadref(&thref, threadid);			pack_threadid(pos, &thref);			pos += BUF_THREAD_ID_SIZE;			*pos++ = ',';		}	}	*--pos = 0;		/* Lose final comma */	kgdb_put_packet(remcomOutBuffer);}/* Return printable info for gdb's 'info threads' command */static void thread_extra_info_msg(void){	int threadid;	struct task_struct *thread = NULL;	char buffer[20], *ptr;	int i;	/* Extract thread ID */	ptr = &remcomInBuffer[17];	hex2int(&ptr, &threadid);	thread = get_thread(threadid);	/* If we don't recognise it, say so */	if (thread == NULL)		strcpy(buffer, "(unknown)");	else		strcpy(buffer, thread->comm);	/* Construct packet */	for (i = 0, ptr = remcomOutBuffer; buffer[i]; i++)		ptr = pack_hex_byte(ptr, buffer[i]);#if	0 /* REVISIT! */	if (thread->thread.pc == (unsigned long)ret_from_fork) {		strcpy(buffer, "<new fork>");		for (i = 0; buffer[i]; i++)			ptr = pack_hex_byte(ptr, buffer[i]);	}#endif	*ptr = '\0';	kgdb_put_packet(remcomOutBuffer);}/* Handle all qFooBarBaz messages - have to use an if statement as   opposed to a switch because q messages can have > 1 char id. */static void query_msg(void){	const char *q_start = &remcomInBuffer[1];	/* qC = return current thread ID */	if (strncmp(q_start, "C", 1) == 0)		thread_id_msg();	/* qfThreadInfo = query all threads (first) */	else if (strncmp(q_start, "fThreadInfo", 11) == 0)		thread_info_msg();	/* qsThreadInfo = query all threads (subsequent). We know we have sent	   them all after the qfThreadInfo message, so there are no to send */	else if (strncmp(q_start, "sThreadInfo", 11) == 0)		kgdb_put_packet("l");	/* el = last */	/* qThreadExtraInfo = supply printable information per thread */	else if (strncmp(q_start, "ThreadExtraInfo", 15) == 0)		thread_extra_info_msg();	/* Unsupported - empty message as per spec */	else		send_empty_msg();}#endif /* CONFIG_KGDB_THREAD *//* * This function does all command procesing for interfacing to gdb. */void do_kgdb(struct pt_regs *trap_regs, unsigned char sigval){	unsigned long flags;	save_flags_cli(flags);	kgdb_regs = *trap_regs; /* Quick and dirty clone of pt_regs */	/*	 * reply to host that an exception has occurred	 *	 * We don't do this on the first call as it would cause a sync problem.	 */	if (kgdb_initialized) {		send_signal_msg(sigval);	} else {		/*		 * This is the first breakpoint, called from		 * start_kernel or elsewhere. We need to		 * (re-)initialize the I/O subsystem.		 */		printk("Breaking into KGDB\n");		if(kgdb_io_init())		{			printk("KGB I/O INIT FAILED...HALTING!");			while(1){ };		}	}	kgdb_initialized = 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -