diff options
| author | Roland McGrath <roland@redhat.com> | 2008-01-30 07:31:52 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:31:52 -0500 |
| commit | 91e7b707a4776185f91f03bd052aa53af820094e (patch) | |
| tree | b354543c109f1ae290e3222d8a3708c0f93e4872 /arch | |
| parent | 4c79a2d8e5b7e0a2f987ace9b6af9e7a1655447b (diff) | |
x86: x86 user_regset general regs
This adds accessor functions in the user_regset style for
the general registers (struct user_regs_struct).
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')
| -rw-r--r-- | arch/x86/kernel/ptrace.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 084805ab7323..ef349ff170a7 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
| 14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
| 15 | #include <linux/ptrace.h> | 15 | #include <linux/ptrace.h> |
| 16 | #include <linux/regset.h> | ||
| 16 | #include <linux/user.h> | 17 | #include <linux/user.h> |
| 17 | #include <linux/security.h> | 18 | #include <linux/security.h> |
| 18 | #include <linux/audit.h> | 19 | #include <linux/audit.h> |
| @@ -368,6 +369,59 @@ static unsigned long getreg(struct task_struct *task, unsigned long offset) | |||
| 368 | return *pt_regs_access(task_pt_regs(task), offset); | 369 | return *pt_regs_access(task_pt_regs(task), offset); |
| 369 | } | 370 | } |
| 370 | 371 | ||
| 372 | static int genregs_get(struct task_struct *target, | ||
| 373 | const struct user_regset *regset, | ||
| 374 | unsigned int pos, unsigned int count, | ||
| 375 | void *kbuf, void __user *ubuf) | ||
| 376 | { | ||
| 377 | if (kbuf) { | ||
| 378 | unsigned long *k = kbuf; | ||
| 379 | while (count > 0) { | ||
| 380 | *k++ = getreg(target, pos); | ||
| 381 | count -= sizeof(*k); | ||
| 382 | pos += sizeof(*k); | ||
| 383 | } | ||
| 384 | } else { | ||
| 385 | unsigned long __user *u = ubuf; | ||
| 386 | while (count > 0) { | ||
| 387 | if (__put_user(getreg(target, pos), u++)) | ||
| 388 | return -EFAULT; | ||
| 389 | count -= sizeof(*u); | ||
| 390 | pos += sizeof(*u); | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | return 0; | ||
| 395 | } | ||
| 396 | |||
| 397 | static int genregs_set(struct task_struct *target, | ||
| 398 | const struct user_regset *regset, | ||
| 399 | unsigned int pos, unsigned int count, | ||
| 400 | const void *kbuf, const void __user *ubuf) | ||
| 401 | { | ||
| 402 | int ret = 0; | ||
| 403 | if (kbuf) { | ||
| 404 | const unsigned long *k = kbuf; | ||
| 405 | while (count > 0 && !ret) { | ||
| 406 | ret = putreg(target, pos, *k++); | ||
| 407 | count -= sizeof(*k); | ||
| 408 | pos += sizeof(*k); | ||
| 409 | } | ||
| 410 | } else { | ||
| 411 | const unsigned long __user *u = ubuf; | ||
| 412 | while (count > 0 && !ret) { | ||
| 413 | unsigned long word; | ||
| 414 | ret = __get_user(word, u++); | ||
| 415 | if (ret) | ||
| 416 | break; | ||
| 417 | ret = putreg(target, pos, word); | ||
| 418 | count -= sizeof(*u); | ||
| 419 | pos += sizeof(*u); | ||
| 420 | } | ||
| 421 | } | ||
| 422 | return ret; | ||
| 423 | } | ||
| 424 | |||
| 371 | /* | 425 | /* |
| 372 | * This function is trivial and will be inlined by the compiler. | 426 | * This function is trivial and will be inlined by the compiler. |
| 373 | * Having it separates the implementation details of debug | 427 | * Having it separates the implementation details of debug |
| @@ -1008,6 +1062,61 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) | |||
| 1008 | #undef R32 | 1062 | #undef R32 |
| 1009 | #undef SEG32 | 1063 | #undef SEG32 |
| 1010 | 1064 | ||
| 1065 | static int genregs32_get(struct task_struct *target, | ||
| 1066 | const struct user_regset *regset, | ||
| 1067 | unsigned int pos, unsigned int count, | ||
| 1068 | void *kbuf, void __user *ubuf) | ||
| 1069 | { | ||
| 1070 | if (kbuf) { | ||
| 1071 | compat_ulong_t *k = kbuf; | ||
| 1072 | while (count > 0) { | ||
| 1073 | getreg32(target, pos, k++); | ||
| 1074 | count -= sizeof(*k); | ||
| 1075 | pos += sizeof(*k); | ||
| 1076 | } | ||
| 1077 | } else { | ||
| 1078 | compat_ulong_t __user *u = ubuf; | ||
| 1079 | while (count > 0) { | ||
| 1080 | compat_ulong_t word; | ||
| 1081 | getreg32(target, pos, &word); | ||
| 1082 | if (__put_user(word, u++)) | ||
| 1083 | return -EFAULT; | ||
| 1084 | count -= sizeof(*u); | ||
| 1085 | pos += sizeof(*u); | ||
| 1086 | } | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | return 0; | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | static int genregs32_set(struct task_struct *target, | ||
| 1093 | const struct user_regset *regset, | ||
| 1094 | unsigned int pos, unsigned int count, | ||
| 1095 | const void *kbuf, const void __user *ubuf) | ||
| 1096 | { | ||
| 1097 | int ret = 0; | ||
| 1098 | if (kbuf) { | ||
| 1099 | const compat_ulong_t *k = kbuf; | ||
| 1100 | while (count > 0 && !ret) { | ||
| 1101 | ret = putreg(target, pos, *k++); | ||
| 1102 | count -= sizeof(*k); | ||
| 1103 | pos += sizeof(*k); | ||
| 1104 | } | ||
| 1105 | } else { | ||
| 1106 | const compat_ulong_t __user *u = ubuf; | ||
| 1107 | while (count > 0 && !ret) { | ||
| 1108 | compat_ulong_t word; | ||
| 1109 | ret = __get_user(word, u++); | ||
| 1110 | if (ret) | ||
| 1111 | break; | ||
| 1112 | ret = putreg(target, pos, word); | ||
| 1113 | count -= sizeof(*u); | ||
| 1114 | pos += sizeof(*u); | ||
| 1115 | } | ||
| 1116 | } | ||
| 1117 | return ret; | ||
| 1118 | } | ||
| 1119 | |||
| 1011 | static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data) | 1120 | static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data) |
| 1012 | { | 1121 | { |
| 1013 | siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t)); | 1122 | siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t)); |
