/* * Copyright 2002-2019 Intel Corporation. * * This software is provided to you as Sample Source Code as defined in the accompanying * End User License Agreement for the Intel(R) Software Development Products ("Agreement") * section 1.L. * * This software and the related documents are provided as is, with no express or implied * warranties, other than those that are expressly stated in the License. */ /* * This tool tests the API PIN_AddDebuggerRegisterEmulator(), which allows * a tool to provide emulated registers to GDB when using application-level debugging. * The tool doesn't do any useful emulation because all registers have the identity * emulation (e.g. the tool emulates REG_RCX by providing the value of REG_RCX). * However, this does demonstrate the usage of the API. */ #include #include #include "pin.H" // // These registers are "emulated" by the tool. // enum EMULATED_REG { EMULATED_REG_RCX, EMULATED_REG_RSP, EMULATED_REG_ST0, EMULATED_REG_FPSW, EMULATED_REG_XMM0 }; // This describes the full set of registers that Pin provides to GDB. // The order and size of each register must match the XML documents // below. Entries with REG_NONE are emulated by the tool. Pin // provides the values for the other registers. // DEBUGGER_REG_DESCRIPTION RegDescs[] = { {REG_RAX, 0, 64}, {REG_RBX, 0, 64}, {REG_NONE, EMULATED_REG_RCX, 64}, {REG_RDX, 0, 64}, {REG_RSI, 0, 64}, {REG_RDI, 0, 64}, {REG_RBP, 0, 64}, {REG_NONE, EMULATED_REG_RSP, 64}, {REG_R8, 0, 64}, {REG_R9, 0, 64}, {REG_R10, 0, 64}, {REG_R11, 0, 64}, {REG_R12, 0, 64}, {REG_R13, 0, 64}, {REG_R14, 0, 64}, {REG_R15, 0, 64}, {REG_INST_PTR, 0, 64}, {REG_RFLAGS, 0, 32}, {REG_SEG_CS, 0, 32}, {REG_SEG_SS, 0, 32}, {REG_SEG_DS, 0, 32}, {REG_SEG_ES, 0, 32}, {REG_SEG_FS, 0, 32}, {REG_SEG_GS, 0, 32}, {REG_NONE, EMULATED_REG_ST0, 80}, {REG_ST1, 0, 80}, {REG_ST2, 0, 80}, {REG_ST3, 0, 80}, {REG_ST4, 0, 80}, {REG_ST5, 0, 80}, {REG_ST6, 0, 80}, {REG_ST7, 0, 80}, {REG_FPCW, 0, 32}, {REG_NONE, EMULATED_REG_FPSW, 32}, {REG_FPTAG_FULL, 0, 32}, {REG_FPIP_SEL, 0, 32}, {REG_FPIP_OFF, 0, 32}, {REG_FPDP_SEL, 0, 32}, {REG_FPDP_OFF, 0, 32}, {REG_FPOPCODE, 0, 32}, {REG_NONE, EMULATED_REG_XMM0, 128}, {REG_XMM1, 0, 128}, {REG_XMM2, 0, 128}, {REG_XMM3, 0, 128}, {REG_XMM4, 0, 128}, {REG_XMM5, 0, 128}, {REG_XMM6, 0, 128}, {REG_XMM7, 0, 128}, {REG_XMM8, 0, 128}, {REG_XMM9, 0, 128}, {REG_XMM10, 0, 128}, {REG_XMM11, 0, 128}, {REG_XMM12, 0, 128}, {REG_XMM13, 0, 128}, {REG_XMM14, 0, 128}, {REG_XMM15, 0, 128}, {REG_MXCSR, 0, 32}, {REG_ORIG_RAX, 0, 64} }; unsigned NumRegs = sizeof(RegDescs) / sizeof(RegDescs[0]); // These XML documents describe the registers to GDB. See the GDB // Manual appendix titled "Target Descriptions" for more information. // const char FeatureDocumentTop[] = "\n" "\n" "\n" "\n" "\n" "\n" "\n" " i386:x86-64\n" " GNU/Linux\n" " \n" " \n" " \n" "\n"; const char FeatureDocumentCore[] = "\n" "\n" "\n" "\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n"; const char FeatureDocumentLinux[] = "\n" "\n" "\n" "\n" "\n" " \n" "\n"; const char FeatureDocumentSSE[] = "\n" "\n" "\n" "\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" " \n" "\n"; static VOID GetReg(unsigned, THREADID, CONTEXT *, VOID *, VOID *); static VOID SetReg(unsigned, THREADID, CONTEXT *, const VOID *, VOID *); static USIZE GetDoc(const std::string &, USIZE, void *, VOID *); static void PrintEmulated(); int main(int argc, char * argv[]) { PIN_Init(argc, argv); PIN_AddDebuggerRegisterEmulator(NumRegs, RegDescs, GetReg, SetReg, GetDoc, 0); PIN_StartProgram(); return 0; } /* * Pin calls this function to get the value of an emulated register. */ static VOID GetReg(unsigned toolRegId, THREADID tid, CONTEXT *ctxt, VOID *data, VOID *) { PrintEmulated(); switch (toolRegId) { case EMULATED_REG_RCX: { ADDRINT *val = static_cast(data); *val = PIN_GetContextReg(ctxt, REG_RCX); break; } case EMULATED_REG_RSP: { ADDRINT *val = static_cast(data); *val = PIN_GetContextReg(ctxt, REG_RSP); break; } case EMULATED_REG_FPSW: { UINT32 *val = static_cast(data); *val = static_cast(PIN_GetContextReg(ctxt, REG_FPSW)); break; } case EMULATED_REG_ST0: { FPSTATE fpstate; PIN_GetContextFPState(ctxt, &fpstate); std::memcpy(data, &fpstate.fxsave_legacy._sts[0], 10); break; } case EMULATED_REG_XMM0: { FPSTATE fpstate; PIN_GetContextFPState(ctxt, &fpstate); std::memcpy(data, &fpstate.fxsave_legacy._xmms[0], 16); break; } default: { ASSERTX(0); break; } } } /* * Pin calls this function to set the value of an emulated register. */ static VOID SetReg(unsigned toolRegId, THREADID tid, CONTEXT *ctxt, const VOID *data, VOID *) { PrintEmulated(); switch (toolRegId) { case EMULATED_REG_RCX: { const ADDRINT *val = static_cast(data); PIN_SetContextReg(ctxt, REG_RCX, *val); break; } case EMULATED_REG_RSP: { const ADDRINT *val = static_cast(data); PIN_SetContextReg(ctxt, REG_RSP, *val); break; } case EMULATED_REG_FPSW: { const UINT32 *val = static_cast(data); PIN_SetContextReg(ctxt, REG_FPSW, static_cast(*val)); break; } case EMULATED_REG_ST0: { FPSTATE fpstate; PIN_GetContextFPState(ctxt, &fpstate); std::memcpy(&fpstate.fxsave_legacy._sts[0], data, 10); PIN_SetContextFPState(ctxt, &fpstate); break; } case EMULATED_REG_XMM0: { FPSTATE fpstate; PIN_GetContextFPState(ctxt, &fpstate); std::memcpy(&fpstate.fxsave_legacy._xmms[0], data, 16); PIN_SetContextFPState(ctxt, &fpstate); break; } default: { ASSERTX(0); break; } } } /* * Pin calls this function to get the content of the XML documents above. */ static USIZE GetDoc(const std::string &name, USIZE size, void *buf, VOID *) { const char *content = 0; size_t docSize = 0; if (name == "target.xml") { content = FeatureDocumentTop; docSize = sizeof(FeatureDocumentTop)-1; } else if (name == "64bit-core.xml") { content = FeatureDocumentCore; docSize = sizeof(FeatureDocumentCore)-1; } else if (name == "64bit-linux.xml") { content = FeatureDocumentLinux; docSize = sizeof(FeatureDocumentLinux)-1; } else if (name == "64bit-sse.xml") { content = FeatureDocumentSSE; docSize = sizeof(FeatureDocumentSSE)-1; } else { return 0; // Unknown document } if (docSize <= size) std::memcpy(buf, content, docSize); return docSize; } static void PrintEmulated() { static bool printed = false; if (!printed) { std::cerr << "Tool is emulating registers" << std::endl; printed = true; } }