~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/um/ptrace_32.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  3  * Licensed under the GPL
  4  */
  5 
  6 #include <linux/mm.h>
  7 #include <linux/sched.h>
  8 #include <linux/uaccess.h>
  9 #include <asm/ptrace-abi.h>
 10 #include <registers.h>
 11 #include <skas.h>
 12 
 13 void arch_switch_to(struct task_struct *to)
 14 {
 15         int err = arch_switch_tls(to);
 16         if (!err)
 17                 return;
 18 
 19         if (err != -EINVAL)
 20                 printk(KERN_WARNING "arch_switch_tls failed, errno %d, "
 21                        "not EINVAL\n", -err);
 22         else
 23                 printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n");
 24 }
 25 
 26 /* determines which flags the user has access to. */
 27 /* 1 = access 0 = no access */
 28 #define FLAG_MASK 0x00044dd5
 29 
 30 static const int reg_offsets[] = {
 31         [EBX] = HOST_BX,
 32         [ECX] = HOST_CX,
 33         [EDX] = HOST_DX,
 34         [ESI] = HOST_SI,
 35         [EDI] = HOST_DI,
 36         [EBP] = HOST_BP,
 37         [EAX] = HOST_AX,
 38         [DS] = HOST_DS,
 39         [ES] = HOST_ES,
 40         [FS] = HOST_FS,
 41         [GS] = HOST_GS,
 42         [EIP] = HOST_IP,
 43         [CS] = HOST_CS,
 44         [EFL] = HOST_EFLAGS,
 45         [UESP] = HOST_SP,
 46         [SS] = HOST_SS,
 47         [ORIG_EAX] = HOST_ORIG_AX,
 48 };
 49 
 50 int putreg(struct task_struct *child, int regno, unsigned long value)
 51 {
 52         regno >>= 2;
 53         switch (regno) {
 54         case EBX:
 55         case ECX:
 56         case EDX:
 57         case ESI:
 58         case EDI:
 59         case EBP:
 60         case EAX:
 61         case EIP:
 62         case UESP:
 63                 break;
 64         case ORIG_EAX:
 65                 /* Update the syscall number. */
 66                 UPT_SYSCALL_NR(&child->thread.regs.regs) = value;
 67                 break;
 68         case FS:
 69                 if (value && (value & 3) != 3)
 70                         return -EIO;
 71                 break;
 72         case GS:
 73                 if (value && (value & 3) != 3)
 74                         return -EIO;
 75                 break;
 76         case DS:
 77         case ES:
 78                 if (value && (value & 3) != 3)
 79                         return -EIO;
 80                 value &= 0xffff;
 81                 break;
 82         case SS:
 83         case CS:
 84                 if ((value & 3) != 3)
 85                         return -EIO;
 86                 value &= 0xffff;
 87                 break;
 88         case EFL:
 89                 value &= FLAG_MASK;
 90                 child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
 91                 return 0;
 92         default :
 93                 panic("Bad register in putreg() : %d\n", regno);
 94         }
 95         child->thread.regs.regs.gp[reg_offsets[regno]] = value;
 96         return 0;
 97 }
 98 
 99 int poke_user(struct task_struct *child, long addr, long data)
100 {
101         if ((addr & 3) || addr < 0)
102                 return -EIO;
103 
104         if (addr < MAX_REG_OFFSET)
105                 return putreg(child, addr, data);
106         else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
107                  (addr <= offsetof(struct user, u_debugreg[7]))) {
108                 addr -= offsetof(struct user, u_debugreg[0]);
109                 addr = addr >> 2;
110                 if ((addr == 4) || (addr == 5))
111                         return -EIO;
112                 child->thread.arch.debugregs[addr] = data;
113                 return 0;
114         }
115         return -EIO;
116 }
117 
118 unsigned long getreg(struct task_struct *child, int regno)
119 {
120         unsigned long mask = ~0UL;
121 
122         regno >>= 2;
123         switch (regno) {
124         case FS:
125         case GS:
126         case DS:
127         case ES:
128         case SS:
129         case CS:
130                 mask = 0xffff;
131                 break;
132         case EIP:
133         case UESP:
134         case EAX:
135         case EBX:
136         case ECX:
137         case EDX:
138         case ESI:
139         case EDI:
140         case EBP:
141         case EFL:
142         case ORIG_EAX:
143                 break;
144         default:
145                 panic("Bad register in getreg() : %d\n", regno);
146         }
147         return mask & child->thread.regs.regs.gp[reg_offsets[regno]];
148 }
149 
150 /* read the word at location addr in the USER area. */
151 int peek_user(struct task_struct *child, long addr, long data)
152 {
153         unsigned long tmp;
154 
155         if ((addr & 3) || addr < 0)
156                 return -EIO;
157 
158         tmp = 0;  /* Default return condition */
159         if (addr < MAX_REG_OFFSET) {
160                 tmp = getreg(child, addr);
161         }
162         else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
163                  (addr <= offsetof(struct user, u_debugreg[7]))) {
164                 addr -= offsetof(struct user, u_debugreg[0]);
165                 addr = addr >> 2;
166                 tmp = child->thread.arch.debugregs[addr];
167         }
168         return put_user(tmp, (unsigned long __user *) data);
169 }
170 
171 static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
172 {
173         int err, n, cpu = task_cpu(child);
174         struct user_i387_struct fpregs;
175 
176         err = save_i387_registers(userspace_pid[cpu],
177                                   (unsigned long *) &fpregs);
178         if (err)
179                 return err;
180 
181         n = copy_to_user(buf, &fpregs, sizeof(fpregs));
182         if(n > 0)
183                 return -EFAULT;
184 
185         return n;
186 }
187 
188 static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
189 {
190         int n, cpu = task_cpu(child);
191         struct user_i387_struct fpregs;
192 
193         n = copy_from_user(&fpregs, buf, sizeof(fpregs));
194         if (n > 0)
195                 return -EFAULT;
196 
197         return restore_i387_registers(userspace_pid[cpu],
198                                     (unsigned long *) &fpregs);
199 }
200 
201 static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
202 {
203         int err, n, cpu = task_cpu(child);
204         struct user_fxsr_struct fpregs;
205 
206         err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
207         if (err)
208                 return err;
209 
210         n = copy_to_user(buf, &fpregs, sizeof(fpregs));
211         if(n > 0)
212                 return -EFAULT;
213 
214         return n;
215 }
216 
217 static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
218 {
219         int n, cpu = task_cpu(child);
220         struct user_fxsr_struct fpregs;
221 
222         n = copy_from_user(&fpregs, buf, sizeof(fpregs));
223         if (n > 0)
224                 return -EFAULT;
225 
226         return restore_fpx_registers(userspace_pid[cpu],
227                                      (unsigned long *) &fpregs);
228 }
229 
230 long subarch_ptrace(struct task_struct *child, long request,
231                     unsigned long addr, unsigned long data)
232 {
233         int ret = -EIO;
234         void __user *datap = (void __user *) data;
235         switch (request) {
236         case PTRACE_GETFPREGS: /* Get the child FPU state. */
237                 ret = get_fpregs(datap, child);
238                 break;
239         case PTRACE_SETFPREGS: /* Set the child FPU state. */
240                 ret = set_fpregs(datap, child);
241                 break;
242         case PTRACE_GETFPXREGS: /* Get the child FPU state. */
243                 ret = get_fpxregs(datap, child);
244                 break;
245         case PTRACE_SETFPXREGS: /* Set the child FPU state. */
246                 ret = set_fpxregs(datap, child);
247                 break;
248         default:
249                 ret = -EIO;
250         }
251         return ret;
252 }
253 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php