tracechild.cc revision 3115
110037SARM gem5 Developers/*
210037SARM gem5 Developers * Copyright (c) 2006 The Regents of The University of Michigan
314127Sgiacomo.travaglini@arm.com * All rights reserved.
410037SARM gem5 Developers *
510037SARM gem5 Developers * Redistribution and use in source and binary forms, with or without
610037SARM gem5 Developers * modification, are permitted provided that the following conditions are
710037SARM gem5 Developers * met: redistributions of source code must retain the above copyright
810037SARM gem5 Developers * notice, this list of conditions and the following disclaimer;
910037SARM gem5 Developers * redistributions in binary form must reproduce the above copyright
1010037SARM gem5 Developers * notice, this list of conditions and the following disclaimer in the
1110037SARM gem5 Developers * documentation and/or other materials provided with the distribution;
1210037SARM gem5 Developers * neither the name of the copyright holders nor the names of its
1310037SARM gem5 Developers * contributors may be used to endorse or promote products derived from
1410037SARM gem5 Developers * this software without specific prior written permission.
1510037SARM gem5 Developers *
1610037SARM gem5 Developers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710037SARM gem5 Developers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810037SARM gem5 Developers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910037SARM gem5 Developers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010037SARM gem5 Developers * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110037SARM gem5 Developers * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210037SARM gem5 Developers * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310037SARM gem5 Developers * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410037SARM gem5 Developers * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510037SARM gem5 Developers * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610037SARM gem5 Developers * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710037SARM gem5 Developers *
2810037SARM gem5 Developers * Authors: Gabe Black
2910037SARM gem5 Developers */
3010037SARM gem5 Developers
3110037SARM gem5 Developers#include "tracechild.hh"
3210037SARM gem5 Developers#include <sys/wait.h>
3310037SARM gem5 Developers#include <sys/ptrace.h>
3410037SARM gem5 Developers#include <iostream>
3510037SARM gem5 Developers#include <errno.h>
3610037SARM gem5 Developers
3710037SARM gem5 Developersusing namespace std;
3810037SARM gem5 Developers
3910037SARM gem5 Developersbool TraceChild::startTracing(const char * pathToFile, const char * arg)
4012538Sgiacomo.travaglini@arm.com{
4112538Sgiacomo.travaglini@arm.com        pid = fork();
4212538Sgiacomo.travaglini@arm.com        if(pid == -1)
4312538Sgiacomo.travaglini@arm.com        {
4412538Sgiacomo.travaglini@arm.com                cout << "fork failed" << endl;
4512538Sgiacomo.travaglini@arm.com                return false;
4612538Sgiacomo.travaglini@arm.com        }
4712538Sgiacomo.travaglini@arm.com        else if(pid == 0)
4812616Sgabeblack@google.com        {
4912538Sgiacomo.travaglini@arm.com                //We're the child. Get things ready and then exec the
5012538Sgiacomo.travaglini@arm.com                //program to trace.
5112538Sgiacomo.travaglini@arm.com
5212538Sgiacomo.travaglini@arm.com                //Let our parent trace us
5312538Sgiacomo.travaglini@arm.com                ptrace(PTRACE_TRACEME, 0, 0, 0);
5412538Sgiacomo.travaglini@arm.com
5512538Sgiacomo.travaglini@arm.com                //Start the program to trace
5612538Sgiacomo.travaglini@arm.com                execl(pathToFile, arg);
5712538Sgiacomo.travaglini@arm.com
5812538Sgiacomo.travaglini@arm.com                //We should never get here, so this is an error!
5912538Sgiacomo.travaglini@arm.com                return false;
6010037SARM gem5 Developers        }
6110037SARM gem5 Developers
6210037SARM gem5 Developers        //From this point forward, we know we're in the parent process.
6310037SARM gem5 Developers        if(!doWait())
6410037SARM gem5 Developers        {
6510037SARM gem5 Developers                cout << "Didn't wait successfully" << endl;
6610037SARM gem5 Developers                return false;
6710037SARM gem5 Developers        }
6810037SARM gem5 Developers        tracing = true;
6912616Sgabeblack@google.com        if(!update(pid))
7010037SARM gem5 Developers        {
7110037SARM gem5 Developers                cout << "Didn't update successfully!" << endl;
7210037SARM gem5 Developers                return false;
7310037SARM gem5 Developers        }
7410184SCurtis.Dunham@arm.com        return true;
7510037SARM gem5 Developers}
7610037SARM gem5 Developers
7710037SARM gem5 Developersbool TraceChild::stopTracing()
7810037SARM gem5 Developers{
7910037SARM gem5 Developers        if(ptrace(PTRACE_KILL, pid, 0, 0) != 0)
8010037SARM gem5 Developers                return false;
8110037SARM gem5 Developers        tracing = false;
8210037SARM gem5 Developers        return true;
8310037SARM gem5 Developers}
8410037SARM gem5 Developers
8510037SARM gem5 Developersbool TraceChild::step()
8610037SARM gem5 Developers{
8710037SARM gem5 Developers        ptraceSingleStep();
8810037SARM gem5 Developers}
8910037SARM gem5 Developers
9010037SARM gem5 Developersbool TraceChild::ptraceSingleStep()
9110037SARM gem5 Developers{
9210037SARM gem5 Developers        if(!tracing)
9310037SARM gem5 Developers        {
9410037SARM gem5 Developers                cout << "Not tracing!" << endl;
9512616Sgabeblack@google.com                return false;
9610037SARM gem5 Developers        }
9710037SARM gem5 Developers        if(ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0)
9810037SARM gem5 Developers        {
9910037SARM gem5 Developers                switch(errno)
10010184SCurtis.Dunham@arm.com                {
10110037SARM gem5 Developers                        case EBUSY: cout << "EBUSY" << endl; break;
10210037SARM gem5 Developers                        case EFAULT: cout << "EFAULT" << endl; break;
10310037SARM gem5 Developers                        case EIO: cout << "EIO" << endl; break;
10410037SARM gem5 Developers                        case EPERM: cout << "EPERM" << endl; break;
10510037SARM gem5 Developers                        case ESRCH: cout << "ESRCH" << endl; break;
10610037SARM gem5 Developers                        default: cout << "Unknown error" << endl; break;
10710037SARM gem5 Developers                }
10810037SARM gem5 Developers                cout << "Not able to single step!" << endl;
10910037SARM gem5 Developers                tracing == false;
11010037SARM gem5 Developers                return false;
11110037SARM gem5 Developers        }
11214127Sgiacomo.travaglini@arm.com        doWait();
11314127Sgiacomo.travaglini@arm.com        update(pid);
11414127Sgiacomo.travaglini@arm.com}
11514127Sgiacomo.travaglini@arm.com
11614127Sgiacomo.travaglini@arm.combool TraceChild::doWait()
11714127Sgiacomo.travaglini@arm.com{
11814127Sgiacomo.travaglini@arm.com        int wait_val;
11914127Sgiacomo.travaglini@arm.com        wait(&wait_val);
12014127Sgiacomo.travaglini@arm.com        if(WIFEXITED(wait_val))
12114127Sgiacomo.travaglini@arm.com        {
12214127Sgiacomo.travaglini@arm.com                cerr << "Program exited! Exit status is "
12314127Sgiacomo.travaglini@arm.com                        << WEXITSTATUS(wait_val) << endl;
12414127Sgiacomo.travaglini@arm.com                tracing = false;
12514127Sgiacomo.travaglini@arm.com                return false;
12614127Sgiacomo.travaglini@arm.com        }
12714127Sgiacomo.travaglini@arm.com        if(WIFSIGNALED(wait_val))
12814127Sgiacomo.travaglini@arm.com        {
12914127Sgiacomo.travaglini@arm.com                if(WTERMSIG(wait_val))
13014127Sgiacomo.travaglini@arm.com                        cerr << "Program terminated by signal "
13114127Sgiacomo.travaglini@arm.com                                << WTERMSIG(wait_val) << endl;
13214127Sgiacomo.travaglini@arm.com                if(WCOREDUMP(wait_val))
13314127Sgiacomo.travaglini@arm.com                        cerr << "Program core dumped!" << endl;
13414127Sgiacomo.travaglini@arm.com                tracing = false;
13512280Sgiacomo.travaglini@arm.com                return false;
13612280Sgiacomo.travaglini@arm.com        }
13712280Sgiacomo.travaglini@arm.com        if(WIFSTOPPED(wait_val) && WSTOPSIG(wait_val) != SIGTRAP)
13812280Sgiacomo.travaglini@arm.com        {
13912280Sgiacomo.travaglini@arm.com                cerr << "Program stopped by signal "
14012280Sgiacomo.travaglini@arm.com                        << WSTOPSIG(wait_val) << endl;
14112280Sgiacomo.travaglini@arm.com                tracing = false;
14212280Sgiacomo.travaglini@arm.com                return false;
14312616Sgabeblack@google.com        }
14412280Sgiacomo.travaglini@arm.com        return true;
14512280Sgiacomo.travaglini@arm.com}
14612280Sgiacomo.travaglini@arm.com