tracechild.cc revision 7071
111308Santhony.gutierrez@amd.com/* 211308Santhony.gutierrez@amd.com * Copyright (c) 2007 The Regents of The University of Michigan 311308Santhony.gutierrez@amd.com * All rights reserved. 411308Santhony.gutierrez@amd.com * 511308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 611308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are 711308Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 811308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer; 911308Santhony.gutierrez@amd.com * redistributions in binary form must reproduce the above copyright 1011308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer in the 1111308Santhony.gutierrez@amd.com * documentation and/or other materials provided with the distribution; 1211308Santhony.gutierrez@amd.com * neither the name of the copyright holders nor the names of its 1311308Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from 1411308Santhony.gutierrez@amd.com * this software without specific prior written permission. 1511308Santhony.gutierrez@amd.com * 1611308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1711308Santhony.gutierrez@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1811308Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1911308Santhony.gutierrez@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2011308Santhony.gutierrez@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2111308Santhony.gutierrez@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2211308Santhony.gutierrez@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2311308Santhony.gutierrez@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2411308Santhony.gutierrez@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2511308Santhony.gutierrez@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2611308Santhony.gutierrez@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2711308Santhony.gutierrez@amd.com * 2811308Santhony.gutierrez@amd.com * Authors: Gabe Black 2911308Santhony.gutierrez@amd.com */ 3011308Santhony.gutierrez@amd.com 3111308Santhony.gutierrez@amd.com#include <iostream> 3211308Santhony.gutierrez@amd.com#include <iomanip> 3311308Santhony.gutierrez@amd.com#include <errno.h> 3411308Santhony.gutierrez@amd.com#include <sys/ptrace.h> 3511308Santhony.gutierrez@amd.com#include <stdint.h> 3611308Santhony.gutierrez@amd.com#include <string.h> 3711308Santhony.gutierrez@amd.com 3811308Santhony.gutierrez@amd.com#include "tracechild_amd64.hh" 3911308Santhony.gutierrez@amd.com 4011308Santhony.gutierrez@amd.comusing namespace std; 4111308Santhony.gutierrez@amd.com 4211308Santhony.gutierrez@amd.comconst char * AMD64TraceChild::regNames[numregs] = { 4311308Santhony.gutierrez@amd.com //GPRs 4411308Santhony.gutierrez@amd.com "rax", "rbx", "rcx", "rdx", 4511308Santhony.gutierrez@amd.com //Index registers 4611308Santhony.gutierrez@amd.com "rsi", "rdi", 4711308Santhony.gutierrez@amd.com //Base pointer and stack pointer 4811308Santhony.gutierrez@amd.com "rbp", "rsp", 4911308Santhony.gutierrez@amd.com //New 64 bit mode registers 5011308Santhony.gutierrez@amd.com "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 5111308Santhony.gutierrez@amd.com //Segmentation registers 5211308Santhony.gutierrez@amd.com "cs", "ds", "es", "fs", "gs", "ss", "fs_base", "gs_base", 5311308Santhony.gutierrez@amd.com //PC 5411308Santhony.gutierrez@amd.com "rip", 5511308Santhony.gutierrez@amd.com //Flags 5611308Santhony.gutierrez@amd.com "eflags", 5711308Santhony.gutierrez@amd.com //MMX 5811308Santhony.gutierrez@amd.com "mmx0_0", "mmx0_1", 5911308Santhony.gutierrez@amd.com "mmx1_0", "mmx1_1", 6011308Santhony.gutierrez@amd.com "mmx2_0", "mmx2_1", 6111308Santhony.gutierrez@amd.com "mmx3_0", "mmx3_1", 6211308Santhony.gutierrez@amd.com "mmx4_0", "mmx4_1", 6311308Santhony.gutierrez@amd.com "mmx5_0", "mmx5_1", 6411308Santhony.gutierrez@amd.com "mmx6_0", "mmx6_1", 6511308Santhony.gutierrez@amd.com "mmx7_0", "mmx7_1", 6611308Santhony.gutierrez@amd.com //XMM 6711308Santhony.gutierrez@amd.com "xmm0_0", "xmm0_1", "xmm0_2", "xmm0_3", 6811308Santhony.gutierrez@amd.com "xmm1_0", "xmm1_1", "xmm1_2", "xmm1_3", 6911308Santhony.gutierrez@amd.com "xmm2_0", "xmm2_1", "xmm2_2", "xmm2_3", 7011308Santhony.gutierrez@amd.com "xmm3_0", "xmm3_1", "xmm3_2", "xmm3_3", 7111308Santhony.gutierrez@amd.com "xmm4_0", "xmm4_1", "xmm4_2", "xmm4_3", 7211308Santhony.gutierrez@amd.com "xmm5_0", "xmm5_1", "xmm5_2", "xmm5_3", 7311308Santhony.gutierrez@amd.com "xmm6_0", "xmm6_1", "xmm6_2", "xmm6_3", 7411308Santhony.gutierrez@amd.com "xmm7_0", "xmm7_1", "xmm7_2", "xmm7_3", 7511308Santhony.gutierrez@amd.com "xmm8_0", "xmm8_1", "xmm8_2", "xmm8_3", 7611308Santhony.gutierrez@amd.com "xmm9_0", "xmm9_1", "xmm9_2", "xmm9_3", 7711308Santhony.gutierrez@amd.com "xmm10_0", "xmm10_1", "xmm10_2", "xmm10_3", 7811308Santhony.gutierrez@amd.com "xmm11_0", "xmm11_1", "xmm11_2", "xmm11_3", 7911308Santhony.gutierrez@amd.com "xmm12_0", "xmm12_1", "xmm12_2", "xmm12_3", 8011308Santhony.gutierrez@amd.com "xmm13_0", "xmm13_1", "xmm13_2", "xmm13_3", 8111308Santhony.gutierrez@amd.com "xmm14_0", "xmm14_1", "xmm14_2", "xmm14_3", 8211308Santhony.gutierrez@amd.com "xmm15_0", "xmm15_1", "xmm15_2", "xmm15_3"}; 8311308Santhony.gutierrez@amd.com 8411308Santhony.gutierrez@amd.combool AMD64TraceChild::sendState(int socket) 8511308Santhony.gutierrez@amd.com{ 8611308Santhony.gutierrez@amd.com uint64_t regVal64 = 0; 8711308Santhony.gutierrez@amd.com uint32_t regVal32 = 0; 8811308Santhony.gutierrez@amd.com for(int x = 0; x <= R15; x++) 8911308Santhony.gutierrez@amd.com { 9011308Santhony.gutierrez@amd.com regVal64 = getRegVal(x); 9111308Santhony.gutierrez@amd.com if(write(socket, ®Val64, sizeof(regVal64)) == -1) 9211308Santhony.gutierrez@amd.com { 9311308Santhony.gutierrez@amd.com cerr << "Write failed! " << strerror(errno) << endl; 9411308Santhony.gutierrez@amd.com tracing = false; 9511308Santhony.gutierrez@amd.com return false; 9611308Santhony.gutierrez@amd.com } 9711308Santhony.gutierrez@amd.com } 9811308Santhony.gutierrez@amd.com regVal64 = getRegVal(RIP); 9911308Santhony.gutierrez@amd.com if(write(socket, ®Val64, sizeof(regVal64)) == -1) 10011308Santhony.gutierrez@amd.com { 10111308Santhony.gutierrez@amd.com cerr << "Write failed! " << strerror(errno) << endl; 10211308Santhony.gutierrez@amd.com tracing = false; 10311308Santhony.gutierrez@amd.com return false; 10411308Santhony.gutierrez@amd.com } 10511308Santhony.gutierrez@amd.com for(int x = MMX0_0; x <= MMX7_1; x++) 10611308Santhony.gutierrez@amd.com { 10711308Santhony.gutierrez@amd.com regVal32 = getRegVal(x); 10811308Santhony.gutierrez@amd.com if(write(socket, ®Val32, sizeof(regVal32)) == -1) 10911308Santhony.gutierrez@amd.com { 11011308Santhony.gutierrez@amd.com cerr << "Write failed! " << strerror(errno) << endl; 11111308Santhony.gutierrez@amd.com tracing = false; 11211308Santhony.gutierrez@amd.com return false; 11311308Santhony.gutierrez@amd.com } 11411308Santhony.gutierrez@amd.com } 11511308Santhony.gutierrez@amd.com for(int x = XMM0_0; x <= XMM15_3; x++) 11611308Santhony.gutierrez@amd.com { 11711308Santhony.gutierrez@amd.com regVal32 = getRegVal(x); 11811308Santhony.gutierrez@amd.com if(write(socket, ®Val32, sizeof(regVal32)) == -1) 11911308Santhony.gutierrez@amd.com { 12011308Santhony.gutierrez@amd.com cerr << "Write failed! " << strerror(errno) << endl; 12111308Santhony.gutierrez@amd.com tracing = false; 12211308Santhony.gutierrez@amd.com return false; 12311308Santhony.gutierrez@amd.com } 12411308Santhony.gutierrez@amd.com } 12511308Santhony.gutierrez@amd.com return true; 12611308Santhony.gutierrez@amd.com} 12711308Santhony.gutierrez@amd.com 12811308Santhony.gutierrez@amd.comint64_t AMD64TraceChild::getRegs(user_regs_struct & myregs, 12911308Santhony.gutierrez@amd.com user_fpregs_struct & myfpregs, int num) 13011308Santhony.gutierrez@amd.com{ 13111308Santhony.gutierrez@amd.com assert(num < numregs && num >= 0); 13211308Santhony.gutierrez@amd.com switch(num) 13311308Santhony.gutierrez@amd.com { 13411308Santhony.gutierrez@amd.com //GPRs 13511308Santhony.gutierrez@amd.com case RAX: return myregs.rax; 13611308Santhony.gutierrez@amd.com case RBX: return myregs.rbx; 13711308Santhony.gutierrez@amd.com case RCX: return myregs.rcx; 13811308Santhony.gutierrez@amd.com case RDX: return myregs.rdx; 13911308Santhony.gutierrez@amd.com //Index registers 14011308Santhony.gutierrez@amd.com case RSI: return myregs.rsi; 14111308Santhony.gutierrez@amd.com case RDI: return myregs.rdi; 14211308Santhony.gutierrez@amd.com //Base pointer and stack pointer 14311308Santhony.gutierrez@amd.com case RBP: return myregs.rbp; 14411308Santhony.gutierrez@amd.com case RSP: return myregs.rsp; 14511308Santhony.gutierrez@amd.com //New 64 bit mode registers 14611308Santhony.gutierrez@amd.com case R8: return myregs.r8; 14711308Santhony.gutierrez@amd.com case R9: return myregs.r9; 14811308Santhony.gutierrez@amd.com case R10: return myregs.r10; 14911308Santhony.gutierrez@amd.com case R11: return myregs.r11; 15011308Santhony.gutierrez@amd.com case R12: return myregs.r12; 15111308Santhony.gutierrez@amd.com case R13: return myregs.r13; 15211308Santhony.gutierrez@amd.com case R14: return myregs.r14; 15311308Santhony.gutierrez@amd.com case R15: return myregs.r15; 15411308Santhony.gutierrez@amd.com //Segmentation registers 15511308Santhony.gutierrez@amd.com case CS: return myregs.cs; 15611308Santhony.gutierrez@amd.com case DS: return myregs.ds; 15711308Santhony.gutierrez@amd.com case ES: return myregs.es; 15811308Santhony.gutierrez@amd.com case FS: return myregs.fs; 15911308Santhony.gutierrez@amd.com case GS: return myregs.gs; 16011308Santhony.gutierrez@amd.com case SS: return myregs.ss; 16111308Santhony.gutierrez@amd.com case FS_BASE: return myregs.fs_base; 16211308Santhony.gutierrez@amd.com case GS_BASE: return myregs.gs_base; 16311308Santhony.gutierrez@amd.com //PC 16411308Santhony.gutierrez@amd.com case RIP: return myregs.rip; 16511308Santhony.gutierrez@amd.com //Flags 16611308Santhony.gutierrez@amd.com case EFLAGS: return myregs.eflags; 16711308Santhony.gutierrez@amd.com //MMX 16811308Santhony.gutierrez@amd.com case MMX0_0: return myfpregs.st_space[0]; 16911308Santhony.gutierrez@amd.com case MMX0_1: return myfpregs.st_space[1]; 17011308Santhony.gutierrez@amd.com case MMX1_0: return myfpregs.st_space[2]; 17111308Santhony.gutierrez@amd.com case MMX1_1: return myfpregs.st_space[3]; 17211308Santhony.gutierrez@amd.com case MMX2_0: return myfpregs.st_space[4]; 17311308Santhony.gutierrez@amd.com case MMX2_1: return myfpregs.st_space[5]; 17411308Santhony.gutierrez@amd.com case MMX3_0: return myfpregs.st_space[6]; 17511308Santhony.gutierrez@amd.com case MMX3_1: return myfpregs.st_space[7]; 17611308Santhony.gutierrez@amd.com case MMX4_0: return myfpregs.st_space[8]; 17711308Santhony.gutierrez@amd.com case MMX4_1: return myfpregs.st_space[9]; 17811308Santhony.gutierrez@amd.com case MMX5_0: return myfpregs.st_space[10]; 17911308Santhony.gutierrez@amd.com case MMX5_1: return myfpregs.st_space[11]; 18011308Santhony.gutierrez@amd.com case MMX6_0: return myfpregs.st_space[12]; 18111308Santhony.gutierrez@amd.com case MMX6_1: return myfpregs.st_space[13]; 18211308Santhony.gutierrez@amd.com case MMX7_0: return myfpregs.st_space[14]; 18311308Santhony.gutierrez@amd.com case MMX7_1: return myfpregs.st_space[15]; 18411308Santhony.gutierrez@amd.com //XMM 18511308Santhony.gutierrez@amd.com case XMM0_0: return myfpregs.xmm_space[0]; 18611308Santhony.gutierrez@amd.com case XMM0_1: return myfpregs.xmm_space[1]; 18711308Santhony.gutierrez@amd.com case XMM0_2: return myfpregs.xmm_space[2]; 18811308Santhony.gutierrez@amd.com case XMM0_3: return myfpregs.xmm_space[3]; 18911308Santhony.gutierrez@amd.com case XMM1_0: return myfpregs.xmm_space[4]; 19011308Santhony.gutierrez@amd.com case XMM1_1: return myfpregs.xmm_space[5]; 19111308Santhony.gutierrez@amd.com case XMM1_2: return myfpregs.xmm_space[6]; 19211308Santhony.gutierrez@amd.com case XMM1_3: return myfpregs.xmm_space[7]; 19311308Santhony.gutierrez@amd.com case XMM2_0: return myfpregs.xmm_space[8]; 19411308Santhony.gutierrez@amd.com case XMM2_1: return myfpregs.xmm_space[9]; 19511308Santhony.gutierrez@amd.com case XMM2_2: return myfpregs.xmm_space[10]; 19611308Santhony.gutierrez@amd.com case XMM2_3: return myfpregs.xmm_space[11]; 19711308Santhony.gutierrez@amd.com case XMM3_0: return myfpregs.xmm_space[12]; 19811308Santhony.gutierrez@amd.com case XMM3_1: return myfpregs.xmm_space[13]; 19911308Santhony.gutierrez@amd.com case XMM3_2: return myfpregs.xmm_space[14]; 20011308Santhony.gutierrez@amd.com case XMM3_3: return myfpregs.xmm_space[15]; 20111308Santhony.gutierrez@amd.com case XMM4_0: return myfpregs.xmm_space[16]; 20211308Santhony.gutierrez@amd.com case XMM4_1: return myfpregs.xmm_space[17]; 20311308Santhony.gutierrez@amd.com case XMM4_2: return myfpregs.xmm_space[18]; 20411308Santhony.gutierrez@amd.com case XMM4_3: return myfpregs.xmm_space[19]; 20511308Santhony.gutierrez@amd.com case XMM5_0: return myfpregs.xmm_space[20]; 20611308Santhony.gutierrez@amd.com case XMM5_1: return myfpregs.xmm_space[21]; 20711308Santhony.gutierrez@amd.com case XMM5_2: return myfpregs.xmm_space[22]; 20811308Santhony.gutierrez@amd.com case XMM5_3: return myfpregs.xmm_space[23]; 20911308Santhony.gutierrez@amd.com case XMM6_0: return myfpregs.xmm_space[24]; 21011308Santhony.gutierrez@amd.com case XMM6_1: return myfpregs.xmm_space[25]; 21111308Santhony.gutierrez@amd.com case XMM6_2: return myfpregs.xmm_space[26]; 21211308Santhony.gutierrez@amd.com case XMM6_3: return myfpregs.xmm_space[27]; 21311308Santhony.gutierrez@amd.com case XMM7_0: return myfpregs.xmm_space[28]; 21411308Santhony.gutierrez@amd.com case XMM7_1: return myfpregs.xmm_space[29]; 21511308Santhony.gutierrez@amd.com case XMM7_2: return myfpregs.xmm_space[30]; 21611308Santhony.gutierrez@amd.com case XMM7_3: return myfpregs.xmm_space[31]; 21711308Santhony.gutierrez@amd.com case XMM8_0: return myfpregs.xmm_space[32]; 21811308Santhony.gutierrez@amd.com case XMM8_1: return myfpregs.xmm_space[33]; 21911308Santhony.gutierrez@amd.com case XMM8_2: return myfpregs.xmm_space[34]; 22011308Santhony.gutierrez@amd.com case XMM8_3: return myfpregs.xmm_space[35]; 22111308Santhony.gutierrez@amd.com case XMM9_0: return myfpregs.xmm_space[36]; 22211308Santhony.gutierrez@amd.com case XMM9_1: return myfpregs.xmm_space[37]; 22311308Santhony.gutierrez@amd.com case XMM9_2: return myfpregs.xmm_space[38]; 22411308Santhony.gutierrez@amd.com case XMM9_3: return myfpregs.xmm_space[39]; 22511435Smitch.hayenga@arm.com case XMM10_0: return myfpregs.xmm_space[40]; 22611308Santhony.gutierrez@amd.com case XMM10_1: return myfpregs.xmm_space[41]; 22711308Santhony.gutierrez@amd.com case XMM10_2: return myfpregs.xmm_space[42]; 22811308Santhony.gutierrez@amd.com case XMM10_3: return myfpregs.xmm_space[43]; 22911308Santhony.gutierrez@amd.com case XMM11_0: return myfpregs.xmm_space[44]; 23011308Santhony.gutierrez@amd.com case XMM11_1: return myfpregs.xmm_space[45]; 23111308Santhony.gutierrez@amd.com case XMM11_2: return myfpregs.xmm_space[46]; 23211308Santhony.gutierrez@amd.com case XMM11_3: return myfpregs.xmm_space[47]; 23311308Santhony.gutierrez@amd.com case XMM12_0: return myfpregs.xmm_space[48]; 23411308Santhony.gutierrez@amd.com case XMM12_1: return myfpregs.xmm_space[49]; 23511308Santhony.gutierrez@amd.com case XMM12_2: return myfpregs.xmm_space[50]; 23611308Santhony.gutierrez@amd.com case XMM12_3: return myfpregs.xmm_space[51]; 23711308Santhony.gutierrez@amd.com case XMM13_0: return myfpregs.xmm_space[52]; 23811308Santhony.gutierrez@amd.com case XMM13_1: return myfpregs.xmm_space[53]; 23911308Santhony.gutierrez@amd.com case XMM13_2: return myfpregs.xmm_space[54]; 24011308Santhony.gutierrez@amd.com case XMM13_3: return myfpregs.xmm_space[55]; 24111308Santhony.gutierrez@amd.com case XMM14_0: return myfpregs.xmm_space[56]; 24211308Santhony.gutierrez@amd.com case XMM14_1: return myfpregs.xmm_space[57]; 24311308Santhony.gutierrez@amd.com case XMM14_2: return myfpregs.xmm_space[58]; 24411308Santhony.gutierrez@amd.com case XMM14_3: return myfpregs.xmm_space[59]; 24511308Santhony.gutierrez@amd.com case XMM15_0: return myfpregs.xmm_space[60]; 24611308Santhony.gutierrez@amd.com case XMM15_1: return myfpregs.xmm_space[61]; 24711308Santhony.gutierrez@amd.com case XMM15_2: return myfpregs.xmm_space[62]; 24811308Santhony.gutierrez@amd.com case XMM15_3: return myfpregs.xmm_space[63]; 24911308Santhony.gutierrez@amd.com default: 25011308Santhony.gutierrez@amd.com assert(0); 25111308Santhony.gutierrez@amd.com return 0; 25211308Santhony.gutierrez@amd.com } 25311308Santhony.gutierrez@amd.com} 25411308Santhony.gutierrez@amd.com 25511308Santhony.gutierrez@amd.combool AMD64TraceChild::update(int pid) 25611308Santhony.gutierrez@amd.com{ 25711308Santhony.gutierrez@amd.com oldregs = regs; 25811308Santhony.gutierrez@amd.com oldfpregs = fpregs; 25911308Santhony.gutierrez@amd.com if(ptrace(PTRACE_GETREGS, pid, 0, ®s) != 0) 26011308Santhony.gutierrez@amd.com { 26111308Santhony.gutierrez@amd.com cerr << "update: " << strerror(errno) << endl; 26211308Santhony.gutierrez@amd.com return false; 26311308Santhony.gutierrez@amd.com } 26411308Santhony.gutierrez@amd.com if(ptrace(PTRACE_GETFPREGS, pid, 0, &fpregs) != 0) 26511308Santhony.gutierrez@amd.com { 26611308Santhony.gutierrez@amd.com cerr << "update: " << strerror(errno) << endl; 26711308Santhony.gutierrez@amd.com return false; 26811308Santhony.gutierrez@amd.com } 26911308Santhony.gutierrez@amd.com for(unsigned int x = 0; x < numregs; x++) 27011308Santhony.gutierrez@amd.com regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x)); 27111308Santhony.gutierrez@amd.com return true; 27211308Santhony.gutierrez@amd.com} 27311308Santhony.gutierrez@amd.com 27411308Santhony.gutierrez@amd.comAMD64TraceChild::AMD64TraceChild() 27511435Smitch.hayenga@arm.com{ 27611308Santhony.gutierrez@amd.com for(unsigned int x = 0; x < numregs; x++) 27711308Santhony.gutierrez@amd.com regDiffSinceUpdate[x] = false; 27811308Santhony.gutierrez@amd.com} 27911308Santhony.gutierrez@amd.com 28011308Santhony.gutierrez@amd.comint64_t AMD64TraceChild::getRegVal(int num) 28111308Santhony.gutierrez@amd.com{ 28211308Santhony.gutierrez@amd.com return getRegs(regs, fpregs, num); 28311308Santhony.gutierrez@amd.com} 28411308Santhony.gutierrez@amd.com 28511308Santhony.gutierrez@amd.comint64_t AMD64TraceChild::getOldRegVal(int num) 28611308Santhony.gutierrez@amd.com{ 28711308Santhony.gutierrez@amd.com return getRegs(oldregs, oldfpregs, num); 28811308Santhony.gutierrez@amd.com} 28911308Santhony.gutierrez@amd.com 29011308Santhony.gutierrez@amd.comchar * AMD64TraceChild::printReg(int num) 29111308Santhony.gutierrez@amd.com{ 29211308Santhony.gutierrez@amd.com sprintf(printBuffer, "0x%016lX", getRegVal(num)); 29311308Santhony.gutierrez@amd.com return printBuffer; 29411308Santhony.gutierrez@amd.com} 29511308Santhony.gutierrez@amd.com 29611308Santhony.gutierrez@amd.comostream & AMD64TraceChild::outputStartState(ostream & os) 29711308Santhony.gutierrez@amd.com{ 29811308Santhony.gutierrez@amd.com uint64_t sp = getSP(); 29911308Santhony.gutierrez@amd.com uint64_t pc = getPC(); 30011308Santhony.gutierrez@amd.com uint64_t highestInfo = 0; 30111308Santhony.gutierrez@amd.com char obuf[1024]; 30211308Santhony.gutierrez@amd.com sprintf(obuf, "Initial stack pointer = 0x%016lx\n", sp); 30311308Santhony.gutierrez@amd.com os << obuf; 30411308Santhony.gutierrez@amd.com sprintf(obuf, "Initial program counter = 0x%016lx\n", pc); 30511308Santhony.gutierrez@amd.com os << obuf; 30611308Santhony.gutierrez@amd.com 30711308Santhony.gutierrez@amd.com //Output the argument count 30811639Salexandru.dutu@amd.com uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 30911308Santhony.gutierrez@amd.com sprintf(obuf, "0x%016lx: Argc = 0x%016lx\n", sp, cargc); 31011308Santhony.gutierrez@amd.com os << obuf; 31111308Santhony.gutierrez@amd.com sp += 8; 31211308Santhony.gutierrez@amd.com 31311308Santhony.gutierrez@amd.com //Output argv pointers 31411308Santhony.gutierrez@amd.com int argCount = 0; 31511308Santhony.gutierrez@amd.com uint64_t cargv; 31611308Santhony.gutierrez@amd.com do 31711308Santhony.gutierrez@amd.com { 31811308Santhony.gutierrez@amd.com cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 31911308Santhony.gutierrez@amd.com sprintf(obuf, "0x%016lx: argv[%d] = 0x%016lx\n", 32011308Santhony.gutierrez@amd.com sp, argCount++, cargv); 32111308Santhony.gutierrez@amd.com if(cargv) 32211308Santhony.gutierrez@amd.com if(highestInfo < cargv) 32311308Santhony.gutierrez@amd.com highestInfo = cargv; 32411308Santhony.gutierrez@amd.com os << obuf; 32511308Santhony.gutierrez@amd.com sp += 8; 32611308Santhony.gutierrez@amd.com } while(cargv); 32711308Santhony.gutierrez@amd.com 32811308Santhony.gutierrez@amd.com //Output the envp pointers 32911308Santhony.gutierrez@amd.com int envCount = 0; 33011308Santhony.gutierrez@amd.com uint64_t cenvp; 33111308Santhony.gutierrez@amd.com do 33211308Santhony.gutierrez@amd.com { 33311308Santhony.gutierrez@amd.com cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 33411308Santhony.gutierrez@amd.com sprintf(obuf, "0x%016lx: envp[%d] = 0x%016lx\n", 33511308Santhony.gutierrez@amd.com sp, envCount++, cenvp); 33611308Santhony.gutierrez@amd.com os << obuf; 33711308Santhony.gutierrez@amd.com sp += 8; 33811308Santhony.gutierrez@amd.com } while(cenvp); 33911308Santhony.gutierrez@amd.com uint64_t auxType, auxVal; 34011308Santhony.gutierrez@amd.com do 34111308Santhony.gutierrez@amd.com { 34211308Santhony.gutierrez@amd.com auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 34311308Santhony.gutierrez@amd.com sp += 8; 34411308Santhony.gutierrez@amd.com auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 34511308Santhony.gutierrez@amd.com sp += 8; 34611308Santhony.gutierrez@amd.com sprintf(obuf, "0x%016lx: Auxiliary vector = {0x%016lx, 0x%016lx}\n", 34711308Santhony.gutierrez@amd.com sp - 16, auxType, auxVal); 34811308Santhony.gutierrez@amd.com os << obuf; 34911308Santhony.gutierrez@amd.com } while(auxType != 0 || auxVal != 0); 35011308Santhony.gutierrez@amd.com //Print out the argument strings, environment strings, and file name. 35111308Santhony.gutierrez@amd.com string current; 35211308Santhony.gutierrez@amd.com uint64_t buf; 35311308Santhony.gutierrez@amd.com uint64_t currentStart = sp; 35411308Santhony.gutierrez@amd.com bool clearedInitialPadding = false; 35511308Santhony.gutierrez@amd.com do 35611308Santhony.gutierrez@amd.com { 35711308Santhony.gutierrez@amd.com buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0); 35811308Santhony.gutierrez@amd.com char * cbuf = (char *)&buf; 35911308Santhony.gutierrez@amd.com for(int x = 0; x < sizeof(uint64_t); x++) 36011308Santhony.gutierrez@amd.com { 36111308Santhony.gutierrez@amd.com if(cbuf[x]) 36211308Santhony.gutierrez@amd.com current += cbuf[x]; 36311308Santhony.gutierrez@amd.com else 36411308Santhony.gutierrez@amd.com { 36511308Santhony.gutierrez@amd.com sprintf(obuf, "0x%016lx: \"%s\"\n", 36611308Santhony.gutierrez@amd.com currentStart, current.c_str()); 36711308Santhony.gutierrez@amd.com os << obuf; 36811308Santhony.gutierrez@amd.com current = ""; 36911308Santhony.gutierrez@amd.com currentStart = sp + x + 1; 37011308Santhony.gutierrez@amd.com } 37111308Santhony.gutierrez@amd.com } 37211308Santhony.gutierrez@amd.com sp += 8; 37311308Santhony.gutierrez@amd.com clearedInitialPadding = clearedInitialPadding || buf != 0; 37411308Santhony.gutierrez@amd.com } while(!clearedInitialPadding || buf != 0 || sp <= highestInfo); 37511308Santhony.gutierrez@amd.com return os; 37611308Santhony.gutierrez@amd.com} 37711308Santhony.gutierrez@amd.com 37811308Santhony.gutierrez@amd.comuint64_t AMD64TraceChild::findSyscall() 37911308Santhony.gutierrez@amd.com{ 38011308Santhony.gutierrez@amd.com uint64_t rip = getPC(); 38111308Santhony.gutierrez@amd.com bool foundOpcode = false; 38211308Santhony.gutierrez@amd.com bool twoByteOpcode = false; 38311308Santhony.gutierrez@amd.com for(;;) 38411308Santhony.gutierrez@amd.com { 38511308Santhony.gutierrez@amd.com uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, rip, 0); 38611308Santhony.gutierrez@amd.com for(int i = 0; i < sizeof(uint64_t); i++) 38711308Santhony.gutierrez@amd.com { 38811308Santhony.gutierrez@amd.com unsigned char byte = buf & 0xFF; 38911308Santhony.gutierrez@amd.com if(!foundOpcode) 39011534Sjohn.kalamatianos@amd.com { 39111534Sjohn.kalamatianos@amd.com if(!(byte == 0x66 || //operand override 39211534Sjohn.kalamatianos@amd.com byte == 0x67 || //address override 39311534Sjohn.kalamatianos@amd.com byte == 0x2E || //cs 39411534Sjohn.kalamatianos@amd.com byte == 0x3E || //ds 39511534Sjohn.kalamatianos@amd.com byte == 0x26 || //es 39611308Santhony.gutierrez@amd.com byte == 0x64 || //fs 39711308Santhony.gutierrez@amd.com byte == 0x65 || //gs 39811308Santhony.gutierrez@amd.com byte == 0x36 || //ss 39911308Santhony.gutierrez@amd.com byte == 0xF0 || //lock 40011308Santhony.gutierrez@amd.com byte == 0xF2 || //repe 40111640Salexandru.dutu@amd.com byte == 0xF3 || //repne 40211640Salexandru.dutu@amd.com (byte >= 0x40 && byte <= 0x4F) // REX 40311640Salexandru.dutu@amd.com )) 40411640Salexandru.dutu@amd.com { 40511640Salexandru.dutu@amd.com foundOpcode = true; 40611640Salexandru.dutu@amd.com } 407 } 408 if(foundOpcode) 409 { 410 if(twoByteOpcode) 411 { 412 //SYSCALL or SYSENTER 413 if(byte == 0x05 || byte == 0x34) 414 return rip + 1; 415 else 416 return 0; 417 } 418 if(!twoByteOpcode) 419 { 420 if(byte == 0xCC) // INT3 421 return rip + 1; 422 else if(byte == 0xCD) // INT with byte immediate 423 return rip + 2; 424 else if(byte == 0x0F) // two byte opcode prefix 425 twoByteOpcode = true; 426 else 427 return 0; 428 } 429 } 430 buf >>= 8; 431 rip++; 432 } 433 } 434} 435 436bool AMD64TraceChild::step() 437{ 438 uint64_t ripAfterSyscall = findSyscall(); 439 if(ripAfterSyscall) 440 { 441 //Get the original contents of memory 442 uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, ripAfterSyscall, 0); 443 //Patch the first two bytes of the memory immediately after this with 444 //jmp -2. Either single stepping will take over before this 445 //instruction, leaving the rip where it should be, or it will take 446 //over after this instruction, -still- leaving the rip where it should 447 //be. 448 uint64_t newBuf = (buf & ~0xFFFF) | 0xFEEB; 449 //Write the patched memory to the processes address space 450 ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, newBuf); 451 //Step and hit it 452 ptraceSingleStep(); 453 //Put things back to the way they started 454 ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, buf); 455 } 456 else 457 { 458 //Get all the way past repe and repne string instructions in one shot. 459 uint64_t newPC, origPC = getPC(); 460 do 461 { 462 ptraceSingleStep(); 463 newPC = getPC(); 464 } while(newPC == origPC); 465 } 466} 467 468TraceChild * genTraceChild() 469{ 470 return new AMD64TraceChild; 471} 472