From 77f712cdb66ce5682824cbb3cd40607c01f8a495 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 28 Jul 2007 20:34:17 -0700 Subject: Statetrace: Fix compilation problem. --HG-- extra : convert_revision : 7f501de99e5389dc3a4172654d7cbe32ed811259 --- util/statetrace/printer.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'util') diff --git a/util/statetrace/printer.cc b/util/statetrace/printer.cc index b14671f2c..178972ea8 100644 --- a/util/statetrace/printer.cc +++ b/util/statetrace/printer.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2006-2007 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -181,7 +181,10 @@ bool NestingPrinter::configure(string config) lastEndPos = endPos; constStrings.push_back(prefix); string subConfig, subString; - int commaPos, lastCommaPos, childSwitchVar; + long int commaPos, lastCommaPos, childSwitchVar; + //Set up the register printer + RegPrinter * regPrinter = new RegPrinter(child); + NestingPrinter * nestingPrinter = new NestingPrinter(child); switch(type) { //If we found a plain register printer @@ -189,8 +192,6 @@ bool NestingPrinter::configure(string config) numPrinters++; //Get the register name subConfig = config.substr(startPos + 2, endPos - startPos - 2); - //Set up the register printer - RegPrinter * regPrinter = new RegPrinter(child); if(!regPrinter->configure(subConfig)) { delete regPrinter; @@ -203,7 +204,6 @@ bool NestingPrinter::configure(string config) case PRINTER_NESTING: numPrinters++; //Punt on reading in all the parameters of the nesting printer - NestingPrinter * nestingPrinter = new NestingPrinter(child); subConfig = config.substr(startPos + 2, endPos - startPos - 2); lastCommaPos = string::npos; commaPos = subConfig.find(","); -- cgit v1.2.3 From fa968da296410a9a6036bdffb17f80be18d99128 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 28 Jul 2007 20:35:33 -0700 Subject: Statetrace: Fix indendation. Set the default hostname to "localhost" instead of my machine at UM. --HG-- extra : convert_revision : f268c04e39fd384e0ac17253faae2233b58e9373 --- util/statetrace/statetrace.cc | 184 +++++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 92 deletions(-) (limited to 'util') diff --git a/util/statetrace/statetrace.cc b/util/statetrace/statetrace.cc index 4fe47dc02..5f7224b25 100644 --- a/util/statetrace/statetrace.cc +++ b/util/statetrace/statetrace.cc @@ -49,115 +49,115 @@ using namespace std; void printUsage(const char * execName) { - cout << execName << " -h | -r -- " << endl; + cout << execName << " -h | -r -- " << endl; } int main(int argc, char * argv[], char * envp[]) { - TraceChild * child = genTraceChild(); - string args; - int startProgramArgs; + TraceChild * child = genTraceChild(); + string args; + int startProgramArgs; - //Parse the command line arguments - bool printInitial = false; - bool printTrace = true; - for(int x = 1; x < argc; x++) + //Parse the command line arguments + bool printInitial = false; + bool printTrace = true; + for(int x = 1; x < argc; x++) + { + if(!strcmp(argv[x], "-h")) { - if(!strcmp(argv[x], "-h")) - { - printUsage(argv[0]); - return 0; - } - else if(!strcmp(argv[x], "-r")) - { - cout << "Legal register names:" << endl; - int numRegs = child->getNumRegs(); - for(unsigned int x = 0; x < numRegs; x++) - { - cout << "\t" << child->getRegName(x) << endl; - } - return 0; - } - else if(!strcmp(argv[x], "-i")) - { - printInitial = true; - } - else if(!strcmp(argv[x], "-nt")) - { - printTrace = false; - } - else if(!strcmp(argv[x], "--")) - { - x++; - if(x >= argc) - { - cerr << "Incorrect usage.\n" << endl; - printUsage(argv[0]); - return 1; - } - startProgramArgs = x; - break; - } - else - { - cerr << "Incorrect usage.\n" << endl; - printUsage(argv[0]); - return 1; - } + printUsage(argv[0]); + return 0; } - if(!child->startTracing(argv[startProgramArgs], - argv + startProgramArgs)) + else if(!strcmp(argv[x], "-r")) { - cerr << "Couldn't start target program" << endl; - return 1; + cout << "Legal register names:" << endl; + int numRegs = child->getNumRegs(); + for(unsigned int x = 0; x < numRegs; x++) + { + cout << "\t" << child->getRegName(x) << endl; + } + return 0; } - if(printInitial) + else if(!strcmp(argv[x], "-i")) { - child->outputStartState(cout); + printInitial = true; } - if(printTrace) + else if(!strcmp(argv[x], "-nt")) { - // Connect to m5 - bool portSet = false; - int port; - int sock = socket(AF_INET, SOCK_STREAM, 0); - if(sock < 0) - { - cerr << "Error opening socket! " << strerror(errno) << endl; - return 1; - } - struct hostent *server; - server = gethostbyname("zower.eecs.umich.edu"); - if(!server) - { - cerr << "Couldn't get host ip! " << strerror(errno) << endl; - return 1; - } - struct sockaddr_in serv_addr; - bzero((char *)&serv_addr, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - bcopy((char *)server->h_addr, - (char *)&serv_addr.sin_addr.s_addr, - server->h_length); - serv_addr.sin_port = htons(8000); - if(connect(sock, (sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) + printTrace = false; + } + else if(!strcmp(argv[x], "--")) + { + x++; + if(x >= argc) { - cerr << "Couldn't connect to server! " << strerror(errno) << endl; + cerr << "Incorrect usage.\n" << endl; + printUsage(argv[0]); return 1; } - child->step(); - while(child->isTracing()) - { - if(!child->sendState(sock)) - break; - child->step(); - } + startProgramArgs = x; + break; } - if(!child->stopTracing()) + else { - cerr << "Couldn't stop child" << endl; - return 1; + cerr << "Incorrect usage.\n" << endl; + printUsage(argv[0]); + return 1; + } + } + if(!child->startTracing(argv[startProgramArgs], + argv + startProgramArgs)) + { + cerr << "Couldn't start target program" << endl; + return 1; + } + if(printInitial) + { + child->outputStartState(cout); + } + if(printTrace) + { + // Connect to m5 + bool portSet = false; + int port; + int sock = socket(AF_INET, SOCK_STREAM, 0); + if(sock < 0) + { + cerr << "Error opening socket! " << strerror(errno) << endl; + return 1; + } + struct hostent *server; + server = gethostbyname("localhost"); + if(!server) + { + cerr << "Couldn't get host ip! " << strerror(errno) << endl; + return 1; + } + struct sockaddr_in serv_addr; + bzero((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + bcopy((char *)server->h_addr, + (char *)&serv_addr.sin_addr.s_addr, + server->h_length); + serv_addr.sin_port = htons(8000); + if(connect(sock, (sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) + { + cerr << "Couldn't connect to server! " << strerror(errno) << endl; + return 1; + } + child->step(); + while(child->isTracing()) + { + if(!child->sendState(sock)) + break; + child->step(); } - return 0; + } + if(!child->stopTracing()) + { + cerr << "Couldn't stop child" << endl; + return 1; + } + return 0; } -- cgit v1.2.3 From 4903b549e77f30abec6fee211adb1f203e14239b Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 28 Jul 2007 20:36:35 -0700 Subject: Statetrace: Implement the AMD64 version of TraceChild. --HG-- extra : convert_revision : cde33fefe46dc05e9b4ea785a4df6b78ac57ccd5 --- util/statetrace/arch/tracechild_amd64.cc | 239 +++++++++++++++++++++++++++++++ util/statetrace/arch/tracechild_amd64.hh | 106 ++++++++++++++ util/statetrace/tracechild_arch.cc | 5 +- 3 files changed, 348 insertions(+), 2 deletions(-) create mode 100644 util/statetrace/arch/tracechild_amd64.cc create mode 100644 util/statetrace/arch/tracechild_amd64.hh (limited to 'util') diff --git a/util/statetrace/arch/tracechild_amd64.cc b/util/statetrace/arch/tracechild_amd64.cc new file mode 100644 index 000000000..505745575 --- /dev/null +++ b/util/statetrace/arch/tracechild_amd64.cc @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2007 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include +#include +#include +#include + +#include "tracechild_amd64.hh" + +using namespace std; + +char * AMD64TraceChild::regNames[numregs] = { + //GPRs + "rax", "rbx", "rcx", "rdx", + //Index registers + "rsi", "rdi", + //Base pointer and stack pointer + "rbp", "rsp", + //New 64 bit mode registers + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + //Segmentation registers + "cs", "ds", "es", "fs", "gs", "ss", "fs_base", "gs_base", + //PC + "rip", + //Flags + "eflags"}; + +bool AMD64TraceChild::sendState(int socket) +{ + uint64_t regVal = 0; + for(int x = 0; x <= R15; x++) + { + regVal = getRegVal(x); + if(write(socket, ®Val, sizeof(regVal)) == -1) + { + cerr << "Write failed! " << strerror(errno) << endl; + tracing = false; + return false; + } + } + regVal = getRegVal(RIP); + if(write(socket, ®Val, sizeof(regVal)) == -1) + { + cerr << "Write failed! " << strerror(errno) << endl; + tracing = false; + return false; + } + return true; +} + +int64_t AMD64TraceChild::getRegs(user_regs_struct & myregs, int num) +{ + assert(num < numregs && num >= 0); + switch(num) + { + //GPRs + case RAX: return myregs.rax; + case RBX: return myregs.rbx; + case RCX: return myregs.rcx; + case RDX: return myregs.rdx; + //Index registers + case RSI: return myregs.rsi; + case RDI: return myregs.rdi; + //Base pointer and stack pointer + case RBP: return myregs.rbp; + case RSP: return myregs.rsp; + //New 64 bit mode registers + case R8: return myregs.r8; + case R9: return myregs.r9; + case R10: return myregs.r10; + case R11: return myregs.r11; + case R12: return myregs.r12; + case R13: return myregs.r13; + case R14: return myregs.r14; + case R15: return myregs.r15; + //Segmentation registers + case CS: return myregs.cs; + case DS: return myregs.ds; + case ES: return myregs.es; + case FS: return myregs.fs; + case GS: return myregs.gs; + case SS: return myregs.ss; + case FS_BASE: return myregs.fs_base; + case GS_BASE: return myregs.gs_base; + //PC + case RIP: return myregs.rip; + //Flags + case EFLAGS: return myregs.eflags; + default: + assert(0); + return 0; + } +} + +bool AMD64TraceChild::update(int pid) +{ + oldregs = regs; + if(ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0) + { + cerr << "update: " << strerror(errno) << endl; + return false; + } + for(unsigned int x = 0; x < numregs; x++) + regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x)); + return true; +} + +AMD64TraceChild::AMD64TraceChild() +{ + for(unsigned int x = 0; x < numregs; x++) + regDiffSinceUpdate[x] = false; +} + +int64_t AMD64TraceChild::getRegVal(int num) +{ + return getRegs(regs, num); +} + +int64_t AMD64TraceChild::getOldRegVal(int num) +{ + return getRegs(oldregs, num); +} + +char * AMD64TraceChild::printReg(int num) +{ + sprintf(printBuffer, "0x%08X", getRegVal(num)); + return printBuffer; +} + +ostream & AMD64TraceChild::outputStartState(ostream & os) +{ + uint64_t sp = getSP(); + uint64_t pc = getPC(); + char obuf[1024]; + sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp); + os << obuf; + sprintf(obuf, "Initial program counter = 0x%016llx\n", pc); + os << obuf; + + //Output the argument count + uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0); + sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc); + os << obuf; + sp += 8; + + //Output argv pointers + int argCount = 0; + uint64_t cargv; + do + { + cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0); + sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n", + sp, argCount++, cargv); + os << obuf; + sp += 8; + } while(cargv); + + //Output the envp pointers + int envCount = 0; + uint64_t cenvp; + do + { + cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0); + sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n", + sp, envCount++, cenvp); + os << obuf; + sp += 8; + } while(cenvp); + uint64_t auxType, auxVal; + do + { + auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0); + sp += 8; + auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0); + sp += 8; + sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n", + sp - 8, auxType, auxVal); + os << obuf; + } while(auxType != 0 || auxVal != 0); + //Print out the argument strings, environment strings, and file name. + string current; + uint64_t buf; + uint64_t currentStart = sp; + bool clearedInitialPadding = false; + do + { + buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0); + char * cbuf = (char *)&buf; + for(int x = 0; x < sizeof(uint64_t); x++) + { + if(cbuf[x]) + current += cbuf[x]; + else + { + sprintf(obuf, "0x%016llx: \"%s\"\n", + currentStart, current.c_str()); + os << obuf; + current = ""; + currentStart = sp + x + 1; + } + } + sp += 8; + clearedInitialPadding = clearedInitialPadding || buf != 0; + } while(!clearedInitialPadding || buf != 0); + return os; +} + +TraceChild * genTraceChild() +{ + return new AMD64TraceChild; +} diff --git a/util/statetrace/arch/tracechild_amd64.hh b/util/statetrace/arch/tracechild_amd64.hh new file mode 100644 index 000000000..36974e56d --- /dev/null +++ b/util/statetrace/arch/tracechild_amd64.hh @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2007 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef REGSTATE_AMD64_HH +#define REGSTATE_AMD64_HH + +#include +#include +#include +#include +#include + +#include "tracechild.hh" + +class AMD64TraceChild : public TraceChild +{ + public: + enum RegNum + { + //GPRs + RAX, RCX, RDX, RBX, + //Base pointer and stack pointer + RSP, RBP, + //Index registers + RSI, RDI, + //New 64 bit mode registers + R8, R9, R10, R11, R12, R13, R14, R15, + //Segmentation registers + CS, DS, ES, FS, GS, SS, FS_BASE, GS_BASE, + //PC + RIP, + //Flags + EFLAGS, + numregs + }; + private: + char printBuffer [256]; + static char * regNames[numregs]; + int64_t getRegs(user_regs_struct & myregs, int num); + user_regs_struct regs; + user_regs_struct oldregs; + bool regDiffSinceUpdate[numregs]; + + protected: + bool update(int pid); + + public: + + AMD64TraceChild(); + + bool sendState(int socket); + + int getNumRegs() + { + return numregs; + } + + bool diffSinceUpdate(int num) + { + assert(num < numregs && num >= 0); + return regDiffSinceUpdate[num]; + } + + std::string getRegName(int num) + { + assert(num < numregs && num >= 0); + return regNames[num]; + } + + int64_t getRegVal(int num); + int64_t getOldRegVal(int num); + uint64_t getPC() {return getRegVal(RIP);} + uint64_t getSP() {return getRegVal(RSP);} + std::ostream & outputStartState(std::ostream & output); + + char * printReg(int num); +}; + +#endif diff --git a/util/statetrace/tracechild_arch.cc b/util/statetrace/tracechild_arch.cc index 603ccb12c..570a12b54 100644 --- a/util/statetrace/tracechild_arch.cc +++ b/util/statetrace/tracechild_arch.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 The Regents of The University of Michigan + * Copyright (c) 2006-2007 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,7 +31,8 @@ #if defined __alpha__ #error "Alpha architecture not implemented" #elif defined __amd64__ - #error "AMD64 architecture not implemented" +// #error "AMD64 architecture not implemented" + #include "arch/tracechild_amd64.cc" #elif defined __hppa__ #error "Hppa architecture not implemented" #elif defined __i386__ || defined __i486__ || \ -- cgit v1.2.3 From c52e28a4d9ddfcfb3e3610b88c1470d3147375a5 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 29 Jul 2007 01:29:53 -0700 Subject: Statetrace: Print the correct address of auxiliary vectors. The address of the stackpointer proceeding the vector minus 8 should be minus 16. --HG-- extra : convert_revision : 648f01e9753e28391fc8d282bd9fe2bd47a0193f --- util/statetrace/arch/tracechild_amd64.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'util') diff --git a/util/statetrace/arch/tracechild_amd64.cc b/util/statetrace/arch/tracechild_amd64.cc index 505745575..d408598e1 100644 --- a/util/statetrace/arch/tracechild_amd64.cc +++ b/util/statetrace/arch/tracechild_amd64.cc @@ -202,7 +202,7 @@ ostream & AMD64TraceChild::outputStartState(ostream & os) auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0); sp += 8; sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n", - sp - 8, auxType, auxVal); + sp - 16, auxType, auxVal); os << obuf; } while(auxType != 0 || auxVal != 0); //Print out the argument strings, environment strings, and file name. -- cgit v1.2.3 From b4087e0e44bba5c4ddbfdb541d50c6c55abed338 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 29 Jul 2007 12:37:35 -0700 Subject: Statetrace: Make statetrace patch amd64 executables for true single stepping after system calls. Because of peculiarities in how system calls are returned from, single stepping executes some system calls and the instruction following them in a single step. Statetrace now patches the executable image when it detects a system call to force "correct" behavior, aka the appearance of stepping one instruction every single time. --HG-- extra : convert_revision : ac6243a2e00ff98f827b005efd27b4dc5be4f774 --- util/statetrace/arch/tracechild_amd64.cc | 83 ++++++++++++++++++++++++++++++++ util/statetrace/arch/tracechild_amd64.hh | 4 ++ 2 files changed, 87 insertions(+) (limited to 'util') diff --git a/util/statetrace/arch/tracechild_amd64.cc b/util/statetrace/arch/tracechild_amd64.cc index d408598e1..088e547e4 100644 --- a/util/statetrace/arch/tracechild_amd64.cc +++ b/util/statetrace/arch/tracechild_amd64.cc @@ -29,6 +29,7 @@ */ #include +#include #include #include #include @@ -233,6 +234,88 @@ ostream & AMD64TraceChild::outputStartState(ostream & os) return os; } +uint64_t AMD64TraceChild::findSyscall() +{ + uint64_t rip = getPC(); + bool foundOpcode = false; + bool twoByteOpcode = false; + for(;;) + { + uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, rip, 0); + for(int i = 0; i < sizeof(uint64_t); i++) + { + unsigned char byte = buf & 0xFF; + if(!foundOpcode) + { + if(!(byte == 0x66 || //operand override + byte == 0x67 || //address override + byte == 0x2E || //cs + byte == 0x3E || //ds + byte == 0x26 || //es + byte == 0x64 || //fs + byte == 0x65 || //gs + byte == 0x36 || //ss + byte == 0xF0 || //lock + byte == 0xF2 || //repe + byte == 0xF3 || //repne + (byte >= 0x40 && byte <= 0x4F) // REX + )) + { + foundOpcode = true; + } + } + if(foundOpcode) + { + if(twoByteOpcode) + { + //SYSCALL or SYSENTER + if(byte == 0x05 || byte == 0x34) + return rip + 1; + else + return 0; + } + if(!twoByteOpcode) + { + if(byte == 0xCC) // INT3 + return rip + 1; + else if(byte == 0xCD) // INT with byte immediate + return rip + 2; + else if(byte == 0x0F) // two byte opcode prefix + twoByteOpcode = true; + else + return 0; + } + } + buf >>= 8; + rip++; + } + } +} + +bool AMD64TraceChild::step() +{ + uint64_t ripAfterSyscall = findSyscall(); + if(ripAfterSyscall) + { + //Get the original contents of memory + uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, ripAfterSyscall, 0); + //Patch the first two bytes of the memory immediately after this with + //jmp -2. Either single stepping will take over before this + //instruction, leaving the rip where it should be, or it will take + //over after this instruction, -still- leaving the rip where it should + //be. + uint64_t newBuf = (buf & ~0xFFFF) | 0xFEEB; + //Write the patched memory to the processes address space + ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, newBuf); + //Step and hit it + ptraceSingleStep(); + //Put things back to the way they started + ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, buf); + } + else + ptraceSingleStep(); +} + TraceChild * genTraceChild() { return new AMD64TraceChild; diff --git a/util/statetrace/arch/tracechild_amd64.hh b/util/statetrace/arch/tracechild_amd64.hh index 36974e56d..e7457f677 100644 --- a/util/statetrace/arch/tracechild_amd64.hh +++ b/util/statetrace/arch/tracechild_amd64.hh @@ -68,6 +68,8 @@ class AMD64TraceChild : public TraceChild user_regs_struct oldregs; bool regDiffSinceUpdate[numregs]; + uint64_t findSyscall(); + protected: bool update(int pid); @@ -101,6 +103,8 @@ class AMD64TraceChild : public TraceChild std::ostream & outputStartState(std::ostream & output); char * printReg(int num); + + bool step(); }; #endif -- cgit v1.2.3