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