root/arch/alpha/kernel/ptrace.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_task
  2. get_reg
  3. put_reg
  4. get_long
  5. put_long
  6. find_extend_vma
  7. read_long
  8. write_long
  9. read_int
  10. write_int
  11. ptrace_set_bpt
  12. ptrace_cancel_bpt
  13. sys_ptrace
  14. syscall_trace

   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/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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 264                                                unsigned long addr)
 265 {
 266         struct vm_area_struct * vma;
 267 
 268         addr &= PAGE_MASK;
 269         vma = find_vma(tsk,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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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->uid) ||
 514                      (current->gid != child->egid) ||
 515                      (current->gid != child->gid)) && !suser())
 516                         return -EPERM;
 517                 /* the same process cannot be attached many times */
 518                 if (child->flags & PF_PTRACED)
 519                         return -EPERM;
 520                 child->flags |= PF_PTRACED;
 521                 if (child->p_pptr != current) {
 522                         REMOVE_LINKS(child);
 523                         child->p_pptr = current;
 524                         SET_LINKS(child);
 525                 }
 526                 send_sig(SIGSTOP, child, 1);
 527                 return 0;
 528         }
 529         if (!(child->flags & PF_PTRACED)) {
 530                 DBG(DBG_MEM, ("child not traced\n"));
 531                 return -ESRCH;
 532         }
 533         if (child->state != TASK_STOPPED) {
 534                 DBG(DBG_MEM, ("child process not stopped\n"));
 535                 if (request != PTRACE_KILL)
 536                         return -ESRCH;
 537         }
 538         if (child->p_pptr != current) {
 539                 DBG(DBG_MEM, ("child not parent of this process\n"));
 540                 return -ESRCH;
 541         }
 542 
 543         switch (request) {
 544         /* when I and D space are separate, these will need to be fixed. */
 545                 case PTRACE_PEEKTEXT: /* read word at location addr. */
 546                 case PTRACE_PEEKDATA: {
 547                         unsigned long tmp;
 548                         int res;
 549 
 550                         res = read_long(child, addr, &tmp);
 551                         DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
 552                         if (res < 0)
 553                                 return res;
 554                         regs.r0 = 0;    /* special return: no errors */
 555                         return tmp;
 556                 }
 557 
 558         /* read register number ADDR. */
 559                 case PTRACE_PEEKUSR:
 560                         regs.r0 = 0;    /* special return: no errors */
 561                         DBG(DBG_MEM, ("peek $%ld=%#lx\n", addr, regs.r0));
 562                         return get_reg(child, addr);
 563 
 564         /* when I and D space are separate, this will have to be fixed. */
 565                 case PTRACE_POKETEXT: /* write the word at location addr. */
 566                 case PTRACE_POKEDATA:
 567                         DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data));
 568                         return write_long(child, addr, data);
 569 
 570                 case PTRACE_POKEUSR: /* write the specified register */
 571                         DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
 572                         return put_reg(child, addr, data);
 573 
 574                 case PTRACE_SYSCALL: /* continue and stop at next
 575                                         (return from) syscall */
 576                 case PTRACE_CONT: { /* restart after signal. */
 577                         if ((unsigned long) data > NSIG)
 578                                 return -EIO;
 579                         if (request == PTRACE_SYSCALL)
 580                                 child->flags |= PF_TRACESYS;
 581                         else
 582                                 child->flags &= ~PF_TRACESYS;
 583                         child->exit_code = data;
 584                         wake_up_process(child);
 585         /* make sure single-step breakpoint is gone. */
 586                         ptrace_cancel_bpt(child);
 587                         return data;
 588                 }
 589 
 590 /*
 591  * make the child exit.  Best I can do is send it a sigkill.
 592  * perhaps it should be put in the status that it wants to
 593  * exit.
 594  */
 595                 case PTRACE_KILL: {
 596                         if (child->state != TASK_ZOMBIE) {
 597                                 wake_up_process(child);
 598                                 child->exit_code = SIGKILL;
 599                         }
 600         /* make sure single-step breakpoint is gone. */
 601                         ptrace_cancel_bpt(child);
 602                         return 0;
 603                 }
 604 
 605                 case PTRACE_SINGLESTEP: {  /* execute single instruction. */
 606                         if ((unsigned long) data > NSIG)
 607                                 return -EIO;
 608                         child->debugreg[4] = -1;        /* mark single-stepping */
 609                         child->flags &= ~PF_TRACESYS;
 610                         wake_up_process(child);
 611                         child->exit_code = data;
 612         /* give it a chance to run. */
 613                         return 0;
 614                 }
 615 
 616                 case PTRACE_DETACH: { /* detach a process that was attached. */
 617                         if ((unsigned long) data > NSIG)
 618                                 return -EIO;
 619                         child->flags &= ~(PF_PTRACED|PF_TRACESYS);
 620                         wake_up_process(child);
 621                         child->exit_code = data;
 622                         REMOVE_LINKS(child);
 623                         child->p_pptr = child->p_opptr;
 624                         SET_LINKS(child);
 625         /* make sure single-step breakpoint is gone. */
 626                         ptrace_cancel_bpt(child);
 627                         return 0;
 628                 }
 629 
 630                 default:
 631                   return -EIO;
 632           }
 633 }
 634 
 635 asmlinkage void syscall_trace(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 636 {
 637         if ((current->flags & (PF_PTRACED|PF_TRACESYS))
 638                         != (PF_PTRACED|PF_TRACESYS))
 639                 return;
 640         current->exit_code = SIGTRAP;
 641         current->state = TASK_STOPPED;
 642         notify_parent(current);
 643         schedule();
 644         /*
 645          * this isn't the same as continuing with a signal, but it will do
 646          * for normal use.  strace only continues with a signal if the
 647          * stopping signal is not SIGTRAP.  -brl
 648          */
 649         if (current->exit_code)
 650                 current->signal |= (1 << (current->exit_code - 1));
 651         current->exit_code = 0;
 652 }

/* [previous][next][first][last][top][bottom][index][help] */