tracechild.cc revision 4780
16019SN/A/* 26019SN/A * Copyright (c) 2007 The Regents of The University of Michigan 37110SN/A * All rights reserved. 47110SN/A * 57110SN/A * Redistribution and use in source and binary forms, with or without 67110SN/A * modification, are permitted provided that the following conditions are 77110SN/A * met: redistributions of source code must retain the above copyright 87110SN/A * notice, this list of conditions and the following disclaimer; 97110SN/A * redistributions in binary form must reproduce the above copyright 107110SN/A * notice, this list of conditions and the following disclaimer in the 117110SN/A * documentation and/or other materials provided with the distribution; 127110SN/A * neither the name of the copyright holders nor the names of its 137110SN/A * contributors may be used to endorse or promote products derived from 147110SN/A * this software without specific prior written permission. 156019SN/A * 166019SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019SN/A * 286019SN/A * Authors: Gabe Black 296019SN/A */ 306019SN/A 316019SN/A#include <iostream> 326019SN/A#include <errno.h> 336019SN/A#include <sys/ptrace.h> 346019SN/A#include <stdint.h> 356019SN/A 366019SN/A#include "tracechild_amd64.hh" 376019SN/A 386019SN/Ausing namespace std; 396019SN/A 406019SN/Achar * AMD64TraceChild::regNames[numregs] = { 416019SN/A //GPRs 426019SN/A "rax", "rbx", "rcx", "rdx", 436019SN/A //Index registers 446019SN/A "rsi", "rdi", 456019SN/A //Base pointer and stack pointer 466019SN/A "rbp", "rsp", 476019SN/A //New 64 bit mode registers 486243SN/A "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 497422Sgblack@eecs.umich.edu //Segmentation registers 507422Sgblack@eecs.umich.edu "cs", "ds", "es", "fs", "gs", "ss", "fs_base", "gs_base", 516243SN/A //PC 526243SN/A "rip", 537138Sgblack@eecs.umich.edu //Flags 547138Sgblack@eecs.umich.edu "eflags"}; 557138Sgblack@eecs.umich.edu 567138Sgblack@eecs.umich.edubool AMD64TraceChild::sendState(int socket) 577138Sgblack@eecs.umich.edu{ 587138Sgblack@eecs.umich.edu uint64_t regVal = 0; 597138Sgblack@eecs.umich.edu for(int x = 0; x <= R15; x++) 607138Sgblack@eecs.umich.edu { 617138Sgblack@eecs.umich.edu regVal = getRegVal(x); 627138Sgblack@eecs.umich.edu if(write(socket, ®Val, sizeof(regVal)) == -1) 637138Sgblack@eecs.umich.edu { 647138Sgblack@eecs.umich.edu cerr << "Write failed! " << strerror(errno) << endl; 657138Sgblack@eecs.umich.edu tracing = false; 667138Sgblack@eecs.umich.edu return false; 677138Sgblack@eecs.umich.edu } 687138Sgblack@eecs.umich.edu } 697138Sgblack@eecs.umich.edu regVal = getRegVal(RIP); 707138Sgblack@eecs.umich.edu if(write(socket, ®Val, sizeof(regVal)) == -1) 717138Sgblack@eecs.umich.edu { 727138Sgblack@eecs.umich.edu cerr << "Write failed! " << strerror(errno) << endl; 737138Sgblack@eecs.umich.edu tracing = false; 747848SAli.Saidi@ARM.com return false; 757848SAli.Saidi@ARM.com } 767848SAli.Saidi@ARM.com return true; 777848SAli.Saidi@ARM.com} 787848SAli.Saidi@ARM.com 797138Sgblack@eecs.umich.eduint64_t AMD64TraceChild::getRegs(user_regs_struct & myregs, int num) 807138Sgblack@eecs.umich.edu{ 817138Sgblack@eecs.umich.edu assert(num < numregs && num >= 0); 827138Sgblack@eecs.umich.edu switch(num) 837138Sgblack@eecs.umich.edu { 847138Sgblack@eecs.umich.edu //GPRs 857138Sgblack@eecs.umich.edu case RAX: return myregs.rax; 867138Sgblack@eecs.umich.edu case RBX: return myregs.rbx; 877138Sgblack@eecs.umich.edu case RCX: return myregs.rcx; 887138Sgblack@eecs.umich.edu case RDX: return myregs.rdx; 897138Sgblack@eecs.umich.edu //Index registers 907138Sgblack@eecs.umich.edu case RSI: return myregs.rsi; 917138Sgblack@eecs.umich.edu case RDI: return myregs.rdi; 927138Sgblack@eecs.umich.edu //Base pointer and stack pointer 937138Sgblack@eecs.umich.edu case RBP: return myregs.rbp; 947138Sgblack@eecs.umich.edu case RSP: return myregs.rsp; 957138Sgblack@eecs.umich.edu //New 64 bit mode registers 967138Sgblack@eecs.umich.edu case R8: return myregs.r8; 977138Sgblack@eecs.umich.edu case R9: return myregs.r9; 987138Sgblack@eecs.umich.edu case R10: return myregs.r10; 997138Sgblack@eecs.umich.edu case R11: return myregs.r11; 1007138Sgblack@eecs.umich.edu case R12: return myregs.r12; 1017138Sgblack@eecs.umich.edu case R13: return myregs.r13; 1027138Sgblack@eecs.umich.edu case R14: return myregs.r14; 1037138Sgblack@eecs.umich.edu case R15: return myregs.r15; 1047138Sgblack@eecs.umich.edu //Segmentation registers 1057848SAli.Saidi@ARM.com case CS: return myregs.cs; 1067848SAli.Saidi@ARM.com case DS: return myregs.ds; 1077848SAli.Saidi@ARM.com case ES: return myregs.es; 1087848SAli.Saidi@ARM.com case FS: return myregs.fs; 1097848SAli.Saidi@ARM.com case GS: return myregs.gs; 1107138Sgblack@eecs.umich.edu case SS: return myregs.ss; 1117138Sgblack@eecs.umich.edu case FS_BASE: return myregs.fs_base; 1127138Sgblack@eecs.umich.edu case GS_BASE: return myregs.gs_base; 1137138Sgblack@eecs.umich.edu //PC 1147138Sgblack@eecs.umich.edu case RIP: return myregs.rip; 1157138Sgblack@eecs.umich.edu //Flags 1167138Sgblack@eecs.umich.edu case EFLAGS: return myregs.eflags; 1177138Sgblack@eecs.umich.edu default: 1187138Sgblack@eecs.umich.edu assert(0); 1197138Sgblack@eecs.umich.edu return 0; 1207138Sgblack@eecs.umich.edu } 1217138Sgblack@eecs.umich.edu} 1227138Sgblack@eecs.umich.edu 1237138Sgblack@eecs.umich.edubool AMD64TraceChild::update(int pid) 1247138Sgblack@eecs.umich.edu{ 1257138Sgblack@eecs.umich.edu oldregs = regs; 1267138Sgblack@eecs.umich.edu if(ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0) 1277138Sgblack@eecs.umich.edu { 1287138Sgblack@eecs.umich.edu cerr << "update: " << strerror(errno) << endl; 1297138Sgblack@eecs.umich.edu return false; 1307138Sgblack@eecs.umich.edu } 1317138Sgblack@eecs.umich.edu for(unsigned int x = 0; x < numregs; x++) 1327138Sgblack@eecs.umich.edu regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x)); 1337138Sgblack@eecs.umich.edu return true; 1347138Sgblack@eecs.umich.edu} 1357138Sgblack@eecs.umich.edu 1367848SAli.Saidi@ARM.comAMD64TraceChild::AMD64TraceChild() 1377848SAli.Saidi@ARM.com{ 1387848SAli.Saidi@ARM.com for(unsigned int x = 0; x < numregs; x++) 1397848SAli.Saidi@ARM.com regDiffSinceUpdate[x] = false; 1407848SAli.Saidi@ARM.com} 1417138Sgblack@eecs.umich.edu 1427138Sgblack@eecs.umich.eduint64_t AMD64TraceChild::getRegVal(int num) 1437138Sgblack@eecs.umich.edu{ 1446019SN/A return getRegs(regs, num); 1456019SN/A} 1466019SN/A 1476019SN/Aint64_t AMD64TraceChild::getOldRegVal(int num) 1486271SN/A{ 1496271SN/A return getRegs(oldregs, num); 1506019SN/A} 1516019SN/A 1526019SN/Achar * AMD64TraceChild::printReg(int num) 1536243SN/A{ 1546019SN/A sprintf(printBuffer, "0x%08X", getRegVal(num)); 1556243SN/A return printBuffer; 1566019SN/A} 1576019SN/A 1586019SN/Aostream & AMD64TraceChild::outputStartState(ostream & os) 1596019SN/A{ 1607597Sminkyu.jeong@arm.com uint64_t sp = getSP(); 1617597Sminkyu.jeong@arm.com uint64_t pc = getPC(); 1626019SN/A char obuf[1024]; 1636019SN/A sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp); 1647646Sgene.wu@arm.com os << obuf; 1657646Sgene.wu@arm.com sprintf(obuf, "Initial program counter = 0x%016llx\n", pc); 1667408Sgblack@eecs.umich.edu os << obuf; 1677408Sgblack@eecs.umich.edu 1687408Sgblack@eecs.umich.edu //Output the argument count 1696019SN/A uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 1706019SN/A sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc); 1716019SN/A os << obuf; 1726019SN/A sp += 8; 1738142SAli.Saidi@ARM.com 1748142SAli.Saidi@ARM.com //Output argv pointers 1758142SAli.Saidi@ARM.com int argCount = 0; 1768142SAli.Saidi@ARM.com uint64_t cargv; 1778142SAli.Saidi@ARM.com do 1788142SAli.Saidi@ARM.com { 1798142SAli.Saidi@ARM.com cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 1808142SAli.Saidi@ARM.com sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n", 1818142SAli.Saidi@ARM.com sp, argCount++, cargv); 1828142SAli.Saidi@ARM.com os << obuf; 1838142SAli.Saidi@ARM.com sp += 8; 1848142SAli.Saidi@ARM.com } while(cargv); 1858142SAli.Saidi@ARM.com 1868142SAli.Saidi@ARM.com //Output the envp pointers 1878142SAli.Saidi@ARM.com int envCount = 0; 1888142SAli.Saidi@ARM.com uint64_t cenvp; 1898142SAli.Saidi@ARM.com do 1908142SAli.Saidi@ARM.com { 1918142SAli.Saidi@ARM.com cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 1928142SAli.Saidi@ARM.com sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n", 1938142SAli.Saidi@ARM.com sp, envCount++, cenvp); 1948142SAli.Saidi@ARM.com os << obuf; 1958142SAli.Saidi@ARM.com sp += 8; 1968142SAli.Saidi@ARM.com } while(cenvp); 1978142SAli.Saidi@ARM.com uint64_t auxType, auxVal; 1988142SAli.Saidi@ARM.com do 1998142SAli.Saidi@ARM.com { 2008142SAli.Saidi@ARM.com auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 2018142SAli.Saidi@ARM.com sp += 8; 2028142SAli.Saidi@ARM.com auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 2038142SAli.Saidi@ARM.com sp += 8; 2048142SAli.Saidi@ARM.com sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n", 2056265SN/A sp - 8, auxType, auxVal); 2066265SN/A os << obuf; 2076265SN/A } while(auxType != 0 || auxVal != 0); 2086265SN/A //Print out the argument strings, environment strings, and file name. 2096265SN/A string current; 2106265SN/A uint64_t buf; 2116265SN/A uint64_t currentStart = sp; 2126265SN/A bool clearedInitialPadding = false; 2136265SN/A do 2146265SN/A { 2156265SN/A buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 2166265SN/A char * cbuf = (char *)&buf; 2176265SN/A for(int x = 0; x < sizeof(uint64_t); x++) 2186265SN/A { 2196270SN/A if(cbuf[x]) 2206270SN/A current += cbuf[x]; 2216270SN/A else 2226270SN/A { 2236270SN/A sprintf(obuf, "0x%016llx: \"%s\"\n", 2246270SN/A currentStart, current.c_str()); 225 os << obuf; 226 current = ""; 227 currentStart = sp + x + 1; 228 } 229 } 230 sp += 8; 231 clearedInitialPadding = clearedInitialPadding || buf != 0; 232 } while(!clearedInitialPadding || buf != 0); 233 return os; 234} 235 236TraceChild * genTraceChild() 237{ 238 return new AMD64TraceChild; 239} 240