int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
			       char *remcomInBuffer, char *remcomOutBuffer,
			       struct pt_regs *regs)
{
	unsigned long addr;
	char *ptr;

	undo_single_step(regs);

	switch (remcomInBuffer[0]) {
	case 's':
	case 'c':
		ptr = &remcomInBuffer[1];
		if (kgdb_hex2long(&ptr, &addr))
			regs->ret = addr;

	case 'D':
	case 'k':
		atomic_set(&kgdb_cpu_doing_single_step, -1);

		if (remcomInBuffer[0] == 's') {
			do_single_step(regs);
			atomic_set(&kgdb_cpu_doing_single_step,
				   smp_processor_id());
		}

		return 0;
	}
	return -1;
}
Beispiel #2
0
/*
 * kgdb_arch_handle_exception - Handle architecture specific GDB packets.
 * @vector: The error vector of the exception that happened.
 * @signo: The signal number of the exception that happened.
 * @err_code: The error code of the exception that happened.
 * @remcom_in_buffer: The buffer of the packet we have read.
 * @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into.
 * @regs: The &struct pt_regs of the current process.
 *
 * This function MUST handle the 'c' and 's' command packets,
 * as well packets to set / remove a hardware breakpoint, if used.
 * If there are additional packets which the hardware needs to handle,
 * they are handled here. The code should return -1 if it wants to
 * process more packets, and a %0 or %1 if it wants to exit from the
 * kgdb callback.
 */
int kgdb_arch_handle_exception(int vector, int signo, int err_code,
			       char *remcom_in_buffer, char *remcom_out_buffer,
			       struct pt_regs *regs)
{
	char *ptr;
	unsigned long address;

	/* Undo any stepping we may have done. */
	undo_single_step(regs);

	switch (remcom_in_buffer[0]) {
	case 'c':
	case 's':
	case 'D':
	case 'k':
		/*
		 * Try to read optional parameter, pc unchanged if no parm.
		 * If this was a compiled-in breakpoint, we need to move
		 * to the next instruction or we will just breakpoint
		 * over and over again.
		 */
		ptr = &remcom_in_buffer[1];
		if (kgdb_hex2long(&ptr, &address))
			regs->pc = address;
		else if (*(unsigned long *)regs->pc == compiled_bpt)
			regs->pc += BREAK_INSTR_SIZE;

		if (remcom_in_buffer[0] == 's') {
			do_single_step(regs);
			kgdb_single_step = 1;
			atomic_set(&kgdb_cpu_doing_single_step,
				   raw_smp_processor_id());
		} else
			atomic_set(&kgdb_cpu_doing_single_step, -1);

		return 0;
	}

	return -1; /* this means that we do not want to exit from the handler */
}