13115SN/A/* 24125SN/A * Copyright (c) 2006-2007 The Regents of The University of Michigan 33115SN/A * All rights reserved. 43115SN/A * 53115SN/A * Redistribution and use in source and binary forms, with or without 63115SN/A * modification, are permitted provided that the following conditions are 73115SN/A * met: redistributions of source code must retain the above copyright 83115SN/A * notice, this list of conditions and the following disclaimer; 93115SN/A * redistributions in binary form must reproduce the above copyright 103115SN/A * notice, this list of conditions and the following disclaimer in the 113115SN/A * documentation and/or other materials provided with the distribution; 123115SN/A * neither the name of the copyright holders nor the names of its 133115SN/A * contributors may be used to endorse or promote products derived from 143115SN/A * this software without specific prior written permission. 153115SN/A * 163115SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173115SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183115SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193115SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203115SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213115SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223115SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233115SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243115SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253115SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263115SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273115SN/A * 283115SN/A * Authors: Gabe Black 293115SN/A */ 303115SN/A 316406SN/A#include <netinet/in.h> 326406SN/A#include <sys/ptrace.h> 336406SN/A#include <sys/socket.h> 343115SN/A#include <sys/types.h> 353115SN/A#include <sys/wait.h> 368229Snate@binkert.org#include <netdb.h> 373115SN/A#include <unistd.h> 383115SN/A 398229Snate@binkert.org#include <cerrno> 408229Snate@binkert.org#include <cstdio> 418229Snate@binkert.org#include <cstring> 428229Snate@binkert.org#include <fstream> 438229Snate@binkert.org#include <iostream> 448229Snate@binkert.org#include <string> 458229Snate@binkert.org 468229Snate@binkert.org#include "base/arch_check.h" 473115SN/A#include "tracechild.hh" 483115SN/A 493115SN/Ausing namespace std; 503115SN/A 518108SN/Avoid 528108SN/AprintUsage(const char * execName) 533115SN/A{ 547414SN/A cout << execName << " <options> -- <command> <arguments>" << endl; 557414SN/A cout << "options:" << endl; 567414SN/A cout << " -h print this help" << endl; 577414SN/A cout << " --host remote m5 host to connect to" << endl; 587414SN/A cout << " -i print initial stack state" << endl; 598114Sgblack@eecs.umich.edu cout << " -nt don't trace execution" << endl; 603115SN/A} 613115SN/A 628108SN/Aint 638108SN/Amain(int argc, char * argv[], char * envp[]) 643115SN/A{ 654779SN/A TraceChild * child = genTraceChild(); 664779SN/A string args; 674779SN/A int startProgramArgs; 683115SN/A 694779SN/A //Parse the command line arguments 704779SN/A bool printInitial = false; 714779SN/A bool printTrace = true; 726408SN/A string host = "localhost"; 737414SN/A 747414SN/A if (argc == 1) { 757414SN/A printUsage(argv[0]); 767414SN/A return 0; 777414SN/A } 788108SN/A for (int x = 1; x < argc; x++) { 798108SN/A if (!strcmp(argv[x], "-h")) { 804779SN/A printUsage(argv[0]); 814779SN/A return 0; 823115SN/A } 838108SN/A if (!strcmp(argv[x], "--host")) { 846408SN/A x++; 858108SN/A if (x >= argc) { 866408SN/A cerr << "Incorrect usage.\n" << endl; 876408SN/A printUsage(argv[0]); 886408SN/A return 1; 896408SN/A } 906408SN/A host = argv[x]; 918108SN/A } else if (!strcmp(argv[x], "-i")) { 924779SN/A printInitial = true; 938108SN/A } else if (!strcmp(argv[x], "-nt")) { 944779SN/A printTrace = false; 958108SN/A } else if (!strcmp(argv[x], "--")) { 964779SN/A x++; 978108SN/A if (x >= argc) { 984779SN/A cerr << "Incorrect usage.\n" << endl; 994779SN/A printUsage(argv[0]); 1004245SN/A return 1; 1013115SN/A } 1024779SN/A startProgramArgs = x; 1034779SN/A break; 1048108SN/A } else { 1054779SN/A cerr << "Incorrect usage.\n" << endl; 1064779SN/A printUsage(argv[0]); 1074779SN/A return 1; 1083115SN/A } 1094779SN/A } 1108108SN/A if (!child->startTracing(argv[startProgramArgs], 1118108SN/A argv + startProgramArgs)) { 1124779SN/A cerr << "Couldn't start target program" << endl; 1134779SN/A return 1; 1144779SN/A } 1156422SN/A child->step(); 1168108SN/A if (printInitial) 1174779SN/A child->outputStartState(cout); 1188108SN/A if (printTrace) { 1194779SN/A // Connect to m5 1204779SN/A bool portSet = false; 1214779SN/A int port; 1224779SN/A int sock = socket(AF_INET, SOCK_STREAM, 0); 1238108SN/A if (sock < 0) { 1244779SN/A cerr << "Error opening socket! " << strerror(errno) << endl; 1254779SN/A return 1; 1264779SN/A } 1274779SN/A struct hostent *server; 1286408SN/A server = gethostbyname(host.c_str()); 1298108SN/A if (!server) { 1304779SN/A cerr << "Couldn't get host ip! " << strerror(errno) << endl; 1314779SN/A return 1; 1324779SN/A } 1334779SN/A struct sockaddr_in serv_addr; 1344779SN/A bzero((char *)&serv_addr, sizeof(serv_addr)); 1354779SN/A serv_addr.sin_family = AF_INET; 1364779SN/A bcopy((char *)server->h_addr, 1374779SN/A (char *)&serv_addr.sin_addr.s_addr, 1384779SN/A server->h_length); 1394779SN/A serv_addr.sin_port = htons(8000); 1408108SN/A if (connect(sock, (sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { 1414779SN/A cerr << "Couldn't connect to server! " << strerror(errno) << endl; 1424779SN/A return 1; 1434779SN/A } 1448108SN/A while (child->isTracing()) { 1458108SN/A if (!child->sendState(sock)) 1468108SN/A break; 1478108SN/A child->step(); 1484779SN/A } 1494779SN/A } 1508108SN/A if (!child->stopTracing()) { 1518108SN/A cerr << "Couldn't stop child" << endl; 1528108SN/A return 1; 1534779SN/A } 1544779SN/A return 0; 1553115SN/A} 1563115SN/A 157