| /* |
| * Alpha register context support |
| * |
| * Copyright (C) 2004 Vincent Béron |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "config.h" |
| |
| #ifdef __ALPHA__ |
| |
| #include <assert.h> |
| #include <errno.h> |
| #ifdef HAVE_SYS_REG_H |
| # include <sys/reg.h> |
| #endif |
| #include <stdarg.h> |
| #include <unistd.h> |
| #ifdef HAVE_SYS_PTRACE_H |
| # include <sys/ptrace.h> |
| #endif |
| |
| #include "file.h" |
| #include "thread.h" |
| #include "request.h" |
| |
| #if 0 /* no longer used */ |
| |
| #ifdef HAVE_SYS_USER_H |
| # include <sys/user.h> |
| #endif |
| |
| /* user definitions from asm/user.h */ |
| struct kernel_user_struct |
| { |
| unsigned long regs[EF_SIZE/8+32]; |
| size_t u_tsize; |
| size_t u_dsize; |
| size_t u_ssize; |
| unsigned long start_code; |
| unsigned long start_data; |
| unsigned long start_stack; |
| long int signal; |
| struct regs * u_ar0; |
| unsigned long magic; |
| char u_comm[32]; |
| }; |
| |
| /* get thread context */ |
| static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context ) |
| { |
| int pid = get_ptrace_pid(thread); |
| if (flags & CONTEXT_FULL) |
| { |
| struct kernel_user_struct regs; |
| if (ptrace( PTRACE_GETREGS, pid, 0, ®s ) == -1) goto error; |
| if (flags & CONTEXT_INTEGER) |
| { |
| context->IntV0 = regs.regs[EF_V0]; |
| context->IntT0 = regs.regs[EF_T0]; |
| context->IntT1 = regs.regs[EF_T1]; |
| context->IntT2 = regs.regs[EF_T2]; |
| context->IntT3 = regs.regs[EF_T3]; |
| context->IntT4 = regs.regs[EF_T4]; |
| context->IntT5 = regs.regs[EF_T5]; |
| context->IntT6 = regs.regs[EF_T6]; |
| context->IntT7 = regs.regs[EF_T7]; |
| context->IntS0 = regs.regs[EF_S0]; |
| context->IntS1 = regs.regs[EF_S1]; |
| context->IntS2 = regs.regs[EF_S2]; |
| context->IntS3 = regs.regs[EF_S3]; |
| context->IntS4 = regs.regs[EF_S4]; |
| context->IntS5 = regs.regs[EF_S5]; |
| context->IntFp = regs.regs[EF_S6]; |
| context->IntA0 = regs.regs[EF_A0]; |
| context->IntA1 = regs.regs[EF_A1]; |
| context->IntA2 = regs.regs[EF_A2]; |
| context->IntA3 = regs.regs[EF_A3]; |
| context->IntA4 = regs.regs[EF_A4]; |
| context->IntA5 = regs.regs[EF_A5]; |
| context->IntT8 = regs.regs[EF_T8]; |
| context->IntT9 = regs.regs[EF_T9]; |
| context->IntT10 = regs.regs[EF_T10]; |
| context->IntT11 = regs.regs[EF_T11]; |
| context->IntT12 = regs.regs[EF_T12]; |
| context->IntAt = regs.regs[EF_AT]; |
| context->IntZero = 0; |
| } |
| if (flags & CONTEXT_CONTROL) |
| { |
| context->IntRa = regs.regs[EF_RA]; |
| context->IntGp = regs.regs[EF_GP]; |
| context->IntSp = regs.regs[EF_SP]; |
| context->Fir = regs.regs[EF_PC]; |
| context->Psr = regs.regs[EF_PS]; |
| } |
| if (flags & CONTEXT_FLOATING_POINT) |
| { |
| context->FltF0 = regs.regs[EF_SIZE/8+0]; |
| context->FltF1 = regs.regs[EF_SIZE/8+1]; |
| context->FltF2 = regs.regs[EF_SIZE/8+2]; |
| context->FltF3 = regs.regs[EF_SIZE/8+3]; |
| context->FltF4 = regs.regs[EF_SIZE/8+4]; |
| context->FltF5 = regs.regs[EF_SIZE/8+5]; |
| context->FltF6 = regs.regs[EF_SIZE/8+6]; |
| context->FltF7 = regs.regs[EF_SIZE/8+7]; |
| context->FltF8 = regs.regs[EF_SIZE/8+8]; |
| context->FltF9 = regs.regs[EF_SIZE/8+9]; |
| context->FltF10 = regs.regs[EF_SIZE/8+10]; |
| context->FltF11 = regs.regs[EF_SIZE/8+11]; |
| context->FltF12 = regs.regs[EF_SIZE/8+12]; |
| context->FltF13 = regs.regs[EF_SIZE/8+13]; |
| context->FltF14 = regs.regs[EF_SIZE/8+14]; |
| context->FltF15 = regs.regs[EF_SIZE/8+15]; |
| context->FltF16 = regs.regs[EF_SIZE/8+16]; |
| context->FltF17 = regs.regs[EF_SIZE/8+17]; |
| context->FltF18 = regs.regs[EF_SIZE/8+18]; |
| context->FltF19 = regs.regs[EF_SIZE/8+19]; |
| context->FltF20 = regs.regs[EF_SIZE/8+20]; |
| context->FltF21 = regs.regs[EF_SIZE/8+21]; |
| context->FltF22 = regs.regs[EF_SIZE/8+22]; |
| context->FltF23 = regs.regs[EF_SIZE/8+23]; |
| context->FltF24 = regs.regs[EF_SIZE/8+24]; |
| context->FltF25 = regs.regs[EF_SIZE/8+25]; |
| context->FltF26 = regs.regs[EF_SIZE/8+26]; |
| context->FltF27 = regs.regs[EF_SIZE/8+27]; |
| context->FltF28 = regs.regs[EF_SIZE/8+28]; |
| context->FltF29 = regs.regs[EF_SIZE/8+29]; |
| context->FltF30 = regs.regs[EF_SIZE/8+30]; |
| context->FltF31 = 0; |
| context->Fpcr = regs.regs[EF_SIZE/8+31]; |
| context->SoftFpcr = 0; /* FIXME */ |
| } |
| context->ContextFlags |= flags & CONTEXT_FULL; |
| } |
| return; |
| error: |
| file_set_error(); |
| } |
| |
| /* set a thread context */ |
| static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context ) |
| { |
| int pid = get_ptrace_pid(thread); |
| if (flags & CONTEXT_FULL) |
| { |
| struct kernel_user_struct regs; |
| if (ptrace( PTRACE_GETREGS, pid, 0, ®s ) == -1) goto error; |
| if (flags & CONTEXT_INTEGER) |
| { |
| regs.regs[EF_V0] = context->IntV0; |
| regs.regs[EF_T0] = context->IntT0; |
| regs.regs[EF_T1] = context->IntT1; |
| regs.regs[EF_T2] = context->IntT2; |
| regs.regs[EF_T3] = context->IntT3; |
| regs.regs[EF_T4] = context->IntT4; |
| regs.regs[EF_T5] = context->IntT5; |
| regs.regs[EF_T6] = context->IntT6; |
| regs.regs[EF_T7] = context->IntT7; |
| regs.regs[EF_S0] = context->IntS0; |
| regs.regs[EF_S1] = context->IntS1; |
| regs.regs[EF_S2] = context->IntS2; |
| regs.regs[EF_S3] = context->IntS3; |
| regs.regs[EF_S4] = context->IntS4; |
| regs.regs[EF_S5] = context->IntS5; |
| regs.regs[EF_S6] = context->IntFp; |
| regs.regs[EF_A0] = context->IntA0; |
| regs.regs[EF_A1] = context->IntA1; |
| regs.regs[EF_A2] = context->IntA2; |
| regs.regs[EF_A3] = context->IntA3; |
| regs.regs[EF_A4] = context->IntA4; |
| regs.regs[EF_A5] = context->IntA5; |
| regs.regs[EF_T8] = context->IntT8; |
| regs.regs[EF_T9] = context->IntT9; |
| regs.regs[EF_T10] = context->IntT10; |
| regs.regs[EF_T11] = context->IntT11; |
| regs.regs[EF_T12] = context->IntT12; |
| regs.regs[EF_AT] = context->IntAt; |
| } |
| if (flags & CONTEXT_CONTROL) |
| { |
| regs.regs[EF_RA] = context->IntRa; |
| regs.regs[EF_GP] = context->IntGp; |
| regs.regs[EF_SP] = context->IntSp; |
| regs.regs[EF_PC] = context->Fir; |
| regs.regs[EF_PS] = context->Psr; |
| } |
| if (flags & CONTEXT_FLOATING_POINT) |
| { |
| regs.regs[EF_SIZE/8+0] = context->FltF0; |
| regs.regs[EF_SIZE/8+1] = context->FltF1; |
| regs.regs[EF_SIZE/8+2] = context->FltF2; |
| regs.regs[EF_SIZE/8+3] = context->FltF3; |
| regs.regs[EF_SIZE/8+4] = context->FltF4; |
| regs.regs[EF_SIZE/8+5] = context->FltF5; |
| regs.regs[EF_SIZE/8+6] = context->FltF6; |
| regs.regs[EF_SIZE/8+7] = context->FltF7; |
| regs.regs[EF_SIZE/8+8] = context->FltF8; |
| regs.regs[EF_SIZE/8+9] = context->FltF9; |
| regs.regs[EF_SIZE/8+10] = context->FltF10; |
| regs.regs[EF_SIZE/8+11] = context->FltF11; |
| regs.regs[EF_SIZE/8+12] = context->FltF12; |
| regs.regs[EF_SIZE/8+13] = context->FltF13; |
| regs.regs[EF_SIZE/8+14] = context->FltF14; |
| regs.regs[EF_SIZE/8+15] = context->FltF15; |
| regs.regs[EF_SIZE/8+16] = context->FltF16; |
| regs.regs[EF_SIZE/8+17] = context->FltF17; |
| regs.regs[EF_SIZE/8+18] = context->FltF18; |
| regs.regs[EF_SIZE/8+19] = context->FltF19; |
| regs.regs[EF_SIZE/8+20] = context->FltF20; |
| regs.regs[EF_SIZE/8+21] = context->FltF21; |
| regs.regs[EF_SIZE/8+22] = context->FltF22; |
| regs.regs[EF_SIZE/8+23] = context->FltF23; |
| regs.regs[EF_SIZE/8+24] = context->FltF24; |
| regs.regs[EF_SIZE/8+25] = context->FltF25; |
| regs.regs[EF_SIZE/8+26] = context->FltF26; |
| regs.regs[EF_SIZE/8+27] = context->FltF27; |
| regs.regs[EF_SIZE/8+28] = context->FltF28; |
| regs.regs[EF_SIZE/8+29] = context->FltF29; |
| regs.regs[EF_SIZE/8+30] = context->FltF30; |
| regs.regs[EF_SIZE/8+31] = context->Fpcr; |
| } |
| if (ptrace( PTRACE_SETREGS, pid, 0, ®s ) == -1) goto error; |
| } |
| return; |
| error: |
| file_set_error(); |
| } |
| |
| #endif /* 0 */ |
| |
| /* copy a context structure according to the flags */ |
| void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags ) |
| { |
| flags &= ~CONTEXT_ALPHA; /* get rid of CPU id */ |
| if (flags & CONTEXT_CONTROL) |
| { |
| to->IntRa = from->IntRa; |
| to->IntGp = from->IntGp; |
| to->IntSp = from->IntSp; |
| to->Fir = from->Fir; |
| to->Psr = from->Psr; |
| } |
| if (flags & CONTEXT_INTEGER) |
| { |
| to->IntV0 = from->IntV0; |
| to->IntT0 = from->IntT0; |
| to->IntT1 = from->IntT1; |
| to->IntT2 = from->IntT2; |
| to->IntT3 = from->IntT3; |
| to->IntT4 = from->IntT4; |
| to->IntT5 = from->IntT5; |
| to->IntT6 = from->IntT6; |
| to->IntT7 = from->IntT7; |
| to->IntS0 = from->IntS0; |
| to->IntS1 = from->IntS1; |
| to->IntS2 = from->IntS2; |
| to->IntS3 = from->IntS3; |
| to->IntS4 = from->IntS4; |
| to->IntS5 = from->IntS5; |
| to->IntFp = from->IntFp; |
| to->IntA0 = from->IntA0; |
| to->IntA1 = from->IntA1; |
| to->IntA2 = from->IntA2; |
| to->IntA3 = from->IntA3; |
| to->IntA4 = from->IntA4; |
| to->IntA5 = from->IntA5; |
| to->IntT8 = from->IntT8; |
| to->IntT9 = from->IntT9; |
| to->IntT10 = from->IntT10; |
| to->IntT11 = from->IntT11; |
| to->IntT12 = from->IntT12; |
| to->IntAt = from->IntAt; |
| to->IntZero = from->IntZero; |
| } |
| if (flags & CONTEXT_FLOATING_POINT) |
| { |
| to->FltF0 = from->FltF0; |
| to->FltF1 = from->FltF1; |
| to->FltF2 = from->FltF2; |
| to->FltF3 = from->FltF3; |
| to->FltF4 = from->FltF4; |
| to->FltF5 = from->FltF5; |
| to->FltF6 = from->FltF6; |
| to->FltF7 = from->FltF7; |
| to->FltF8 = from->FltF8; |
| to->FltF9 = from->FltF9; |
| to->FltF10 = from->FltF10; |
| to->FltF11 = from->FltF11; |
| to->FltF12 = from->FltF12; |
| to->FltF13 = from->FltF13; |
| to->FltF14 = from->FltF14; |
| to->FltF15 = from->FltF15; |
| to->FltF16 = from->FltF16; |
| to->FltF17 = from->FltF17; |
| to->FltF18 = from->FltF18; |
| to->FltF19 = from->FltF19; |
| to->FltF20 = from->FltF20; |
| to->FltF21 = from->FltF21; |
| to->FltF22 = from->FltF22; |
| to->FltF23 = from->FltF23; |
| to->FltF24 = from->FltF24; |
| to->FltF25 = from->FltF25; |
| to->FltF26 = from->FltF26; |
| to->FltF27 = from->FltF27; |
| to->FltF28 = from->FltF28; |
| to->FltF29 = from->FltF29; |
| to->FltF30 = from->FltF30; |
| to->FltF31 = from->FltF31; |
| to->Fpcr = from->Fpcr; |
| to->SoftFpcr = from->SoftFpcr; |
| } |
| to->ContextFlags |= flags; |
| } |
| |
| /* retrieve the current instruction pointer of a context */ |
| void *get_context_ip( const CONTEXT *context ) |
| { |
| return (void *)context->Fir; |
| } |
| |
| /* return the context flag that contains the CPU id */ |
| unsigned int get_context_cpu_flag(void) |
| { |
| return CONTEXT_ALPHA; |
| } |
| |
| /* return only the context flags that correspond to system regs */ |
| /* (system regs are the ones we can't access on the client side) */ |
| unsigned int get_context_system_regs( unsigned int flags ) |
| { |
| return 0; /* FIXME: implement client-side handling */ |
| } |
| |
| #endif /* __ALPHA__ */ |