Exemplo n.º 1
0
static int check_and_rewind_pc(char *put_str, char *arg)
{
	unsigned long addr = lookup_addr(arg);
	int offset = 0;

	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));
#ifdef CONFIG_X86
	/* On x86 a breakpoint stop requires it to be decremented */
	if (addr + 1 == kgdbts_regs.ip)
		offset = -1;
#endif
	if (strcmp(arg, "silent") &&
		instruction_pointer(&kgdbts_regs) + offset != addr) {
		eprintk("kgdbts: BP mismatch %lx expected %lx\n",
			   instruction_pointer(&kgdbts_regs) + offset, addr);
		return 1;
	}
#ifdef CONFIG_X86
	/* On x86 adjust the instruction pointer if needed */
	kgdbts_regs.ip += offset;
#endif
	return 0;
}
Exemplo n.º 2
0
static void emul_sstep_get(char *arg)
{
	if (!arch_needs_sstep_emulation) {
		fill_get_buf(arg);
		return;
	}
	switch (sstep_state) {
	case 0:
		v2printk("Emulate single step\n");
		/* Start by looking at the current PC */
		fill_get_buf("g");
		break;
	case 1:
		/* set breakpoint */
		break_helper("Z0", NULL, sstep_addr);
		break;
	case 2:
		/* Continue */
		fill_get_buf("c");
		break;
	case 3:
		/* Clear breakpoint */
		break_helper("z0", NULL, sstep_addr);
		break;
	default:
		eprintk("kgdbts: ERROR failed sstep get emulation\n");
	}
	sstep_state++;
}
Exemplo n.º 3
0
static int check_and_rewind_pc(char *put_str, char *arg)
{
	unsigned long addr = lookup_addr(arg);
	unsigned long ip;
	int offset = 0;

	kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs,
		 NUMREGBYTES);
	gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
	ip = instruction_pointer(&kgdbts_regs);
	v2printk("Stopped at IP: %lx\n", ip);
#ifdef GDB_ADJUSTS_BREAK_OFFSET
	/* On some arches, a breakpoint stop requires it to be decremented */
	if (addr + BREAK_INSTR_SIZE == ip)
		offset = -BREAK_INSTR_SIZE;
#endif
	if (strcmp(arg, "silent") && ip + offset != addr) {
		eprintk("kgdbts: BP mismatch %lx expected %lx\n",
			   ip + offset, addr);
		return 1;
	}
	/* Readjust the instruction pointer if needed */
	ip += offset;
#ifdef GDB_ADJUSTS_BREAK_OFFSET
	instruction_pointer_set(&kgdbts_regs, ip);
#endif
	return 0;
}
Exemplo n.º 4
0
static int put_cont_catch(char *put_str, char *arg)
{
	/* This is at the end of the test and we catch any and all input */
	v2printk("kgdbts: cleanup task: %lx\n", sstep_thread_id);
	ts.idx--;
	return 0;
}
Exemplo n.º 5
0
static int check_single_step(char *put_str, char *arg)
{
	unsigned long addr = lookup_addr(arg);
	static int matched_id;

	/*
	 * From an arch indepent point of view the instruction pointer
	 * should be on a different instruction
	 */
	kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs,
		 NUMREGBYTES);
	gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
	v2printk("Singlestep stopped at IP: %lx\n",
		   instruction_pointer(&kgdbts_regs));

	if (sstep_thread_id != cont_thread_id) {
		/*
		 * Ensure we stopped in the same thread id as before, else the
		 * debugger should continue until the original thread that was
		 * single stepped is scheduled again, emulating gdb's behavior.
		 */
		v2printk("ThrID does not match: %lx\n", cont_thread_id);
		if (arch_needs_sstep_emulation) {
			if (matched_id &&
			    instruction_pointer(&kgdbts_regs) != addr)
				goto continue_test;
			matched_id++;
			ts.idx -= 2;
			sstep_state = 0;
			return 0;
		}
		cont_instead_of_sstep = 1;
		ts.idx -= 4;
		return 0;
	}
continue_test:
	matched_id = 0;
	if (instruction_pointer(&kgdbts_regs) == addr) {
		eprintk("kgdbts: SingleStep failed at %lx\n",
			   instruction_pointer(&kgdbts_regs));
		return 1;
	}

	return 0;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
static int check_and_rewind_pc(char *put_str, char *arg)
{
	unsigned long addr = lookup_addr(arg);
	unsigned long ip;
	int offset = 0;

	kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs,
		 NUMREGBYTES);
	gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
	ip = instruction_pointer(&kgdbts_regs);
	v2printk("Stopped at IP: %lx\n", ip);
#ifdef GDB_ADJUSTS_BREAK_OFFSET
	/* On some arches, a breakpoint stop requires it to be decremented */
	if (addr + BREAK_INSTR_SIZE == ip)
		offset = -BREAK_INSTR_SIZE;
#endif

	if (arch_needs_sstep_emulation && sstep_addr &&
	    ip + offset == sstep_addr &&
	    ((!strcmp(arg, "sys_open") || !strcmp(arg, "do_fork")))) {
		/* This is special case for emulated single step */
		v2printk("Emul: rewind hit single step bp\n");
		restart_from_top_after_write = 1;
	} else if (strcmp(arg, "silent") && ip + offset != addr) {
		eprintk("kgdbts: BP mismatch %lx expected %lx\n",
			   ip + offset, addr);
		return 1;
	}
	/* Readjust the instruction pointer if needed */
	ip += offset;
	cont_addr = ip;
#ifdef GDB_ADJUSTS_BREAK_OFFSET
	instruction_pointer_set(&kgdbts_regs, ip);
#endif
	return 0;
}
Exemplo n.º 8
0
static void fill_get_buf(char *buf)
{
	unsigned char checksum = 0;
	int count = 0;
	char ch;

	strcpy(get_buf, "$");
	strcat(get_buf, buf);
	while ((ch = buf[count])) {
		checksum += ch;
		count++;
	}
	strcat(get_buf, "#");
	get_buf[count + 2] = hex_asc_hi(checksum);
	get_buf[count + 3] = hex_asc_lo(checksum);
	get_buf[count + 4] = '\0';
	v2printk("get%i: %s\n", ts.idx, get_buf);
}
Exemplo n.º 9
0
static int check_single_step(char *put_str, char *arg)
{
	unsigned long addr = lookup_addr(arg);
	/*
	 * From an arch indepent point of view the instruction pointer
	 * should be on a different instruction
	 */
	kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs,
		 NUMREGBYTES);
	gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
	v2printk("Singlestep stopped at IP: %lx\n",
		   instruction_pointer(&kgdbts_regs));
	if (instruction_pointer(&kgdbts_regs) == addr) {
		eprintk("kgdbts: SingleStep failed at %lx\n",
			   instruction_pointer(&kgdbts_regs));
		return 1;
	}

	return 0;
}
Exemplo n.º 10
0
static int run_simple_test(int is_get_char, int chr)
{
	int ret = 0;
	if (is_get_char) {
		/* Send an ACK on the get if a prior put completed and set the
		 * send ack variable
		 */
		if (send_ack) {
			send_ack = 0;
			return '+';
		}
		/* On the first get char, fill the transmit buffer and then
		 * take from the get_string.
		 */
		if (get_buf_cnt == 0) {
			if (ts.tst[ts.idx].get_handler)
				ts.tst[ts.idx].get_handler(ts.tst[ts.idx].get);
			else
				fill_get_buf(ts.tst[ts.idx].get);
		}

		if (get_buf[get_buf_cnt] == '\0') {
			eprintk("kgdbts: ERROR GET: EOB on '%s' at %i\n",
			   ts.name, ts.idx);
			get_buf_cnt = 0;
			fill_get_buf("D");
		}
		ret = get_buf[get_buf_cnt];
		get_buf_cnt++;
		return ret;
	}

	/* This callback is a put char which is when kgdb sends data to
	 * this I/O module.
	 */
	if (ts.tst[ts.idx].get[0] == '\0' &&
		ts.tst[ts.idx].put[0] == '\0') {
		eprintk("kgdbts: ERROR: beyond end of test on"
			   " '%s' line %i\n", ts.name, ts.idx);
		return 0;
	}

	if (put_buf_cnt >= BUFMAX) {
		eprintk("kgdbts: ERROR: put buffer overflow on"
			   " '%s' line %i\n", ts.name, ts.idx);
		put_buf_cnt = 0;
		return 0;
	}
	/* Ignore everything until the first valid packet start '$' */
	if (put_buf_cnt == 0 && chr != '$')
		return 0;

	put_buf[put_buf_cnt] = chr;
	put_buf_cnt++;

	/* End of packet == #XX so look for the '#' */
	if (put_buf_cnt > 3 && put_buf[put_buf_cnt - 3] == '#') {
		if (put_buf_cnt >= BUFMAX) {
			eprintk("kgdbts: ERROR: put buffer overflow on"
				" '%s' line %i\n", ts.name, ts.idx);
			put_buf_cnt = 0;
			return 0;
		}
		put_buf[put_buf_cnt] = '\0';
		v2printk("put%i: %s\n", ts.idx, put_buf);
		/* Trigger check here */
		if (ts.validate_put && ts.validate_put(put_buf)) {
			eprintk("kgdbts: ERROR PUT: end of test "
			   "buffer on '%s' line %i expected %s got %s\n",
			   ts.name, ts.idx, ts.tst[ts.idx].put, put_buf);
		}
		ts.idx++;
		put_buf_cnt = 0;
		get_buf_cnt = 0;
		send_ack = 1;
	}
	return 0;
}
Exemplo n.º 11
0
/* This is noinline such that it can be used for a single location to
 * place a breakpoint
 */
static noinline void kgdbts_break_test(void)
{
	v2printk("kgdbts: breakpoint complete\n");
}