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, &regVal, 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, &regVal, 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, &regs) != 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