Пример #1
0
static int emul_sstep_put(char *put_str, char *arg)
{
	if (!arch_needs_sstep_emulation) {
		char *ptr = &put_str[11];
		if (put_str[1] != 'T' || put_str[2] != '0')
			return 1;
		kgdb_hex2long(&ptr, &sstep_thread_id);
		return 0;
	}
	switch (sstep_state) {
	case 1:
		/* validate the "g" packet to get the IP */
		kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs,
			 NUMREGBYTES);
		gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
		v2printk("Stopped at IP: %lx\n",
			 instruction_pointer(&kgdbts_regs));
		/* Want to stop at IP + break instruction size by default */
		sstep_addr = cont_addr + BREAK_INSTR_SIZE;
		break;
	case 2:
		if (strncmp(put_str, "$OK", 3)) {
			eprintk("kgdbts: failed sstep break set\n");
			return 1;
		}
		break;
	case 3:
		if (strncmp(put_str, "$T0", 3)) {
			eprintk("kgdbts: failed continue sstep\n");
			return 1;
		} else {
			char *ptr = &put_str[11];
			kgdb_hex2long(&ptr, &sstep_thread_id);
		}
		break;
	case 4:
		if (strncmp(put_str, "$OK", 3)) {
			eprintk("kgdbts: failed sstep break unset\n");
			return 1;
		}
		/* Single step is complete so continue on! */
		sstep_state = 0;
		return 0;
	default:
		eprintk("kgdbts: ERROR failed sstep put emulation\n");
	}

	/* Continue on the same test line until emulation is complete */
	ts.idx--;
	return 0;
}
Пример #2
0
int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
			       char *remcomInBuffer, char *remcomOutBuffer,
			       struct pt_regs *linux_regs)
{
	unsigned long addr;
	char *ptr;

	switch (remcomInBuffer[0]) {
	case 'c':
		/* try to read optional parameter, pc unchanged if no parm */
		ptr = &remcomInBuffer[1];
		if (kgdb_hex2long(&ptr, &addr)) {
			linux_regs->pc = addr;
			linux_regs->npc = addr + 4;
		}
		/* fallthru */

	case 'D':
	case 'k':
		if (linux_regs->pc == (unsigned long) arch_kgdb_breakpoint) {
			linux_regs->pc = linux_regs->npc;
			linux_regs->npc += 4;
		}
		return 0;
	}
	return -1;
}
Пример #3
0
int kgdb_arch_handle_exception(int exception_vector, int signo,
			       int err_code, char *remcom_in_buffer,
			       char *remcom_out_buffer,
			       struct pt_regs *linux_regs)
{
	unsigned long addr;
	char *ptr;

	switch (remcom_in_buffer[0]) {
	case 'D':
	case 'k':
	case 'c':
		/*
		 * Try to read optional parameter, pc unchanged if no parm.
		 * If this was a compiled 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, &addr))
			linux_regs->ARM_pc = addr;
		else if (compiled_break == 1)
			linux_regs->ARM_pc += 4;

		compiled_break = 0;

		return 0;
	}

	return -1;
}
Пример #4
0
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;
}
Пример #5
0
/*
 * Handle the 's' and 'c' commands
 */
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;
	int cpu = smp_processor_id();

	switch (remcom_in_buffer[0]) {
	case 's':
	case 'c':
		/* handle the optional parameter */
		ptr = &remcom_in_buffer[1];
		if (kgdb_hex2long(&ptr, &address))
			regs->cp0_epc = address;

		atomic_set(&kgdb_cpu_doing_single_step, -1);
		if (remcom_in_buffer[0] == 's')
			atomic_set(&kgdb_cpu_doing_single_step, cpu);

		return 0;
	}

	return -1;
}
Пример #6
0
/*
 * Handle unknown packets and [CcsDk] packets
 * - at this point breakpoints have been installed
 */
int kgdb_arch_handle_exception(int vector, int signo, int err_code,
                               char *remcom_in_buffer, char *remcom_out_buffer,
                               struct pt_regs *regs)
{
    long addr;
    char *ptr;

    switch (remcom_in_buffer[0]) {
    case 'c':
    case 's':
        /* try to read optional parameter, pc unchanged if no parm */
        ptr = &remcom_in_buffer[1];
        if (kgdb_hex2long(&ptr, &addr))
            regs->pc = addr;
    case 'D':
    case 'k':
        atomic_set(&kgdb_cpu_doing_single_step, -1);

        if (remcom_in_buffer[0] == 's') {
            kgdb_arch_do_singlestep(regs);
            kgdb_single_step = 1;
            atomic_set(&kgdb_cpu_doing_single_step,
                       raw_smp_processor_id());
        }
        return 0;
    }
    return -1; /* this means that we do not want to exit from the handler */
}
Пример #7
0
int kgdb_arch_handle_exception(int exception_vector, int signo,
			       int err_code, char *remcom_in_buffer,
			       char *remcom_out_buffer,
			       struct pt_regs *linux_regs)
{
	unsigned long addr;
	char *ptr;

	switch (remcom_in_buffer[0]) {
	case 'D':
	case 'k':
	case 'c':
		ptr = &remcom_in_buffer[1];
		if (kgdb_hex2long(&ptr, &addr))
			linux_regs->ARM_pc = addr;
		else if (compiled_break == 1)
			linux_regs->ARM_pc += 4;

		compiled_break = 0;

		return 0;
	}

	return -1;
}
Пример #8
0
static int get_thread_id_continue(char *put_str, char *arg)
{
	char *ptr = &put_str[11];

	if (put_str[1] != 'T' || put_str[2] != '0')
		return 1;
	kgdb_hex2long(&ptr, &cont_thread_id);
	return 0;
}
Пример #9
0
Файл: kgdb.c Проект: 274914765/C
int kgdb_arch_handle_exception(int exceptionVector, int signo,
                   int err_code, char *remcom_in_buffer,
                   char *remcom_out_buffer,
                   struct pt_regs *linux_regs)
{
    long addr;
    long breakno;
    char *ptr;
    int newPC;
    int wp_status;

    switch (remcom_in_buffer[0]) {
    case 'c':
    case 's':
        if (kgdb_contthread && kgdb_contthread != current) {
            strcpy(remcom_out_buffer, "E00");
            break;
        }

        kgdb_contthread = NULL;

        /* try to read optional parameter, pc unchanged if no parm */
        ptr = &remcom_in_buffer[1];
        if (kgdb_hex2long(&ptr, &addr)) {
            linux_regs->retx = addr;
        }
        newPC = linux_regs->retx;

        /* clear the trace bit */
        linux_regs->syscfg &= 0xfffffffe;

        /* set the trace bit if we're stepping */
        if (remcom_in_buffer[0] == 's') {
            linux_regs->syscfg |= 0x1;
            debugger_step = 1;
        }

        wp_status = bfin_read_WPSTAT();
        CSYNC();

        if (exceptionVector == VEC_WATCH) {
            for (breakno = 0; breakno < 6; ++breakno) {
                if (wp_status & (1 << breakno)) {
                    breakinfo->skip = 1;
                    break;
                }
            }
        }
        kgdb_correct_hw_break();

        bfin_write_WPSTAT(0);

        return 0;
    }            /* switch */
    return -1;        /* this means that we do not want to exit from the handler */
}
Пример #10
0
static int kgdb_fr_reg(int regnum, char *inbuffer, struct pt_regs * ptregs,
	struct unw_frame_info *info, unsigned long *reg,
	struct ia64_fpreg *freg, int rw)
{
	int result = 1;

	if (!(regnum >= IA64_FR0_REGNUM && regnum <= (IA64_FR0_REGNUM + 127)))
		return 0;

	switch (regnum) {
	case IA64_FR0_REGNUM + 6:
	case IA64_FR0_REGNUM + 7:
	case IA64_FR0_REGNUM + 8:
	case IA64_FR0_REGNUM + 9:
	case IA64_FR0_REGNUM + 10:
	case IA64_FR0_REGNUM + 11:
	case IA64_FR0_REGNUM + 12:
		if (rw) {
#ifndef XEN
			char *ptr = inbuffer;

			freg->u.bits[0] = *reg;
			kgdb_hex2long(&ptr, &freg->u.bits[1]);
			*(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) =
				*freg;
#else
			printk("%s: %d: writing to fpreg is not supported.\n",
				   __func__, __LINE__);
#endif
			break;
		} else if (!ptregs)
			result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM,
				freg, rw);
		else
#ifndef XEN
			*freg =
			*(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6)));
#else
		    //XXX struct ia64_fpreg and struct pt_fpreg are same.
			*freg = *((struct ia64_fpreg*)(&ptregs->f6 +
										   (regnum - (IA64_FR0_REGNUM + 6))));
#endif
		break;
	default:
		if (!rw)
			result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM,
				freg, rw);
		else
			result = 0;
		break;
	}

	return result;
}
Пример #11
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 e_vector, int signo, int err_code,
			       char *remcomInBuffer, char *remcomOutBuffer,
			       struct pt_regs *linux_regs)
{
	unsigned long addr;
	unsigned long dr6;
	char *ptr;
	int newPC;

	switch (remcomInBuffer[0]) {
	case 'c':
	case 's':
		/* try to read optional parameter, pc unchanged if no parm */
		ptr = &remcomInBuffer[1];
		if (kgdb_hex2long(&ptr, &addr))
			linux_regs->ip = addr;
	case 'D':
	case 'k':
		newPC = linux_regs->ip;

		/* clear the trace bit */
		linux_regs->flags &= ~X86_EFLAGS_TF;
		atomic_set(&kgdb_cpu_doing_single_step, -1);

		/* set the trace bit if we're stepping */
		if (remcomInBuffer[0] == 's') {
			linux_regs->flags |= X86_EFLAGS_TF;
			atomic_set(&kgdb_cpu_doing_single_step,
				   raw_smp_processor_id());
		}

		get_debugreg(dr6, 6);
		if (!(dr6 & 0x4000)) {
			int breakno;

			for (breakno = 0; breakno < 4; breakno++) {
				if (dr6 & (1 << breakno) &&
				    breakinfo[breakno].type == 0) {
					/* Set restore flag: */
					linux_regs->flags |= X86_EFLAGS_RF;
					break;
				}
			}
		}
		set_debugreg(0UL, 6);
		kgdb_correct_hw_break();

		return 0;
	}

	/* this means that we do not want to exit from the handler: */
	return -1;
}
Пример #12
0
/* Write memory due to an 'M' or 'X' packet. */
static int write_mem_msg(int binary)
{
	char *ptr = &remcom_in_buffer[1];
	unsigned long addr;
	unsigned long length;
	int err;

	if (kgdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' &&
	    kgdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') {
		if (binary)
			err = kgdb_ebin2mem(ptr, (char *)addr, length);
		else
			err = kgdb_hex2mem(ptr, (char *)addr, length);
		if (err)
			return err;
		if (CACHE_FLUSH_IS_SAFE)
			flush_icache_range(addr, addr + length);
		return 0;
	}

	return -EINVAL;
}
Пример #13
0
static void kgdb_arch_update_addr(struct pt_regs *regs,
				char *remcom_in_buffer)
{
	unsigned long addr;
	char *ptr;

	ptr = &remcom_in_buffer[1];
	if (kgdb_hex2long(&ptr, &addr))
		kgdb_arch_set_pc(regs, addr);
	else if (compiled_break == 1)
		kgdb_arch_set_pc(regs, regs->pc + 4);

	compiled_break = 0;
}
Пример #14
0
int kgdb_arch_handle_exception(int vector, int signo,
			       int err_code, char *remcom_in_buffer,
			       char *remcom_out_buffer,
			       struct pt_regs *regs)
{
	long addr;
	char *ptr;
	int newPC;
	int i;

	switch (remcom_in_buffer[0]) {
	case 'c':
	case 's':
		if (kgdb_contthread && kgdb_contthread != current) {
			strcpy(remcom_out_buffer, "E00");
			break;
		}

		kgdb_contthread = NULL;

		/* try to read optional parameter, pc unchanged if no parm */
		ptr = &remcom_in_buffer[1];
		if (kgdb_hex2long(&ptr, &addr)) {
			regs->retx = addr;
		}
		newPC = regs->retx;

		/* clear the trace bit */
		regs->syscfg &= 0xfffffffe;

		/* set the trace bit if we're stepping */
		if (remcom_in_buffer[0] == 's') {
			regs->syscfg |= 0x1;
			kgdb_single_step = regs->ipend;
			kgdb_single_step >>= 6;
			for (i = 10; i > 0; i--, kgdb_single_step >>= 1)
				if (kgdb_single_step & 1)
					break;
			/* i indicate event priority of current stopped instruction
			 * user space instruction is 0, IVG15 is 1, IVTMR is 10.
			 * kgdb_single_step > 0 means in single step mode
			 */
			kgdb_single_step = i + 1;
		}

		bfin_correct_hw_break();

		return 0;
	}			/* switch */
Пример #15
0
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 addr;

	switch (remcom_in_buffer[0]) {
	case 's':
	case 'c':
		/* handle the optional parameters */
		ptr = &remcom_in_buffer[1];
		if (kgdb_hex2long(&ptr, &addr))
			regs->ea = addr;

		return 0;
	}

	return -1; /* this means that we do not want to exit from the handler */
}
Пример #16
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 */
}
Пример #17
0
/*
 * This function does PowerPC specific processing for interfacing to gdb.
 */
int kgdb_arch_handle_exception(int vector, int signo, int err_code,
			       char *remcom_in_buffer, char *remcom_out_buffer,
			       struct pt_regs *linux_regs)
{
	char *ptr = &remcom_in_buffer[1];
	unsigned long addr;

	switch (remcom_in_buffer[0])
		{
		/*
		 * sAA..AA   Step one instruction from AA..AA
		 * This will return an error to gdb ..
		 */
		case 's':
		case 'c':
			/* handle the optional parameter */
			if (kgdb_hex2long (&ptr, &addr))
				linux_regs->nip = addr;

			atomic_set(&cpu_doing_single_step, -1);
			/* set the trace bit if we're stepping */
			if (remcom_in_buffer[0] == 's') {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
				mtspr(SPRN_DBCR0,
				      mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
				linux_regs->msr |= MSR_DE;
#else
				linux_regs->msr |= MSR_SE;
#endif
				debugger_step = 1;
				if (kgdb_contthread)
					atomic_set(&cpu_doing_single_step,
							smp_processor_id());
			}
			return 0;
	}

	return -1;
}
Пример #18
0
void kgdb_put_reg(char *inbuffer, char *outbuffer, int regnum,
		  struct unw_frame_info *info, struct pt_regs *ptregs)
{
	unsigned long reg;
	char nat = 0;
	struct ia64_fpreg freg;
	int i;
	char *ptr;

	ptr = inbuffer;
	kgdb_hex2long(&ptr, &reg);
	strcpy(outbuffer, "OK");

	if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) ||
	    (regnum >= (IA64_GR0_REGNUM + 4) && regnum <= (IA64_GR0_REGNUM + 7))
	    || (regnum >= (IA64_GR0_REGNUM + 16)
		&& regnum <= (IA64_GR0_REGNUM + 31))) {
		unw_access_gr(info, regnum - IA64_GR0_REGNUM, &reg, &nat, 1);
	} else
	    if ((regnum >= (IA64_GR0_REGNUM + 2)
		 && regnum <= (IA64_GR0_REGNUM + 3))
		|| (regnum >= (IA64_GR0_REGNUM + 8)
		    && regnum <= (IA64_GR0_REGNUM + 15))) {
		for (i = 0;
		     i <
		     (sizeof(gr_reg_to_ptreg_index) /
		      sizeof(gr_reg_to_ptreg_index[0])); i++)
			if (gr_reg_to_ptreg_index[0].reg == regnum) {
				*((unsigned long *)
				  (((void *)ptregs) +
				   gr_reg_to_ptreg_index[i].ptregoff)) = reg;
				break;
			}
	} else if (regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7))
		switch (regnum) {
		case IA64_BR0_REGNUM:
		case IA64_BR0_REGNUM + 6:
		case IA64_BR0_REGNUM + 7:
			for (i = 0; i < (sizeof(br_reg_to_ptreg_index) /
					 sizeof(br_reg_to_ptreg_index[0])); i++)
				if (br_reg_to_ptreg_index[i].reg == regnum) {
					*((unsigned long *)
					  (((void *)ptregs) +
					   br_reg_to_ptreg_index[i].ptregoff)) =
			 reg;
					break;
				}
			break;
		case IA64_BR0_REGNUM + 1:
		case IA64_BR0_REGNUM + 2:
		case IA64_BR0_REGNUM + 3:
		case IA64_BR0_REGNUM + 4:
		case IA64_BR0_REGNUM + 5:
			unw_access_br(info, regnum - IA64_BR0_REGNUM, &reg, 1);
			break;
	} else if (regnum >= IA64_FR0_REGNUM
		   && regnum <= (IA64_FR0_REGNUM + 127))
		switch (regnum) {
		case IA64_FR0_REGNUM + 6:
		case IA64_FR0_REGNUM + 7:
		case IA64_FR0_REGNUM + 8:
		case IA64_FR0_REGNUM + 9:
		case IA64_FR0_REGNUM + 10:
		case IA64_FR0_REGNUM + 11:
		case IA64_FR0_REGNUM + 12:
			freg.u.bits[0] = reg;
			kgdb_hex2long(&ptr, &freg.u.bits[1]);
			*(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) =
			    freg;
			break;
		default:
			break;
	} else if (regnum == IA64_IP_REGNUM)
		ptregs->cr_iip = reg;
	else if (regnum == IA64_CFM_REGNUM)
		ptregs->cr_ifs = reg;
	else if (regnum == IA64_PSR_REGNUM)
		ptregs->cr_ipsr = reg;
	else if (regnum == IA64_PR_REGNUM)
		ptregs->pr = reg;
	else if (regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM)
		switch (regnum) {
		case IA64_CSD_REGNUM:
			ptregs->ar_csd = reg;
			break;
		case IA64_SSD_REGNUM:
			ptregs->ar_ssd = reg;
		case IA64_UNAT_REGNUM:
			ptregs->ar_unat = reg;
		case IA64_RNAT_REGNUM:
			unw_access_ar(info, UNW_AR_RNAT, &reg, 1);
			break;
		case IA64_BSPSTORE_REGNUM:
			unw_access_ar(info, UNW_AR_BSPSTORE, &reg, 1);
			break;
		case IA64_PFS_REGNUM:
			unw_access_ar(info, UNW_AR_PFS, &reg, 1);
			break;
		case IA64_LC_REGNUM:
			unw_access_ar(info, UNW_AR_LC, &reg, 1);
			break;
		case IA64_EC_REGNUM:
			unw_access_ar(info, UNW_AR_EC, &reg, 1);
			break;
		case IA64_FPSR_REGNUM:
			ptregs->ar_fpsr = reg;
			break;
		case IA64_RSC_REGNUM:
			ptregs->ar_rsc = reg;
			break;
		case IA64_CCV_REGNUM:
			unw_access_ar(info, UNW_AR_CCV, &reg, 1);
			break;
	} else
		strcpy(outbuffer, "E01");

	return;
}