aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/ptrace.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2008-01-30 07:31:01 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:31:01 -0500
commitcb757c41f3c2e1ac6f950f9d070e9849983efc18 (patch)
tree467d326b24d8556dc5ebe4a5723663be04bdf5b0 /arch/x86/kernel/ptrace.c
parent86976cd805eccf46d9b720bb188a540fc5769427 (diff)
x86: x86 ia32 ptrace getreg/putreg merge
This reimplements the 64-bit IA32-emulation register access functions in arch/x86/kernel/ptrace.c, where they can share some guts with the native access functions directly. These functions are not used yet, but this paves the way to move IA32 ptrace support into this file to share its local functions. [akpm@linuxfoundation.org: Build fix] 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/ptrace.c')
-rw-r--r--arch/x86/kernel/ptrace.c130
1 files changed, 128 insertions, 2 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 509804957f5f..d56aa18309f8 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -215,14 +215,14 @@ static int set_segment_reg(struct task_struct *task,
215#ifdef CONFIG_IA32_EMULATION 215#ifdef CONFIG_IA32_EMULATION
216 if (test_tsk_thread_flag(task, TIF_IA32)) 216 if (test_tsk_thread_flag(task, TIF_IA32))
217 task_pt_regs(task)->cs = value; 217 task_pt_regs(task)->cs = value;
218 break;
219#endif 218#endif
219 break;
220 case offsetof(struct user_regs_struct,ss): 220 case offsetof(struct user_regs_struct,ss):
221#ifdef CONFIG_IA32_EMULATION 221#ifdef CONFIG_IA32_EMULATION
222 if (test_tsk_thread_flag(task, TIF_IA32)) 222 if (test_tsk_thread_flag(task, TIF_IA32))
223 task_pt_regs(task)->ss = value; 223 task_pt_regs(task)->ss = value;
224 break;
225#endif 224#endif
225 break;
226 } 226 }
227 227
228 return 0; 228 return 0;
@@ -634,6 +634,132 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
634 return ret; 634 return ret;
635} 635}
636 636
637#ifdef CONFIG_IA32_EMULATION
638
639#include <asm/user32.h>
640
641#define R32(l,q) \
642 case offsetof(struct user32, regs.l): \
643 regs->q = value; break
644
645#define SEG32(rs) \
646 case offsetof(struct user32, regs.rs): \
647 return set_segment_reg(child, \
648 offsetof(struct user_regs_struct, rs), \
649 value); \
650 break
651
652static int putreg32(struct task_struct *child, unsigned regno, u32 value)
653{
654 struct pt_regs *regs = task_pt_regs(child);
655
656 switch (regno) {
657
658 SEG32(cs);
659 SEG32(ds);
660 SEG32(es);
661 SEG32(fs);
662 SEG32(gs);
663 SEG32(ss);
664
665 R32(ebx, bx);
666 R32(ecx, cx);
667 R32(edx, dx);
668 R32(edi, di);
669 R32(esi, si);
670 R32(ebp, bp);
671 R32(eax, ax);
672 R32(orig_eax, orig_ax);
673 R32(eip, ip);
674 R32(esp, sp);
675
676 case offsetof(struct user32, regs.eflags):
677 return set_flags(child, value);
678
679 case offsetof(struct user32, u_debugreg[0]) ...
680 offsetof(struct user32, u_debugreg[7]):
681 regno -= offsetof(struct user32, u_debugreg[0]);
682 return ptrace_set_debugreg(child, regno / 4, value);
683
684 default:
685 if (regno > sizeof(struct user32) || (regno & 3))
686 return -EIO;
687
688 /*
689 * Other dummy fields in the virtual user structure
690 * are ignored
691 */
692 break;
693 }
694 return 0;
695}
696
697#undef R32
698#undef SEG32
699
700#define R32(l,q) \
701 case offsetof(struct user32, regs.l): \
702 *val = regs->q; break
703
704#define SEG32(rs) \
705 case offsetof(struct user32, regs.rs): \
706 *val = get_segment_reg(child, \
707 offsetof(struct user_regs_struct, rs)); \
708 break
709
710static int getreg32(struct task_struct *child, unsigned regno, u32 *val)
711{
712 struct pt_regs *regs = task_pt_regs(child);
713
714 switch (regno) {
715
716 SEG32(ds);
717 SEG32(es);
718 SEG32(fs);
719 SEG32(gs);
720
721 R32(cs, cs);
722 R32(ss, ss);
723 R32(ebx, bx);
724 R32(ecx, cx);
725 R32(edx, dx);
726 R32(edi, di);
727 R32(esi, si);
728 R32(ebp, bp);
729 R32(eax, ax);
730 R32(orig_eax, orig_ax);
731 R32(eip, ip);
732 R32(esp, sp);
733
734 case offsetof(struct user32, regs.eflags):
735 *val = get_flags(child);
736 break;
737
738 case offsetof(struct user32, u_debugreg[0]) ...
739 offsetof(struct user32, u_debugreg[7]):
740 regno -= offsetof(struct user32, u_debugreg[0]);
741 *val = ptrace_get_debugreg(child, regno / 4);
742 break;
743
744 default:
745 if (regno > sizeof(struct user32) || (regno & 3))
746 return -EIO;
747
748 /*
749 * Other dummy fields in the virtual user structure
750 * are ignored
751 */
752 *val = 0;
753 break;
754 }
755 return 0;
756}
757
758#undef R32
759#undef SEG32
760
761#endif /* CONFIG_IA32_EMULATION */
762
637#ifdef CONFIG_X86_32 763#ifdef CONFIG_X86_32
638 764
639void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) 765void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)