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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [alpha/] [kernel/] [ptrace.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/* 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/head.h>
8
#include <linux/kernel.h>
9
#include <linux/sched.h>
10
#include <linux/mm.h>
11
#include <linux/errno.h>
12
#include <linux/ptrace.h>
13
#include <linux/user.h>
14
#include <linux/debugreg.h>
15
 
16
#include <asm/segment.h>
17
#include <asm/pgtable.h>
18
#include <asm/system.h>
19
 
20
#undef DEBUG
21
 
22
#ifdef DEBUG
23
 
24
  enum {
25
      DBG_MEM           = (1<<0),
26
      DBG_BPT           = (1<<1),
27
      DBG_MEM_ALL       = (1<<2)
28
  };
29
 
30
  int debug_mask = DBG_BPT;
31
 
32
# define DBG(fac,args)  {if ((fac) & debug_mask) printk args;}
33
 
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
 *  +================================+ --------------------------
49
 *  | PALcode saved frame (ps, pc,   | ^                      ^
50
 *  | gp, a0, a1, a2)                | |                      |
51
 *  +================================+ | struct pt_regs       |
52
 *  |                                | |                      |
53
 *  | frame generated by SAVE_ALL    | |                      |
54
 *  |                                | v                      | P
55
 *  +================================+                        | A
56
 *  |                                | ^                      | G
57
 *  | frame saved by do_switch_stack | | struct switch_stack  | E
58
 *  |                                | v                      | _
59
 *  +================================+                        | S
60
 *  |                                |                        | I
61
 *  |                                |                        | Z
62
 *  /                                /                        | E
63
 *  /                                /                        |
64
 *  |                                |                        |
65
 *  |                                |                        |
66
 *  |                                |                        v
67
 *  +================================+ <-------------------------
68
 *                                      task->kernel_stack_page
69
 */
70
#define PT_REG(reg)     (PAGE_SIZE - sizeof(struct pt_regs)     \
71
                         + (long)&((struct pt_regs *)0)->reg)
72
#define SW_REG(reg)     (PAGE_SIZE - sizeof(struct pt_regs)     \
73
                         - sizeof(struct switch_stack)          \
74
                         + (long)&((struct switch_stack *)0)->reg)
75
/*
76
 * The following table maps a register index into the stack offset at
77
 * which the register is saved.  Register indices are 0-31 for integer
78
 * regs, 32-63 for fp regs, and 64 for the pc.  Notice that sp and
79
 * zero have no stack-slot and need to be treated specially (see
80
 * get_reg/put_reg below).
81
 */
82
enum {
83
        REG_R0 = 0, REG_F0 = 32, REG_PC = 64
84
};
85
 
86
static unsigned short regoff[] = {
87
        PT_REG(    r0), PT_REG(    r1), PT_REG(    r2), PT_REG(   r3),
88
        PT_REG(    r4), PT_REG(    r5), PT_REG(    r6), PT_REG(   r7),
89
        PT_REG(    r8), SW_REG(    r9), SW_REG(   r10), SW_REG(  r11),
90
        SW_REG(   r12), SW_REG(   r13), SW_REG(   r14), SW_REG(  r15),
91
        PT_REG(   r16), PT_REG(   r17), PT_REG(   r18), PT_REG(  r19),
92
        PT_REG(   r20), PT_REG(   r21), PT_REG(   r22), PT_REG(  r23),
93
        PT_REG(   r24), PT_REG(   r25), PT_REG(   r26), PT_REG(  r27),
94
        PT_REG(   r28), PT_REG(    gp),            -1,             -1,
95
        SW_REG(fp[ 0]), SW_REG(fp[ 1]), SW_REG(fp[ 2]), SW_REG(fp[ 3]),
96
        SW_REG(fp[ 4]), SW_REG(fp[ 5]), SW_REG(fp[ 6]), SW_REG(fp[ 7]),
97
        SW_REG(fp[ 8]), SW_REG(fp[ 9]), SW_REG(fp[10]), SW_REG(fp[11]),
98
        SW_REG(fp[12]), SW_REG(fp[13]), SW_REG(fp[14]), SW_REG(fp[15]),
99
        SW_REG(fp[16]), SW_REG(fp[17]), SW_REG(fp[18]), SW_REG(fp[19]),
100
        SW_REG(fp[20]), SW_REG(fp[21]), SW_REG(fp[22]), SW_REG(fp[23]),
101
        SW_REG(fp[24]), SW_REG(fp[25]), SW_REG(fp[26]), SW_REG(fp[27]),
102
        SW_REG(fp[28]), SW_REG(fp[29]), SW_REG(fp[30]), SW_REG(fp[31]),
103
        PT_REG(    pc)
104
};
105
 
106
static long zero;
107
 
108
 
109
/* change a pid into a task struct. */
110
static inline struct task_struct * get_task(int pid)
111
{
112
        int i;
113
 
114
        for (i = 1; i < NR_TASKS; i++) {
115
                if (task[i] != NULL && (task[i]->pid == pid))
116
                        return task[i];
117
        }
118
        return NULL;
119
}
120
 
121
/*
122
 * Get contents of register REGNO in task TASK.
123
 */
124
static inline long get_reg(struct task_struct * task, long regno)
125
{
126
        long *addr;
127
 
128
        if (regno == 30) {
129
                addr = &task->tss.usp;
130
        } else if (regno == 31) {
131
                zero = 0;
132
                addr = &zero;
133
        } else {
134
                addr = (long *) (task->kernel_stack_page + regoff[regno]);
135
        }
136
        return *addr;
137
}
138
 
139
/*
140
 * Write contents of register REGNO in task TASK.
141
 */
142
static inline int put_reg(struct task_struct *task, long regno, long data)
143
{
144
        long *addr, zero;
145
 
146
        if (regno == 30) {
147
                addr = &task->tss.usp;
148
        } else if (regno == 31) {
149
                addr = &zero;
150
        } else {
151
                addr = (long *) (task->kernel_stack_page + regoff[regno]);
152
        }
153
        *addr = data;
154
        return 0;
155
}
156
 
157
/*
158
 * This routine gets a long from any process space by following the page
159
 * tables. NOTE! You should check that the long isn't on a page boundary,
160
 * and that it is in the task area before calling this: this routine does
161
 * no checking.
162
 */
163
static unsigned long get_long(struct task_struct * tsk,
164
        struct vm_area_struct * vma, unsigned long addr)
165
{
166
        pgd_t * pgdir;
167
        pmd_t * pgmiddle;
168
        pte_t * pgtable;
169
        unsigned long page;
170
 
171
        DBG(DBG_MEM_ALL, ("getting long at 0x%lx\n", addr));
172
repeat:
173
        pgdir = pgd_offset(vma->vm_mm, addr);
174
        if (pgd_none(*pgdir)) {
175
                do_no_page(tsk, vma, addr, 0);
176
                goto repeat;
177
        }
178
        if (pgd_bad(*pgdir)) {
179
                printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
180
                pgd_clear(pgdir);
181
                return 0;
182
        }
183
        pgmiddle = pmd_offset(pgdir, addr);
184
        if (pmd_none(*pgmiddle)) {
185
                do_no_page(tsk, vma, addr, 0);
186
                goto repeat;
187
        }
188
        if (pmd_bad(*pgmiddle)) {
189
                printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
190
                pmd_clear(pgmiddle);
191
                return 0;
192
        }
193
        pgtable = pte_offset(pgmiddle, addr);
194
        if (!pte_present(*pgtable)) {
195
                do_no_page(tsk, vma, addr, 0);
196
                goto repeat;
197
        }
198
        page = pte_page(*pgtable);
199
/* this is a hack for non-kernel-mapped video buffers and similar */
200
        if (page >= high_memory)
201
                return 0;
202
        page += addr & ~PAGE_MASK;
203
        return *(unsigned long *) page;
204
}
205
 
206
/*
207
 * This routine puts a long into any process space by following the page
208
 * tables. NOTE! You should check that the long isn't on a page boundary,
209
 * and that it is in the task area before calling this: this routine does
210
 * no checking.
211
 *
212
 * Now keeps R/W state of page so that a text page stays readonly
213
 * even if a debugger scribbles breakpoints into it.  -M.U-
214
 */
215
static void put_long(struct task_struct * tsk, struct vm_area_struct * vma,
216
        unsigned long addr, unsigned long data)
217
{
218
        pgd_t *pgdir;
219
        pmd_t *pgmiddle;
220
        pte_t *pgtable;
221
        unsigned long page;
222
 
223
repeat:
224
        pgdir = pgd_offset(vma->vm_mm, addr);
225
        if (!pgd_present(*pgdir)) {
226
                do_no_page(tsk, vma, addr, 1);
227
                goto repeat;
228
        }
229
        if (pgd_bad(*pgdir)) {
230
                printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
231
                pgd_clear(pgdir);
232
                return;
233
        }
234
        pgmiddle = pmd_offset(pgdir, addr);
235
        if (pmd_none(*pgmiddle)) {
236
                do_no_page(tsk, vma, addr, 1);
237
                goto repeat;
238
        }
239
        if (pmd_bad(*pgmiddle)) {
240
                printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
241
                pmd_clear(pgmiddle);
242
                return;
243
        }
244
        pgtable = pte_offset(pgmiddle, addr);
245
        if (!pte_present(*pgtable)) {
246
                do_no_page(tsk, vma, addr, 1);
247
                goto repeat;
248
        }
249
        page = pte_page(*pgtable);
250
        if (!pte_write(*pgtable)) {
251
                do_wp_page(tsk, vma, addr, 1);
252
                goto repeat;
253
        }
254
/* this is a hack for non-kernel-mapped video buffers and similar */
255
        if (page < high_memory)
256
                *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
257
/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
258
/* this should also re-instate whatever read-only mode there was before */
259
        set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
260
        flush_tlb();
261
}
262
 
263
static struct vm_area_struct * find_extend_vma(struct task_struct * tsk,
264
                                               unsigned long addr)
265
{
266
        struct vm_area_struct * vma;
267
 
268
        addr &= PAGE_MASK;
269
        vma = find_vma(tsk->mm,addr);
270
        if (!vma)
271
                return NULL;
272
        if (vma->vm_start <= addr)
273
                return vma;
274
        if (!(vma->vm_flags & VM_GROWSDOWN))
275
                return NULL;
276
        if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur)
277
                return NULL;
278
        vma->vm_offset -= vma->vm_start - addr;
279
        vma->vm_start = addr;
280
        return vma;
281
}
282
 
283
/*
284
 * This routine checks the page boundaries, and that the offset is
285
 * within the task area. It then calls get_long() to read a long.
286
 */
287
static int read_long(struct task_struct * tsk, unsigned long addr,
288
                     unsigned long * result)
289
{
290
        struct vm_area_struct * vma = find_extend_vma(tsk, addr);
291
 
292
        DBG(DBG_MEM_ALL, ("in read_long\n"));
293
        if (!vma) {
294
                printk("Unable to find vma for addr 0x%lx\n",addr);
295
                return -EIO;
296
        }
297
        if ((addr & ~PAGE_MASK) > (PAGE_SIZE - sizeof(long))) {
298
                struct vm_area_struct * vma_high = vma;
299
                unsigned long low, align;
300
 
301
                if (addr + sizeof(long) >= vma->vm_end) {
302
                        vma_high = vma->vm_next;
303
                        if (!vma_high || vma_high->vm_start != vma->vm_end)
304
                                return -EIO;
305
                }
306
                align = addr & (sizeof(long) - 1);
307
                addr -= align;
308
                low = get_long(tsk, vma, addr);
309
                if (align) {
310
                    unsigned long high;
311
 
312
                    high = get_long(tsk, vma_high, addr + sizeof(long));
313
                    low >>= align * 8;
314
                    low  |= high << (64 - align * 8);
315
                }
316
                *result = low;
317
        } else {
318
                long l = get_long(tsk, vma, addr);
319
 
320
                DBG(DBG_MEM_ALL, ("value is 0x%lx\n", l));
321
                *result = l;
322
        }
323
        return 0;
324
}
325
 
326
/*
327
 * This routine checks the page boundaries, and that the offset is
328
 * within the task area. It then calls put_long() to write a long.
329
 */
330
static int write_long(struct task_struct * tsk, unsigned long addr,
331
        unsigned long data)
332
{
333
        struct vm_area_struct * vma = find_extend_vma(tsk, addr);
334
 
335
        if (!vma)
336
                return -EIO;
337
        if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
338
                unsigned long low, high, align;
339
                struct vm_area_struct * vma_high = vma;
340
 
341
                if (addr + sizeof(long) >= vma->vm_end) {
342
                        vma_high = vma->vm_next;
343
                        if (!vma_high || vma_high->vm_start != vma->vm_end)
344
                                return -EIO;
345
                }
346
                align = addr & (sizeof(long) - 1);
347
                addr -= align;
348
                low  = get_long(tsk, vma, addr);
349
                high = get_long(tsk, vma_high, addr + sizeof(long));
350
                low  &= ~0UL >> (64 - align * 8);
351
                high &= ~0UL << (align * 8);
352
                low  |= data << (align * 8);
353
                high |= data >> (64 - align * 8);
354
                put_long(tsk, vma, addr, low);
355
                put_long(tsk, vma_high, addr + sizeof(long), high);
356
        } else
357
                put_long(tsk, vma, addr, data);
358
        return 0;
359
}
360
 
361
/*
362
 * Read a 32bit int from address space TSK.
363
 */
364
static int read_int(struct task_struct * tsk, unsigned long addr,
365
                    unsigned int *data)
366
{
367
        unsigned long l, align;
368
        int res;
369
 
370
        align = addr & 0x7;
371
        addr &= ~0x7;
372
 
373
        res = read_long(tsk, addr, &l);
374
        if (res < 0)
375
          return res;
376
 
377
        if (align == 0) {
378
                *data = l;
379
        } else {
380
                *data = l >> 32;
381
        }
382
        return 0;
383
}
384
 
385
/*
386
 * Write a 32bit word to address space TSK.
387
 *
388
 * For simplicity, do a read-modify-write of the 64bit word that
389
 * contains the 32bit word that we are about to write.
390
 */
391
static int write_int(struct task_struct * tsk, unsigned long addr,
392
                     unsigned int data)
393
{
394
        unsigned long l, align;
395
        int res;
396
 
397
        align = addr & 0x7;
398
        addr &= ~0x7;
399
 
400
        res = read_long(tsk, addr, &l);
401
        if (res < 0)
402
          return res;
403
 
404
        if (align == 0) {
405
                l = (l & 0xffffffff00000000UL) | ((unsigned long) data <<  0);
406
        } else {
407
                l = (l & 0x00000000ffffffffUL) | ((unsigned long) data << 32);
408
        }
409
        return write_long(tsk, addr, l);
410
}
411
 
412
/*
413
 * Set breakpoint.
414
 */
415
int ptrace_set_bpt(struct task_struct * child)
416
{
417
        int displ, i, res, reg_b, nsaved = 0;
418
        u32 insn, op_code;
419
        unsigned long pc;
420
 
421
        pc  = get_reg(child, REG_PC);
422
        res = read_int(child, pc, &insn);
423
        if (res < 0)
424
          return res;
425
 
426
        op_code = insn >> 26;
427
        if (op_code >= 0x30) {
428
                /*
429
                 * It's a branch: instead of trying to figure out
430
                 * whether the branch will be taken or not, we'll put
431
                 * a breakpoint at either location.  This is simpler,
432
                 * more reliable, and probably not a whole lot slower
433
                 * than the alternative approach of emulating the
434
                 * branch (emulation can be tricky for fp branches).
435
                 */
436
                displ = ((s32)(insn << 11)) >> 9;
437
                child->debugreg[nsaved++] = pc + 4;
438
                if (displ)              /* guard against unoptimized code */
439
                  child->debugreg[nsaved++] = pc + 4 + displ;
440
                DBG(DBG_BPT, ("execing branch\n"));
441
        } else if (op_code == 0x1a) {
442
                reg_b = (insn >> 16) & 0x1f;
443
                child->debugreg[nsaved++] = get_reg(child, reg_b);
444
                DBG(DBG_BPT, ("execing jump\n"));
445
        } else {
446
                child->debugreg[nsaved++] = pc + 4;
447
                DBG(DBG_BPT, ("execing normal insn\n"));
448
        }
449
 
450
        /* install breakpoints: */
451
        for (i = 0; i < nsaved; ++i) {
452
                res = read_int(child, child->debugreg[i], &insn);
453
                if (res < 0)
454
                  return res;
455
                child->debugreg[i + 2] = insn;
456
                DBG(DBG_BPT, ("    -> next_pc=%lx\n", child->debugreg[i]));
457
                res = write_int(child, child->debugreg[i], BREAKINST);
458
                if (res < 0)
459
                  return res;
460
        }
461
        child->debugreg[4] = nsaved;
462
        return 0;
463
}
464
 
465
/*
466
 * Ensure no single-step breakpoint is pending.  Returns non-zero
467
 * value if child was being single-stepped.
468
 */
469
int ptrace_cancel_bpt(struct task_struct * child)
470
{
471
        int i, nsaved = child->debugreg[4];
472
 
473
        child->debugreg[4] = 0;
474
 
475
        if (nsaved > 2) {
476
            printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
477
            nsaved = 2;
478
        }
479
 
480
        for (i = 0; i < nsaved; ++i) {
481
                write_int(child, child->debugreg[i], child->debugreg[i + 2]);
482
        }
483
        return (nsaved != 0);
484
}
485
 
486
asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
487
                           int a4, int a5, struct pt_regs regs)
488
{
489
        struct task_struct *child;
490
        struct user * dummy;
491
 
492
        dummy = NULL;
493
 
494
        DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
495
                      request, pid, addr, data));
496
        if (request == PTRACE_TRACEME) {
497
                /* are we already being traced? */
498
                if (current->flags & PF_PTRACED)
499
                        return -EPERM;
500
                /* set the ptrace bit in the process flags. */
501
                current->flags |= PF_PTRACED;
502
                return 0;
503
        }
504
        if (pid == 1)           /* you may not mess with init */
505
                return -EPERM;
506
        if (!(child = get_task(pid)))
507
                return -ESRCH;
508
        if (request == PTRACE_ATTACH) {
509
                if (child == current)
510
                        return -EPERM;
511
                if ((!child->dumpable ||
512
                     (current->uid != child->euid) ||
513
                     (current->uid != child->suid) ||
514
                     (current->uid != child->uid) ||
515
                     (current->gid != child->egid) ||
516
                     (current->gid != child->sgid) ||
517
                     (current->gid != child->gid)) && !suser())
518
                        return -EPERM;
519
                /* the same process cannot be attached many times */
520
                if (child->flags & PF_PTRACED)
521
                        return -EPERM;
522
                child->flags |= PF_PTRACED;
523
                if (child->p_pptr != current) {
524
                        REMOVE_LINKS(child);
525
                        child->p_pptr = current;
526
                        SET_LINKS(child);
527
                }
528
                send_sig(SIGSTOP, child, 1);
529
                return 0;
530
        }
531
        if (!(child->flags & PF_PTRACED)) {
532
                DBG(DBG_MEM, ("child not traced\n"));
533
                return -ESRCH;
534
        }
535
        if (child->state != TASK_STOPPED) {
536
                DBG(DBG_MEM, ("child process not stopped\n"));
537
                if (request != PTRACE_KILL)
538
                        return -ESRCH;
539
        }
540
        if (child->p_pptr != current) {
541
                DBG(DBG_MEM, ("child not parent of this process\n"));
542
                return -ESRCH;
543
        }
544
 
545
        switch (request) {
546
        /* when I and D space are separate, these will need to be fixed. */
547
                case PTRACE_PEEKTEXT: /* read word at location addr. */
548
                case PTRACE_PEEKDATA: {
549
                        unsigned long tmp;
550
                        int res;
551
 
552
                        res = read_long(child, addr, &tmp);
553
                        DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
554
                        if (res < 0)
555
                                return res;
556
                        regs.r0 = 0;     /* special return: no errors */
557
                        return tmp;
558
                }
559
 
560
        /* read register number ADDR. */
561
                case PTRACE_PEEKUSR:
562
                        regs.r0 = 0;     /* special return: no errors */
563
                        DBG(DBG_MEM, ("peek $%ld=%#lx\n", addr, regs.r0));
564
                        return get_reg(child, addr);
565
 
566
        /* when I and D space are separate, this will have to be fixed. */
567
                case PTRACE_POKETEXT: /* write the word at location addr. */
568
                case PTRACE_POKEDATA:
569
                        DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data));
570
                        return write_long(child, addr, data);
571
 
572
                case PTRACE_POKEUSR: /* write the specified register */
573
                        DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
574
                        return put_reg(child, addr, data);
575
 
576
                case PTRACE_SYSCALL: /* continue and stop at next
577
                                        (return from) syscall */
578
                case PTRACE_CONT: { /* restart after signal. */
579
                        if ((unsigned long) data > NSIG)
580
                                return -EIO;
581
                        if (request == PTRACE_SYSCALL)
582
                                child->flags |= PF_TRACESYS;
583
                        else
584
                                child->flags &= ~PF_TRACESYS;
585
                        child->exit_code = data;
586
                        wake_up_process(child);
587
        /* make sure single-step breakpoint is gone. */
588
                        ptrace_cancel_bpt(child);
589
                        return data;
590
                }
591
 
592
/*
593
 * make the child exit.  Best I can do is send it a sigkill.
594
 * perhaps it should be put in the status that it wants to
595
 * exit.
596
 */
597
                case PTRACE_KILL: {
598
                        if (child->state != TASK_ZOMBIE) {
599
                                wake_up_process(child);
600
                                child->exit_code = SIGKILL;
601
                        }
602
        /* make sure single-step breakpoint is gone. */
603
                        ptrace_cancel_bpt(child);
604
                        return 0;
605
                }
606
 
607
                case PTRACE_SINGLESTEP: {  /* execute single instruction. */
608
                        if ((unsigned long) data > NSIG)
609
                                return -EIO;
610
                        child->debugreg[4] = -1;        /* mark single-stepping */
611
                        child->flags &= ~PF_TRACESYS;
612
                        wake_up_process(child);
613
                        child->exit_code = data;
614
        /* give it a chance to run. */
615
                        return 0;
616
                }
617
 
618
                case PTRACE_DETACH: { /* detach a process that was attached. */
619
                        if ((unsigned long) data > NSIG)
620
                                return -EIO;
621
                        child->flags &= ~(PF_PTRACED|PF_TRACESYS);
622
                        wake_up_process(child);
623
                        child->exit_code = data;
624
                        REMOVE_LINKS(child);
625
                        child->p_pptr = child->p_opptr;
626
                        SET_LINKS(child);
627
        /* make sure single-step breakpoint is gone. */
628
                        ptrace_cancel_bpt(child);
629
                        return 0;
630
                }
631
 
632
                default:
633
                  return -EIO;
634
          }
635
}
636
 
637
asmlinkage void syscall_trace(void)
638
{
639
        if ((current->flags & (PF_PTRACED|PF_TRACESYS))
640
                        != (PF_PTRACED|PF_TRACESYS))
641
                return;
642
        current->exit_code = SIGTRAP;
643
        current->state = TASK_STOPPED;
644
        notify_parent(current, SIGCHLD);
645
        schedule();
646
        /*
647
         * this isn't the same as continuing with a signal, but it will do
648
         * for normal use.  strace only continues with a signal if the
649
         * stopping signal is not SIGTRAP.  -brl
650
         */
651
        if (current->exit_code)
652
                current->signal |= (1 << (current->exit_code - 1));
653
        current->exit_code = 0;
654
}

powered by: WebSVN 2.1.0

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