tracechild.cc revision 8108
1360SN/A/*
210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2006-2007 The Regents of The University of Michigan
310796Sbrandon.potter@amd.com * All rights reserved.
410027SChris.Adeniyi-Jones@arm.com *
510027SChris.Adeniyi-Jones@arm.com * Redistribution and use in source and binary forms, with or without
610027SChris.Adeniyi-Jones@arm.com * modification, are permitted provided that the following conditions are
710027SChris.Adeniyi-Jones@arm.com * met: redistributions of source code must retain the above copyright
810027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer;
910027SChris.Adeniyi-Jones@arm.com * redistributions in binary form must reproduce the above copyright
1010027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer in the
1110027SChris.Adeniyi-Jones@arm.com * documentation and/or other materials provided with the distribution;
1210027SChris.Adeniyi-Jones@arm.com * neither the name of the copyright holders nor the names of its
1310027SChris.Adeniyi-Jones@arm.com * contributors may be used to endorse or promote products derived from
1410027SChris.Adeniyi-Jones@arm.com * this software without specific prior written permission.
151458SN/A *
16360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27360SN/A *
28360SN/A * Authors: Gabe Black
29360SN/A */
30360SN/A
31360SN/A#include "tracechild.hh"
32360SN/A#include <cstring>
33360SN/A#include <errno.h>
34360SN/A#include <iostream>
35360SN/A#include <sys/ptrace.h>
36360SN/A#include <sys/wait.h>
37360SN/A
38360SN/Ausing namespace std;
39360SN/A
402665Ssaidi@eecs.umich.edubool
412665Ssaidi@eecs.umich.eduTraceChild::startTracing(const char * pathToFile, char * const argv[])
422665Ssaidi@eecs.umich.edu{
43360SN/A    instructions = 0;
44360SN/A    pid = fork();
451354SN/A    if (pid == -1) {
461354SN/A        cout << "fork failed" << endl;
47360SN/A        return false;
4812018Sandreas.sandberg@arm.com    } else if (pid == 0) {
4912018Sandreas.sandberg@arm.com        //We're the child. Get things ready and then exec the program to trace.
5012018Sandreas.sandberg@arm.com        //Let our parent trace us
5112018Sandreas.sandberg@arm.com        if (ptrace(PTRACE_TRACEME, 0, 0, 0) == -1) {
5212018Sandreas.sandberg@arm.com            cout << "Failure calling TRACEME\n" << strerror(errno) << endl;
5312018Sandreas.sandberg@arm.com            return false;
5412018Sandreas.sandberg@arm.com        }
552064SN/A
5612018Sandreas.sandberg@arm.com        //Set up an empty environment for the child... We would want to
5712018Sandreas.sandberg@arm.com        //specify this somehow at some point
5812018Sandreas.sandberg@arm.com        char * env[] = {NULL};
5912018Sandreas.sandberg@arm.com
6012018Sandreas.sandberg@arm.com        //Start the program to trace
6112018Sandreas.sandberg@arm.com        execve(pathToFile, argv, env);
6211799Sbrandon.potter@amd.com
6312018Sandreas.sandberg@arm.com        //We should never get here, so this is an error!
6412018Sandreas.sandberg@arm.com        cout << "Exec failed\n" <<  strerror(errno) << endl;
6512018Sandreas.sandberg@arm.com        return false;
6612018Sandreas.sandberg@arm.com    }
6712018Sandreas.sandberg@arm.com
6812018Sandreas.sandberg@arm.com    //From this point forward, we know we're in the parent process.
6911799Sbrandon.potter@amd.com    if (!doWait()) {
70360SN/A        cout << "Didn't wait successfully" << endl;
71360SN/A        return false;
72360SN/A    }
73360SN/A    tracing = true;
74360SN/A    return true;
75360SN/A}
761809SN/A
7711800Sbrandon.potter@amd.combool
7811392Sbrandon.potter@amd.comTraceChild::stopTracing()
791809SN/A{
8011392Sbrandon.potter@amd.com    if (ptrace(PTRACE_KILL, pid, 0, 0) != 0)
8111383Sbrandon.potter@amd.com        return false;
823113Sgblack@eecs.umich.edu    tracing = false;
8311799Sbrandon.potter@amd.com    return true;
8411759Sbrandon.potter@amd.com}
8511812Sbaz21@cam.ac.uk
8611812Sbaz21@cam.ac.ukbool
8711799Sbrandon.potter@amd.comTraceChild::step()
888229Snate@binkert.org{
898229Snate@binkert.org    ptraceSingleStep();
9011594Santhony.gutierrez@amd.com}
917075Snate@binkert.org
928229Snate@binkert.orgbool
9311856Sbrandon.potter@amd.comTraceChild::ptraceSingleStep()
947075Snate@binkert.org{
95360SN/A    if (!tracing) {
9612461Sgabeblack@google.com        cout << "Not tracing!" << endl;
9711886Sbrandon.potter@amd.com        return false;
9811800Sbrandon.potter@amd.com    }
9911392Sbrandon.potter@amd.com    if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0) {
10012334Sgabeblack@google.com        switch (errno) {
1011354SN/A          case EBUSY: cout << "EBUSY" << endl; break;
1026216Snate@binkert.org          case EFAULT: cout << "EFAULT" << endl; break;
1036658Snate@binkert.org          case EIO: cout << "EIO" << endl; break;
1042474SN/A          case EPERM: cout << "EPERM" << endl; break;
1052680Sktlim@umich.edu          case ESRCH: cout << "ESRCH" << endl; break;
1068229Snate@binkert.org          default: cout << "Unknown error" << endl; break;
10711886Sbrandon.potter@amd.com        }
10810496Ssteve.reinhardt@amd.com        cout << "Not able to single step!" << endl;
10911911SBrandon.Potter@amd.com        tracing == false;
1108229Snate@binkert.org        return false;
11111794Sbrandon.potter@amd.com    }
11211886Sbrandon.potter@amd.com    doWait();
11310497Ssteve.reinhardt@amd.com    update(pid);
11411794Sbrandon.potter@amd.com}
115360SN/A
116360SN/Abool
117360SN/ATraceChild::doWait()
118360SN/A{
119360SN/A    int wait_val;
120360SN/A    wait(&wait_val);
121360SN/A    if (WIFEXITED(wait_val)) {
122360SN/A        cerr << "Program exited! Exit status is "
123360SN/A             << WEXITSTATUS(wait_val) << endl;
124360SN/A        cerr << "Executed " << instructions
125378SN/A             << " instructions." << endl;
1261706SN/A        tracing = false;
12711851Sbrandon.potter@amd.com        return false;
128378SN/A    }
129378SN/A    if (WIFSIGNALED(wait_val)) {
130378SN/A        if (WTERMSIG(wait_val))
131378SN/A            cerr << "Program terminated by signal "
132378SN/A                 << WTERMSIG(wait_val) << endl;
1331706SN/A        if (WCOREDUMP(wait_val))
13411851Sbrandon.potter@amd.com            cerr << "Program core dumped!" << endl;
135360SN/A        tracing = false;
13611760Sbrandon.potter@amd.com        cerr << "Executed " << instructions
13711760Sbrandon.potter@amd.com             << " instructions." << endl;
13811851Sbrandon.potter@amd.com        return false;
13911760Sbrandon.potter@amd.com    }
1406109Ssanchezd@stanford.edu    if (WIFSTOPPED(wait_val) && WSTOPSIG(wait_val) != SIGTRAP) {
1411706SN/A        cerr << "Program stopped by signal " << WSTOPSIG(wait_val) << endl;
14211851Sbrandon.potter@amd.com        tracing = false;
143378SN/A        cerr << "Executed " << instructions << " instructions." << endl;
1446109Ssanchezd@stanford.edu            return false;
1456109Ssanchezd@stanford.edu    }
14611851Sbrandon.potter@amd.com    return true;
1476109Ssanchezd@stanford.edu}
14811886Sbrandon.potter@amd.com