The i386-dependent part of the Remote Debug Agent of NLKD. Signed-Off-By: Jan Beulich Index: 2.6.14-nlkd/debug/nlkd/rda/rdaIA32.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ 2.6.14-nlkd/debug/nlkd/rda/rdaIA32.c 2005-06-27 12:00:41.000000000 +0200 @@ -0,0 +1,431 @@ +/***************************************************************************** + * + * File Name: rdaIA32.c + * Created by: Jan Beulich + * Date created: 23Jan2003 + * + * %version: 7 % + * %derived_by: jbeulich % + * %date_modified: Mon Jun 27 04:00:30 2005 % + * + *****************************************************************************/ +/***************************************************************************** + * * + * Copyright (c) 2003-2005 Novell, Inc. All Rights Reserved. * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of version 2 of the GNU General Public License * + * as published by the Free Software Foundation. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, contact Novell, Inc. * + * * + * To contact Novell about this file by physical or electronic mail, * + * you may find current contact information at www.novell.com. * + * * + *****************************************************************************/ +/***************************************************************************** + * + * File Description: + * + *****************************************************************************/ + +#include + +#include "rda.h" + +#define r_FTW (r_invalid - 1) +#define r_FIP (r_invalid - 2) +#define r_FDP (r_invalid - 3) +#define r_FOP (r_invalid - 4) + +#undef EAX /* colliding with include/asm/ptrace.h */ +#undef ECX +#undef EDX +#undef EBX +#undef EBP +#undef ESP +#undef ESI +#undef EDI +#undef EIP +#undef CS +#undef DS +#undef ES +#undef FS +#undef GS +#undef SS +#define REGINFO(gdb, w, cls, idx) gdb, +enum gdb_registers { +#include "rdaIA32.incl" + gdbCOUNT +}; +#undef REGINFO + +union fpreg_u { + float80_t raw; + struct { + uint32_t mant_lo; + uint32_t mant_hi; + uint16_t sign_exp; + }; +}; + +cdeBool_t rdaSetPC(RdaSessionState*state, uintptr_t address) { + if(!cdeWriteEIP(state->currentFrame, address)) { + rdaError(state, RDA_EINVAL); + return cdeFalse; + } + return cdeTrue; +} + +void rdaPutFrameInfo(RdaSessionState*state) { + const ftaFullInterruptionCtx_t*frame = state->currentFrame; + int sigval; + uint32_t value; + + switch(cdeGetInterruptionType(frame, NULL)) { + default: + sigval = 2; + break; + case IA32_ILLEGAL_OPCODE: + sigval = 4; + break; + case IA32_DEBUG: + case IA32_BREAKPOINT: + sigval = 5; + break; + case IA32_RSVD_0F: + case IA32_RSVD_14: + case IA32_RSVD_15: + case IA32_RSVD_16: + case IA32_RSVD_17: + case IA32_RSVD_18: + case IA32_RSVD_19: + case IA32_RSVD_1A: + case IA32_RSVD_1B: + case IA32_RSVD_1C: + case IA32_RSVD_1D: + case IA32_RSVD_1E: + case IA32_RSVD_1F: + sigval = 6; + break; + case IA32_DOUBLE_FAULT: + sigval = 7; + break; + case IA32_DIVIDE_ERROR: + case IA32_DEVICE_NOT_AVAILABLE: + case IA32_FP_ERROR: + case IA32_SIMD_FP_ERROR: + sigval = 8; + break; + case IA32_ALIGNMENT_CHECK: + sigval = 10; + break; + case IA32_COPROCESSOR_SEGMENT_OVERRUN: + case IA32_INVALID_TSS: + case IA32_SEGMENT_NOT_PRESENT: + case IA32_GENERAL_PROTECTION_FAULT: + case IA32_PAGE_FAULT: + sigval = 11; + break; + case IA32_OVERFLOW: + case IA32_BOUNDS_CHECK: + case IA32_STACK_FAULT: + sigval = 16; + break; + } + rdaPutHex(state, sigval, 1); + rdaPutHex(state, EIP, 0); + rdaPutChar(state, ':'); + rdaPutHex(state, cdeReadEIP(frame), -4); + rdaPutChar(state, ';'); + if(cdeReadGR(reg_esp, frame, &value)) { + rdaPutHex(state, ESP, 0); + rdaPutChar(state, ':'); + rdaPutHex(state, value, -4); + rdaPutChar(state, ';'); + } + if(cdeReadGR(reg_ebp, frame, &value)) { + rdaPutHex(state, EBP, 0); + rdaPutChar(state, ':'); + rdaPutHex(state, value, -4); + rdaPutChar(state, ';'); + } +} + +#define REGINFO(gdb, w, cls, idx) {r_##cls, idx}, +static const struct regInfo { + signed char type; + unsigned char index; +} regInfo[] = { +#include "rdaIA32.incl" +}; +#undef REGINFO + +void rdaGetRegisters(RdaSessionState*state, + const char*input, + size_t inputSize) { + unsigned i; + + if(state->currentFrame == NULL) { + rdaError(state, RDA_EAGAIN); + return; + } + if(inputSize != 0) { + rdaError(state, RDA_EINVAL); + return; + } + for(i = 0; i < gdbCOUNT; ++i) { + switch(regInfo[i].type) { + case r_eip: + rdaPutHex(state, cdeReadEIP(state->currentFrame), -4); + break; + case r_eflags: + rdaPutHex(state, cdeReadEFLAGS(state->currentFrame), -4); + break; + case r_general: { + uint32_t value; + + if(!cdeReadGR(regInfo[i].index, state->currentFrame, &value)) + value = 0; + rdaPutHex(state, value, -4); + } + break; + case r_selector: { + uint16_t value; + + if(!cdeReadSR(regInfo[i].index, state->currentFrame, &value)) + value = 0; + rdaPutHex(state, value, -4); + } + break; + case r_floating: { + union fpreg_u value; + + if(!cdeReadFR(regInfo[i].index, state->currentFrame, &value.raw)) + dbgZeroMem(&value, sizeof(value)); + rdaPutHex(state, value.mant_lo, -4); + rdaPutHex(state, value.mant_hi, -4); + rdaPutHex(state, value.sign_exp, -2); + } + break; + case r_fcw: { + uint16_t value; + + if(!cdeReadFpuControlWord(state->currentFrame, &value)) + value = 0; + rdaPutHex(state, value, -4); + } + break; + case r_fsw: { + uint16_t value; + + if(!cdeReadFpuStatusWord(state->currentFrame, &value)) + value = 0; + rdaPutHex(state, value, -4); + } + break; + case r_FTW: { + uint16_t value; + + if(!cdeReadFpuTagWord(state->currentFrame, &value)) + value = 0; + rdaPutHex(state, value, -4); + } + break; + case r_FIP: { + struct CdeAddress address; + + if(!cdeReadFpuCodePointer(state->currentFrame, &address)) + dbgZeroMem(&address, sizeof(address)); + rdaPutHex(state, regInfo[i].index ? address.selector : address.offset, -4); + } + break; + case r_FDP: { + struct CdeAddress address; + + if(!cdeReadFpuDataPointer(state->currentFrame, &address)) + dbgZeroMem(&address, sizeof(address)); + rdaPutHex(state, regInfo[i].index ? address.selector : address.offset, -4); + } + break; + case r_FOP: { + uint16_t value; + + if(!cdeReadFpuOpcode(state->currentFrame, &value)) + value = 0; + rdaPutHex(state, value, -4); + } + break; + case r_xmm: + if(cdeWriteMXCSR(NULL, 0)) { + xmmreg_t value; + + if(!cdeReadXMM(regInfo[i].index, state->currentFrame, &value)) + dbgZeroMem(&value, sizeof(value)); + rdaPutHex(state, value.d[0], -4); + rdaPutHex(state, value.d[1], -4); + rdaPutHex(state, value.d[2], -4); + rdaPutHex(state, value.d[3], -4); + } + break; + case r_mxcsr: + if(cdeWriteMXCSR(NULL, 0)) { + uint32_t value; + + if(!cdeReadMXCSR(state->currentFrame, &value)) + dbgZeroMem(&value, sizeof(value)); + rdaPutHex(state, value, -4); + } + break; + default: + RTASSERT(!(regInfo + i)); + break; + } + } +} + +static cdeBool_t setReg(RdaSessionState*state, + const struct regInfo*info, + const char**pInput) { + cdeBool_t result = cdeFalse; + + switch(info->type) { + uint32_t value; + + case r_eip: + value = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + result = cdeWriteEIP(state->currentFrame, value); + break; + case r_eflags: + value = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + result = cdeWriteEFLAGS(state->currentFrame, value); + break; + case r_general: + value = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + result = cdeWriteGR(info->index, state->currentFrame, value); + break; + case r_selector: + value = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + result = (value == (uint16_t)value && cdeWriteSR(info->index, state->currentFrame, (uint16_t)value)); + break; + case r_floating: { + union fpreg_u value; + + value.mant_lo = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + value.mant_hi = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + value.sign_exp = (uint16_t)rdaGetHex(*pInput, pInput, -2); + if(*pInput != NULL) + result = cdeWriteFR(info->index, state->currentFrame, &value.raw); + } + break; + case r_fcw: + value = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + result = (value == (uint16_t)value && cdeWriteFpuControlWord(state->currentFrame, (uint16_t)value)); + break; + case r_fsw: + value = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + result = (value == (uint16_t)value && cdeWriteFpuStatusWord(state->currentFrame, (uint16_t)value)); + break; + case r_FTW: + value = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + result = (value == (uint16_t)value && cdeWriteFpuTagWord(state->currentFrame, (uint16_t)value)); + break; + case r_FIP: + case r_FDP: + case r_FOP: + result = cdeFalse; + break; + case r_xmm: { + xmmreg_t value; + + value.d[0] = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + value.d[1] = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + value.d[2] = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + value.d[3] = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + result = cdeWriteXMM(info->index, state->currentFrame, &value); + } + break; + case r_mxcsr: + value = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + result = cdeWriteMXCSR(state->currentFrame, value); + break; + default: + RTASSERT(!info); + break; + } + if(*pInput == NULL) { + rdaError(state, RDA_EFORMAT); + result = cdeFalse; + } + else if(!result) + rdaError(state, RDA_EINVAL); + return result; +} + +void rdaSetRegisters(RdaSessionState*state, + const char*input, + size_t inputSize) { + unsigned index; + const char*end; + + if(state->currentFrame == NULL) { + rdaError(state, RDA_EAGAIN); + return; + } + if(inputSize & 1) { + rdaError(state, RDA_EINVAL); + return; + } + for(index = 0, end = input; index < gdbCOUNT; ++index) { + if(!setReg(state, regInfo + index, &end)) + return; + if(input + inputSize == end) + break; + } + if(index == gdbCOUNT) + rdaOK(state); + else + rdaError(state, RDA_EPARTIAL); +} + +void rdaSetRegister(RdaSessionState*state, + const char*input, + size_t inputSize) { + const char*end; + uintptr_t index = rdaGetHex(input, &end, 0); + + if(index >= gdbCOUNT) { + rdaError(state, RDA_EINVAL); + return; + } + if(state->currentFrame == NULL) { + rdaError(state, RDA_EAGAIN); + return; + } + if(!setReg(state, regInfo + index, &input)) + return; + if(input + inputSize == end) + rdaOK(state); + else + rdaError(state, RDA_EFORMAT); +} Index: 2.6.14-nlkd/debug/nlkd/rda/rdaIA32.incl =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ 2.6.14-nlkd/debug/nlkd/rda/rdaIA32.incl 2005-06-27 12:01:06.000000000 +0200 @@ -0,0 +1,78 @@ +/***************************************************************************** + * + * File Name: rdaIA32.incl + * Created by: Jan Beulich + * Date created: 23Jan2003 + * + * %version: 3 % + * %derived_by: jbeulich % + * %date_modified: Mon Jun 27 04:00:55 2005 % + * + *****************************************************************************/ +/***************************************************************************** + * * + * Copyright (c) 2003-2005 Novell, Inc. All Rights Reserved. * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of version 2 of the GNU General Public License * + * as published by the Free Software Foundation. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, contact Novell, Inc. * + * * + * To contact Novell about this file by physical or electronic mail, * + * you may find current contact information at www.novell.com. * + * * + *****************************************************************************/ +/***************************************************************************** + * + * File Description: + * + *****************************************************************************/ + +REGINFO(EAX, 4, general, reg_eax) +REGINFO(ECX, 4, general, reg_ecx) +REGINFO(EDX, 4, general, reg_edx) +REGINFO(EBX, 4, general, reg_ebx) +REGINFO(ESP, 4, general, reg_esp) +REGINFO(EBP, 4, general, reg_ebp) +REGINFO(ESI, 4, general, reg_esi) +REGINFO(EDI, 4, general, reg_edi) +REGINFO(EIP, 4, eip, 0) +REGINFO(EFLAGS, 4, eflags, 0) +REGINFO(CS, 4, selector, sreg_cs) +REGINFO(SS, 4, selector, sreg_ss) +REGINFO(DS, 4, selector, sreg_ds) +REGINFO(ES, 4, selector, sreg_es) +REGINFO(FS, 4, selector, sreg_fs) +REGINFO(GS, 4, selector, sreg_gs) +REGINFO(ST0, 10, floating, st0) +REGINFO(ST1, 10, floating, st1) +REGINFO(ST2, 10, floating, st2) +REGINFO(ST3, 10, floating, st3) +REGINFO(ST4, 10, floating, st4) +REGINFO(ST5, 10, floating, st5) +REGINFO(ST6, 10, floating, st6) +REGINFO(ST7, 10, floating, st7) +REGINFO(FCTRL, 4, fcw, 0) +REGINFO(FSTAT, 4, fsw, 0) +REGINFO(FTAG, 4, FTW, 0) +REGINFO(FISEG, 4, FIP, 1) +REGINFO(FIOFF, 4, FIP, 0) +REGINFO(FOSEG, 4, FDP, 1) +REGINFO(FOOFF, 4, FDP, 0) +REGINFO(FOP, 4, FOP, 0) +REGINFO(XMM0, 16, xmm, 0) +REGINFO(XMM1, 16, xmm, 1) +REGINFO(XMM2, 16, xmm, 2) +REGINFO(XMM3, 16, xmm, 3) +REGINFO(XMM4, 16, xmm, 4) +REGINFO(XMM5, 16, xmm, 5) +REGINFO(XMM6, 16, xmm, 6) +REGINFO(XMM7, 16, xmm, 7) +REGINFO(MXCSR, 4, mxcsr, 0)