~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/alpha/kernel/ptrace.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ptrace.c */
 
2
/* By Ross Biro 1/23/92 */
 
3
/* edited by Linus Torvalds */
 
4
/* mangled further by Bob Manson (manson@santafe.edu) */
 
5
/* more mutilation by David Mosberger (davidm@azstarnet.com) */
 
6
 
 
7
#include <linux/kernel.h>
 
8
#include <linux/sched.h>
 
9
#include <linux/mm.h>
 
10
#include <linux/smp.h>
 
11
#include <linux/errno.h>
 
12
#include <linux/ptrace.h>
 
13
#include <linux/user.h>
 
14
#include <linux/security.h>
 
15
#include <linux/signal.h>
 
16
 
 
17
#include <asm/uaccess.h>
 
18
#include <asm/pgtable.h>
 
19
#include <asm/system.h>
 
20
#include <asm/fpu.h>
 
21
 
 
22
#include "proto.h"
 
23
 
 
24
#define DEBUG   DBG_MEM
 
25
#undef DEBUG
 
26
 
 
27
#ifdef DEBUG
 
28
enum {
 
29
        DBG_MEM         = (1<<0),
 
30
        DBG_BPT         = (1<<1),
 
31
        DBG_MEM_ALL     = (1<<2)
 
32
};
 
33
#define DBG(fac,args)   {if ((fac) & DEBUG) printk args;}
 
34
#else
 
35
#define DBG(fac,args)
 
36
#endif
 
37
 
 
38
#define BREAKINST       0x00000080      /* call_pal bpt */
 
39
 
 
40
/*
 
41
 * does not yet catch signals sent when the child dies.
 
42
 * in exit.c or in signal.c.
 
43
 */
 
44
 
 
45
/*
 
46
 * Processes always block with the following stack-layout:
 
47
 *
 
48
 *  +================================+ <---- task + 2*PAGE_SIZE
 
49
 *  | PALcode saved frame (ps, pc,   | ^
 
50
 *  | gp, a0, a1, a2)                | |
 
51
 *  +================================+ | struct pt_regs
 
52
 *  |                                | |
 
53
 *  | frame generated by SAVE_ALL    | |
 
54
 *  |                                | v
 
55
 *  +================================+
 
56
 *  |                                | ^
 
57
 *  | frame saved by do_switch_stack | | struct switch_stack
 
58
 *  |                                | v
 
59
 *  +================================+
 
60
 */
 
61
 
 
62
/* 
 
63
 * The following table maps a register index into the stack offset at
 
64
 * which the register is saved.  Register indices are 0-31 for integer
 
65
 * regs, 32-63 for fp regs, and 64 for the pc.  Notice that sp and
 
66
 * zero have no stack-slot and need to be treated specially (see
 
67
 * get_reg/put_reg below).
 
68
 */
 
69
enum {
 
70
        REG_R0 = 0, REG_F0 = 32, REG_FPCR = 63, REG_PC = 64
 
71
};
 
72
 
 
73
#define PT_REG(reg) \
 
74
  (PAGE_SIZE*2 - sizeof(struct pt_regs) + offsetof(struct pt_regs, reg))
 
75
 
 
76
#define SW_REG(reg) \
 
77
 (PAGE_SIZE*2 - sizeof(struct pt_regs) - sizeof(struct switch_stack) \
 
78
  + offsetof(struct switch_stack, reg))
 
79
 
 
80
static int regoff[] = {
 
81
        PT_REG(    r0), PT_REG(    r1), PT_REG(    r2), PT_REG(   r3),
 
82
        PT_REG(    r4), PT_REG(    r5), PT_REG(    r6), PT_REG(   r7),
 
83
        PT_REG(    r8), SW_REG(    r9), SW_REG(   r10), SW_REG(  r11),
 
84
        SW_REG(   r12), SW_REG(   r13), SW_REG(   r14), SW_REG(  r15),
 
85
        PT_REG(   r16), PT_REG(   r17), PT_REG(   r18), PT_REG(  r19),
 
86
        PT_REG(   r20), PT_REG(   r21), PT_REG(   r22), PT_REG(  r23),
 
87
        PT_REG(   r24), PT_REG(   r25), PT_REG(   r26), PT_REG(  r27),
 
88
        PT_REG(   r28), PT_REG(    gp),            -1,             -1,
 
89
        SW_REG(fp[ 0]), SW_REG(fp[ 1]), SW_REG(fp[ 2]), SW_REG(fp[ 3]),
 
90
        SW_REG(fp[ 4]), SW_REG(fp[ 5]), SW_REG(fp[ 6]), SW_REG(fp[ 7]),
 
91
        SW_REG(fp[ 8]), SW_REG(fp[ 9]), SW_REG(fp[10]), SW_REG(fp[11]),
 
92
        SW_REG(fp[12]), SW_REG(fp[13]), SW_REG(fp[14]), SW_REG(fp[15]),
 
93
        SW_REG(fp[16]), SW_REG(fp[17]), SW_REG(fp[18]), SW_REG(fp[19]),
 
94
        SW_REG(fp[20]), SW_REG(fp[21]), SW_REG(fp[22]), SW_REG(fp[23]),
 
95
        SW_REG(fp[24]), SW_REG(fp[25]), SW_REG(fp[26]), SW_REG(fp[27]),
 
96
        SW_REG(fp[28]), SW_REG(fp[29]), SW_REG(fp[30]), SW_REG(fp[31]),
 
97
        PT_REG(    pc)
 
98
};
 
99
 
 
100
static unsigned long zero;
 
101
 
 
102
/*
 
103
 * Get address of register REGNO in task TASK.
 
104
 */
 
105
static unsigned long *
 
106
get_reg_addr(struct task_struct * task, unsigned long regno)
 
107
{
 
108
        unsigned long *addr;
 
109
 
 
110
        if (regno == 30) {
 
111
                addr = &task_thread_info(task)->pcb.usp;
 
112
        } else if (regno == 65) {
 
113
                addr = &task_thread_info(task)->pcb.unique;
 
114
        } else if (regno == 31 || regno > 65) {
 
115
                zero = 0;
 
116
                addr = &zero;
 
117
        } else {
 
118
                addr = task_stack_page(task) + regoff[regno];
 
119
        }
 
120
        return addr;
 
121
}
 
122
 
 
123
/*
 
124
 * Get contents of register REGNO in task TASK.
 
125
 */
 
126
static unsigned long
 
127
get_reg(struct task_struct * task, unsigned long regno)
 
128
{
 
129
        /* Special hack for fpcr -- combine hardware and software bits.  */
 
130
        if (regno == 63) {
 
131
                unsigned long fpcr = *get_reg_addr(task, regno);
 
132
                unsigned long swcr
 
133
                  = task_thread_info(task)->ieee_state & IEEE_SW_MASK;
 
134
                swcr = swcr_update_status(swcr, fpcr);
 
135
                return fpcr | swcr;
 
136
        }
 
137
        return *get_reg_addr(task, regno);
 
138
}
 
139
 
 
140
/*
 
141
 * Write contents of register REGNO in task TASK.
 
142
 */
 
143
static int
 
144
put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
 
145
{
 
146
        if (regno == 63) {
 
147
                task_thread_info(task)->ieee_state
 
148
                  = ((task_thread_info(task)->ieee_state & ~IEEE_SW_MASK)
 
149
                     | (data & IEEE_SW_MASK));
 
150
                data = (data & FPCR_DYN_MASK) | ieee_swcr_to_fpcr(data);
 
151
        }
 
152
        *get_reg_addr(task, regno) = data;
 
153
        return 0;
 
154
}
 
155
 
 
156
static inline int
 
157
read_int(struct task_struct *task, unsigned long addr, int * data)
 
158
{
 
159
        int copied = access_process_vm(task, addr, data, sizeof(int), 0);
 
160
        return (copied == sizeof(int)) ? 0 : -EIO;
 
161
}
 
162
 
 
163
static inline int
 
164
write_int(struct task_struct *task, unsigned long addr, int data)
 
165
{
 
166
        int copied = access_process_vm(task, addr, &data, sizeof(int), 1);
 
167
        return (copied == sizeof(int)) ? 0 : -EIO;
 
168
}
 
169
 
 
170
/*
 
171
 * Set breakpoint.
 
172
 */
 
173
int
 
174
ptrace_set_bpt(struct task_struct * child)
 
175
{
 
176
        int displ, i, res, reg_b, nsaved = 0;
 
177
        unsigned int insn, op_code;
 
178
        unsigned long pc;
 
179
 
 
180
        pc  = get_reg(child, REG_PC);
 
181
        res = read_int(child, pc, (int *) &insn);
 
182
        if (res < 0)
 
183
                return res;
 
184
 
 
185
        op_code = insn >> 26;
 
186
        if (op_code >= 0x30) {
 
187
                /*
 
188
                 * It's a branch: instead of trying to figure out
 
189
                 * whether the branch will be taken or not, we'll put
 
190
                 * a breakpoint at either location.  This is simpler,
 
191
                 * more reliable, and probably not a whole lot slower
 
192
                 * than the alternative approach of emulating the
 
193
                 * branch (emulation can be tricky for fp branches).
 
194
                 */
 
195
                displ = ((s32)(insn << 11)) >> 9;
 
196
                task_thread_info(child)->bpt_addr[nsaved++] = pc + 4;
 
197
                if (displ)              /* guard against unoptimized code */
 
198
                        task_thread_info(child)->bpt_addr[nsaved++]
 
199
                          = pc + 4 + displ;
 
200
                DBG(DBG_BPT, ("execing branch\n"));
 
201
        } else if (op_code == 0x1a) {
 
202
                reg_b = (insn >> 16) & 0x1f;
 
203
                task_thread_info(child)->bpt_addr[nsaved++] = get_reg(child, reg_b);
 
204
                DBG(DBG_BPT, ("execing jump\n"));
 
205
        } else {
 
206
                task_thread_info(child)->bpt_addr[nsaved++] = pc + 4;
 
207
                DBG(DBG_BPT, ("execing normal insn\n"));
 
208
        }
 
209
 
 
210
        /* install breakpoints: */
 
211
        for (i = 0; i < nsaved; ++i) {
 
212
                res = read_int(child, task_thread_info(child)->bpt_addr[i],
 
213
                               (int *) &insn);
 
214
                if (res < 0)
 
215
                        return res;
 
216
                task_thread_info(child)->bpt_insn[i] = insn;
 
217
                DBG(DBG_BPT, ("    -> next_pc=%lx\n",
 
218
                              task_thread_info(child)->bpt_addr[i]));
 
219
                res = write_int(child, task_thread_info(child)->bpt_addr[i],
 
220
                                BREAKINST);
 
221
                if (res < 0)
 
222
                        return res;
 
223
        }
 
224
        task_thread_info(child)->bpt_nsaved = nsaved;
 
225
        return 0;
 
226
}
 
227
 
 
228
/*
 
229
 * Ensure no single-step breakpoint is pending.  Returns non-zero
 
230
 * value if child was being single-stepped.
 
231
 */
 
232
int
 
233
ptrace_cancel_bpt(struct task_struct * child)
 
234
{
 
235
        int i, nsaved = task_thread_info(child)->bpt_nsaved;
 
236
 
 
237
        task_thread_info(child)->bpt_nsaved = 0;
 
238
 
 
239
        if (nsaved > 2) {
 
240
                printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
 
241
                nsaved = 2;
 
242
        }
 
243
 
 
244
        for (i = 0; i < nsaved; ++i) {
 
245
                write_int(child, task_thread_info(child)->bpt_addr[i],
 
246
                          task_thread_info(child)->bpt_insn[i]);
 
247
        }
 
248
        return (nsaved != 0);
 
249
}
 
250
 
 
251
void user_enable_single_step(struct task_struct *child)
 
252
{
 
253
        /* Mark single stepping.  */
 
254
        task_thread_info(child)->bpt_nsaved = -1;
 
255
}
 
256
 
 
257
void user_disable_single_step(struct task_struct *child)
 
258
{
 
259
        ptrace_cancel_bpt(child);
 
260
}
 
261
 
 
262
/*
 
263
 * Called by kernel/ptrace.c when detaching..
 
264
 *
 
265
 * Make sure the single step bit is not set.
 
266
 */
 
267
void ptrace_disable(struct task_struct *child)
 
268
 
269
        user_disable_single_step(child);
 
270
}
 
271
 
 
272
long arch_ptrace(struct task_struct *child, long request,
 
273
                 unsigned long addr, unsigned long data)
 
274
{
 
275
        unsigned long tmp;
 
276
        size_t copied;
 
277
        long ret;
 
278
 
 
279
        switch (request) {
 
280
        /* When I and D space are separate, these will need to be fixed.  */
 
281
        case PTRACE_PEEKTEXT: /* read word at location addr. */
 
282
        case PTRACE_PEEKDATA:
 
283
                copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
 
284
                ret = -EIO;
 
285
                if (copied != sizeof(tmp))
 
286
                        break;
 
287
                
 
288
                force_successful_syscall_return();
 
289
                ret = tmp;
 
290
                break;
 
291
 
 
292
        /* Read register number ADDR. */
 
293
        case PTRACE_PEEKUSR:
 
294
                force_successful_syscall_return();
 
295
                ret = get_reg(child, addr);
 
296
                DBG(DBG_MEM, ("peek $%lu->%#lx\n", addr, ret));
 
297
                break;
 
298
 
 
299
        /* When I and D space are separate, this will have to be fixed.  */
 
300
        case PTRACE_POKETEXT: /* write the word at location addr. */
 
301
        case PTRACE_POKEDATA:
 
302
                ret = generic_ptrace_pokedata(child, addr, data);
 
303
                break;
 
304
 
 
305
        case PTRACE_POKEUSR: /* write the specified register */
 
306
                DBG(DBG_MEM, ("poke $%lu<-%#lx\n", addr, data));
 
307
                ret = put_reg(child, addr, data);
 
308
                break;
 
309
        default:
 
310
                ret = ptrace_request(child, request, addr, data);
 
311
                break;
 
312
        }
 
313
        return ret;
 
314
}
 
315
 
 
316
asmlinkage void
 
317
syscall_trace(void)
 
318
{
 
319
        if (!test_thread_flag(TIF_SYSCALL_TRACE))
 
320
                return;
 
321
        if (!(current->ptrace & PT_PTRACED))
 
322
                return;
 
323
        /* The 0x80 provides a way for the tracing parent to distinguish
 
324
           between a syscall stop and SIGTRAP delivery */
 
325
        ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
 
326
                                 ? 0x80 : 0));
 
327
 
 
328
        /*
 
329
         * This isn't the same as continuing with a signal, but it will do
 
330
         * for normal use.  strace only continues with a signal if the
 
331
         * stopping signal is not SIGTRAP.  -brl
 
332
         */
 
333
        if (current->exit_code) {
 
334
                send_sig(current->exit_code, current, 1);
 
335
                current->exit_code = 0;
 
336
        }
 
337
}