The x86_64-dependent part of the Remote Debug Agent of NLKD. Signed-Off-By: Jan Beulich Index: 2.6.14-nlkd/debug/nlkd/rda/rdaAMD64.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ 2.6.14-nlkd/debug/nlkd/rda/rdaAMD64.c 2005-06-27 11:59:51.000000000 +0200 @@ -0,0 +1,406 @@ +/***************************************************************************** + * + * File Name: rdaAMD64.c + * Created by: Jan Beulich + * Date created: 28Jan2003 + * + * %version: 7 % + * %derived_by: jbeulich % + * %date_modified: Mon Jun 27 03:59:40 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) + +#define REGINFO(gdb, w, cls, idx) gdb, +enum gdb_registers { +#include "rdaAMD64.incl" + gdbCOUNT +}; +#undef REGINFO + +union fpreg_u { + float80_t raw; + struct { + uint64_t mant; + uint16_t sign_exp; + }; +}; + +cdeBool_t rdaSetPC(RdaSessionState*state, uintptr_t address) { + if(!cdeWriteRIP(state->currentFrame, address)) { + rdaError(state, RDA_EINVAL); + return cdeFalse; + } + return cdeTrue; +} + +void rdaPutFrameInfo(RdaSessionState*state) { + const ftaFullInterruptionCtx_t*frame = state->currentFrame; + int sigval; + uint64_t value; + + switch(cdeGetInterruptionType(frame, NULL)) { + default: + sigval = 2; + break; + case AMD64_ILLEGAL_OPCODE: + sigval = 4; + break; + case AMD64_DEBUG: + case AMD64_BREAKPOINT: + sigval = 5; + break; + case AMD64_RSVD_09: + case AMD64_RSVD_0F: + case AMD64_RSVD_14: + case AMD64_RSVD_15: + case AMD64_RSVD_16: + case AMD64_RSVD_17: + case AMD64_RSVD_18: + case AMD64_RSVD_19: + case AMD64_RSVD_1A: + case AMD64_RSVD_1B: + case AMD64_RSVD_1C: + case AMD64_RSVD_1D: + case AMD64_RSVD_1E: + case AMD64_RSVD_1F: + sigval = 6; + break; + case AMD64_DOUBLE_FAULT: + sigval = 7; + break; + case AMD64_DIVIDE_ERROR: + case AMD64_DEVICE_NOT_AVAILABLE: + case AMD64_FP_ERROR: + case AMD64_SIMD_FP_ERROR: + sigval = 8; + break; + case AMD64_ALIGNMENT_CHECK: + sigval = 10; + break; + case AMD64_INVALID_TSS: + case AMD64_SEGMENT_NOT_PRESENT: + case AMD64_GENERAL_PROTECTION_FAULT: + case AMD64_PAGE_FAULT: + sigval = 11; + break; + case AMD64_OVERFLOW: + case AMD64_BOUNDS_CHECK: + case AMD64_STACK_FAULT: + sigval = 16; + break; + } + rdaPutHex(state, sigval, 1); + rdaPutHex(state, RIP, 0); + rdaPutChar(state, ':'); + rdaPutHex(state, cdeReadRIP(frame), -8); + rdaPutChar(state, ';'); + if(cdeReadGR(reg_rsp, frame, &value)) { + rdaPutHex(state, RSP, 0); + rdaPutChar(state, ':'); + rdaPutHex(state, value, -8); + rdaPutChar(state, ';'); + } + if(cdeReadGR(reg_rbp, frame, &value)) { + rdaPutHex(state, RBP, 0); + rdaPutChar(state, ':'); + rdaPutHex(state, value, -8); + rdaPutChar(state, ';'); + } +} + +#define REGINFO(gdb, w, cls, idx) {r_##cls, idx}, +static const struct regInfo { + signed char type; + unsigned char index; +} regInfo[] = { +#include "rdaAMD64.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_rip: + rdaPutHex(state, cdeReadRIP(state->currentFrame), -8); + break; + case r_rflags: + rdaPutHex(state, cdeReadRFLAGS(state->currentFrame), -4); + break; + case r_general: { + uint64_t value; + + if(!cdeReadGR(regInfo[i].index, state->currentFrame, &value)) + value = 0; + rdaPutHex(state, value, -8); + } + break; + case r_selector: { + uint16_t value; + + if(!cdeReadSR(regInfo[i].index, state->currentFrame, &value, NULL)) + 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, -8); + 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.q[0], -8); + rdaPutHex(state, value.q[1], -8); + } + 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) { + uint64_t value; + + case r_rip: + value = rdaGetHex(*pInput, pInput, -8); + if(*pInput != NULL) + result = cdeWriteRIP(state->currentFrame, value); + break; + case r_rflags: + value = rdaGetHex(*pInput, pInput, -4); + if(*pInput != NULL) + result = cdeWriteRFLAGS(state->currentFrame, value); + break; + case r_general: + value = rdaGetHex(*pInput, pInput, -8); + 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, NULL)); + break; + case r_floating: { + union fpreg_u value; + + value.mant = rdaGetHex(*pInput, pInput, -8); + 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.q[0] = rdaGetHex(*pInput, pInput, -8); + if(*pInput != NULL) + value.q[1] = rdaGetHex(*pInput, pInput, -8); + 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, (uint32_t)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/rdaAMD64.incl =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ 2.6.14-nlkd/debug/nlkd/rda/rdaAMD64.incl 2005-06-27 12:00:17.000000000 +0200 @@ -0,0 +1,92 @@ +/***************************************************************************** + * + * File Name: rdaAMD64.incl + * Created by: Jan Beulich + * Date created: 28Jan2003 + * + * %version: 3 % + * %derived_by: jbeulich % + * %date_modified: Mon Jun 27 04:00:05 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(RAX, 8, general, reg_rax) +REGINFO(RCX, 8, general, reg_rcx) +REGINFO(RDX, 8, general, reg_rdx) +REGINFO(RBX, 8, general, reg_rbx) +REGINFO(RSP, 8, general, reg_rsp) +REGINFO(RBP, 8, general, reg_rbp) +REGINFO(RSI, 8, general, reg_rsi) +REGINFO(RDI, 8, general, reg_rdi) +REGINFO(R8, 8, general, reg_r8) +REGINFO(R9, 8, general, reg_r9) +REGINFO(R10, 8, general, reg_r10) +REGINFO(R11, 8, general, reg_r11) +REGINFO(R12, 8, general, reg_r12) +REGINFO(R13, 8, general, reg_r13) +REGINFO(R14, 8, general, reg_r14) +REGINFO(R15, 8, general, reg_r15) +REGINFO(RIP, 8, rip, 0) +REGINFO(EFLAGS, 4, rflags, 0) +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(XMM8, 16, xmm, 8) +REGINFO(XMM9, 16, xmm, 9) +REGINFO(XMM10, 16, xmm, 10) +REGINFO(XMM11, 16, xmm, 11) +REGINFO(XMM12, 16, xmm, 12) +REGINFO(XMM13, 16, xmm, 13) +REGINFO(XMM14, 16, xmm, 14) +REGINFO(XMM15, 16, xmm, 15) +REGINFO(MXCSR, 4, mxcsr, 0)