tracechild_sparc.cc

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 488 行 · 第 1/2 页

CC
488
字号
#include <iostream>#include <errno.h>#include <sys/ptrace.h>#include <stdint.h>#include "tracechild_sparc.hh"using namespace std;string SparcTraceChild::regNames[numregs] = {    //Global registers    "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",    //Output registers    "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",    //Local registers    "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",    //Input registers    "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",    //Floating point    "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",    "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",    "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",    "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",    //Miscelaneous    "fsr", "fprs", "pc", "npc", "y", "cwp", "pstate", "asi", "ccr"};bool SparcTraceChild::sendState(int socket){    uint64_t regVal = 0;    for(int x = 0; x <= I7; x++)    {        regVal = getRegVal(x);        if(write(socket, &regVal, sizeof(regVal)) == -1)        {            cerr << "Write failed! " << strerror(errno) << endl;            tracing = false;            return false;        }    }    regVal = getRegVal(PC);    if(write(socket, &regVal, sizeof(regVal)) == -1)    {        cerr << "Write failed! " << strerror(errno) << endl;        tracing = false;        return false;    }    regVal = getRegVal(NPC);    if(write(socket, &regVal, sizeof(regVal)) == -1)    {        cerr << "Write failed! " << strerror(errno) << endl;        tracing = false;        return false;    }    regVal = getRegVal(CCR);    if(write(socket, &regVal, sizeof(regVal)) == -1)    {        cerr << "Write failed! " << strerror(errno) << endl;        tracing = false;        return false;    }    return true;}int64_t getRegs(regs & myregs, fpu & myfpu,        uint64_t * locals, uint64_t * inputs, int num){    assert(num < SparcTraceChild::numregs && num >= 0);    switch(num)    {        //Global registers        case SparcTraceChild::G0: return 0;        case SparcTraceChild::G1: return myregs.r_g1;        case SparcTraceChild::G2: return myregs.r_g2;        case SparcTraceChild::G3: return myregs.r_g3;        case SparcTraceChild::G4: return myregs.r_g4;        case SparcTraceChild::G5: return myregs.r_g5;        case SparcTraceChild::G6: return myregs.r_g6;        case SparcTraceChild::G7: return myregs.r_g7;        //Output registers        case SparcTraceChild::O0: return myregs.r_o0;        case SparcTraceChild::O1: return myregs.r_o1;        case SparcTraceChild::O2: return myregs.r_o2;        case SparcTraceChild::O3: return myregs.r_o3;        case SparcTraceChild::O4: return myregs.r_o4;        case SparcTraceChild::O5: return myregs.r_o5;        case SparcTraceChild::O6: return myregs.r_o6;        case SparcTraceChild::O7: return myregs.r_o7;        //Local registers        case SparcTraceChild::L0: return locals[0];        case SparcTraceChild::L1: return locals[1];        case SparcTraceChild::L2: return locals[2];        case SparcTraceChild::L3: return locals[3];        case SparcTraceChild::L4: return locals[4];        case SparcTraceChild::L5: return locals[5];        case SparcTraceChild::L6: return locals[6];        case SparcTraceChild::L7: return locals[7];        //Input registers        case SparcTraceChild::I0: return inputs[0];        case SparcTraceChild::I1: return inputs[1];        case SparcTraceChild::I2: return inputs[2];        case SparcTraceChild::I3: return inputs[3];        case SparcTraceChild::I4: return inputs[4];        case SparcTraceChild::I5: return inputs[5];        case SparcTraceChild::I6: return inputs[6];        case SparcTraceChild::I7: return inputs[7];        //Floating point        case SparcTraceChild::F0: return myfpu.f_fpstatus.fpu_fr[0];        case SparcTraceChild::F2: return myfpu.f_fpstatus.fpu_fr[1];        case SparcTraceChild::F4: return myfpu.f_fpstatus.fpu_fr[2];        case SparcTraceChild::F6: return myfpu.f_fpstatus.fpu_fr[3];        case SparcTraceChild::F8: return myfpu.f_fpstatus.fpu_fr[4];        case SparcTraceChild::F10: return myfpu.f_fpstatus.fpu_fr[5];        case SparcTraceChild::F12: return myfpu.f_fpstatus.fpu_fr[6];        case SparcTraceChild::F14: return myfpu.f_fpstatus.fpu_fr[7];        case SparcTraceChild::F16: return myfpu.f_fpstatus.fpu_fr[8];        case SparcTraceChild::F18: return myfpu.f_fpstatus.fpu_fr[9];        case SparcTraceChild::F20: return myfpu.f_fpstatus.fpu_fr[10];        case SparcTraceChild::F22: return myfpu.f_fpstatus.fpu_fr[11];        case SparcTraceChild::F24: return myfpu.f_fpstatus.fpu_fr[12];        case SparcTraceChild::F26: return myfpu.f_fpstatus.fpu_fr[13];        case SparcTraceChild::F28: return myfpu.f_fpstatus.fpu_fr[14];        case SparcTraceChild::F30: return myfpu.f_fpstatus.fpu_fr[15];        case SparcTraceChild::F32: return myfpu.f_fpstatus.fpu_fr[16];        case SparcTraceChild::F34: return myfpu.f_fpstatus.fpu_fr[17];        case SparcTraceChild::F36: return myfpu.f_fpstatus.fpu_fr[18];        case SparcTraceChild::F38: return myfpu.f_fpstatus.fpu_fr[19];        case SparcTraceChild::F40: return myfpu.f_fpstatus.fpu_fr[20];        case SparcTraceChild::F42: return myfpu.f_fpstatus.fpu_fr[21];        case SparcTraceChild::F44: return myfpu.f_fpstatus.fpu_fr[22];        case SparcTraceChild::F46: return myfpu.f_fpstatus.fpu_fr[23];        case SparcTraceChild::F48: return myfpu.f_fpstatus.fpu_fr[24];        case SparcTraceChild::F50: return myfpu.f_fpstatus.fpu_fr[25];        case SparcTraceChild::F52: return myfpu.f_fpstatus.fpu_fr[26];        case SparcTraceChild::F54: return myfpu.f_fpstatus.fpu_fr[27];        case SparcTraceChild::F56: return myfpu.f_fpstatus.fpu_fr[28];        case SparcTraceChild::F58: return myfpu.f_fpstatus.fpu_fr[29];        case SparcTraceChild::F60: return myfpu.f_fpstatus.fpu_fr[30];        case SparcTraceChild::F62: return myfpu.f_fpstatus.fpu_fr[31];        //Miscelaneous        case SparcTraceChild::FSR: return myfpu.f_fpstatus.Fpu_fsr;        case SparcTraceChild::FPRS: return myregs.r_fprs;        case SparcTraceChild::PC: return myregs.r_tpc;        case SparcTraceChild::NPC: return myregs.r_tnpc;        case SparcTraceChild::Y: return myregs.r_y;        case SparcTraceChild::CWP:            return (myregs.r_tstate >> 0) & ((1 << 5) - 1);        case SparcTraceChild::PSTATE:            return (myregs.r_tstate >> 8) & ((1 << 13) - 1);        case SparcTraceChild::ASI:            return (myregs.r_tstate >> 24) & ((1 << 8) - 1);        case SparcTraceChild::CCR:            return (myregs.r_tstate >> 32) & ((1 << 8) - 1);        default:            assert(0);            return 0;    }}bool SparcTraceChild::update(int pid){    memcpy(&oldregs, &theregs, sizeof(regs));    memcpy(&oldfpregs, &thefpregs, sizeof(fpu));    memcpy(oldLocals, locals, 8 * sizeof(uint64_t));    memcpy(oldInputs, inputs, 8 * sizeof(uint64_t));    if(ptrace(PTRACE_GETREGS, pid, &theregs, 0) != 0)    {        cerr << "Update failed" << endl;        return false;    }    uint64_t stackPointer = getSP();    uint64_t stackBias = 2047;    bool v9 = stackPointer % 2;    for(unsigned int x = 0; x < 8; x++)    {        uint64_t localAddr = stackPointer +            (v9 ? (stackBias + x * 8) : (x * 4));        locals[x] = ptrace(PTRACE_PEEKTEXT, pid, localAddr, 0);        if(!v9) locals[x] >>= 32;        uint64_t inputAddr = stackPointer +            (v9 ? (stackBias + x * 8 + (8 * 8)) : (x * 4 + 8 * 4));        inputs[x] = ptrace(PTRACE_PEEKTEXT, pid, inputAddr, 0);        if(!v9) inputs[x] >>= 32;    }    if(ptrace(PTRACE_GETFPREGS, pid, &thefpregs, 0) != 0)        return false;    for(unsigned int x = 0; x < numregs; x++)        regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));    return true;}SparcTraceChild::SparcTraceChild(){    for(unsigned int x = 0; x < numregs; x++)        regDiffSinceUpdate[x] = false;}int SparcTraceChild::getTargets(uint32_t inst, uint64_t pc, uint64_t npc,        uint64_t &target1, uint64_t &target2){    //We can identify the instruction categories we care about using the top    //10 bits of the instruction, excluding the annul bit in the 3rd most    //significant bit position and the condition field. We'll call these    //bits the "sig" for signature.    uint32_t sig = (inst >> 22) & 0x307;    uint32_t cond = (inst >> 25) & 0xf;    bool annul = (inst & (1 << 29));    //Check if it's a ba...    bool ba = (cond == 0x8) &&        (sig == 0x1 || sig == 0x2 || sig == 0x5 || sig == 0x6);    //or a bn...    bool bn = (cond == 0x0) &&        (sig == 0x1 || sig == 0x2 || sig == 0x5 || sig == 0x6);    //or a bcc    bool bcc = (cond & 0x7) &&        (sig == 0x1 || sig == 0x2 || sig == 0x3 || sig == 0x5 || sig == 0x6);    if(annul)    {        if(bcc)        {            target1 = npc;            target2 = npc + 4;            return 2;        }        else if(ba)        {            //This branches immediately to the effective address of the branch            //which we'll have to calculate.            uint64_t disp = 0;            int64_t extender = 0;            //Figure out how big the displacement field is, and grab the bits            if(sig == 0x1 || sig == 0x5)            {                disp = inst & ((1 << 19) - 1);                extender = 1 << 18;            }            else            {                disp = inst & ((1 << 22) - 1);                extender = 1 << 21;            }            //This does sign extension, believe it or not.            disp = (disp ^ extender) - extender;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?