diff --git a/server/Makefile.in b/server/Makefile.in index 969b33c73d7..0fb042da388 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -12,6 +12,7 @@ C_SRCS = \ class.c \ clipboard.c \ console.c \ + context_alpha.c \ context_i386.c \ context_powerpc.c \ context_sparc.c \ diff --git a/server/context_alpha.c b/server/context_alpha.c new file mode 100644 index 00000000000..bf4df52c2cd --- /dev/null +++ b/server/context_alpha.c @@ -0,0 +1,406 @@ +/* + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#ifdef __ALPHA__ + +#include +#include +#ifdef HAVE_SYS_REG_H +# include +#endif +#include +#include +#ifdef HAVE_SYS_PTRACE_H +# include +#endif + +#include "file.h" +#include "thread.h" +#include "request.h" + +#ifdef HAVE_SYS_USER_H +# include +#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 */ + } + if (ptrace( PTRACE_SETREGS, pid, 0, ®s ) == -1) goto error; + } + 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; + } + } + return; + error: + file_set_error(); +} + +/* copy a context structure according to the flags */ +static void copy_context( CONTEXT *to, const CONTEXT *from, int flags ) +{ + 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; + } +} + +/* retrieve the current instruction pointer of a thread */ +void *get_thread_ip( struct thread *thread ) +{ + CONTEXT context; + context.Fir = 0; + if (suspend_for_ptrace( thread )) + { + get_thread_context( thread, CONTEXT_CONTROL, &context ); + resume_after_ptrace( thread ); + } + return (void *)context.Fir; +} + +/* determine if we should continue the thread in single-step mode */ +int get_thread_single_step( struct thread *thread ) +{ + return 0; /* FIXME */ +} + +/* send a signal to a specific thread */ +int tkill( int pid, int sig ) +{ + /* FIXME: should do something here */ + errno = ENOSYS; + return -1; +} + +/* retrieve the current context of a thread */ +DECL_HANDLER(get_thread_context) +{ + struct thread *thread; + void *data; + int flags = req->flags & ~CONTEXT_ALPHA; /* get rid of CPU id */ + + if (get_reply_max_size() < sizeof(CONTEXT)) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + } + if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return; + + if ((data = set_reply_data_size( sizeof(CONTEXT) ))) + { + if (thread->context) /* thread is inside an exception event */ + { + copy_context( data, thread->context, flags ); + flags = 0; + } + if (flags && suspend_for_ptrace( thread )) + { + get_thread_context( thread, flags, data ); + resume_after_ptrace( thread ); + } + } + release_object( thread ); +} + +/* set the current context of a thread */ +DECL_HANDLER(set_thread_context) +{ + struct thread *thread; + int flags = req->flags & ~CONTEXT_ALPHA; /* get rid of CPU id */ + + if (get_req_data_size() < sizeof(CONTEXT)) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + } + if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT ))) + { + if (thread->context) /* thread is inside an exception event */ + { + copy_context( thread->context, get_req_data(), flags ); + flags = 0; + } + if (flags && suspend_for_ptrace( thread )) + { + set_thread_context( thread, flags, get_req_data() ); + resume_after_ptrace( thread ); + } + release_object( thread ); + } +} + +#endif /* __ALPHA__ */