tracechild.cc revision 4780
12221SN/A/* 22221SN/A * Copyright (c) 2007 The Regents of The University of Michigan 32221SN/A * All rights reserved. 42221SN/A * 52221SN/A * Redistribution and use in source and binary forms, with or without 62221SN/A * modification, are permitted provided that the following conditions are 72221SN/A * met: redistributions of source code must retain the above copyright 82221SN/A * notice, this list of conditions and the following disclaimer; 92221SN/A * redistributions in binary form must reproduce the above copyright 102221SN/A * notice, this list of conditions and the following disclaimer in the 112221SN/A * documentation and/or other materials provided with the distribution; 122221SN/A * neither the name of the copyright holders nor the names of its 132221SN/A * contributors may be used to endorse or promote products derived from 142221SN/A * this software without specific prior written permission. 152221SN/A * 162221SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172221SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182221SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192221SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202221SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212221SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222221SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232221SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242221SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252221SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262221SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Gabe Black 292665Ssaidi@eecs.umich.edu */ 302221SN/A 312221SN/A#include <iostream> 322221SN/A#include <errno.h> 332221SN/A#include <sys/ptrace.h> 342221SN/A#include <stdint.h> 352221SN/A 362221SN/A#include "tracechild_amd64.hh" 372221SN/A 382221SN/Ausing namespace std; 392223SN/A 402221SN/Achar * AMD64TraceChild::regNames[numregs] = { 412221SN/A //GPRs 422223SN/A "rax", "rbx", "rcx", "rdx", 432223SN/A //Index registers 442221SN/A "rsi", "rdi", 452223SN/A //Base pointer and stack pointer 462221SN/A "rbp", "rsp", 472221SN/A //New 64 bit mode registers 482221SN/A "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 492221SN/A //Segmentation registers 502221SN/A "cs", "ds", "es", "fs", "gs", "ss", "fs_base", "gs_base", 512223SN/A //PC 522223SN/A "rip", 532223SN/A //Flags 542221SN/A "eflags"}; 552221SN/A 562223SN/Abool AMD64TraceChild::sendState(int socket) 572221SN/A{ 582221SN/A uint64_t regVal = 0; 592221SN/A for(int x = 0; x <= R15; x++) 602223SN/A { 612223SN/A regVal = getRegVal(x); 622223SN/A if(write(socket, ®Val, sizeof(regVal)) == -1) 632221SN/A { 642221SN/A cerr << "Write failed! " << strerror(errno) << endl; 652223SN/A tracing = false; 662223SN/A return false; 672223SN/A } 682221SN/A } 692221SN/A regVal = getRegVal(RIP); 702221SN/A if(write(socket, ®Val, sizeof(regVal)) == -1) 712223SN/A { 722221SN/A cerr << "Write failed! " << strerror(errno) << endl; 732221SN/A tracing = false; 742221SN/A return false; 752223SN/A } 762223SN/A return true; 772223SN/A} 782221SN/A 792221SN/Aint64_t AMD64TraceChild::getRegs(user_regs_struct & myregs, int num) 802223SN/A{ 812223SN/A assert(num < numregs && num >= 0); 822223SN/A switch(num) 832221SN/A { 842221SN/A //GPRs 852221SN/A case RAX: return myregs.rax; 862221SN/A case RBX: return myregs.rbx; 872221SN/A case RCX: return myregs.rcx; 882223SN/A case RDX: return myregs.rdx; 892221SN/A //Index registers 902221SN/A case RSI: return myregs.rsi; 912221SN/A case RDI: return myregs.rdi; 922221SN/A //Base pointer and stack pointer 932223SN/A case RBP: return myregs.rbp; 942221SN/A case RSP: return myregs.rsp; 952221SN/A //New 64 bit mode registers 962223SN/A case R8: return myregs.r8; 972221SN/A case R9: return myregs.r9; 982221SN/A case R10: return myregs.r10; 992221SN/A case R11: return myregs.r11; 1002223SN/A case R12: return myregs.r12; 1012223SN/A case R13: return myregs.r13; 1022223SN/A case R14: return myregs.r14; 1032221SN/A case R15: return myregs.r15; 1042221SN/A //Segmentation registers 1052223SN/A case CS: return myregs.cs; 1062223SN/A case DS: return myregs.ds; 1072223SN/A case ES: return myregs.es; 1082221SN/A case FS: return myregs.fs; 1092221SN/A case GS: return myregs.gs; 1102223SN/A case SS: return myregs.ss; 1112221SN/A case FS_BASE: return myregs.fs_base; 1122221SN/A case GS_BASE: return myregs.gs_base; 1132221SN/A //PC 1142223SN/A case RIP: return myregs.rip; 1152223SN/A //Flags 1162223SN/A case EFLAGS: return myregs.eflags; 1172221SN/A default: 1182221SN/A assert(0); 1192223SN/A return 0; 1202223SN/A } 1212223SN/A} 1222221SN/A 1232221SN/Abool AMD64TraceChild::update(int pid) 1242223SN/A{ 1252221SN/A oldregs = regs; 1262221SN/A if(ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0) 1272221SN/A { 1282223SN/A cerr << "update: " << strerror(errno) << endl; 1292223SN/A return false; 1302223SN/A } 1312221SN/A for(unsigned int x = 0; x < numregs; x++) 1322221SN/A regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x)); 1332223SN/A return true; 1342223SN/A} 1352223SN/A 1362221SN/AAMD64TraceChild::AMD64TraceChild() 1372221SN/A{ 1382223SN/A for(unsigned int x = 0; x < numregs; x++) 1392221SN/A regDiffSinceUpdate[x] = false; 1402221SN/A} 1412221SN/A 1422223SN/Aint64_t AMD64TraceChild::getRegVal(int num) 1432223SN/A{ 1442223SN/A return getRegs(regs, num); 1452221SN/A} 1462221SN/A 1472223SN/Aint64_t AMD64TraceChild::getOldRegVal(int num) 1482223SN/A{ 1492223SN/A return getRegs(oldregs, num); 1502221SN/A} 1512221SN/A 1522223SN/Achar * AMD64TraceChild::printReg(int num) 1532221SN/A{ 1542221SN/A sprintf(printBuffer, "0x%08X", getRegVal(num)); 1552221SN/A return printBuffer; 1562223SN/A} 1572223SN/A 1582223SN/Aostream & AMD64TraceChild::outputStartState(ostream & os) 1592221SN/A{ 1602221SN/A uint64_t sp = getSP(); 1612223SN/A uint64_t pc = getPC(); 1622223SN/A char obuf[1024]; 1632223SN/A sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp); 1642221SN/A os << obuf; 1652221SN/A sprintf(obuf, "Initial program counter = 0x%016llx\n", pc); 1662223SN/A os << obuf; 1672221SN/A 1682221SN/A //Output the argument count 1692221SN/A uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 1702223SN/A sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc); 1712223SN/A os << obuf; 1722223SN/A sp += 8; 1732221SN/A 1742221SN/A //Output argv pointers 1752223SN/A int argCount = 0; 1762223SN/A uint64_t cargv; 1772223SN/A do 1782221SN/A { 1792221SN/A cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 1802223SN/A sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n", 1812221SN/A sp, argCount++, cargv); 1822221SN/A os << obuf; 1832221SN/A sp += 8; 1842223SN/A } while(cargv); 1852223SN/A 1862223SN/A //Output the envp pointers 1872221SN/A int envCount = 0; 1882221SN/A uint64_t cenvp; 1892223SN/A do 1902223SN/A { 1912223SN/A cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 1922221SN/A sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n", 1932221SN/A sp, envCount++, cenvp); 1942223SN/A os << obuf; 1952221SN/A sp += 8; 1962221SN/A } while(cenvp); 1972221SN/A uint64_t auxType, auxVal; 1982223SN/A do 1992223SN/A { 2002223SN/A auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 2012221SN/A sp += 8; 2022221SN/A auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 2032223SN/A sp += 8; 2042223SN/A sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n", 2052223SN/A sp - 8, auxType, auxVal); 2062221SN/A os << obuf; 2072221SN/A } while(auxType != 0 || auxVal != 0); 2082223SN/A //Print out the argument strings, environment strings, and file name. 2092221SN/A string current; 2102221SN/A uint64_t buf; 2112221SN/A uint64_t currentStart = sp; 2122223SN/A bool clearedInitialPadding = false; 2132223SN/A do 2142223SN/A { 2152221SN/A buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 2162221SN/A char * cbuf = (char *)&buf; 2172223SN/A for(int x = 0; x < sizeof(uint64_t); x++) 2182223SN/A { 2192223SN/A if(cbuf[x]) 2202221SN/A current += cbuf[x]; 2212221SN/A else 2222469SN/A { 2232221SN/A sprintf(obuf, "0x%016llx: \"%s\"\n", 2242221SN/A currentStart, current.c_str()); 2252221SN/A os << obuf; 2262223SN/A current = ""; 2272223SN/A currentStart = sp + x + 1; 2282223SN/A } 2292221SN/A } 2302221SN/A sp += 8; 2312223SN/A clearedInitialPadding = clearedInitialPadding || buf != 0; 2322223SN/A } while(!clearedInitialPadding || buf != 0); 2332223SN/A return os; 2342221SN/A} 2352221SN/A 2362223SN/ATraceChild * genTraceChild() 2372221SN/A{ 2382221SN/A return new AMD64TraceChild; 2392221SN/A} 2402223SN/A