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