[BACK]Return to linux_ptrace.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / compat / linux / arch / arm

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/compat/linux/arch/arm/linux_ptrace.c between version 1.14 and 1.14.6.1

version 1.14, 2008/12/17 20:51:33 version 1.14.6.1, 2010/07/03 01:19:31
Line 90  struct linux_reg {
Line 90  struct linux_reg {
 int linux_ptrace_disabled = 1;  /* bitrotted */  int linux_ptrace_disabled = 1;  /* bitrotted */
   
 int  int
 linux_sys_ptrace_arch(struct lwp *l, const struct linux_sys_ptrace_args *uap, register_t *retval)  linux_sys_ptrace_arch(struct lwp *l, const struct linux_sys_ptrace_args *uap,
       register_t *retval)
 {  {
         /* {          /* {
                 syscallarg(int) request;                  syscallarg(int) request;
Line 98  linux_sys_ptrace_arch(struct lwp *l, con
Line 99  linux_sys_ptrace_arch(struct lwp *l, con
                 syscallarg(int) addr;                  syscallarg(int) addr;
                 syscallarg(int) data;                  syscallarg(int) data;
         } */          } */
         struct proc *p = l->l_proc;          struct proc *p = l->l_proc, *t;
         int request, error;  
         struct proc *t;                         /* target process */  
         struct lwp *lt;          struct lwp *lt;
         struct reg *regs = NULL;          struct reg *regs = NULL;
         struct fpreg *fpregs = NULL;  
         struct linux_reg *linux_regs = NULL;          struct linux_reg *linux_regs = NULL;
         struct linux_fpreg *linux_fpregs = NULL;          int request, error;
   
         if (linux_ptrace_disabled)          if (linux_ptrace_disabled)
                 return ENOSYS;                  return ENOSYS;
   
           error = 0;
         request = SCARG(uap, request);          request = SCARG(uap, request);
           regs = kmem_alloc(sizeof(struct reg), KM_SLEEP);
           linux_regs = kmem_alloc(sizeof(struct linux_reg), KM_SLEEP);
   
         if ((request != LINUX_PTRACE_GETREGS) &&          switch (request) {
             (request != LINUX_PTRACE_SETREGS))          case LINUX_PTRACE_GETREGS:
                 return EIO;                  break;
           case LINUX_PTRACE_SETREGS:
         /* Find the process we're supposed to be operating on. */                  error = copyin((void *)SCARG(uap, data), linux_regs,
         if ((t = pfind(SCARG(uap, pid))) == NULL)                      sizeof(struct linux_reg));
                 return ESRCH;                  if (error) {
                           goto out;
         /*                  }
          * You can't do what you want to the process if:                  break;
          *      (1) It's not being traced at all,          default:
          */                  error = EIO;
         if (!ISSET(t->p_slflag, PSL_TRACED))                  goto out;
                 return EPERM;          }
   
         /*          /* Find the process we are supposed to be operating on. */
          *      (2) it's being traced by procfs (which has          mutex_enter(proc_lock);
          *          different signal delivery semantics),          if ((t = proc_find(SCARG(uap, pid))) == NULL) {
          */                  mutex_exit(proc_lock);
         if (ISSET(t->p_slflag, PSL_FSTRACE))                  error = ESRCH;
                 return EBUSY;                  goto out;
           }
           mutex_enter(t->p_lock);
           mutex_exit(proc_lock);
   
         /*          /*
          *      (3) it's not being traced by _you_, or           * You cannot do what you want to the process if:
            * 1. It is not being traced at all,
          */           */
         if (t->p_pptr != p)          if (!ISSET(t->p_slflag, PSL_TRACED)) {
                 return EBUSY;                  mutex_exit(t->p_lock);
                   error = EPERM;
                   goto out;
           }
         /*          /*
          *      (4) it's not currently stopped.           * 2. It is being traced by procfs (which has different signal
          */           *    delivery semantics),
         if (t->p_stat != SSTOP || !t->p_waited)           * 3. It is not being traced by _you_, or
                 return EBUSY;           * 4. It is not currently stopped.
   
         /* XXX NJWLWP  
          * The entire ptrace interface needs work to be useful to  
          * a process with multiple LWPs. For the moment, we'll  
          * just kluge this and fail on others.  
          */           */
           if (ISSET(t->p_slflag, PSL_FSTRACE) || t->p_pptr != p ||
         if (p->p_nlwps > 1)              t->p_stat != SSTOP || !t->p_waited) {
                 return (ENOSYS);                  mutex_exit(t->p_lock);
                   error = EBUSY;
                   goto out;
           }
           /* XXX: ptrace needs revamp for multi-threading support. */
           if (t->p_nlwps > 1) {
                   mutex_exit(t->p_lock);
                   error = ENOSYS;
                   goto out;
           }
         lt = LIST_FIRST(&t->p_lwps);          lt = LIST_FIRST(&t->p_lwps);
   
         *retval = 0;          *retval = 0;
   
         switch (request) {          switch (request) {
         case  LINUX_PTRACE_GETREGS:          case LINUX_PTRACE_GETREGS:
                 regs = malloc(sizeof(struct reg), M_TEMP, M_WAITOK);  
                 linux_regs = malloc(sizeof(struct linux_reg),  
                         M_TEMP, M_WAITOK);  
   
                 error = process_read_regs(lt, regs);                  error = process_read_regs(lt, regs);
                 if (error != 0)                  mutex_exit(t->p_lock);
                         goto out;                  if (error) {
                           break;
                   }
                 memcpy(linux_regs->uregs, regs->r, 13 * sizeof(register_t));                  memcpy(linux_regs->uregs, regs->r, 13 * sizeof(register_t));
                 linux_regs->uregs[LINUX_REG_SP] = regs->r_sp;                  linux_regs->uregs[LINUX_REG_SP] = regs->r_sp;
                 linux_regs->uregs[LINUX_REG_LR] = regs->r_lr;                  linux_regs->uregs[LINUX_REG_LR] = regs->r_lr;
Line 178  linux_sys_ptrace_arch(struct lwp *l, con
Line 184  linux_sys_ptrace_arch(struct lwp *l, con
   
                 error = copyout(linux_regs, (void *)SCARG(uap, data),                  error = copyout(linux_regs, (void *)SCARG(uap, data),
                     sizeof(struct linux_reg));                      sizeof(struct linux_reg));
                 goto out;                  break;
   
         case  LINUX_PTRACE_SETREGS:  
                 regs = malloc(sizeof(struct reg), M_TEMP, M_WAITOK);  
                 linux_regs = malloc(sizeof(struct linux_reg),  
                         M_TEMP, M_WAITOK);  
   
                 error = copyin((void *)SCARG(uap, data), linux_regs,  
                     sizeof(struct linux_reg));  
                 if (error != 0)  
                         goto out;  
   
           case LINUX_PTRACE_SETREGS:
                 memcpy(regs->r, linux_regs->uregs, 13 * sizeof(register_t));                  memcpy(regs->r, linux_regs->uregs, 13 * sizeof(register_t));
                 regs->r_sp = linux_regs->uregs[LINUX_REG_SP];                  regs->r_sp = linux_regs->uregs[LINUX_REG_SP];
                 regs->r_lr = linux_regs->uregs[LINUX_REG_LR];                  regs->r_lr = linux_regs->uregs[LINUX_REG_LR];
                 regs->r_pc = linux_regs->uregs[LINUX_REG_PC];                  regs->r_pc = linux_regs->uregs[LINUX_REG_PC];
                 regs->r_cpsr = linux_regs->uregs[LINUX_REG_CPSR];                  regs->r_cpsr = linux_regs->uregs[LINUX_REG_CPSR];
   
                 error = process_write_regs(lt, regs);                  error = process_write_regs(lt, regs);
                 goto out;                  /* FALLTHROUGH */
   
         default:          default:
                 /* never reached */                  mutex_exit(t->p_lock);
                 break;  
         }          }
   out:
         return EIO;  
   
     out:  
         if (regs)          if (regs)
                 free(regs, M_TEMP);                  kmem_free(regs, sizeof(*regs));
         if (fpregs)  
                 free(fpregs, M_TEMP);  
         if (linux_regs)          if (linux_regs)
                 free(linux_regs, M_TEMP);                  kmem_free(linux_regs, sizeof(*linux_regs));
         if (linux_fpregs)          return error;
                 free(linux_fpregs, M_TEMP);  
         return (error);  
   
 }  }

Legend:
Removed from v.1.14  
changed lines
  Added in v.1.14.6.1

CVSweb <webmaster@jp.NetBSD.org>