tracechild.cc revision 5049
12SN/A/*
28733Sgeoffrey.blake@arm.com * Copyright (c) 2007 The Regents of The University of Michigan
38733Sgeoffrey.blake@arm.com * All rights reserved.
48733Sgeoffrey.blake@arm.com *
58733Sgeoffrey.blake@arm.com * Redistribution and use in source and binary forms, with or without
68733Sgeoffrey.blake@arm.com * modification, are permitted provided that the following conditions are
78733Sgeoffrey.blake@arm.com * met: redistributions of source code must retain the above copyright
88733Sgeoffrey.blake@arm.com * notice, this list of conditions and the following disclaimer;
98733Sgeoffrey.blake@arm.com * redistributions in binary form must reproduce the above copyright
108733Sgeoffrey.blake@arm.com * notice, this list of conditions and the following disclaimer in the
118733Sgeoffrey.blake@arm.com * documentation and/or other materials provided with the distribution;
128733Sgeoffrey.blake@arm.com * neither the name of the copyright holders nor the names of its
138733Sgeoffrey.blake@arm.com * contributors may be used to endorse or promote products derived from
142188SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272SN/A *
282SN/A * Authors: Gabe Black
292SN/A */
302SN/A
312SN/A#include <iostream>
322SN/A#include <iomanip>
332SN/A#include <errno.h>
342SN/A#include <sys/ptrace.h>
352SN/A#include <stdint.h>
362SN/A
372SN/A#include "tracechild_amd64.hh"
382SN/A
392665SN/Ausing namespace std;
402665SN/A
412665SN/Achar * AMD64TraceChild::regNames[numregs] = {
422SN/A                //GPRs
432SN/A                "rax", "rbx", "rcx", "rdx",
442683Sktlim@umich.edu                //Index registers
452683Sktlim@umich.edu                "rsi", "rdi",
462SN/A                //Base pointer and stack pointer
479020Sgblack@eecs.umich.edu                "rbp", "rsp",
486313Sgblack@eecs.umich.edu                //New 64 bit mode registers
492190SN/A                "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
506329Sgblack@eecs.umich.edu                //Segmentation registers
514997Sgblack@eecs.umich.edu                "cs", "ds", "es", "fs", "gs", "ss", "fs_base", "gs_base",
526316Sgblack@eecs.umich.edu                //PC
536216Snate@binkert.org                "rip",
546658Snate@binkert.org                //Flags
552680SN/A                "eflags",
562683Sktlim@umich.edu                //MMX
578232Snate@binkert.org                "mmx0_0", "mmx0_1",
588232Snate@binkert.org                "mmx1_0", "mmx1_1",
598777Sgblack@eecs.umich.edu                "mmx2_0", "mmx2_1",
602395SN/A                "mmx3_0", "mmx3_1",
612190SN/A                "mmx4_0", "mmx4_1",
622188SN/A                "mmx5_0", "mmx5_1",
638777Sgblack@eecs.umich.edu                "mmx6_0", "mmx6_1",
64217SN/A                "mmx7_0", "mmx7_1",
658777Sgblack@eecs.umich.edu                //XMM
662SN/A                "xmm0_0",  "xmm0_1",  "xmm0_2",  "xmm0_3",
672SN/A                "xmm1_0",  "xmm1_1",  "xmm1_2",  "xmm1_3",
688887Sgeoffrey.blake@arm.com                "xmm2_0",  "xmm2_1",  "xmm2_2",  "xmm2_3",
691070SN/A                "xmm3_0",  "xmm3_1",  "xmm3_2",  "xmm3_3",
701917SN/A                "xmm4_0",  "xmm4_1",  "xmm4_2",  "xmm4_3",
711917SN/A                "xmm5_0",  "xmm5_1",  "xmm5_2",  "xmm5_3",
722521SN/A                "xmm6_0",  "xmm6_1",  "xmm6_2",  "xmm6_3",
733548Sgblack@eecs.umich.edu                "xmm7_0",  "xmm7_1",  "xmm7_2",  "xmm7_3",
743548Sgblack@eecs.umich.edu                "xmm8_0",  "xmm8_1",  "xmm8_2",  "xmm8_3",
753548Sgblack@eecs.umich.edu                "xmm9_0",  "xmm9_1",  "xmm9_2",  "xmm9_3",
768902Sandreas.hansson@arm.com                "xmm10_0", "xmm10_1", "xmm10_2", "xmm10_3",
778902Sandreas.hansson@arm.com                "xmm11_0", "xmm11_1", "xmm11_2", "xmm11_3",
782330SN/A                "xmm12_0", "xmm12_1", "xmm12_2", "xmm12_3",
792683Sktlim@umich.edu                "xmm13_0", "xmm13_1", "xmm13_2", "xmm13_3",
802683Sktlim@umich.edu                "xmm14_0", "xmm14_1", "xmm14_2", "xmm14_3",
812683Sktlim@umich.edu                "xmm15_0", "xmm15_1", "xmm15_2", "xmm15_3"};
822683Sktlim@umich.edu
832683Sktlim@umich.edubool AMD64TraceChild::sendState(int socket)
842683Sktlim@umich.edu{
852683Sktlim@umich.edu    uint64_t regVal64 = 0;
862683Sktlim@umich.edu    uint32_t regVal32 = 0;
872683Sktlim@umich.edu    for(int x = 0; x <= R15; x++)
882683Sktlim@umich.edu    {
892683Sktlim@umich.edu        regVal64 = getRegVal(x);
902683Sktlim@umich.edu        if(write(socket, &regVal64, sizeof(regVal64)) == -1)
912683Sktlim@umich.edu        {
922683Sktlim@umich.edu            cerr << "Write failed! " << strerror(errno) << endl;
932683Sktlim@umich.edu            tracing = false;
942SN/A            return false;
952683Sktlim@umich.edu        }
962SN/A    }
972107SN/A    regVal64 = getRegVal(RIP);
982107SN/A    if(write(socket, &regVal64, sizeof(regVal64)) == -1)
992159SN/A    {
1002455SN/A        cerr << "Write failed! " << strerror(errno) << endl;
1012455SN/A        tracing = false;
1022SN/A        return false;
1032680SN/A    }
1042SN/A    for(int x = MMX0_0; x <= MMX7_1; x++)
1052190SN/A    {
1066315Sgblack@eecs.umich.edu        regVal32 = getRegVal(x);
1076315Sgblack@eecs.umich.edu        if(write(socket, &regVal32, sizeof(regVal32)) == -1)
1086315Sgblack@eecs.umich.edu        {
1096315Sgblack@eecs.umich.edu            cerr << "Write failed! " << strerror(errno) << endl;
1106316Sgblack@eecs.umich.edu            tracing = false;
1119384SAndreas.Sandberg@arm.com            return false;
1122SN/A        }
1137720Sgblack@eecs.umich.edu    }
1146324Sgblack@eecs.umich.edu    for(int x = XMM0_0; x <= XMM15_3; x++)
1157597Sminkyu.jeong@arm.com    {
1167597Sminkyu.jeong@arm.com        regVal32 = getRegVal(x);
1177597Sminkyu.jeong@arm.com        if(write(socket, &regVal32, sizeof(regVal32)) == -1)
1182190SN/A        {
1198357Sksewell@umich.edu            cerr << "Write failed! " << strerror(errno) << endl;
1208357Sksewell@umich.edu            tracing = false;
1218735Sandreas.hanson@arm.com            return false;
1228357Sksewell@umich.edu        }
1238357Sksewell@umich.edu    }
1242683Sktlim@umich.edu    return true;
1252188SN/A}
1262378SN/A
1272400SN/Aint64_t AMD64TraceChild::getRegs(user_regs_struct & myregs,
1286022Sgblack@eecs.umich.edu        user_fpregs_struct & myfpregs, int num)
1296022Sgblack@eecs.umich.edu{
1302SN/A    assert(num < numregs && num >= 0);
1319020Sgblack@eecs.umich.edu    switch(num)
1328541Sgblack@eecs.umich.edu    {
1332683Sktlim@umich.edu        //GPRs
1348793Sgblack@eecs.umich.edu        case RAX: return myregs.rax;
1352683Sktlim@umich.edu        case RBX: return myregs.rbx;
1369384SAndreas.Sandberg@arm.com        case RCX: return myregs.rcx;
1372683Sktlim@umich.edu        case RDX: return myregs.rdx;
1388793Sgblack@eecs.umich.edu        //Index registers
1398820Sgblack@eecs.umich.edu        case RSI: return myregs.rsi;
1409384SAndreas.Sandberg@arm.com        case RDI: return myregs.rdi;
1419384SAndreas.Sandberg@arm.com        //Base pointer and stack pointer
1422862Sktlim@umich.edu        case RBP: return myregs.rbp;
1432864Sktlim@umich.edu        case RSP: return myregs.rsp;
1442862Sktlim@umich.edu        //New 64 bit mode registers
1452683Sktlim@umich.edu        case R8: return myregs.r8;
1462SN/A        case R9: return myregs.r9;
1472680SN/A        case R10: return myregs.r10;
148180SN/A        case R11: return myregs.r11;
1492SN/A        case R12: return myregs.r12;
1502SN/A        case R13: return myregs.r13;
1512864Sktlim@umich.edu        case R14: return myregs.r14;
1522864Sktlim@umich.edu        case R15: return myregs.r15;
1532862Sktlim@umich.edu        //Segmentation registers
1542862Sktlim@umich.edu        case CS: return myregs.cs;
155217SN/A        case DS: return myregs.ds;
156237SN/A        case ES: return myregs.es;
157217SN/A        case FS: return myregs.fs;
1582683Sktlim@umich.edu        case GS: return myregs.gs;
1592683Sktlim@umich.edu        case SS: return myregs.ss;
1605891Sgblack@eecs.umich.edu        case FS_BASE: return myregs.fs_base;
1612683Sktlim@umich.edu        case GS_BASE: return myregs.gs_base;
1622190SN/A        //PC
1632683Sktlim@umich.edu        case RIP: return myregs.rip;
1642683Sktlim@umich.edu        //Flags
1652683Sktlim@umich.edu        case EFLAGS: return myregs.eflags;
1662683Sktlim@umich.edu        //MMX
1672680SN/A        case MMX0_0: return myfpregs.st_space[0];
1682190SN/A        case MMX0_1: return myfpregs.st_space[1];
1695358Sgblack@eecs.umich.edu        case MMX1_0: return myfpregs.st_space[2];
1705358Sgblack@eecs.umich.edu        case MMX1_1: return myfpregs.st_space[3];
1715358Sgblack@eecs.umich.edu        case MMX2_0: return myfpregs.st_space[4];
1725358Sgblack@eecs.umich.edu        case MMX2_1: return myfpregs.st_space[5];
1735358Sgblack@eecs.umich.edu        case MMX3_0: return myfpregs.st_space[6];
1745358Sgblack@eecs.umich.edu        case MMX3_1: return myfpregs.st_space[7];
1755358Sgblack@eecs.umich.edu        case MMX4_0: return myfpregs.st_space[8];
1765358Sgblack@eecs.umich.edu        case MMX4_1: return myfpregs.st_space[9];
1775358Sgblack@eecs.umich.edu        case MMX5_0: return myfpregs.st_space[10];
1785358Sgblack@eecs.umich.edu        case MMX5_1: return myfpregs.st_space[11];
1795358Sgblack@eecs.umich.edu        case MMX6_0: return myfpregs.st_space[12];
1805358Sgblack@eecs.umich.edu        case MMX6_1: return myfpregs.st_space[13];
1815358Sgblack@eecs.umich.edu        case MMX7_0: return myfpregs.st_space[14];
1825358Sgblack@eecs.umich.edu        case MMX7_1: return myfpregs.st_space[15];
1835358Sgblack@eecs.umich.edu        //XMM
1845358Sgblack@eecs.umich.edu        case XMM0_0: return myfpregs.xmm_space[0];
1852683Sktlim@umich.edu        case XMM0_1: return myfpregs.xmm_space[1];
1862521SN/A        case XMM0_2: return myfpregs.xmm_space[2];
1875702Ssaidi@eecs.umich.edu        case XMM0_3: return myfpregs.xmm_space[3];
1885702Ssaidi@eecs.umich.edu        case XMM1_0: return myfpregs.xmm_space[4];
1895702Ssaidi@eecs.umich.edu        case XMM1_1: return myfpregs.xmm_space[5];
1905702Ssaidi@eecs.umich.edu        case XMM1_2: return myfpregs.xmm_space[6];
1912683Sktlim@umich.edu        case XMM1_3: return myfpregs.xmm_space[7];
1922683Sktlim@umich.edu        case XMM2_0: return myfpregs.xmm_space[8];
1932683Sktlim@umich.edu        case XMM2_1: return myfpregs.xmm_space[9];
1942683Sktlim@umich.edu        case XMM2_2: return myfpregs.xmm_space[10];
1958735Sandreas.hanson@arm.com        case XMM2_3: return myfpregs.xmm_space[11];
1962683Sktlim@umich.edu        case XMM3_0: return myfpregs.xmm_space[12];
1976022Sgblack@eecs.umich.edu        case XMM3_1: return myfpregs.xmm_space[13];
1982683Sktlim@umich.edu        case XMM3_2: return myfpregs.xmm_space[14];
1996022Sgblack@eecs.umich.edu        case XMM3_3: return myfpregs.xmm_space[15];
2002683Sktlim@umich.edu        case XMM4_0: return myfpregs.xmm_space[16];
2018887Sgeoffrey.blake@arm.com        case XMM4_1: return myfpregs.xmm_space[17];
2028733Sgeoffrey.blake@arm.com        case XMM4_2: return myfpregs.xmm_space[18];
2039020Sgblack@eecs.umich.edu        case XMM4_3: return myfpregs.xmm_space[19];
2048541Sgblack@eecs.umich.edu        case XMM5_0: return myfpregs.xmm_space[20];
2054997Sgblack@eecs.umich.edu        case XMM5_1: return myfpregs.xmm_space[21];
2064997Sgblack@eecs.umich.edu        case XMM5_2: return myfpregs.xmm_space[22];
2072683Sktlim@umich.edu        case XMM5_3: return myfpregs.xmm_space[23];
2082683Sktlim@umich.edu        case XMM6_0: return myfpregs.xmm_space[24];
2092683Sktlim@umich.edu        case XMM6_1: return myfpregs.xmm_space[25];
2102683Sktlim@umich.edu        case XMM6_2: return myfpregs.xmm_space[26];
2112683Sktlim@umich.edu        case XMM6_3: return myfpregs.xmm_space[27];
2122683Sktlim@umich.edu        case XMM7_0: return myfpregs.xmm_space[28];
2139180Sandreas.hansson@arm.com        case XMM7_1: return myfpregs.xmm_space[29];
2142683Sktlim@umich.edu        case XMM7_2: return myfpregs.xmm_space[30];
2152683Sktlim@umich.edu        case XMM7_3: return myfpregs.xmm_space[31];
2162683Sktlim@umich.edu        case XMM8_0: return myfpregs.xmm_space[32];
2172683Sktlim@umich.edu        case XMM8_1: return myfpregs.xmm_space[33];
2182683Sktlim@umich.edu        case XMM8_2: return myfpregs.xmm_space[34];
2192683Sktlim@umich.edu        case XMM8_3: return myfpregs.xmm_space[35];
2202683Sktlim@umich.edu        case XMM9_0: return myfpregs.xmm_space[36];
2212SN/A        case XMM9_1: return myfpregs.xmm_space[37];
2222SN/A        case XMM9_2: return myfpregs.xmm_space[38];
2232683Sktlim@umich.edu        case XMM9_3: return myfpregs.xmm_space[39];
2242190SN/A        case XMM10_0: return myfpregs.xmm_space[40];
2256315Sgblack@eecs.umich.edu        case XMM10_1: return myfpregs.xmm_space[41];
2266315Sgblack@eecs.umich.edu        case XMM10_2: return myfpregs.xmm_space[42];
2277720Sgblack@eecs.umich.edu        case XMM10_3: return myfpregs.xmm_space[43];
2286316Sgblack@eecs.umich.edu        case XMM11_0: return myfpregs.xmm_space[44];
2296315Sgblack@eecs.umich.edu        case XMM11_1: return myfpregs.xmm_space[45];
2309384SAndreas.Sandberg@arm.com        case XMM11_2: return myfpregs.xmm_space[46];
2316315Sgblack@eecs.umich.edu        case XMM11_3: return myfpregs.xmm_space[47];
2322190SN/A        case XMM12_0: return myfpregs.xmm_space[48];
2332SN/A        case XMM12_1: return myfpregs.xmm_space[49];
2342SN/A        case XMM12_2: return myfpregs.xmm_space[50];
2352SN/A        case XMM12_3: return myfpregs.xmm_space[51];
2362SN/A        case XMM13_0: return myfpregs.xmm_space[52];
2372SN/A        case XMM13_1: return myfpregs.xmm_space[53];
2389384SAndreas.Sandberg@arm.com        case XMM13_2: return myfpregs.xmm_space[54];
2396323Sgblack@eecs.umich.edu        case XMM13_3: return myfpregs.xmm_space[55];
2406418Sgblack@eecs.umich.edu        case XMM14_0: return myfpregs.xmm_space[56];
2417601Sminkyu.jeong@arm.com        case XMM14_1: return myfpregs.xmm_space[57];
2427601Sminkyu.jeong@arm.com        case XMM14_2: return myfpregs.xmm_space[58];
2436418Sgblack@eecs.umich.edu        case XMM14_3: return myfpregs.xmm_space[59];
2442SN/A        case XMM15_0: return myfpregs.xmm_space[60];
2452SN/A        case XMM15_1: return myfpregs.xmm_space[61];
2462455SN/A        case XMM15_2: return myfpregs.xmm_space[62];
2472SN/A        case XMM15_3: return myfpregs.xmm_space[63];
2489384SAndreas.Sandberg@arm.com        default:
2496323Sgblack@eecs.umich.edu                assert(0);
2507341Sgblack@eecs.umich.edu                return 0;
2517601Sminkyu.jeong@arm.com    }
2527601Sminkyu.jeong@arm.com}
2537341Sgblack@eecs.umich.edu
2542SN/Abool AMD64TraceChild::update(int pid)
2552SN/A{
2562455SN/A    oldregs = regs;
2572455SN/A    oldfpregs = fpregs;
2589384SAndreas.Sandberg@arm.com    if(ptrace(PTRACE_GETREGS, pid, 0, &regs) != 0)
2596323Sgblack@eecs.umich.edu    {
2607341Sgblack@eecs.umich.edu        cerr << "update: " << strerror(errno) << endl;
2617601Sminkyu.jeong@arm.com        return false;
2627601Sminkyu.jeong@arm.com    }
2637341Sgblack@eecs.umich.edu    if(ptrace(PTRACE_GETFPREGS, pid, 0, &fpregs) != 0)
2642SN/A    {
2652SN/A        cerr << "update: " << strerror(errno) << endl;
2662SN/A        return false;
2672SN/A    }
2689384SAndreas.Sandberg@arm.com    for(unsigned int x = 0; x < numregs; x++)
2696323Sgblack@eecs.umich.edu        regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
2707601Sminkyu.jeong@arm.com    return true;
2717601Sminkyu.jeong@arm.com}
2726316Sgblack@eecs.umich.edu
2732SN/AAMD64TraceChild::AMD64TraceChild()
2742SN/A{
2752455SN/A    for(unsigned int x = 0; x < numregs; x++)
2762SN/A        regDiffSinceUpdate[x] = false;
2779384SAndreas.Sandberg@arm.com}
2786323Sgblack@eecs.umich.edu
2796315Sgblack@eecs.umich.eduint64_t AMD64TraceChild::getRegVal(int num)
2807601Sminkyu.jeong@arm.com{
2817601Sminkyu.jeong@arm.com        return getRegs(regs, fpregs, num);
2822SN/A}
2832SN/A
2842455SN/Aint64_t AMD64TraceChild::getOldRegVal(int num)
2852455SN/A{
2869384SAndreas.Sandberg@arm.com        return getRegs(oldregs, oldfpregs, num);
2876323Sgblack@eecs.umich.edu}
2888733Sgeoffrey.blake@arm.com
2898733Sgeoffrey.blake@arm.comchar * AMD64TraceChild::printReg(int num)
2908733Sgeoffrey.blake@arm.com{
2918733Sgeoffrey.blake@arm.com        sprintf(printBuffer, "0x%08X", getRegVal(num));
2927601Sminkyu.jeong@arm.com        return printBuffer;
2937601Sminkyu.jeong@arm.com}
2942SN/A
2952SN/Aostream & AMD64TraceChild::outputStartState(ostream & os)
2967720Sgblack@eecs.umich.edu{
2977720Sgblack@eecs.umich.edu    uint64_t sp = getSP();
2982SN/A    uint64_t pc = getPC();
2997720Sgblack@eecs.umich.edu    uint64_t highestInfo = 0;
3002SN/A    char obuf[1024];
3012SN/A    sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp);
3027720Sgblack@eecs.umich.edu    os << obuf;
3037720Sgblack@eecs.umich.edu    sprintf(obuf, "Initial program counter = 0x%016llx\n", pc);
3042190SN/A    os << obuf;
3057720Sgblack@eecs.umich.edu
3062190SN/A    //Output the argument count
3072190SN/A    uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
3088733Sgeoffrey.blake@arm.com    sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc);
3098733Sgeoffrey.blake@arm.com    os << obuf;
3108733Sgeoffrey.blake@arm.com    sp += 8;
3118733Sgeoffrey.blake@arm.com
3128733Sgeoffrey.blake@arm.com    //Output argv pointers
3138733Sgeoffrey.blake@arm.com    int argCount = 0;
3147720Sgblack@eecs.umich.edu    uint64_t cargv;
3157720Sgblack@eecs.umich.edu    do
3163276Sgblack@eecs.umich.edu    {
3177720Sgblack@eecs.umich.edu        cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
3183276Sgblack@eecs.umich.edu        sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n",
3193276Sgblack@eecs.umich.edu                sp, argCount++, cargv);
3207720Sgblack@eecs.umich.edu        if(cargv)
3217720Sgblack@eecs.umich.edu            if(highestInfo < cargv)
3223276Sgblack@eecs.umich.edu                highestInfo = cargv;
3237720Sgblack@eecs.umich.edu        os << obuf;
3243276Sgblack@eecs.umich.edu        sp += 8;
3253276Sgblack@eecs.umich.edu    } while(cargv);
3267720Sgblack@eecs.umich.edu
3277720Sgblack@eecs.umich.edu    //Output the envp pointers
3282190SN/A    int envCount = 0;
3297720Sgblack@eecs.umich.edu    uint64_t cenvp;
3302251SN/A    do
3312251SN/A    {
3327597Sminkyu.jeong@arm.com        cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
3337597Sminkyu.jeong@arm.com        sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n",
3347597Sminkyu.jeong@arm.com                sp, envCount++, cenvp);
3357597Sminkyu.jeong@arm.com        os << obuf;
3367597Sminkyu.jeong@arm.com        sp += 8;
3377597Sminkyu.jeong@arm.com    } while(cenvp);
3387597Sminkyu.jeong@arm.com    uint64_t auxType, auxVal;
3397597Sminkyu.jeong@arm.com    do
3407597Sminkyu.jeong@arm.com    {
3417597Sminkyu.jeong@arm.com        auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
3426221Snate@binkert.org        sp += 8;
3436221Snate@binkert.org        auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
3444172Ssaidi@eecs.umich.edu        sp += 8;
3459384SAndreas.Sandberg@arm.com        sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n",
3464172Ssaidi@eecs.umich.edu                sp - 16, auxType, auxVal);
3474172Ssaidi@eecs.umich.edu        os << obuf;
3486221Snate@binkert.org    } while(auxType != 0 || auxVal != 0);
3496221Snate@binkert.org    //Print out the argument strings, environment strings, and file name.
3502SN/A    string current;
3519384SAndreas.Sandberg@arm.com    uint64_t buf;
3522SN/A    uint64_t currentStart = sp;
3532SN/A    bool clearedInitialPadding = false;
3546221Snate@binkert.org    do
3556221Snate@binkert.org    {
3562SN/A        buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
3579384SAndreas.Sandberg@arm.com        char * cbuf = (char *)&buf;
3582SN/A        for(int x = 0; x < sizeof(uint64_t); x++)
3592SN/A        {
3606221Snate@binkert.org            if(cbuf[x])
3616221Snate@binkert.org                current += cbuf[x];
3622SN/A            else
3639384SAndreas.Sandberg@arm.com            {
3646313Sgblack@eecs.umich.edu                sprintf(obuf, "0x%016llx: \"%s\"\n",
3656313Sgblack@eecs.umich.edu                        currentStart, current.c_str());
3666313Sgblack@eecs.umich.edu                os << obuf;
3676313Sgblack@eecs.umich.edu                current = "";
3686313Sgblack@eecs.umich.edu                currentStart = sp + x + 1;
3699384SAndreas.Sandberg@arm.com            }
3706313Sgblack@eecs.umich.edu        }
3716313Sgblack@eecs.umich.edu        sp += 8;
3726313Sgblack@eecs.umich.edu        clearedInitialPadding = clearedInitialPadding || buf != 0;
3736313Sgblack@eecs.umich.edu    } while(!clearedInitialPadding || buf != 0 || sp <= highestInfo);
3746313Sgblack@eecs.umich.edu    return os;
3759384SAndreas.Sandberg@arm.com}
3762SN/A
3772SN/Auint64_t AMD64TraceChild::findSyscall()
3782190SN/A{
3792190SN/A    uint64_t rip = getPC();
3802190SN/A    bool foundOpcode = false;
3812190SN/A    bool twoByteOpcode = false;
3822190SN/A    for(;;)
3832561SN/A    {
3842SN/A        uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, rip, 0);
3852680SN/A        for(int i = 0; i < sizeof(uint64_t); i++)
3862SN/A        {
3872SN/A            unsigned char byte = buf & 0xFF;
3882SN/A            if(!foundOpcode)
3892SN/A            {
3902SN/A                if(!(byte == 0x66 || //operand override
3912SN/A                     byte == 0x67 || //address override
3922683Sktlim@umich.edu                     byte == 0x2E || //cs
3932SN/A                     byte == 0x3E || //ds
3942SN/A                     byte == 0x26 || //es
3952SN/A                     byte == 0x64 || //fs
3962SN/A                     byte == 0x65 || //gs
3972190SN/A                     byte == 0x36 || //ss
398                     byte == 0xF0 || //lock
399                     byte == 0xF2 || //repe
400                     byte == 0xF3 || //repne
401                     (byte >= 0x40 && byte <= 0x4F) // REX
402                    ))
403                {
404                    foundOpcode = true;
405                }
406            }
407            if(foundOpcode)
408            {
409                if(twoByteOpcode)
410                {
411                    //SYSCALL or SYSENTER
412                    if(byte == 0x05 || byte == 0x34)
413                        return rip + 1;
414                    else
415                        return 0;
416                }
417                if(!twoByteOpcode)
418                {
419                    if(byte == 0xCC) // INT3
420                        return rip + 1;
421                    else if(byte == 0xCD) // INT with byte immediate
422                        return rip + 2;
423                    else if(byte == 0x0F) // two byte opcode prefix
424                        twoByteOpcode = true;
425                    else
426                        return 0;
427                }
428            }
429            buf >>= 8;
430            rip++;
431        }
432    }
433}
434
435bool AMD64TraceChild::step()
436{
437    uint64_t ripAfterSyscall = findSyscall();
438    if(ripAfterSyscall)
439    {
440        //Get the original contents of memory
441        uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, ripAfterSyscall, 0);
442        //Patch the first two bytes of the memory immediately after this with
443        //jmp -2. Either single stepping will take over before this
444        //instruction, leaving the rip where it should be, or it will take
445        //over after this instruction, -still- leaving the rip where it should
446        //be.
447        uint64_t newBuf = (buf & ~0xFFFF) | 0xFEEB;
448        //Write the patched memory to the processes address space
449        ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, newBuf);
450        //Step and hit it
451        ptraceSingleStep();
452        //Put things back to the way they started
453        ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, buf);
454    }
455    else
456    {
457        //Get all the way past repe and repne string instructions in one shot.
458        uint64_t newPC, origPC = getPC();
459        do
460        {
461            ptraceSingleStep();
462            newPC = getPC();
463        } while(newPC == origPC);
464    }
465}
466
467TraceChild * genTraceChild()
468{
469        return new AMD64TraceChild;
470}
471