tracechild.cc revision 4955
16313Sgblack@eecs.umich.edu/*
212477SCurtis.Dunham@arm.com * Copyright (c) 2007 The Regents of The University of Michigan
37093Sgblack@eecs.umich.edu * All rights reserved.
47093Sgblack@eecs.umich.edu *
57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
146313Sgblack@eecs.umich.edu * this software without specific prior written permission.
156313Sgblack@eecs.umich.edu *
166313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276313Sgblack@eecs.umich.edu *
286313Sgblack@eecs.umich.edu * Authors: Gabe Black
296313Sgblack@eecs.umich.edu */
306313Sgblack@eecs.umich.edu
316313Sgblack@eecs.umich.edu#include <iostream>
326313Sgblack@eecs.umich.edu#include <iomanip>
336313Sgblack@eecs.umich.edu#include <errno.h>
346313Sgblack@eecs.umich.edu#include <sys/ptrace.h>
356313Sgblack@eecs.umich.edu#include <stdint.h>
366313Sgblack@eecs.umich.edu
376313Sgblack@eecs.umich.edu#include "tracechild_amd64.hh"
386313Sgblack@eecs.umich.edu
396313Sgblack@eecs.umich.eduusing namespace std;
406313Sgblack@eecs.umich.edu
416313Sgblack@eecs.umich.educhar * AMD64TraceChild::regNames[numregs] = {
426313Sgblack@eecs.umich.edu                //GPRs
436313Sgblack@eecs.umich.edu                "rax", "rbx", "rcx", "rdx",
447404SAli.Saidi@ARM.com                //Index registers
456313Sgblack@eecs.umich.edu                "rsi", "rdi",
4610461SAndreas.Sandberg@ARM.com                //Base pointer and stack pointer
4712479SCurtis.Dunham@arm.com                "rbp", "rsp",
486333Sgblack@eecs.umich.edu                //New 64 bit mode registers
4910037SARM gem5 Developers                "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
507404SAli.Saidi@ARM.com                //Segmentation registers
516313Sgblack@eecs.umich.edu                "cs", "ds", "es", "fs", "gs", "ss", "fs_base", "gs_base",
5212109SRekai.GonzalezAlberquilla@arm.com                //PC
538232Snate@binkert.org                "rip",
5412109SRekai.GonzalezAlberquilla@arm.com                //Flags
559384SAndreas.Sandberg@arm.com                "eflags"};
5611165SRekai.GonzalezAlberquilla@arm.com
576313Sgblack@eecs.umich.edubool AMD64TraceChild::sendState(int socket)
589384SAndreas.Sandberg@arm.com{
5910461SAndreas.Sandberg@ARM.com    uint64_t regVal = 0;
606333Sgblack@eecs.umich.edu    for(int x = 0; x <= R15; x++)
616313Sgblack@eecs.umich.edu    {
626313Sgblack@eecs.umich.edu        regVal = getRegVal(x);
636313Sgblack@eecs.umich.edu        if(write(socket, &regVal, sizeof(regVal)) == -1)
646313Sgblack@eecs.umich.edu        {
656313Sgblack@eecs.umich.edu            cerr << "Write failed! " << strerror(errno) << endl;
669384SAndreas.Sandberg@arm.com            tracing = false;
676313Sgblack@eecs.umich.edu            return false;
686313Sgblack@eecs.umich.edu        }
6910037SARM gem5 Developers    }
7010037SARM gem5 Developers    regVal = getRegVal(RIP);
7110037SARM gem5 Developers    if(write(socket, &regVal, sizeof(regVal)) == -1)
7211165SRekai.GonzalezAlberquilla@arm.com    {
7311165SRekai.GonzalezAlberquilla@arm.com        cerr << "Write failed! " << strerror(errno) << endl;
7412109SRekai.GonzalezAlberquilla@arm.com        tracing = false;
7511165SRekai.GonzalezAlberquilla@arm.com        return false;
7610461SAndreas.Sandberg@ARM.com    }
7710461SAndreas.Sandberg@ARM.com    return true;
7810461SAndreas.Sandberg@ARM.com}
7910461SAndreas.Sandberg@ARM.com
8010461SAndreas.Sandberg@ARM.comint64_t AMD64TraceChild::getRegs(user_regs_struct & myregs, int num)
8110461SAndreas.Sandberg@ARM.com{
8210844Sandreas.sandberg@arm.com        assert(num < numregs && num >= 0);
8310844Sandreas.sandberg@arm.com        switch(num)
8410844Sandreas.sandberg@arm.com        {
8510037SARM gem5 Developers                //GPRs
8611771SCurtis.Dunham@arm.com                case RAX: return myregs.rax;
8710037SARM gem5 Developers                case RBX: return myregs.rbx;
8810037SARM gem5 Developers                case RCX: return myregs.rcx;
8910037SARM gem5 Developers                case RDX: return myregs.rdx;
9010037SARM gem5 Developers                //Index registers
9110037SARM gem5 Developers                case RSI: return myregs.rsi;
9210037SARM gem5 Developers                case RDI: return myregs.rdi;
9312478SCurtis.Dunham@arm.com                //Base pointer and stack pointer
9410037SARM gem5 Developers                case RBP: return myregs.rbp;
9512477SCurtis.Dunham@arm.com                case RSP: return myregs.rsp;
9612477SCurtis.Dunham@arm.com                //New 64 bit mode registers
9712478SCurtis.Dunham@arm.com                case R8: return myregs.r8;
9812478SCurtis.Dunham@arm.com                case R9: return myregs.r9;
9912478SCurtis.Dunham@arm.com                case R10: return myregs.r10;
10012478SCurtis.Dunham@arm.com                case R11: return myregs.r11;
10112478SCurtis.Dunham@arm.com                case R12: return myregs.r12;
10212478SCurtis.Dunham@arm.com                case R13: return myregs.r13;
10312478SCurtis.Dunham@arm.com                case R14: return myregs.r14;
10412478SCurtis.Dunham@arm.com                case R15: return myregs.r15;
10512478SCurtis.Dunham@arm.com                //Segmentation registers
10612478SCurtis.Dunham@arm.com                case CS: return myregs.cs;
10712478SCurtis.Dunham@arm.com                case DS: return myregs.ds;
10812478SCurtis.Dunham@arm.com                case ES: return myregs.es;
10912478SCurtis.Dunham@arm.com                case FS: return myregs.fs;
11012478SCurtis.Dunham@arm.com                case GS: return myregs.gs;
11112478SCurtis.Dunham@arm.com                case SS: return myregs.ss;
11212478SCurtis.Dunham@arm.com                case FS_BASE: return myregs.fs_base;
11310037SARM gem5 Developers                case GS_BASE: return myregs.gs_base;
11410037SARM gem5 Developers                //PC
11512477SCurtis.Dunham@arm.com                case RIP: return myregs.rip;
11612479SCurtis.Dunham@arm.com                //Flags
11712477SCurtis.Dunham@arm.com                case EFLAGS: return myregs.eflags;
11812477SCurtis.Dunham@arm.com                default:
11912477SCurtis.Dunham@arm.com                        assert(0);
12012479SCurtis.Dunham@arm.com                        return 0;
12112477SCurtis.Dunham@arm.com        }
12212477SCurtis.Dunham@arm.com}
12312477SCurtis.Dunham@arm.com
12412477SCurtis.Dunham@arm.combool AMD64TraceChild::update(int pid)
12512477SCurtis.Dunham@arm.com{
12612477SCurtis.Dunham@arm.com    oldregs = regs;
12712477SCurtis.Dunham@arm.com    if(ptrace(PTRACE_GETREGS, pid, 0, &regs) != 0)
12812478SCurtis.Dunham@arm.com    {
12912478SCurtis.Dunham@arm.com        cerr << "update: " << strerror(errno) << endl;
13012478SCurtis.Dunham@arm.com        return false;
13112478SCurtis.Dunham@arm.com    }
13212478SCurtis.Dunham@arm.com    for(unsigned int x = 0; x < numregs; x++)
13312478SCurtis.Dunham@arm.com        regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
13412478SCurtis.Dunham@arm.com    return true;
13512478SCurtis.Dunham@arm.com}
13612478SCurtis.Dunham@arm.com
13712478SCurtis.Dunham@arm.comAMD64TraceChild::AMD64TraceChild()
13812478SCurtis.Dunham@arm.com{
13912478SCurtis.Dunham@arm.com    for(unsigned int x = 0; x < numregs; x++)
14012478SCurtis.Dunham@arm.com        regDiffSinceUpdate[x] = false;
14112478SCurtis.Dunham@arm.com}
14212478SCurtis.Dunham@arm.com
14312478SCurtis.Dunham@arm.comint64_t AMD64TraceChild::getRegVal(int num)
14412479SCurtis.Dunham@arm.com{
14512479SCurtis.Dunham@arm.com        return getRegs(regs, num);
14612479SCurtis.Dunham@arm.com}
14712479SCurtis.Dunham@arm.com
14812479SCurtis.Dunham@arm.comint64_t AMD64TraceChild::getOldRegVal(int num)
14912479SCurtis.Dunham@arm.com{
15012479SCurtis.Dunham@arm.com        return getRegs(oldregs, num);
15112479SCurtis.Dunham@arm.com}
15212479SCurtis.Dunham@arm.com
15312479SCurtis.Dunham@arm.comchar * AMD64TraceChild::printReg(int num)
15412479SCurtis.Dunham@arm.com{
15512479SCurtis.Dunham@arm.com        sprintf(printBuffer, "0x%08X", getRegVal(num));
15612479SCurtis.Dunham@arm.com        return printBuffer;
15712479SCurtis.Dunham@arm.com}
15812479SCurtis.Dunham@arm.com
15912479SCurtis.Dunham@arm.comostream & AMD64TraceChild::outputStartState(ostream & os)
16012479SCurtis.Dunham@arm.com{
16112479SCurtis.Dunham@arm.com    uint64_t sp = getSP();
16212479SCurtis.Dunham@arm.com    uint64_t pc = getPC();
16312479SCurtis.Dunham@arm.com    uint64_t highestInfo = 0;
16412479SCurtis.Dunham@arm.com    char obuf[1024];
16512479SCurtis.Dunham@arm.com    sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp);
16612479SCurtis.Dunham@arm.com    os << obuf;
16712479SCurtis.Dunham@arm.com    sprintf(obuf, "Initial program counter = 0x%016llx\n", pc);
16812479SCurtis.Dunham@arm.com    os << obuf;
16912479SCurtis.Dunham@arm.com
17012479SCurtis.Dunham@arm.com    //Output the argument count
17112479SCurtis.Dunham@arm.com    uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
17212479SCurtis.Dunham@arm.com    sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc);
17312479SCurtis.Dunham@arm.com    os << obuf;
17412479SCurtis.Dunham@arm.com    sp += 8;
17512479SCurtis.Dunham@arm.com
17612479SCurtis.Dunham@arm.com    //Output argv pointers
17712479SCurtis.Dunham@arm.com    int argCount = 0;
17812479SCurtis.Dunham@arm.com    uint64_t cargv;
17912479SCurtis.Dunham@arm.com    do
18012479SCurtis.Dunham@arm.com    {
18112479SCurtis.Dunham@arm.com        cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
18212479SCurtis.Dunham@arm.com        sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n",
18312479SCurtis.Dunham@arm.com                sp, argCount++, cargv);
18412479SCurtis.Dunham@arm.com        if(cargv)
18512479SCurtis.Dunham@arm.com            if(highestInfo < cargv)
18612479SCurtis.Dunham@arm.com                highestInfo = cargv;
18712479SCurtis.Dunham@arm.com        os << obuf;
18812479SCurtis.Dunham@arm.com        sp += 8;
18912479SCurtis.Dunham@arm.com    } while(cargv);
19012479SCurtis.Dunham@arm.com
19112479SCurtis.Dunham@arm.com    //Output the envp pointers
19212479SCurtis.Dunham@arm.com    int envCount = 0;
19312479SCurtis.Dunham@arm.com    uint64_t cenvp;
19412479SCurtis.Dunham@arm.com    do
19512479SCurtis.Dunham@arm.com    {
19612479SCurtis.Dunham@arm.com        cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
19712479SCurtis.Dunham@arm.com        sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n",
19812479SCurtis.Dunham@arm.com                sp, envCount++, cenvp);
19912479SCurtis.Dunham@arm.com        os << obuf;
20012479SCurtis.Dunham@arm.com        sp += 8;
20112479SCurtis.Dunham@arm.com    } while(cenvp);
20212479SCurtis.Dunham@arm.com    uint64_t auxType, auxVal;
20312479SCurtis.Dunham@arm.com    do
20412479SCurtis.Dunham@arm.com    {
20512479SCurtis.Dunham@arm.com        auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
20612479SCurtis.Dunham@arm.com        sp += 8;
20712479SCurtis.Dunham@arm.com        auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
20812479SCurtis.Dunham@arm.com        sp += 8;
20912479SCurtis.Dunham@arm.com        sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n",
21012479SCurtis.Dunham@arm.com                sp - 16, auxType, auxVal);
21112479SCurtis.Dunham@arm.com        os << obuf;
21212479SCurtis.Dunham@arm.com    } while(auxType != 0 || auxVal != 0);
21312479SCurtis.Dunham@arm.com    //Print out the argument strings, environment strings, and file name.
21412479SCurtis.Dunham@arm.com    string current;
21512479SCurtis.Dunham@arm.com    uint64_t buf;
21612479SCurtis.Dunham@arm.com    uint64_t currentStart = sp;
21712479SCurtis.Dunham@arm.com    bool clearedInitialPadding = false;
21812479SCurtis.Dunham@arm.com    do
21912479SCurtis.Dunham@arm.com    {
22012479SCurtis.Dunham@arm.com        buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
22112479SCurtis.Dunham@arm.com        char * cbuf = (char *)&buf;
22212479SCurtis.Dunham@arm.com        for(int x = 0; x < sizeof(uint64_t); x++)
22312479SCurtis.Dunham@arm.com        {
22412479SCurtis.Dunham@arm.com            if(cbuf[x])
22512479SCurtis.Dunham@arm.com                current += cbuf[x];
22612479SCurtis.Dunham@arm.com            else
22712479SCurtis.Dunham@arm.com            {
22812479SCurtis.Dunham@arm.com                sprintf(obuf, "0x%016llx: \"%s\"\n",
22912479SCurtis.Dunham@arm.com                        currentStart, current.c_str());
23012479SCurtis.Dunham@arm.com                os << obuf;
23112479SCurtis.Dunham@arm.com                current = "";
23212479SCurtis.Dunham@arm.com                currentStart = sp + x + 1;
23312479SCurtis.Dunham@arm.com            }
23412479SCurtis.Dunham@arm.com        }
23512479SCurtis.Dunham@arm.com        sp += 8;
23612479SCurtis.Dunham@arm.com        clearedInitialPadding = clearedInitialPadding || buf != 0;
23712479SCurtis.Dunham@arm.com    } while(!clearedInitialPadding || buf != 0 || sp <= highestInfo);
23812479SCurtis.Dunham@arm.com    return os;
23912479SCurtis.Dunham@arm.com}
24012479SCurtis.Dunham@arm.com
24112479SCurtis.Dunham@arm.comuint64_t AMD64TraceChild::findSyscall()
24212479SCurtis.Dunham@arm.com{
24312479SCurtis.Dunham@arm.com    uint64_t rip = getPC();
24412479SCurtis.Dunham@arm.com    bool foundOpcode = false;
24512479SCurtis.Dunham@arm.com    bool twoByteOpcode = false;
24612479SCurtis.Dunham@arm.com    for(;;)
24712479SCurtis.Dunham@arm.com    {
24812479SCurtis.Dunham@arm.com        uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, rip, 0);
24912479SCurtis.Dunham@arm.com        for(int i = 0; i < sizeof(uint64_t); i++)
25012479SCurtis.Dunham@arm.com        {
25112479SCurtis.Dunham@arm.com            unsigned char byte = buf & 0xFF;
25212479SCurtis.Dunham@arm.com            if(!foundOpcode)
25312479SCurtis.Dunham@arm.com            {
25412479SCurtis.Dunham@arm.com                if(!(byte == 0x66 || //operand override
25512479SCurtis.Dunham@arm.com                     byte == 0x67 || //address override
25612479SCurtis.Dunham@arm.com                     byte == 0x2E || //cs
25712479SCurtis.Dunham@arm.com                     byte == 0x3E || //ds
25812479SCurtis.Dunham@arm.com                     byte == 0x26 || //es
25912479SCurtis.Dunham@arm.com                     byte == 0x64 || //fs
26012479SCurtis.Dunham@arm.com                     byte == 0x65 || //gs
26112479SCurtis.Dunham@arm.com                     byte == 0x36 || //ss
26212479SCurtis.Dunham@arm.com                     byte == 0xF0 || //lock
26312479SCurtis.Dunham@arm.com                     byte == 0xF2 || //repe
26412479SCurtis.Dunham@arm.com                     byte == 0xF3 || //repne
26512479SCurtis.Dunham@arm.com                     (byte >= 0x40 && byte <= 0x4F) // REX
26612479SCurtis.Dunham@arm.com                    ))
26712479SCurtis.Dunham@arm.com                {
26812479SCurtis.Dunham@arm.com                    foundOpcode = true;
26912479SCurtis.Dunham@arm.com                }
27012479SCurtis.Dunham@arm.com            }
27112479SCurtis.Dunham@arm.com            if(foundOpcode)
27212479SCurtis.Dunham@arm.com            {
27312479SCurtis.Dunham@arm.com                if(twoByteOpcode)
27412479SCurtis.Dunham@arm.com                {
27512479SCurtis.Dunham@arm.com                    //SYSCALL or SYSENTER
27612479SCurtis.Dunham@arm.com                    if(byte == 0x05 || byte == 0x34)
27712479SCurtis.Dunham@arm.com                        return rip + 1;
27812479SCurtis.Dunham@arm.com                    else
27912479SCurtis.Dunham@arm.com                        return 0;
28012479SCurtis.Dunham@arm.com                }
28112479SCurtis.Dunham@arm.com                if(!twoByteOpcode)
28212479SCurtis.Dunham@arm.com                {
28312479SCurtis.Dunham@arm.com                    if(byte == 0xCC) // INT3
28412479SCurtis.Dunham@arm.com                        return rip + 1;
28512479SCurtis.Dunham@arm.com                    else if(byte == 0xCD) // INT with byte immediate
28612479SCurtis.Dunham@arm.com                        return rip + 2;
28712479SCurtis.Dunham@arm.com                    else if(byte == 0x0F) // two byte opcode prefix
28812479SCurtis.Dunham@arm.com                        twoByteOpcode = true;
28912479SCurtis.Dunham@arm.com                    else
29012479SCurtis.Dunham@arm.com                        return 0;
29112479SCurtis.Dunham@arm.com                }
29212479SCurtis.Dunham@arm.com            }
29312479SCurtis.Dunham@arm.com            buf >>= 8;
29412479SCurtis.Dunham@arm.com            rip++;
29512479SCurtis.Dunham@arm.com        }
29612479SCurtis.Dunham@arm.com    }
29712479SCurtis.Dunham@arm.com}
29812479SCurtis.Dunham@arm.com
29912479SCurtis.Dunham@arm.combool AMD64TraceChild::step()
30012479SCurtis.Dunham@arm.com{
30112479SCurtis.Dunham@arm.com    uint64_t ripAfterSyscall = findSyscall();
30212479SCurtis.Dunham@arm.com    if(ripAfterSyscall)
30312479SCurtis.Dunham@arm.com    {
30412479SCurtis.Dunham@arm.com        //Get the original contents of memory
30512479SCurtis.Dunham@arm.com        uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, ripAfterSyscall, 0);
30612479SCurtis.Dunham@arm.com        //Patch the first two bytes of the memory immediately after this with
30712479SCurtis.Dunham@arm.com        //jmp -2. Either single stepping will take over before this
30812479SCurtis.Dunham@arm.com        //instruction, leaving the rip where it should be, or it will take
30912479SCurtis.Dunham@arm.com        //over after this instruction, -still- leaving the rip where it should
31012479SCurtis.Dunham@arm.com        //be.
31112479SCurtis.Dunham@arm.com        uint64_t newBuf = (buf & ~0xFFFF) | 0xFEEB;
31212479SCurtis.Dunham@arm.com        //Write the patched memory to the processes address space
31312479SCurtis.Dunham@arm.com        ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, newBuf);
31412479SCurtis.Dunham@arm.com        //Step and hit it
31512479SCurtis.Dunham@arm.com        ptraceSingleStep();
31612479SCurtis.Dunham@arm.com        //Put things back to the way they started
31712479SCurtis.Dunham@arm.com        ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, buf);
31812479SCurtis.Dunham@arm.com    }
31912479SCurtis.Dunham@arm.com    else
32012479SCurtis.Dunham@arm.com    {
32112479SCurtis.Dunham@arm.com        //Get all the way past repe and repne string instructions in one shot.
32212479SCurtis.Dunham@arm.com        uint64_t newPC, origPC = getPC();
32312479SCurtis.Dunham@arm.com        do
32412479SCurtis.Dunham@arm.com        {
32512479SCurtis.Dunham@arm.com            ptraceSingleStep();
32612479SCurtis.Dunham@arm.com            newPC = getPC();
32712479SCurtis.Dunham@arm.com        } while(newPC == origPC);
32812479SCurtis.Dunham@arm.com    }
32912479SCurtis.Dunham@arm.com}
33010037SARM gem5 Developers
33110037SARM gem5 DevelopersTraceChild * genTraceChild()
33212477SCurtis.Dunham@arm.com{
33312479SCurtis.Dunham@arm.com        return new AMD64TraceChild;
33412479SCurtis.Dunham@arm.com}
33512477SCurtis.Dunham@arm.com