tracechild.cc revision 4780
12221SN/A/*
22221SN/A * Copyright (c) 2007 The Regents of The University of Michigan
32221SN/A * All rights reserved.
42221SN/A *
52221SN/A * Redistribution and use in source and binary forms, with or without
62221SN/A * modification, are permitted provided that the following conditions are
72221SN/A * met: redistributions of source code must retain the above copyright
82221SN/A * notice, this list of conditions and the following disclaimer;
92221SN/A * redistributions in binary form must reproduce the above copyright
102221SN/A * notice, this list of conditions and the following disclaimer in the
112221SN/A * documentation and/or other materials provided with the distribution;
122221SN/A * neither the name of the copyright holders nor the names of its
132221SN/A * contributors may be used to endorse or promote products derived from
142221SN/A * this software without specific prior written permission.
152221SN/A *
162221SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172221SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182221SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192221SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202221SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212221SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222221SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232221SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242221SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252221SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262221SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Gabe Black
292665Ssaidi@eecs.umich.edu */
302221SN/A
312221SN/A#include <iostream>
322221SN/A#include <errno.h>
332221SN/A#include <sys/ptrace.h>
342221SN/A#include <stdint.h>
352221SN/A
362221SN/A#include "tracechild_amd64.hh"
372221SN/A
382221SN/Ausing namespace std;
392223SN/A
402221SN/Achar * AMD64TraceChild::regNames[numregs] = {
412221SN/A                //GPRs
422223SN/A                "rax", "rbx", "rcx", "rdx",
432223SN/A                //Index registers
442221SN/A                "rsi", "rdi",
452223SN/A                //Base pointer and stack pointer
462221SN/A                "rbp", "rsp",
472221SN/A                //New 64 bit mode registers
482221SN/A                "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
492221SN/A                //Segmentation registers
502221SN/A                "cs", "ds", "es", "fs", "gs", "ss", "fs_base", "gs_base",
512223SN/A                //PC
522223SN/A                "rip",
532223SN/A                //Flags
542221SN/A                "eflags"};
552221SN/A
562223SN/Abool AMD64TraceChild::sendState(int socket)
572221SN/A{
582221SN/A    uint64_t regVal = 0;
592221SN/A    for(int x = 0; x <= R15; x++)
602223SN/A    {
612223SN/A        regVal = getRegVal(x);
622223SN/A        if(write(socket, &regVal, sizeof(regVal)) == -1)
632221SN/A        {
642221SN/A            cerr << "Write failed! " << strerror(errno) << endl;
652223SN/A            tracing = false;
662223SN/A            return false;
672223SN/A        }
682221SN/A    }
692221SN/A    regVal = getRegVal(RIP);
702221SN/A    if(write(socket, &regVal, sizeof(regVal)) == -1)
712223SN/A    {
722221SN/A        cerr << "Write failed! " << strerror(errno) << endl;
732221SN/A        tracing = false;
742221SN/A        return false;
752223SN/A    }
762223SN/A    return true;
772223SN/A}
782221SN/A
792221SN/Aint64_t AMD64TraceChild::getRegs(user_regs_struct & myregs, int num)
802223SN/A{
812223SN/A        assert(num < numregs && num >= 0);
822223SN/A        switch(num)
832221SN/A        {
842221SN/A                //GPRs
852221SN/A                case RAX: return myregs.rax;
862221SN/A                case RBX: return myregs.rbx;
872221SN/A                case RCX: return myregs.rcx;
882223SN/A                case RDX: return myregs.rdx;
892221SN/A                //Index registers
902221SN/A                case RSI: return myregs.rsi;
912221SN/A                case RDI: return myregs.rdi;
922221SN/A                //Base pointer and stack pointer
932223SN/A                case RBP: return myregs.rbp;
942221SN/A                case RSP: return myregs.rsp;
952221SN/A                //New 64 bit mode registers
962223SN/A                case R8: return myregs.r8;
972221SN/A                case R9: return myregs.r9;
982221SN/A                case R10: return myregs.r10;
992221SN/A                case R11: return myregs.r11;
1002223SN/A                case R12: return myregs.r12;
1012223SN/A                case R13: return myregs.r13;
1022223SN/A                case R14: return myregs.r14;
1032221SN/A                case R15: return myregs.r15;
1042221SN/A                //Segmentation registers
1052223SN/A                case CS: return myregs.cs;
1062223SN/A                case DS: return myregs.ds;
1072223SN/A                case ES: return myregs.es;
1082221SN/A                case FS: return myregs.fs;
1092221SN/A                case GS: return myregs.gs;
1102223SN/A                case SS: return myregs.ss;
1112221SN/A                case FS_BASE: return myregs.fs_base;
1122221SN/A                case GS_BASE: return myregs.gs_base;
1132221SN/A                //PC
1142223SN/A                case RIP: return myregs.rip;
1152223SN/A                //Flags
1162223SN/A                case EFLAGS: return myregs.eflags;
1172221SN/A                default:
1182221SN/A                        assert(0);
1192223SN/A                        return 0;
1202223SN/A        }
1212223SN/A}
1222221SN/A
1232221SN/Abool AMD64TraceChild::update(int pid)
1242223SN/A{
1252221SN/A    oldregs = regs;
1262221SN/A    if(ptrace(PTRACE_GETREGS, pid, 0, &regs) != 0)
1272221SN/A    {
1282223SN/A        cerr << "update: " << strerror(errno) << endl;
1292223SN/A        return false;
1302223SN/A    }
1312221SN/A    for(unsigned int x = 0; x < numregs; x++)
1322221SN/A        regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
1332223SN/A    return true;
1342223SN/A}
1352223SN/A
1362221SN/AAMD64TraceChild::AMD64TraceChild()
1372221SN/A{
1382223SN/A    for(unsigned int x = 0; x < numregs; x++)
1392221SN/A        regDiffSinceUpdate[x] = false;
1402221SN/A}
1412221SN/A
1422223SN/Aint64_t AMD64TraceChild::getRegVal(int num)
1432223SN/A{
1442223SN/A        return getRegs(regs, num);
1452221SN/A}
1462221SN/A
1472223SN/Aint64_t AMD64TraceChild::getOldRegVal(int num)
1482223SN/A{
1492223SN/A        return getRegs(oldregs, num);
1502221SN/A}
1512221SN/A
1522223SN/Achar * AMD64TraceChild::printReg(int num)
1532221SN/A{
1542221SN/A        sprintf(printBuffer, "0x%08X", getRegVal(num));
1552221SN/A        return printBuffer;
1562223SN/A}
1572223SN/A
1582223SN/Aostream & AMD64TraceChild::outputStartState(ostream & os)
1592221SN/A{
1602221SN/A    uint64_t sp = getSP();
1612223SN/A    uint64_t pc = getPC();
1622223SN/A    char obuf[1024];
1632223SN/A    sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp);
1642221SN/A    os << obuf;
1652221SN/A    sprintf(obuf, "Initial program counter = 0x%016llx\n", pc);
1662223SN/A    os << obuf;
1672221SN/A
1682221SN/A    //Output the argument count
1692221SN/A    uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
1702223SN/A    sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc);
1712223SN/A    os << obuf;
1722223SN/A    sp += 8;
1732221SN/A
1742221SN/A    //Output argv pointers
1752223SN/A    int argCount = 0;
1762223SN/A    uint64_t cargv;
1772223SN/A    do
1782221SN/A    {
1792221SN/A        cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
1802223SN/A        sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n",
1812221SN/A                sp, argCount++, cargv);
1822221SN/A        os << obuf;
1832221SN/A        sp += 8;
1842223SN/A    } while(cargv);
1852223SN/A
1862223SN/A    //Output the envp pointers
1872221SN/A    int envCount = 0;
1882221SN/A    uint64_t cenvp;
1892223SN/A    do
1902223SN/A    {
1912223SN/A        cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
1922221SN/A        sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n",
1932221SN/A                sp, envCount++, cenvp);
1942223SN/A        os << obuf;
1952221SN/A        sp += 8;
1962221SN/A    } while(cenvp);
1972221SN/A    uint64_t auxType, auxVal;
1982223SN/A    do
1992223SN/A    {
2002223SN/A        auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
2012221SN/A        sp += 8;
2022221SN/A        auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
2032223SN/A        sp += 8;
2042223SN/A        sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n",
2052223SN/A                sp - 8, auxType, auxVal);
2062221SN/A        os << obuf;
2072221SN/A    } while(auxType != 0 || auxVal != 0);
2082223SN/A    //Print out the argument strings, environment strings, and file name.
2092221SN/A    string current;
2102221SN/A    uint64_t buf;
2112221SN/A    uint64_t currentStart = sp;
2122223SN/A    bool clearedInitialPadding = false;
2132223SN/A    do
2142223SN/A    {
2152221SN/A        buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
2162221SN/A        char * cbuf = (char *)&buf;
2172223SN/A        for(int x = 0; x < sizeof(uint64_t); x++)
2182223SN/A        {
2192223SN/A            if(cbuf[x])
2202221SN/A                current += cbuf[x];
2212221SN/A            else
2222469SN/A            {
2232221SN/A                sprintf(obuf, "0x%016llx: \"%s\"\n",
2242221SN/A                        currentStart, current.c_str());
2252221SN/A                os << obuf;
2262223SN/A                current = "";
2272223SN/A                currentStart = sp + x + 1;
2282223SN/A            }
2292221SN/A        }
2302221SN/A        sp += 8;
2312223SN/A        clearedInitialPadding = clearedInitialPadding || buf != 0;
2322223SN/A    } while(!clearedInitialPadding || buf != 0);
2332223SN/A    return os;
2342221SN/A}
2352221SN/A
2362223SN/ATraceChild * genTraceChild()
2372221SN/A{
2382221SN/A        return new AMD64TraceChild;
2392221SN/A}
2402223SN/A