1 /*
   2  * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 package sun.jvm.hotspot.tools;
  26 
  27 import java.io.PrintStream;
  28 import java.util.Hashtable;
  29 import sun.jvm.hotspot.*;
  30 import sun.jvm.hotspot.runtime.*;
  31 import sun.jvm.hotspot.debugger.*;
  32 
  33 // generic command line or GUI tool.
  34 // override run & code main as shown below.
  35 
  36 public abstract class Tool implements Runnable {
  37    private HotSpotAgent agent;
  38    private int debugeeType;
  39 
  40    // debugeeType is one of constants below
  41    protected static final int DEBUGEE_PID    = 0;
  42    protected static final int DEBUGEE_CORE   = 1;
  43    protected static final int DEBUGEE_REMOTE = 2;
  44 
  45    public String getName() {
  46       return getClass().getName();
  47    }
  48 
  49    protected boolean needsJavaPrefix() {
  50       return true;
  51    }
  52 
  53    protected void setAgent(HotSpotAgent a) {
  54       agent = a;
  55    }
  56 
  57    protected void setDebugeeType(int dt) {
  58       debugeeType = dt;
  59    }
  60 
  61    protected HotSpotAgent getAgent() {
  62       return agent;
  63    }
  64 
  65    protected int getDebugeeType() {
  66       return debugeeType;
  67    }
  68 
  69    protected void printUsage() {
  70       String name = null;
  71       if (needsJavaPrefix()) {
  72          name = "java " + getName();
  73       } else {
  74          name = getName();
  75       }
  76       System.out.println("Usage: " + name + " [option] <pid>");
  77       System.out.println("\t\t(to connect to a live java process)");
  78       System.out.println("   or " + name + " [option] <executable> <core>");
  79       System.out.println("\t\t(to connect to a core file)");
  80       System.out.println("   or " + name + " [option] [server_id@]<remote server IP or hostname>");
  81       System.out.println("\t\t(to connect to a remote debug server)");
  82       System.out.println();
  83       System.out.println("where option must be one of:");
  84       printFlagsUsage();
  85    }
  86 
  87    protected void printFlagsUsage() {
  88        System.out.println("    -h | -help\tto print this help message");
  89    }
  90 
  91    protected void usage() {
  92       printUsage();
  93       System.exit(1);
  94    }
  95 
  96    /*
  97       Derived class main should be of the following form:
  98 
  99       public static void main(String[] args) {
 100          <derived class> obj = new <derived class>;
 101          obj.start(args);
 102       }
 103 
 104    */
 105 
 106    protected void stop() {
 107       if (agent != null) {
 108          agent.detach();
 109          System.exit(0);
 110       }
 111    }
 112 
 113    protected void start(String[] args) {
 114       if ((args.length < 1) || (args.length > 2)) {
 115          usage();
 116       }
 117 
 118       // Attempt to handle -h or -help or some invalid flag
 119       if (args[0].startsWith("-")) {
 120           usage();
 121       }
 122 
 123       PrintStream err = System.err;
 124 
 125       int pid = 0;
 126       String coreFileName   = null;
 127       String executableName = null;
 128       String remoteServer   = null;
 129 
 130       switch (args.length) {
 131         case 1:
 132            try {
 133               pid = Integer.parseInt(args[0]);
 134               debugeeType = DEBUGEE_PID;
 135            } catch (NumberFormatException e) {
 136               // try remote server
 137               remoteServer = args[0];
 138               debugeeType  = DEBUGEE_REMOTE;
 139            }
 140            break;
 141 
 142         case 2:
 143            executableName = args[0];
 144            coreFileName   = args[1];
 145            debugeeType    = DEBUGEE_CORE;
 146            break;
 147 
 148         default:
 149            usage();
 150       }
 151 
 152       agent = new HotSpotAgent();
 153       try {
 154         switch (debugeeType) {
 155           case DEBUGEE_PID:
 156              err.println("Attaching to process ID " + pid + ", please wait...");
 157              agent.attach(pid);
 158              break;
 159 
 160           case DEBUGEE_CORE:
 161              err.println("Attaching to core " + coreFileName +
 162                          " from executable " + executableName + ", please wait...");
 163              agent.attach(executableName, coreFileName);
 164              break;
 165 
 166           case DEBUGEE_REMOTE:
 167              err.println("Attaching to remote server " + remoteServer + ", please wait...");
 168              agent.attach(remoteServer);
 169              break;
 170         }
 171       }
 172       catch (DebuggerException e) {
 173         switch (debugeeType) {
 174           case DEBUGEE_PID:
 175              err.print("Error attaching to process: ");
 176              break;
 177 
 178           case DEBUGEE_CORE:
 179              err.print("Error attaching to core file: ");
 180              break;
 181 
 182           case DEBUGEE_REMOTE:
 183              err.print("Error attaching to remote server: ");
 184              break;
 185         }
 186         if (e.getMessage() != null) {
 187           err.print(e.getMessage());
 188         }
 189         err.println();
 190         System.exit(1);
 191       }
 192 
 193       err.println("Debugger attached successfully.");
 194 
 195       VM vm = VM.getVM();
 196       if (vm.isCore()) {
 197         err.println("Core build detected.");
 198       } else if (vm.isClientCompiler()) {
 199         err.println("Client compiler detected.");
 200       } else if (vm.isServerCompiler()) {
 201         err.println("Server compiler detected.");
 202       } else {
 203         throw new RuntimeException("Fatal error: "
 204             + "should have been able to detect core/C1/C2 build");
 205       }
 206 
 207       String version = vm.getVMRelease();
 208       if (version != null) {
 209         err.print("JVM version is ");
 210         err.println(version);
 211       }
 212 
 213       run();
 214    }
 215 }