step.c 4.78 KB
Newer Older
Roland McGrath's avatar
Roland McGrath committed
1 2 3 4 5 6 7
/*
 * x86 single-step support code, common to 32-bit and 64-bit.
 */
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/ptrace.h>

8
unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs)
Roland McGrath's avatar
Roland McGrath committed
9 10 11
{
	unsigned long addr, seg;

12
	addr = regs->ip;
Roland McGrath's avatar
Roland McGrath committed
13
	seg = regs->cs & 0xffff;
14
	if (v8086_mode(regs)) {
15 16 17
		addr = (addr & 0xffff) + (seg << 4);
		return addr;
	}
Roland McGrath's avatar
Roland McGrath committed
18 19 20 21 22 23 24

	/*
	 * We'll assume that the code segments in the GDT
	 * are all zero-based. That is largely true: the
	 * TLS segments are used for data, and the PNPBIOS
	 * and APM bios ones we just ignore here.
	 */
25
	if ((seg & SEGMENT_TI_MASK) == SEGMENT_LDT) {
Roland McGrath's avatar
Roland McGrath committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
		u32 *desc;
		unsigned long base;

		seg &= ~7UL;

		mutex_lock(&child->mm->context.lock);
		if (unlikely((seg >> 3) >= child->mm->context.size))
			addr = -1L; /* bogus selector, access would fault */
		else {
			desc = child->mm->context.ldt + seg;
			base = ((desc[0] >> 16) |
				((desc[1] & 0xff) << 16) |
				(desc[1] & 0xff000000));

			/* 16-bit code segment? */
			if (!((desc[1] >> 22) & 1))
				addr &= 0xffff;
			addr += base;
		}
		mutex_unlock(&child->mm->context.lock);
	}

	return addr;
}

static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
{
	int i, copied;
	unsigned char opcode[15];
55
	unsigned long addr = convert_ip_to_linear(child, regs);
Roland McGrath's avatar
Roland McGrath committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72

	copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
	for (i = 0; i < copied; i++) {
		switch (opcode[i]) {
		/* popf and iret */
		case 0x9d: case 0xcf:
			return 1;

			/* CHECKME: 64 65 */

		/* opcode and address size prefixes */
		case 0x66: case 0x67:
			continue;
		/* irrelevant prefixes (segment overrides and repeats) */
		case 0x26: case 0x2e:
		case 0x36: case 0x3e:
		case 0x64: case 0x65:
Roland McGrath's avatar
Roland McGrath committed
73
		case 0xf0: case 0xf2: case 0xf3:
Roland McGrath's avatar
Roland McGrath committed
74 75
			continue;

76
#ifdef CONFIG_X86_64
Roland McGrath's avatar
Roland McGrath committed
77 78 79 80 81 82
		case 0x40 ... 0x4f:
			if (regs->cs != __USER_CS)
				/* 32-bit mode: register increment */
				return 0;
			/* 64-bit mode: REX prefix */
			continue;
83
#endif
Roland McGrath's avatar
Roland McGrath committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

			/* CHECKME: f2, f3 */

		/*
		 * pushf: NOTE! We should probably not let
		 * the user see the TF bit being set. But
		 * it's more pain than it's worth to avoid
		 * it, and a debugger could emulate this
		 * all in user space if it _really_ cares.
		 */
		case 0x9c:
		default:
			return 0;
		}
	}
	return 0;
}

102 103 104 105
/*
 * Enable single-stepping.  Return nonzero if user mode is not using TF itself.
 */
static int enable_single_step(struct task_struct *child)
Roland McGrath's avatar
Roland McGrath committed
106 107 108 109 110 111 112 113 114 115 116 117 118
{
	struct pt_regs *regs = task_pt_regs(child);

	/*
	 * Always set TIF_SINGLESTEP - this guarantees that
	 * we single-step system calls etc..  This will also
	 * cause us to set TF when returning to user mode.
	 */
	set_tsk_thread_flag(child, TIF_SINGLESTEP);

	/*
	 * If TF was already set, don't do anything else
	 */
119
	if (regs->flags & X86_EFLAGS_TF)
120
		return 0;
Roland McGrath's avatar
Roland McGrath committed
121 122

	/* Set TF on the kernel stack.. */
123
	regs->flags |= X86_EFLAGS_TF;
Roland McGrath's avatar
Roland McGrath committed
124 125 126 127 128 129 130

	/*
	 * ..but if TF is changed by the instruction we will trace,
	 * don't mark it as being "us" that set it, so that we
	 * won't clear it by hand later.
	 */
	if (is_setting_trap_flag(child, regs))
131
		return 0;
Roland McGrath's avatar
Roland McGrath committed
132

133
	set_tsk_thread_flag(child, TIF_FORCED_TF);
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164

	return 1;
}

/*
 * Install this value in MSR_IA32_DEBUGCTLMSR whenever child is running.
 */
static void write_debugctlmsr(struct task_struct *child, unsigned long val)
{
	child->thread.debugctlmsr = val;

	if (child != current)
		return;

	wrmsrl(MSR_IA32_DEBUGCTLMSR, val);
}

/*
 * Enable single or block step.
 */
static void enable_step(struct task_struct *child, bool block)
{
	/*
	 * Make sure block stepping (BTF) is not enabled unless it should be.
	 * Note that we don't try to worry about any is_setting_trap_flag()
	 * instructions after the first when using block stepping.
	 * So noone should try to use debugger block stepping in a program
	 * that uses user-mode single stepping itself.
	 */
	if (enable_single_step(child) && block) {
		set_tsk_thread_flag(child, TIF_DEBUGCTLMSR);
165 166 167 168
		write_debugctlmsr(child,
				  child->thread.debugctlmsr | DEBUGCTLMSR_BTF);
	} else {
	    write_debugctlmsr(child,
Jan Beulich's avatar
Jan Beulich committed
169
			      child->thread.debugctlmsr & ~DEBUGCTLMSR_BTF);
170 171 172

	    if (!child->thread.debugctlmsr)
		    clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR);
173 174 175 176 177 178 179 180 181 182 183
	}
}

void user_enable_single_step(struct task_struct *child)
{
	enable_step(child, 0);
}

void user_enable_block_step(struct task_struct *child)
{
	enable_step(child, 1);
Roland McGrath's avatar
Roland McGrath committed
184 185 186 187
}

void user_disable_single_step(struct task_struct *child)
{
188 189 190
	/*
	 * Make sure block stepping (BTF) is disabled.
	 */
191
	write_debugctlmsr(child,
Jan Beulich's avatar
Jan Beulich committed
192
			  child->thread.debugctlmsr & ~DEBUGCTLMSR_BTF);
193 194 195

	if (!child->thread.debugctlmsr)
		clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR);
196

Roland McGrath's avatar
Roland McGrath committed
197 198 199 200
	/* Always clear TIF_SINGLESTEP... */
	clear_tsk_thread_flag(child, TIF_SINGLESTEP);

	/* But touch TF only if it was set by us.. */
201
	if (test_and_clear_tsk_thread_flag(child, TIF_FORCED_TF))
202
		task_pt_regs(child)->flags &= ~X86_EFLAGS_TF;
Roland McGrath's avatar
Roland McGrath committed
203
}