OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [or32/] [kernel/] [ptrace.c] - Blame information for rev 7

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 xianfeng
/*
2
 *  linux/arch/or32/kernel/ptrace.c
3
 *
4
 *  or32 version
5
 *    author(s): Matjaz Breskvar (phoenix@bsemi.com)
6
 *
7
 *  derived from cris, i386, m68k, ppc, sh ports.
8
 *
9
 *  changes:
10
 *  18. 11. 2003: Matjaz Breskvar (phoenix@bsemi.com)
11
 *    initial port to or32 architecture
12
 *  31. 12. 2005: Gyorgy Jeney (nog@bsemi.com)
13
 *    Added actual ptrace implementation except for single step traceing
14
 *    (Basically copy arch/i386/kernel/ptrace.c)
15
 *
16
 *  Based on:
17
 *
18
 *  linux/arch/m68k/kernel/ptrace
19
 *
20
 *  Copyright (C) 1994 by Hamish Macdonald
21
 *  Taken from linux/kernel/ptrace.c and modified for M680x0.
22
 *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
23
 *
24
 * This file is subject to the terms and conditions of the GNU General
25
 * Public License.  See the file COPYING in the main directory of
26
 * this archive for more details.
27
 */
28
 
29
#include <stddef.h>
30
#include <linux/kernel.h>
31
#include <linux/sched.h>
32
#include <linux/string.h>
33
 
34
#include <linux/mm.h>
35
#include <linux/smp_lock.h>
36
#include <linux/errno.h>
37
#include <linux/ptrace.h>
38
#include <linux/user.h>
39
#include <linux/audit.h>
40
 
41
#include <asm/segment.h>
42
#include <asm/page.h>
43
#include <asm/pgtable.h>
44
#include <asm/system.h>
45
#include <asm/or32-hf.h>
46
 
47
/*
48
 * does not yet catch signals sent when the child dies.
49
 * in exit.c or in signal.c.
50
 */
51
 
52
 
53
/*
54
 * Get contents of register REGNO in task TASK.
55
 */
56
static inline long get_reg(struct task_struct *task, int regno)
57
{
58
        if(regno < sizeof(struct pt_regs))
59
                return *((unsigned long *)user_regs(task->stack) + (regno >> 2));
60
        switch(regno) {
61
        case offsetof(struct user, start_code):
62
                return task->mm->start_code;
63
        case offsetof(struct user, start_data):
64
                return task->mm->start_data;
65
        case offsetof(struct user, start_stack):
66
                return task->mm->start_stack;
67
        default:
68
                printk("Don't know how to get offset %i of struct user\n",
69
                       regno);
70
        }
71
        return 0;
72
}
73
 
74
/*
75
 * Write contents of register REGNO in task TASK.
76
 */
77
static inline int put_reg(struct task_struct *task, int regno,
78
                          unsigned long data)
79
{
80
        /* Whatever happens, don't let any process the the sr flags and elevate
81
         * their privaleges to kernel mode. */
82
        if((regno < sizeof(struct pt_regs)) &&
83
           (regno != offsetof(struct pt_regs, sr))) {
84
                *((unsigned long *)task->thread.regs + (regno >> 2)) = data;
85
                return 0;
86
        }
87
        return -EIO;
88
}
89
 
90
static void set_singlestep(struct task_struct *child)
91
{
92
        /* FIXME */
93
#if 0
94
        struct pt_regs *regs = get_child_regs(child);
95
 
96
        /*
97
         * Always set TIF_SINGLESTEP - this guarantees that
98
         * we single-step system calls etc..  This will also
99
         * cause us to set TF when returning to user mode.
100
         */
101
        set_tsk_thread_flag(child, TIF_SINGLESTEP);
102
 
103
        /*
104
         * If TF was already set, don't do anything else
105
         */
106
        if (regs->eflags & TRAP_FLAG)
107
                return;
108
 
109
        /* Set TF on the kernel stack.. */
110
        regs->eflags |= TRAP_FLAG;
111
 
112
        child->ptrace |= PT_DTRACE;
113
#endif
114
}
115
 
116
 
117
static void clear_singlestep(struct task_struct *child)
118
{
119
        /* FIXME */
120
#if 0
121
        /* Always clear TIF_SINGLESTEP... */
122
        clear_tsk_thread_flag(child, TIF_SINGLESTEP);
123
 
124
        /* But touch TF only if it was set by us.. */
125
        if (child->ptrace & PT_DTRACE) {
126
                struct pt_regs *regs = get_child_regs(child);
127
                regs->eflags &= ~TRAP_FLAG;
128
                child->ptrace &= ~PT_DTRACE;
129
        }
130
#endif
131
}
132
 
133
/*
134
 * Called by kernel/ptrace.c when detaching..
135
 *
136
 * Make sure the single step bit is not set.
137
 */
138
void ptrace_disable(struct task_struct *child)
139
{
140
        printk("ptrace_disable(): TODO\n");
141
        clear_singlestep(child);
142
        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
143
}
144
 
145
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
146
{
147
        int ret;
148
        unsigned long __user *datap = (unsigned long __user *)data;
149
 
150
        switch (request) {
151
        /* when I and D space are separate, these will need to be fixed. */
152
        case PTRACE_PEEKTEXT: /* read word at location addr. */
153
        case PTRACE_PEEKDATA: {
154
                unsigned long tmp;
155
                int copied;
156
 
157
                copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
158
                ret = -EIO;
159
                if (copied != sizeof(tmp))
160
                        break;
161
                ret = put_user(tmp,(unsigned long *) datap);
162
                break;
163
        }
164
 
165
        /* read the word at location addr in the USER area. */
166
        case PTRACE_PEEKUSR:
167
                ret = -EIO;
168
                if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
169
                        break;
170
 
171
                ret = put_user(get_reg(child, addr), datap);
172
                break;
173
 
174
        /* when I and D space are separate, this will have to be fixed. */
175
        case PTRACE_POKETEXT: /* write the word at location addr. */
176
        case PTRACE_POKEDATA:
177
                ret = 0;
178
                if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
179
                        break;
180
                ret = -EIO;
181
                break;
182
 
183
        case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
184
                ret = -EIO;
185
                if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
186
                        break;
187
 
188
                ret = put_reg(child, addr, data);
189
                break;
190
 
191
        case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
192
        case PTRACE_CONT: /* restart after signal. */
193
                ret = -EIO;
194
                if (!valid_signal(data))
195
                        break;
196
                if (request == PTRACE_SYSCALL) {
197
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
198
                } else {
199
                        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
200
                }
201
                child->exit_code = data;
202
                /* make sure the single step bit is not set. */
203
                clear_singlestep(child);
204
                wake_up_process(child);
205
                ret = 0;
206
                break;
207
 
208
/*
209
 * make the child exit.  Best I can do is send it a sigkill.
210
 * perhaps it should be put in the status that it wants to
211
 * exit.
212
 */
213
        case PTRACE_KILL:
214
                ret = 0;
215
                if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
216
                        break;
217
                child->exit_code = SIGKILL;
218
                /* make sure the single step bit is not set. */
219
                clear_singlestep(child);
220
                wake_up_process(child);
221
                break;
222
 
223
                /*case PTRACE_SYSEMU_SINGLESTEP:  Same as SYSEMU, but singlestep if not syscall RGD */
224
        case PTRACE_SINGLESTEP:  /* set the trap flag. */
225
                printk("SINGLESTEP: TODO\n");
226
                ret = -ENOSYS;
227
#if 0
228
                ret = -EIO;
229
                if (!valid_signal(data))
230
                        break;
231
 
232
                if (request == PTRACE_SYSEMU_SINGLESTEP)
233
                        set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
234
                else
235
                        clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
236
 
237
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
238
                set_singlestep(child);
239
                child->exit_code = data;
240
                /* give it a chance to run. */
241
                wake_up_process(child);
242
                ret = 0;
243
#endif
244
                break;
245
 
246
        case PTRACE_DETACH: /* detach a process that was attached. */
247
                ret = ptrace_detach(child, data);
248
                break;
249
 
250
        default:
251
                ret = ptrace_request(child, request, addr, data);
252
                break;
253
        }
254
        return ret;
255
}
256
 
257
/* notification of system call entry/exit
258
 * - triggered by current->work.syscall_trace
259
 */
260
asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
261
{
262
        if (unlikely(current->audit_context) && entryexit)
263
          audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]), regs->regs[2]);/*RGD current*/
264
 
265
        if (!test_thread_flag(TIF_SYSCALL_TRACE))
266
                goto out;
267
        if (!(current->ptrace & PT_PTRACED))
268
                goto out;
269
 
270
        /* The 0x80 provides a way for the tracing parent to distinguish
271
           between a syscall stop and SIGTRAP delivery */
272
        ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ?
273
                                 0x80 : 0));
274
 
275
        /*
276
         * this isn't the same as continuing with a signal, but it will do
277
         * for normal use.  strace only continues with a signal if the
278
         * stopping signal is not SIGTRAP.  -brl
279
         */
280
        if (current->exit_code) {
281
                send_sig(current->exit_code, current, 1);
282
                current->exit_code = 0;
283
        }
284
 out:
285
        if (unlikely(current->audit_context) && !entryexit)
286
                audit_syscall_entry(audit_arch(), regs->regs[2],
287
                                    regs->regs[4], regs->regs[5],
288
                                    regs->regs[6], regs->regs[7]);/*RGD*/
289
 
290
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.