step.c (e1f287735c1e58c653b516931b5d3dd899edcb77) | step.c (10faa81e102e2b7695f386812055cd2ef9e44b4c) |
---|---|
1/* 2 * x86 single-step support code, common to 32-bit and 64-bit. 3 */ 4#include <linux/sched.h> 5#include <linux/mm.h> 6#include <linux/ptrace.h> 7 8#ifdef CONFIG_X86_32 --- 93 unchanged lines hidden (view full) --- 102 case 0x9c: 103 default: 104 return 0; 105 } 106 } 107 return 0; 108} 109 | 1/* 2 * x86 single-step support code, common to 32-bit and 64-bit. 3 */ 4#include <linux/sched.h> 5#include <linux/mm.h> 6#include <linux/ptrace.h> 7 8#ifdef CONFIG_X86_32 --- 93 unchanged lines hidden (view full) --- 102 case 0x9c: 103 default: 104 return 0; 105 } 106 } 107 return 0; 108} 109 |
110void user_enable_single_step(struct task_struct *child) | 110/* 111 * Enable single-stepping. Return nonzero if user mode is not using TF itself. 112 */ 113static int enable_single_step(struct task_struct *child) |
111{ 112 struct pt_regs *regs = task_pt_regs(child); 113 114 /* 115 * Always set TIF_SINGLESTEP - this guarantees that 116 * we single-step system calls etc.. This will also 117 * cause us to set TF when returning to user mode. 118 */ 119 set_tsk_thread_flag(child, TIF_SINGLESTEP); 120 121 /* 122 * If TF was already set, don't do anything else 123 */ 124 if (regs->eflags & X86_EFLAGS_TF) | 114{ 115 struct pt_regs *regs = task_pt_regs(child); 116 117 /* 118 * Always set TIF_SINGLESTEP - this guarantees that 119 * we single-step system calls etc.. This will also 120 * cause us to set TF when returning to user mode. 121 */ 122 set_tsk_thread_flag(child, TIF_SINGLESTEP); 123 124 /* 125 * If TF was already set, don't do anything else 126 */ 127 if (regs->eflags & X86_EFLAGS_TF) |
125 return; | 128 return 0; |
126 127 /* Set TF on the kernel stack.. */ 128 regs->eflags |= X86_EFLAGS_TF; 129 130 /* 131 * ..but if TF is changed by the instruction we will trace, 132 * don't mark it as being "us" that set it, so that we 133 * won't clear it by hand later. 134 */ 135 if (is_setting_trap_flag(child, regs)) | 129 130 /* Set TF on the kernel stack.. */ 131 regs->eflags |= X86_EFLAGS_TF; 132 133 /* 134 * ..but if TF is changed by the instruction we will trace, 135 * don't mark it as being "us" that set it, so that we 136 * won't clear it by hand later. 137 */ 138 if (is_setting_trap_flag(child, regs)) |
136 return; | 139 return 0; |
137 138 set_tsk_thread_flag(child, TIF_FORCED_TF); | 140 141 set_tsk_thread_flag(child, TIF_FORCED_TF); |
142 143 return 1; |
|
139} 140 | 144} 145 |
146/* 147 * Install this value in MSR_IA32_DEBUGCTLMSR whenever child is running. 148 */ 149static void write_debugctlmsr(struct task_struct *child, unsigned long val) 150{ 151 child->thread.debugctlmsr = val; 152 153 if (child != current) 154 return; 155 156#ifdef CONFIG_X86_64 157 wrmsrl(MSR_IA32_DEBUGCTLMSR, val); 158#else 159 wrmsr(MSR_IA32_DEBUGCTLMSR, val, 0); 160#endif 161} 162 163/* 164 * Enable single or block step. 165 */ 166static void enable_step(struct task_struct *child, bool block) 167{ 168 /* 169 * Make sure block stepping (BTF) is not enabled unless it should be. 170 * Note that we don't try to worry about any is_setting_trap_flag() 171 * instructions after the first when using block stepping. 172 * So noone should try to use debugger block stepping in a program 173 * that uses user-mode single stepping itself. 174 */ 175 if (enable_single_step(child) && block) { 176 set_tsk_thread_flag(child, TIF_DEBUGCTLMSR); 177 write_debugctlmsr(child, DEBUGCTLMSR_BTF); 178 } else if (test_and_clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR)) { 179 write_debugctlmsr(child, 0); 180 } 181} 182 183void user_enable_single_step(struct task_struct *child) 184{ 185 enable_step(child, 0); 186} 187 188void user_enable_block_step(struct task_struct *child) 189{ 190 enable_step(child, 1); 191} 192 |
|
141void user_disable_single_step(struct task_struct *child) 142{ | 193void user_disable_single_step(struct task_struct *child) 194{ |
195 /* 196 * Make sure block stepping (BTF) is disabled. 197 */ 198 if (test_and_clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR)) 199 write_debugctlmsr(child, 0); 200 |
|
143 /* Always clear TIF_SINGLESTEP... */ 144 clear_tsk_thread_flag(child, TIF_SINGLESTEP); 145 146 /* But touch TF only if it was set by us.. */ 147 if (test_and_clear_tsk_thread_flag(child, TIF_FORCED_TF)) 148 task_pt_regs(child)->eflags &= ~X86_EFLAGS_TF; 149} | 201 /* Always clear TIF_SINGLESTEP... */ 202 clear_tsk_thread_flag(child, TIF_SINGLESTEP); 203 204 /* But touch TF only if it was set by us.. */ 205 if (test_and_clear_tsk_thread_flag(child, TIF_FORCED_TF)) 206 task_pt_regs(child)->eflags &= ~X86_EFLAGS_TF; 207} |