Loading arch/ia64/kernel/ptrace.c +58 −91 Original line number Diff line number Diff line Loading @@ -1489,9 +1489,17 @@ access_elf_reg(struct task_struct *target, struct unw_frame_info *info, return access_elf_areg(target, info, addr, data, write_access); } struct regset_membuf { struct membuf to; int ret; }; void do_gpregs_get(struct unw_frame_info *info, void *arg) { struct regset_getset *dst = arg; struct regset_membuf *dst = arg; struct membuf to = dst->to; unsigned int n; elf_greg_t reg; if (unw_unwind_to_user(info) < 0) return; Loading @@ -1509,35 +1517,13 @@ void do_gpregs_get(struct unw_frame_info *info, void *arg) /* Skip r0 */ if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(1)) { dst->ret = user_regset_copyout_zero(&dst->pos, &dst->count, &dst->u.get.kbuf, &dst->u.get.ubuf, 0, ELF_GR_OFFSET(1)); if (dst->ret) return; } while (dst->count && dst->pos < ELF_AR_END_OFFSET) { unsigned int n, from, to; elf_greg_t tmp[16]; from = dst->pos; to = from + min(dst->count, (unsigned)sizeof(tmp)); if (to > ELF_AR_END_OFFSET) to = ELF_AR_END_OFFSET; for (n = 0; from < to; from += sizeof(elf_greg_t), n++) { if (access_elf_reg(dst->target, info, from, &tmp[n], 0) < 0) { membuf_zero(&to, 8); for (n = 8; to.left && n < ELF_AR_END_OFFSET; n += 8) { if (access_elf_reg(info->task, info, n, ®, 0) < 0) { dst->ret = -EIO; return; } } dst->ret = user_regset_copyout(&dst->pos, &dst->count, &dst->u.get.kbuf, &dst->u.get.ubuf, tmp, dst->pos, to); if (dst->ret) return; membuf_store(&to, reg); } } Loading Loading @@ -1588,60 +1574,36 @@ void do_gpregs_set(struct unw_frame_info *info, void *arg) void do_fpregs_get(struct unw_frame_info *info, void *arg) { struct regset_getset *dst = arg; struct task_struct *task = dst->target; elf_fpreg_t tmp[30]; int index, min_copy, i; struct task_struct *task = info->task; struct regset_membuf *dst = arg; struct membuf to = dst->to; elf_fpreg_t reg; unsigned int n; if (unw_unwind_to_user(info) < 0) return; /* Skip pos 0 and 1 */ if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(2)) { dst->ret = user_regset_copyout_zero(&dst->pos, &dst->count, &dst->u.get.kbuf, &dst->u.get.ubuf, 0, ELF_FP_OFFSET(2)); if (dst->count == 0 || dst->ret) return; } membuf_zero(&to, 2 * sizeof(elf_fpreg_t)); /* fr2-fr31 */ if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(32)) { index = (dst->pos - ELF_FP_OFFSET(2)) / sizeof(elf_fpreg_t); min_copy = min(((unsigned int)ELF_FP_OFFSET(32)), dst->pos + dst->count); for (i = dst->pos; i < min_copy; i += sizeof(elf_fpreg_t), index++) if (unw_get_fr(info, i / sizeof(elf_fpreg_t), &tmp[index])) { for (n = 2; to.left && n < 32; n++) { if (unw_get_fr(info, n, ®)) { dst->ret = -EIO; return; } dst->ret = user_regset_copyout(&dst->pos, &dst->count, &dst->u.get.kbuf, &dst->u.get.ubuf, tmp, ELF_FP_OFFSET(2), ELF_FP_OFFSET(32)); if (dst->count == 0 || dst->ret) return; membuf_write(&to, ®, sizeof(reg)); } /* fph */ if (dst->count > 0) { ia64_flush_fph(dst->target); if (!to.left) return; ia64_flush_fph(task); if (task->thread.flags & IA64_THREAD_FPH_VALID) dst->ret = user_regset_copyout( &dst->pos, &dst->count, &dst->u.get.kbuf, &dst->u.get.ubuf, &dst->target->thread.fph, ELF_FP_OFFSET(32), -1); membuf_write(&to, &task->thread.fph, 96 * sizeof(reg)); else /* Zero fill instead. */ dst->ret = user_regset_copyout_zero( &dst->pos, &dst->count, &dst->u.get.kbuf, &dst->u.get.ubuf, ELF_FP_OFFSET(32), -1); } membuf_zero(&to, 96 * sizeof(reg)); } void do_fpregs_set(struct unw_frame_info *info, void *arg) Loading Loading @@ -1717,6 +1679,20 @@ void do_fpregs_set(struct unw_frame_info *info, void *arg) } } static void unwind_and_call(void (*call)(struct unw_frame_info *, void *), struct task_struct *target, void *data) { if (target == current) unw_init_running(call, data); else { struct unw_frame_info info; memset(&info, 0, sizeof(info)); unw_init_from_blocked_task(&info, target); (*call)(&info, data); } } static int do_regset_call(void (*call)(struct unw_frame_info *, void *), struct task_struct *target, Loading @@ -1728,27 +1704,18 @@ do_regset_call(void (*call)(struct unw_frame_info *, void *), .pos = pos, .count = count, .u.set = { .kbuf = kbuf, .ubuf = ubuf }, .ret = 0 }; if (target == current) unw_init_running(call, &info); else { struct unw_frame_info ufi; memset(&ufi, 0, sizeof(ufi)); unw_init_from_blocked_task(&ufi, target); (*call)(&ufi, &info); } unwind_and_call(call, target, &info); return info.ret; } static int gpregs_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) struct membuf to) { return do_regset_call(do_gpregs_get, target, regset, pos, count, kbuf, ubuf); struct regset_membuf info = {.to = to}; unwind_and_call(do_gpregs_get, target, &info); return info.ret; } static int gpregs_set(struct task_struct *target, Loading Loading @@ -1790,11 +1757,11 @@ fpregs_active(struct task_struct *target, const struct user_regset *regset) static int fpregs_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) struct membuf to) { return do_regset_call(do_fpregs_get, target, regset, pos, count, kbuf, ubuf); struct regset_membuf info = {.to = to}; unwind_and_call(do_fpregs_get, target, &info); return info.ret; } static int fpregs_set(struct task_struct *target, Loading Loading @@ -2033,14 +2000,14 @@ static const struct user_regset native_regsets[] = { .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, .size = sizeof(elf_greg_t), .align = sizeof(elf_greg_t), .get = gpregs_get, .set = gpregs_set, .regset_get = gpregs_get, .set = gpregs_set, .writeback = gpregs_writeback }, { .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, .size = sizeof(elf_fpreg_t), .align = sizeof(elf_fpreg_t), .get = fpregs_get, .set = fpregs_set, .active = fpregs_active .regset_get = fpregs_get, .set = fpregs_set, .active = fpregs_active }, }; Loading Loading
arch/ia64/kernel/ptrace.c +58 −91 Original line number Diff line number Diff line Loading @@ -1489,9 +1489,17 @@ access_elf_reg(struct task_struct *target, struct unw_frame_info *info, return access_elf_areg(target, info, addr, data, write_access); } struct regset_membuf { struct membuf to; int ret; }; void do_gpregs_get(struct unw_frame_info *info, void *arg) { struct regset_getset *dst = arg; struct regset_membuf *dst = arg; struct membuf to = dst->to; unsigned int n; elf_greg_t reg; if (unw_unwind_to_user(info) < 0) return; Loading @@ -1509,35 +1517,13 @@ void do_gpregs_get(struct unw_frame_info *info, void *arg) /* Skip r0 */ if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(1)) { dst->ret = user_regset_copyout_zero(&dst->pos, &dst->count, &dst->u.get.kbuf, &dst->u.get.ubuf, 0, ELF_GR_OFFSET(1)); if (dst->ret) return; } while (dst->count && dst->pos < ELF_AR_END_OFFSET) { unsigned int n, from, to; elf_greg_t tmp[16]; from = dst->pos; to = from + min(dst->count, (unsigned)sizeof(tmp)); if (to > ELF_AR_END_OFFSET) to = ELF_AR_END_OFFSET; for (n = 0; from < to; from += sizeof(elf_greg_t), n++) { if (access_elf_reg(dst->target, info, from, &tmp[n], 0) < 0) { membuf_zero(&to, 8); for (n = 8; to.left && n < ELF_AR_END_OFFSET; n += 8) { if (access_elf_reg(info->task, info, n, ®, 0) < 0) { dst->ret = -EIO; return; } } dst->ret = user_regset_copyout(&dst->pos, &dst->count, &dst->u.get.kbuf, &dst->u.get.ubuf, tmp, dst->pos, to); if (dst->ret) return; membuf_store(&to, reg); } } Loading Loading @@ -1588,60 +1574,36 @@ void do_gpregs_set(struct unw_frame_info *info, void *arg) void do_fpregs_get(struct unw_frame_info *info, void *arg) { struct regset_getset *dst = arg; struct task_struct *task = dst->target; elf_fpreg_t tmp[30]; int index, min_copy, i; struct task_struct *task = info->task; struct regset_membuf *dst = arg; struct membuf to = dst->to; elf_fpreg_t reg; unsigned int n; if (unw_unwind_to_user(info) < 0) return; /* Skip pos 0 and 1 */ if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(2)) { dst->ret = user_regset_copyout_zero(&dst->pos, &dst->count, &dst->u.get.kbuf, &dst->u.get.ubuf, 0, ELF_FP_OFFSET(2)); if (dst->count == 0 || dst->ret) return; } membuf_zero(&to, 2 * sizeof(elf_fpreg_t)); /* fr2-fr31 */ if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(32)) { index = (dst->pos - ELF_FP_OFFSET(2)) / sizeof(elf_fpreg_t); min_copy = min(((unsigned int)ELF_FP_OFFSET(32)), dst->pos + dst->count); for (i = dst->pos; i < min_copy; i += sizeof(elf_fpreg_t), index++) if (unw_get_fr(info, i / sizeof(elf_fpreg_t), &tmp[index])) { for (n = 2; to.left && n < 32; n++) { if (unw_get_fr(info, n, ®)) { dst->ret = -EIO; return; } dst->ret = user_regset_copyout(&dst->pos, &dst->count, &dst->u.get.kbuf, &dst->u.get.ubuf, tmp, ELF_FP_OFFSET(2), ELF_FP_OFFSET(32)); if (dst->count == 0 || dst->ret) return; membuf_write(&to, ®, sizeof(reg)); } /* fph */ if (dst->count > 0) { ia64_flush_fph(dst->target); if (!to.left) return; ia64_flush_fph(task); if (task->thread.flags & IA64_THREAD_FPH_VALID) dst->ret = user_regset_copyout( &dst->pos, &dst->count, &dst->u.get.kbuf, &dst->u.get.ubuf, &dst->target->thread.fph, ELF_FP_OFFSET(32), -1); membuf_write(&to, &task->thread.fph, 96 * sizeof(reg)); else /* Zero fill instead. */ dst->ret = user_regset_copyout_zero( &dst->pos, &dst->count, &dst->u.get.kbuf, &dst->u.get.ubuf, ELF_FP_OFFSET(32), -1); } membuf_zero(&to, 96 * sizeof(reg)); } void do_fpregs_set(struct unw_frame_info *info, void *arg) Loading Loading @@ -1717,6 +1679,20 @@ void do_fpregs_set(struct unw_frame_info *info, void *arg) } } static void unwind_and_call(void (*call)(struct unw_frame_info *, void *), struct task_struct *target, void *data) { if (target == current) unw_init_running(call, data); else { struct unw_frame_info info; memset(&info, 0, sizeof(info)); unw_init_from_blocked_task(&info, target); (*call)(&info, data); } } static int do_regset_call(void (*call)(struct unw_frame_info *, void *), struct task_struct *target, Loading @@ -1728,27 +1704,18 @@ do_regset_call(void (*call)(struct unw_frame_info *, void *), .pos = pos, .count = count, .u.set = { .kbuf = kbuf, .ubuf = ubuf }, .ret = 0 }; if (target == current) unw_init_running(call, &info); else { struct unw_frame_info ufi; memset(&ufi, 0, sizeof(ufi)); unw_init_from_blocked_task(&ufi, target); (*call)(&ufi, &info); } unwind_and_call(call, target, &info); return info.ret; } static int gpregs_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) struct membuf to) { return do_regset_call(do_gpregs_get, target, regset, pos, count, kbuf, ubuf); struct regset_membuf info = {.to = to}; unwind_and_call(do_gpregs_get, target, &info); return info.ret; } static int gpregs_set(struct task_struct *target, Loading Loading @@ -1790,11 +1757,11 @@ fpregs_active(struct task_struct *target, const struct user_regset *regset) static int fpregs_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) struct membuf to) { return do_regset_call(do_fpregs_get, target, regset, pos, count, kbuf, ubuf); struct regset_membuf info = {.to = to}; unwind_and_call(do_fpregs_get, target, &info); return info.ret; } static int fpregs_set(struct task_struct *target, Loading Loading @@ -2033,14 +2000,14 @@ static const struct user_regset native_regsets[] = { .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, .size = sizeof(elf_greg_t), .align = sizeof(elf_greg_t), .get = gpregs_get, .set = gpregs_set, .regset_get = gpregs_get, .set = gpregs_set, .writeback = gpregs_writeback }, { .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, .size = sizeof(elf_fpreg_t), .align = sizeof(elf_fpreg_t), .get = fpregs_get, .set = fpregs_set, .active = fpregs_active .regset_get = fpregs_get, .set = fpregs_set, .active = fpregs_active }, }; Loading