diff options
| -rw-r--r-- | arch/m68k/include/asm/ptrace.h | 17 | ||||
| -rw-r--r-- | arch/m68k/kernel/ptrace.c | 75 |
2 files changed, 38 insertions, 54 deletions
diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h index 8c9194b98548..117adb1e4806 100644 --- a/arch/m68k/include/asm/ptrace.h +++ b/arch/m68k/include/asm/ptrace.h | |||
| @@ -71,6 +71,8 @@ struct switch_stack { | |||
| 71 | #define PTRACE_GETFPREGS 14 | 71 | #define PTRACE_GETFPREGS 14 |
| 72 | #define PTRACE_SETFPREGS 15 | 72 | #define PTRACE_SETFPREGS 15 |
| 73 | 73 | ||
| 74 | #define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */ | ||
| 75 | |||
| 74 | #ifdef __KERNEL__ | 76 | #ifdef __KERNEL__ |
| 75 | 77 | ||
| 76 | #ifndef PS_S | 78 | #ifndef PS_S |
| @@ -82,6 +84,21 @@ struct switch_stack { | |||
| 82 | #define instruction_pointer(regs) ((regs)->pc) | 84 | #define instruction_pointer(regs) ((regs)->pc) |
| 83 | #define profile_pc(regs) instruction_pointer(regs) | 85 | #define profile_pc(regs) instruction_pointer(regs) |
| 84 | extern void show_regs(struct pt_regs *); | 86 | extern void show_regs(struct pt_regs *); |
| 87 | |||
| 88 | /* | ||
| 89 | * These are defined as per linux/ptrace.h, which see. | ||
| 90 | */ | ||
| 91 | struct task_struct; | ||
| 92 | |||
| 93 | #ifdef CONFIG_MMU | ||
| 94 | #define arch_has_single_step() (1) | ||
| 95 | extern void user_enable_single_step(struct task_struct *); | ||
| 96 | extern void user_disable_single_step(struct task_struct *); | ||
| 97 | |||
| 98 | #define arch_has_block_step() (1) | ||
| 99 | extern void user_enable_block_step(struct task_struct *); | ||
| 100 | #endif | ||
| 101 | |||
| 85 | #endif /* __KERNEL__ */ | 102 | #endif /* __KERNEL__ */ |
| 86 | #endif /* __ASSEMBLY__ */ | 103 | #endif /* __ASSEMBLY__ */ |
| 87 | #endif /* _M68K_PTRACE_H */ | 104 | #endif /* _M68K_PTRACE_H */ |
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 2075543c2d92..bd0842059d11 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c | |||
| @@ -35,7 +35,9 @@ | |||
| 35 | #define SR_MASK 0x001f | 35 | #define SR_MASK 0x001f |
| 36 | 36 | ||
| 37 | /* sets the trace bits. */ | 37 | /* sets the trace bits. */ |
| 38 | #define TRACE_BITS 0x8000 | 38 | #define TRACE_BITS 0xC000 |
| 39 | #define T1_BIT 0x8000 | ||
| 40 | #define T0_BIT 0x4000 | ||
| 39 | 41 | ||
| 40 | /* Find the stack offset for a register, relative to thread.esp0. */ | 42 | /* Find the stack offset for a register, relative to thread.esp0. */ |
| 41 | #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) | 43 | #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) |
| @@ -118,18 +120,30 @@ void ptrace_disable(struct task_struct *child) | |||
| 118 | singlestep_disable(child); | 120 | singlestep_disable(child); |
| 119 | } | 121 | } |
| 120 | 122 | ||
| 123 | void user_enable_single_step(struct task_struct *child) | ||
| 124 | { | ||
| 125 | unsigned long tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); | ||
| 126 | put_reg(child, PT_SR, tmp | (T1_BIT << 16)); | ||
| 127 | set_tsk_thread_flag(child, TIF_DELAYED_TRACE); | ||
| 128 | } | ||
| 129 | |||
| 130 | void user_enable_block_step(struct task_struct *child) | ||
| 131 | { | ||
| 132 | unsigned long tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); | ||
| 133 | put_reg(child, PT_SR, tmp | (T0_BIT << 16)); | ||
| 134 | } | ||
| 135 | |||
| 136 | void user_disable_single_step(struct task_struct *child) | ||
| 137 | { | ||
| 138 | singlestep_disable(child); | ||
| 139 | } | ||
| 140 | |||
| 121 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 141 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
| 122 | { | 142 | { |
| 123 | unsigned long tmp; | 143 | unsigned long tmp; |
| 124 | int i, ret = 0; | 144 | int i, ret = 0; |
| 125 | 145 | ||
| 126 | switch (request) { | 146 | switch (request) { |
| 127 | /* when I and D space are separate, these will need to be fixed. */ | ||
| 128 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | ||
| 129 | case PTRACE_PEEKDATA: | ||
| 130 | ret = generic_ptrace_peekdata(child, addr, data); | ||
| 131 | break; | ||
| 132 | |||
| 133 | /* read the word at location addr in the USER area. */ | 147 | /* read the word at location addr in the USER area. */ |
| 134 | case PTRACE_PEEKUSR: | 148 | case PTRACE_PEEKUSR: |
| 135 | if (addr & 3) | 149 | if (addr & 3) |
| @@ -153,12 +167,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 153 | ret = put_user(tmp, (unsigned long *)data); | 167 | ret = put_user(tmp, (unsigned long *)data); |
| 154 | break; | 168 | break; |
| 155 | 169 | ||
| 156 | /* when I and D space are separate, this will have to be fixed. */ | ||
| 157 | case PTRACE_POKETEXT: /* write the word at location addr. */ | ||
| 158 | case PTRACE_POKEDATA: | ||
| 159 | ret = generic_ptrace_pokedata(child, addr, data); | ||
| 160 | break; | ||
| 161 | |||
| 162 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 170 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
| 163 | if (addr & 3) | 171 | if (addr & 3) |
| 164 | goto out_eio; | 172 | goto out_eio; |
| @@ -185,47 +193,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 185 | goto out_eio; | 193 | goto out_eio; |
| 186 | break; | 194 | break; |
| 187 | 195 | ||
| 188 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | ||
| 189 | case PTRACE_CONT: /* restart after signal. */ | ||
| 190 | if (!valid_signal(data)) | ||
| 191 | goto out_eio; | ||
| 192 | |||
| 193 | if (request == PTRACE_SYSCALL) | ||
| 194 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 195 | else | ||
| 196 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 197 | child->exit_code = data; | ||
| 198 | singlestep_disable(child); | ||
| 199 | wake_up_process(child); | ||
| 200 | break; | ||
| 201 | |||
| 202 | /* | ||
| 203 | * make the child exit. Best I can do is send it a sigkill. | ||
| 204 | * perhaps it should be put in the status that it wants to | ||
| 205 | * exit. | ||
| 206 | */ | ||
| 207 | case PTRACE_KILL: | ||
| 208 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
| 209 | break; | ||
| 210 | child->exit_code = SIGKILL; | ||
| 211 | singlestep_disable(child); | ||
| 212 | wake_up_process(child); | ||
| 213 | break; | ||
| 214 | |||
| 215 | case PTRACE_SINGLESTEP: /* set the trap flag. */ | ||
| 216 | if (!valid_signal(data)) | ||
| 217 | goto out_eio; | ||
| 218 | |||
| 219 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 220 | tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); | ||
| 221 | put_reg(child, PT_SR, tmp); | ||
| 222 | set_tsk_thread_flag(child, TIF_DELAYED_TRACE); | ||
| 223 | |||
| 224 | child->exit_code = data; | ||
| 225 | /* give it a chance to run. */ | ||
| 226 | wake_up_process(child); | ||
| 227 | break; | ||
| 228 | |||
| 229 | case PTRACE_GETREGS: /* Get all gp regs from the child. */ | 196 | case PTRACE_GETREGS: /* Get all gp regs from the child. */ |
| 230 | for (i = 0; i < 19; i++) { | 197 | for (i = 0; i < 19; i++) { |
| 231 | tmp = get_reg(child, i); | 198 | tmp = get_reg(child, i); |
