diff options
author | Roland McGrath <roland@redhat.com> | 2008-01-30 07:31:54 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:31:54 -0500 |
commit | 5a4646a4efed8c835f76c3b88f3155f6ab5b8d9b (patch) | |
tree | ec056ab850e3551e4e7e046d7652d3b01e311b05 /arch/x86/kernel | |
parent | 975511be74d1b82bf041aaed2861a242abfe3886 (diff) |
x86: x86 ptrace user_regset
This cleans up the PTRACE_*REGS* request code so each one is just a
simple call to copy_regset_to_user or copy_regset_from_user. The
ptrace layouts already match the user_regset formats (core dump formats).
Signed-off-by: Roland McGrath <roland@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/ptrace.c | 236 |
1 files changed, 77 insertions, 159 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 196cc27bd39a..f8b89059e6ed 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -750,9 +750,13 @@ void ptrace_disable(struct task_struct *child) | |||
750 | } | 750 | } |
751 | } | 751 | } |
752 | 752 | ||
753 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | ||
754 | static const struct user_regset_view user_x86_32_view; /* Initialized below. */ | ||
755 | #endif | ||
756 | |||
753 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 757 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
754 | { | 758 | { |
755 | int i, ret; | 759 | int ret; |
756 | unsigned long __user *datap = (unsigned long __user *)data; | 760 | unsigned long __user *datap = (unsigned long __user *)data; |
757 | 761 | ||
758 | switch (request) { | 762 | switch (request) { |
@@ -805,82 +809,46 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
805 | } | 809 | } |
806 | break; | 810 | break; |
807 | 811 | ||
808 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ | 812 | case PTRACE_GETREGS: /* Get all gp regs from the child. */ |
809 | if (!access_ok(VERIFY_WRITE, datap, sizeof(struct user_regs_struct))) { | 813 | return copy_regset_to_user(child, |
810 | ret = -EIO; | 814 | task_user_regset_view(current), |
811 | break; | 815 | REGSET_GENERAL, |
812 | } | 816 | 0, sizeof(struct user_regs_struct), |
813 | for (i = 0; i < sizeof(struct user_regs_struct); i += sizeof(long)) { | 817 | datap); |
814 | __put_user(getreg(child, i), datap); | 818 | |
815 | datap++; | 819 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ |
816 | } | 820 | return copy_regset_from_user(child, |
817 | ret = 0; | 821 | task_user_regset_view(current), |
818 | break; | 822 | REGSET_GENERAL, |
819 | } | 823 | 0, sizeof(struct user_regs_struct), |
820 | 824 | datap); | |
821 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | 825 | |
822 | unsigned long tmp; | 826 | case PTRACE_GETFPREGS: /* Get the child FPU state. */ |
823 | if (!access_ok(VERIFY_READ, datap, sizeof(struct user_regs_struct))) { | 827 | return copy_regset_to_user(child, |
824 | ret = -EIO; | 828 | task_user_regset_view(current), |
825 | break; | 829 | REGSET_FP, |
826 | } | 830 | 0, sizeof(struct user_i387_struct), |
827 | for (i = 0; i < sizeof(struct user_regs_struct); i += sizeof(long)) { | 831 | datap); |
828 | __get_user(tmp, datap); | 832 | |
829 | putreg(child, i, tmp); | 833 | case PTRACE_SETFPREGS: /* Set the child FPU state. */ |
830 | datap++; | 834 | return copy_regset_from_user(child, |
831 | } | 835 | task_user_regset_view(current), |
832 | ret = 0; | 836 | REGSET_FP, |
833 | break; | 837 | 0, sizeof(struct user_i387_struct), |
834 | } | 838 | datap); |
835 | |||
836 | case PTRACE_GETFPREGS: { /* Get the child FPU state. */ | ||
837 | if (!access_ok(VERIFY_WRITE, datap, | ||
838 | sizeof(struct user_i387_struct))) { | ||
839 | ret = -EIO; | ||
840 | break; | ||
841 | } | ||
842 | ret = 0; | ||
843 | if (!tsk_used_math(child)) | ||
844 | init_fpu(child); | ||
845 | get_fpregs((struct user_i387_struct __user *)data, child); | ||
846 | break; | ||
847 | } | ||
848 | |||
849 | case PTRACE_SETFPREGS: { /* Set the child FPU state. */ | ||
850 | if (!access_ok(VERIFY_READ, datap, | ||
851 | sizeof(struct user_i387_struct))) { | ||
852 | ret = -EIO; | ||
853 | break; | ||
854 | } | ||
855 | set_stopped_child_used_math(child); | ||
856 | set_fpregs(child, (struct user_i387_struct __user *)data); | ||
857 | ret = 0; | ||
858 | break; | ||
859 | } | ||
860 | 839 | ||
861 | #ifdef CONFIG_X86_32 | 840 | #ifdef CONFIG_X86_32 |
862 | case PTRACE_GETFPXREGS: { /* Get the child extended FPU state. */ | 841 | case PTRACE_GETFPXREGS: /* Get the child extended FPU state. */ |
863 | if (!access_ok(VERIFY_WRITE, datap, | 842 | return copy_regset_to_user(child, &user_x86_32_view, |
864 | sizeof(struct user_fxsr_struct))) { | 843 | REGSET_XFP, |
865 | ret = -EIO; | 844 | 0, sizeof(struct user_fxsr_struct), |
866 | break; | 845 | datap); |
867 | } | 846 | |
868 | if (!tsk_used_math(child)) | 847 | case PTRACE_SETFPXREGS: /* Set the child extended FPU state. */ |
869 | init_fpu(child); | 848 | return copy_regset_from_user(child, &user_x86_32_view, |
870 | ret = get_fpxregs((struct user_fxsr_struct __user *)data, child); | 849 | REGSET_XFP, |
871 | break; | 850 | 0, sizeof(struct user_fxsr_struct), |
872 | } | 851 | datap); |
873 | |||
874 | case PTRACE_SETFPXREGS: { /* Set the child extended FPU state. */ | ||
875 | if (!access_ok(VERIFY_READ, datap, | ||
876 | sizeof(struct user_fxsr_struct))) { | ||
877 | ret = -EIO; | ||
878 | break; | ||
879 | } | ||
880 | set_stopped_child_used_math(child); | ||
881 | ret = set_fpxregs(child, (struct user_fxsr_struct __user *)data); | ||
882 | break; | ||
883 | } | ||
884 | #endif | 852 | #endif |
885 | 853 | ||
886 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | 854 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION |
@@ -1243,90 +1211,40 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) | |||
1243 | ret = putreg32(child, addr, data); | 1211 | ret = putreg32(child, addr, data); |
1244 | break; | 1212 | break; |
1245 | 1213 | ||
1246 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ | 1214 | case PTRACE_GETREGS: /* Get all gp regs from the child. */ |
1247 | int i; | 1215 | return copy_regset_to_user(child, &user_x86_32_view, |
1248 | 1216 | REGSET_GENERAL, | |
1249 | if (!access_ok(VERIFY_WRITE, datap, 16*4)) { | 1217 | 0, sizeof(struct user_regs_struct32), |
1250 | ret = -EIO; | 1218 | datap); |
1251 | break; | 1219 | |
1252 | } | 1220 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ |
1253 | ret = 0; | 1221 | return copy_regset_from_user(child, &user_x86_32_view, |
1254 | for (i = 0; i < sizeof(struct user_regs_struct32); i += sizeof(__u32)) { | 1222 | REGSET_GENERAL, 0, |
1255 | getreg32(child, i, &val); | 1223 | sizeof(struct user_regs_struct32), |
1256 | ret |= __put_user(val, (u32 __user *)datap); | 1224 | datap); |
1257 | datap += sizeof(u32); | 1225 | |
1258 | } | 1226 | case PTRACE_GETFPREGS: /* Get the child FPU state. */ |
1259 | break; | 1227 | return copy_regset_to_user(child, &user_x86_32_view, |
1260 | } | 1228 | REGSET_FP, 0, |
1261 | 1229 | sizeof(struct user_i387_ia32_struct), | |
1262 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | 1230 | datap); |
1263 | unsigned long tmp; | 1231 | |
1264 | int i; | 1232 | case PTRACE_SETFPREGS: /* Set the child FPU state. */ |
1265 | 1233 | return copy_regset_from_user( | |
1266 | if (!access_ok(VERIFY_READ, datap, 16*4)) { | 1234 | child, &user_x86_32_view, REGSET_FP, |
1267 | ret = -EIO; | 1235 | 0, sizeof(struct user_i387_ia32_struct), datap); |
1268 | break; | 1236 | |
1269 | } | 1237 | case PTRACE_GETFPXREGS: /* Get the child extended FPU state. */ |
1270 | ret = 0; | 1238 | return copy_regset_to_user(child, &user_x86_32_view, |
1271 | for (i = 0; i < sizeof(struct user_regs_struct32); i += sizeof(u32)) { | 1239 | REGSET_XFP, 0, |
1272 | ret |= __get_user(tmp, (u32 __user *)datap); | 1240 | sizeof(struct user32_fxsr_struct), |
1273 | putreg32(child, i, tmp); | 1241 | datap); |
1274 | datap += sizeof(u32); | 1242 | |
1275 | } | 1243 | case PTRACE_SETFPXREGS: /* Set the child extended FPU state. */ |
1276 | break; | 1244 | return copy_regset_from_user(child, &user_x86_32_view, |
1277 | } | 1245 | REGSET_XFP, 0, |
1278 | 1246 | sizeof(struct user32_fxsr_struct), | |
1279 | case PTRACE_GETFPREGS: | 1247 | datap); |
1280 | ret = -EIO; | ||
1281 | if (!access_ok(VERIFY_READ, compat_ptr(data), | ||
1282 | sizeof(struct user_i387_struct))) | ||
1283 | break; | ||
1284 | save_i387_ia32(child, datap, childregs, 1); | ||
1285 | ret = 0; | ||
1286 | break; | ||
1287 | |||
1288 | case PTRACE_SETFPREGS: | ||
1289 | ret = -EIO; | ||
1290 | if (!access_ok(VERIFY_WRITE, datap, | ||
1291 | sizeof(struct user_i387_struct))) | ||
1292 | break; | ||
1293 | ret = 0; | ||
1294 | /* don't check EFAULT to be bug-to-bug compatible to i386 */ | ||
1295 | restore_i387_ia32(child, datap, 1); | ||
1296 | break; | ||
1297 | |||
1298 | case PTRACE_GETFPXREGS: { | ||
1299 | struct user32_fxsr_struct __user *u = datap; | ||
1300 | |||
1301 | init_fpu(child); | ||
1302 | ret = -EIO; | ||
1303 | if (!access_ok(VERIFY_WRITE, u, sizeof(*u))) | ||
1304 | break; | ||
1305 | ret = -EFAULT; | ||
1306 | if (__copy_to_user(u, &child->thread.i387.fxsave, sizeof(*u))) | ||
1307 | break; | ||
1308 | ret = __put_user(childregs->cs, &u->fcs); | ||
1309 | ret |= __put_user(child->thread.ds, &u->fos); | ||
1310 | break; | ||
1311 | } | ||
1312 | case PTRACE_SETFPXREGS: { | ||
1313 | struct user32_fxsr_struct __user *u = datap; | ||
1314 | |||
1315 | unlazy_fpu(child); | ||
1316 | ret = -EIO; | ||
1317 | if (!access_ok(VERIFY_READ, u, sizeof(*u))) | ||
1318 | break; | ||
1319 | /* | ||
1320 | * no checking to be bug-to-bug compatible with i386. | ||
1321 | * but silence warning | ||
1322 | */ | ||
1323 | if (__copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u))) | ||
1324 | ; | ||
1325 | set_stopped_child_used_math(child); | ||
1326 | child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask; | ||
1327 | ret = 0; | ||
1328 | break; | ||
1329 | } | ||
1330 | 1248 | ||
1331 | case PTRACE_GETEVENTMSG: | 1249 | case PTRACE_GETEVENTMSG: |
1332 | ret = put_user(child->ptrace_message, | 1250 | ret = put_user(child->ptrace_message, |